Add a massive set of changes for converting to use the ast_debug() macro.
[asterisk/asterisk.git] / apps / app_voicemail.c
index 8e27d90..675d966 100644 (file)
  * \brief Comedian Mail - Voicemail System
  *
  * \author Mark Spencer <markster@digium.com>
+ *
+ * \extref Unixodbc - http://www.unixodbc.org
+ * \extref A source distribution of University of Washington's IMAP
+c-client (http://www.washington.edu/imap/
  * 
  * \par See also
  * \arg \ref Config_vm
+ * \note For information about voicemail IMAP storage, read doc/imapstorage.txt
  * \ingroup applications
- * \note This module requires res_adsi to load.
+ * \note This module requires res_adsi to load. This needs to be optional
+ * during compilation.
+ *
+ *
+ *
+ * \note  This file is now almost impossible to work with, due to all #ifdefs.
+ *        Feels like the database code before realtime. Someone - please come up
+ *        with a plan to clean this up.
  */
 
+/*** MODULEINFO
+       <depend>res_smdi</depend>
+ ***/
+
 /*** MAKEOPTS
 <category name="MENUSELECT_OPTS_app_voicemail" displayname="Voicemail Build Options" positive_output="yes" remove_on_change="apps/app_voicemail.o">
        <member name="ODBC_STORAGE" displayname="Storage of Voicemail using ODBC">
                <depend>unixodbc</depend>
+               <conflict>IMAP_STORAGE</conflict>
                <defaultenabled>no</defaultenabled>
        </member>
        <member name="IMAP_STORAGE" displayname="Storage of Voicemail using IMAP4">
                <depend>imap_tk</depend>
+               <conflict>ODBC_STORAGE</conflict>
                <use>ssl</use>
                <defaultenabled>no</defaultenabled>
        </member>
@@ -58,6 +76,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <sys/mman.h>
 #include <time.h>
 #include <dirent.h>
+
 #ifdef IMAP_STORAGE
 #include <ctype.h>
 #include <signal.h>
@@ -66,6 +85,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "imap4r1.h"
 #include "linkage.h"
 #endif
+
 #include "asterisk/lock.h"
 #include "asterisk/file.h"
 #include "asterisk/logger.h"
@@ -84,14 +104,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/smdi.h"
+#include "asterisk/event.h"
+
 #ifdef ODBC_STORAGE
 #include "asterisk/res_odbc.h"
 #endif
 
 #ifdef IMAP_STORAGE
-AST_MUTEX_DEFINE_STATIC(imaptemp_lock);
-static char imaptemp[1024];
-
 static char imapserver[48];
 static char imapport[8];
 static char imapflags[128];
@@ -106,13 +125,13 @@ static char delimiter = '\0';
 struct vm_state;
 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 void status (MAILSTREAM *stream); */ /* No need for this. */
-static void display_body (BODY *body, char *pfx, long i);
-static char *get_header_by_tag(char *header, char *tag);
+/* Forward declarations for IMAP */
+static int init_mailstream(struct vm_state *vms, int box);
+static void write_file(char *filename, char *buffer, unsigned long len);
+static void display_body(BODY *body, char *pfx, long i);
+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 char *get_user_by_mailbox(char *mailbox);
+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 void vmstate_insert(struct vm_state *vms);
@@ -127,13 +146,16 @@ 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, struct vm_state *vms, int box, int target);
 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);
-static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box);
+
+
+
 struct vmstate {
        struct vm_state *vms;
-       struct vmstate *next;
+       AST_LIST_ENTRY(vmstate) list;
 };
-AST_MUTEX_DEFINE_STATIC(vmstate_lock);
-static struct vmstate *vmstates = NULL;
+
+static AST_LIST_HEAD_STATIC(vmstates, vmstate);
+
 #endif
 
 #define SMDI_MWI_WAIT_TIMEOUT 1000 /* 1 second */
@@ -142,6 +164,7 @@ static struct vmstate *vmstates = NULL;
 /* Don't modify these here; set your umask at runtime instead */
 #define        VOICEMAIL_DIR_MODE      0777
 #define        VOICEMAIL_FILE_MODE     0666
+#define        CHUNKSIZE       65536
 
 #define VOICEMAIL_CONFIG "voicemail.conf"
 #define ASTERISK_USERNAME "asterisk"
@@ -188,7 +211,6 @@ enum {
        OPT_UNAVAIL_GREETING = (1 << 2),
        OPT_RECORDGAIN =       (1 << 3),
        OPT_PREPEND_MAILBOX =  (1 << 4),
-       OPT_PRIORITY_JUMP =    (1 << 5),
        OPT_AUTOPLAY =         (1 << 6),
 } vm_option_flags;
 
@@ -205,7 +227,6 @@ AST_APP_OPTIONS(vm_app_options, {
        AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
        AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
        AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
-       AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
        AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER),
 });
 
@@ -291,7 +312,8 @@ struct baseio {
        unsigned char iobuf[BASEMAXINLINE];
 };
 
-/*! Structure for linked list of users */
+/*! Structure for linked list of users 
+ * Use ast_vm_user_destroy() to free one of these structures. */
 struct ast_vm_user {
        char context[AST_MAX_CONTEXT];   /*!< Voicemail context */
        char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox id, unique within vm context */
@@ -311,14 +333,16 @@ struct ast_vm_user {
        unsigned int flags;              /*!< VM_ flags */      
        int saydurationm;
        int maxmsg;                      /*!< Maximum number of msgs per folder for this mailbox */
+       int maxsecs;                     /*!< Maximum number of seconds per message for this mailbox */
 #ifdef IMAP_STORAGE
-       char imapuser[80];      /* IMAP server login */
-       char imappassword[80];  /* IMAP server password if authpassword not defined */
+       char imapuser[80];               /*!< IMAP server login */
+       char imappassword[80];           /*!< IMAP server password if authpassword not defined */
 #endif
-       double volgain;         /*!< Volume gain for voicemails sent via email */
+       double volgain;                  /*!< Volume gain for voicemails sent via email */
        AST_LIST_ENTRY(ast_vm_user) list;
 };
 
+/*! Voicemail time zones */
 struct vm_zone {
        AST_LIST_ENTRY(vm_zone) list;
        char name[80];
@@ -326,13 +350,14 @@ struct vm_zone {
        char msg_format[512];
 };
 
+/*! Voicemail mailbox state */
 struct vm_state {
        char curbox[80];
        char username[80];
-       char curdir[256];
-       char vmbox[256];
-       char fn[256];
-       char fn2[256];
+       char curdir[PATH_MAX];
+       char vmbox[PATH_MAX];
+       char fn[PATH_MAX];
+       char fn2[PATH_MAX];
        int *deleted;
        int *heard;
        int curmsg;
@@ -342,30 +367,18 @@ struct vm_state {
        int starting;
        int repeats;
 #ifdef IMAP_STORAGE
-       int updated; /* decremented on each mail check until 1 -allows delay */
+       int updated;                         /*!< decremented on each mail check until 1 -allows delay */
        long msgArray[256];
        MAILSTREAM *mailstream;
        int vmArrayIndex;
-       char imapuser[80]; /* IMAP server login */
+       char imapuser[80];                   /*!< IMAP server login */
        int interactive;
        unsigned int quota_limit;
        unsigned int quota_usage;
        struct vm_state *persist_vms;
 #endif
 };
-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);
-static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
-static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
-                       char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
-                       signed char record_gain);
-static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
-static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
-static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
-static void 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);
-#if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
-static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
-#endif
-static void apply_options(struct ast_vm_user *vmu, const char *options);
+
 
 #ifdef ODBC_STORAGE
 static char odbc_database[80];
@@ -406,89 +419,85 @@ static char ext_pass_cmd[128];
 #define PWDCHANGE_EXTERNAL (1 << 2)
 static int pwdchange = PWDCHANGE_INTERNAL;
 
-#if ODBC_STORAGE
+#ifdef ODBC_STORAGE
 #define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
-#elif IMAP_STORAGE
-#define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
 #else
-#define tdesc "Comedian Mail (Voicemail System)"
+# ifdef IMAP_STORAGE
+# define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
+# else
+# define tdesc "Comedian Mail (Voicemail System)"
+# endif
 #endif
 
 static char userscontext[AST_MAX_EXTENSION] = "default";
 
 static char *addesc = "Comedian Mail";
 
-static char *synopsis_vm =
-"Leave a Voicemail message";
+static char *synopsis_vm = "Leave a Voicemail message";
 
 static char *descrip_vm =
-"  VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This\n"
-"application allows the calling party to leave a message for the specified\n"
-"list of mailboxes. When multiple mailboxes are specified, the greeting will\n"
-"be taken from the first mailbox specified. Dialplan execution will stop if the\n"
-"specified mailbox does not exist.\n"
-"  The Voicemail application will exit if any of the following DTMF digits are\n"
-"received:\n"
-"    0 - Jump to the 'o' extension in the current dialplan context.\n"
-"    * - Jump to the 'a' extension in the current dialplan context.\n"
-"  This application will set the following channel variable upon completion:\n"
-"    VMSTATUS - This indicates the status of the execution of the VoiceMail\n"
-"               application. The possible values are:\n"
-"               SUCCESS | USEREXIT | FAILED\n\n"
-"  Options:\n"
-"    b    - Play the 'busy' greeting to the calling party.\n"
-"    g(#) - Use the specified amount of gain when recording the voicemail\n"
-"           message. The units are whole-number decibels (dB).\n"
-"    s    - Skip the playback of instructions for leaving a message to the\n"
-"           calling party.\n"
-"    u    - Play the 'unavailble greeting.\n"
-"    j    - Jump to priority n+101 if the mailbox is not found or some other\n"
-"           error occurs.\n";
-
-static char *synopsis_vmain =
-"Check Voicemail messages";
+       "  VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This\n"
+       "application allows the calling party to leave a message for the specified\n"
+       "list of mailboxes. When multiple mailboxes are specified, the greeting will\n"
+       "be taken from the first mailbox specified. Dialplan execution will stop if the\n"
+       "specified mailbox does not exist.\n"
+       "  The Voicemail application will exit if any of the following DTMF digits are\n"
+       "received:\n"
+       "    0 - Jump to the 'o' extension in the current dialplan context.\n"
+       "    * - Jump to the 'a' extension in the current dialplan context.\n"
+       "  This application will set the following channel variable upon completion:\n"
+       "    VMSTATUS - This indicates the status of the execution of the VoiceMail\n"
+       "               application. The possible values are:\n"
+       "               SUCCESS | USEREXIT | FAILED\n\n"
+       "  Options:\n"
+       "    b    - Play the 'busy' greeting to the calling party.\n"
+       "    g(#) - Use the specified amount of gain when recording the voicemail\n"
+       "           message. The units are whole-number decibels (dB).\n"
+       "    s    - Skip the playback of instructions for leaving a message to the\n"
+       "           calling party.\n"
+       "    u    - Play the 'unavailable greeting.\n";
+
+static char *synopsis_vmain = "Check Voicemail messages";
 
 static char *descrip_vmain =
-"  VoiceMailMain([mailbox][@context][|options]): This application allows the\n"
-"calling party to check voicemail messages. A specific mailbox, and optional\n"
-"corresponding context, may be specified. If a mailbox is not provided, the\n"
-"calling party will be prompted to enter one. If a context is not specified,\n"
-"the 'default' context will be used.\n\n"
-"  Options:\n"
-"    p    - Consider the mailbox parameter as a prefix to the mailbox that\n"
-"           is entered by the caller.\n"
-"    g(#) - Use the specified amount of gain when recording a voicemail\n"
-"           message. The units are whole-number decibels (dB).\n"
-"    s    - Skip checking the passcode for the mailbox.\n"
-"    a(#) - Skip folder prompt and go directly to folder specified.\n"
-"           Defaults to INBOX\n";
+       "  VoiceMailMain([mailbox][@context][|options]): This application allows the\n"
+       "calling party to check voicemail messages. A specific mailbox, and optional\n"
+       "corresponding context, may be specified. If a mailbox is not provided, the\n"
+       "calling party will be prompted to enter one. If a context is not specified,\n"
+       "the 'default' context will be used.\n\n"
+       "  Options:\n"
+       "    p    - Consider the mailbox parameter as a prefix to the mailbox that\n"
+       "           is entered by the caller.\n"
+       "    g(#) - Use the specified amount of gain when recording a voicemail\n"
+       "           message. The units are whole-number decibels (dB).\n"
+       "    s    - Skip checking the passcode for the mailbox.\n"
+       "    a(#) - Skip folder prompt and go directly to folder specified.\n"
+       "           Defaults to INBOX\n";
 
 static char *synopsis_vm_box_exists =
 "Check to see if Voicemail mailbox exists";
 
 static char *descrip_vm_box_exists =
-"  MailboxExists(mailbox[@context][|options]): Check to see if the specified\n"
-"mailbox exists. If no voicemail context is specified, the 'default' context\n"
-"will be used.\n"
-"  This application will set the following channel variable upon completion:\n"
-"    VMBOXEXISTSSTATUS - This will contain the status of the execution of the\n"
-"                        MailboxExists application. Possible values include:\n"
-"                        SUCCESS | FAILED\n\n"
-"  Options:\n"
-"    j - Jump to priority n+101 if the mailbox is found.\n";
-
-static char *synopsis_vmauthenticate =
-"Authenticate with Voicemail passwords";
+       "  MailboxExists(mailbox[@context][|options]): Check to see if the specified\n"
+       "mailbox exists. If no voicemail context is specified, the 'default' context\n"
+       "will be used.\n"
+       "  This application will set the following channel variable upon completion:\n"
+       "    VMBOXEXISTSSTATUS - This will contain the status of the execution of the\n"
+       "                        MailboxExists application. Possible values include:\n"
+       "                        SUCCESS | FAILED\n\n"
+       "  Options: (none)\n";
+
+static char *synopsis_vmauthenticate = "Authenticate with Voicemail passwords";
 
 static char *descrip_vmauthenticate =
-"  VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
-"same way as the Authenticate application, but the passwords are taken from\n"
-"voicemail.conf.\n"
-"  If the mailbox is specified, only that mailbox's password will be considered\n"
-"valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
-"be set with the authenticated mailbox.\n\n"
-"  Options:\n"
-"    s - Skip playing the initial prompts.\n";
+       "  VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
+       "same way as the Authenticate application, but the passwords are taken from\n"
+       "voicemail.conf.\n"
+       "  If the mailbox is specified, only that mailbox's password will be considered\n"
+       "valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
+       "be set with the authenticated mailbox.\n\n"
+       "  Options:\n"
+       "    s - Skip playing the initial prompts.\n";
 
 /* Leave a message */
 static char *app = "VoiceMail";
@@ -510,12 +519,48 @@ static char externnotify[160];
 static struct ast_smdi_interface *smdi_iface = NULL;
 static char vmfmts[80];
 static double volgain;
-static int vmminmessage;
-static int vmmaxmessage;
+static int vmminsecs;
+static int vmmaxsecs;
 static int maxgreet;
 static int skipms;
 static int maxlogins;
 
+/*! Poll mailboxes for changes since there is something external to
+ *  app_voicemail that may change them. */
+static unsigned int poll_mailboxes;
+
+/*! Polling frequency */
+static unsigned int poll_freq;
+/*! By default, poll every 30 seconds */
+#define DEFAULT_POLL_FREQ 30
+
+AST_MUTEX_DEFINE_STATIC(poll_lock);
+static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t poll_thread = AST_PTHREADT_NULL;
+static unsigned char poll_thread_run;
+
+/*! Subscription to ... MWI event subscriptions */
+static struct ast_event_sub *mwi_sub_sub;
+/*! Subscription to ... MWI event un-subscriptions */
+static struct ast_event_sub *mwi_unsub_sub;
+
+/*!
+ * \brief An MWI subscription
+ *
+ * This is so we can keep track of which mailboxes are subscribed to.
+ * This way, we know which mailboxes to poll when the pollmailboxes
+ * option is being used.
+ */
+struct mwi_sub {
+       AST_RWLIST_ENTRY(mwi_sub) entry;
+       int old_new;
+       int old_old;
+       uint32_t uniqueid;
+       char mailbox[1];
+};
+
+static AST_RWLIST_HEAD_STATIC(mwi_subs, mwi_sub);
+
 /* custom password sounds */
 static char vm_password[80] = "vm-password";
 static char vm_newpassword[80] = "vm-newpassword";
@@ -548,6 +593,24 @@ static unsigned char adsisec[4] = "\x9B\xDB\xF7\xAC";
 static int adsiver = 1;
 static char emaildateformat[32] = "%A, %B %d, %Y at %r";
 
+/* Forward declarations - generic */
+static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box);
+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);
+static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
+static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
+                       char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
+                       signed char record_gain, struct vm_state *vms);
+static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
+static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
+static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
+static void 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);
+static void apply_options(struct ast_vm_user *vmu, const char *options);
+
+#if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
+static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
+#endif
+
+
 
 static void populate_defaults(struct ast_vm_user *vmu)
 {
@@ -560,6 +623,8 @@ static void populate_defaults(struct ast_vm_user *vmu)
                ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
        if (exitcontext)
                ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
+       if (vmmaxsecs)
+               vmu->maxsecs = vmmaxsecs;
        if (maxmsg)
                vmu->maxmsg = maxmsg;
        vmu->volgain = volgain;
@@ -616,6 +681,13 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v
                ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
        } else if (!strcasecmp(var, "exitcontext")) {
                ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
+       } else if (!strcasecmp(var, "maxmessage")) {
+               if (vmu->maxsecs <= 0) {
+                       ast_log(LOG_WARNING, "Invalid max message length of %s. Using global value %i\n", value, vmmaxsecs);
+                       vmu->maxsecs = vmmaxsecs;
+               } else {
+                       vmu->maxsecs = atoi(value);
+               }
        } else if (!strcasecmp(var, "maxmsg")) {
                vmu->maxmsg = atoi(value);
                if (vmu->maxmsg <= 0) {
@@ -667,8 +739,11 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *
        struct ast_variable *tmp;
        tmp = var;
        while (tmp) {
-               if (!strcasecmp(tmp->name, "password")) {
+               if (!strcasecmp(tmp->name, "vmsecret")) {
                        ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
+               } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) { /* don't overwrite vmsecret if it exists */
+                       if (ast_strlen_zero(retval->password))
+                               ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
                } else if (!strcasecmp(tmp->name, "uniqueid")) {
                        ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
                } else if (!strcasecmp(tmp->name, "pager")) {
@@ -679,6 +754,12 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *
                        ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
                } else if (!strcasecmp(tmp->name, "context")) {
                        ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
+#ifdef IMAP_STORAGE
+               } else if (!strcasecmp(tmp->name, "imapuser")) {
+                       ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
+               } else if (!strcasecmp(tmp->name, "imappassword")) {
+                       ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
+#endif
                } else
                        apply_option(retval, tmp->name, tmp->value);
                tmp = tmp->next;
@@ -707,7 +788,7 @@ static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const cha
                        ast_variables_destroy(var);
                } else { 
                        if (!ivm) 
-                               free(retval);
+                               ast_free(retval);
                        retval = NULL;
                }       
        } 
@@ -763,134 +844,72 @@ static int reset_user_pw(const char *context, const char *mailbox, const char *n
 
 static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
 {
-       /*  There's probably a better way of doing this. */
-       /*  That's why I've put the password change in a separate function. */
-       /*  This could also be done with a database function */
-       
-       FILE *configin;
-       FILE *configout;
-       int linenum=0;
-       char inbuf[256];
-       char orig[256];
-       char currcontext[256] ="";
-       char tmpin[PATH_MAX];
-       char tmpout[PATH_MAX];
-       struct stat statbuf;
-
+       struct ast_config   *cfg=NULL;
+       struct ast_variable *var=NULL;
+       struct ast_category *cat=NULL;
+       char *category=NULL, *value=NULL, *new=NULL;
+       const char *tmp=NULL;
+                                       
        if (!change_password_realtime(vmu, newpassword))
                return;
 
-       snprintf(tmpin, sizeof(tmpin), "%s/voicemail.conf", ast_config_AST_CONFIG_DIR);
-       snprintf(tmpout, sizeof(tmpout), "%s/voicemail.conf.new", ast_config_AST_CONFIG_DIR);
-       configin = fopen(tmpin,"r");
-       if (configin)
-               configout = fopen(tmpout,"w+");
-       else
-               configout = NULL;
-       if (!configin || !configout) {
-               if (configin)
-                       fclose(configin);
-               else
-                       ast_log(LOG_WARNING, "Warning: Unable to open '%s' for reading: %s\n", tmpin, strerror(errno));
-               if (configout)
-                       fclose(configout);
-               else
-                       ast_log(LOG_WARNING, "Warning: Unable to open '%s' for writing: %s\n", tmpout, strerror(errno));
-                       return;
-       }
-
-       while (!feof(configin)) {
-               char *user = NULL, *pass = NULL, *rest = NULL, *comment = NULL, *tmpctx = NULL, *tmpctxend = NULL;
-
-               /* Read in the line */
-               if (fgets(inbuf, sizeof(inbuf), configin) == NULL)
-                       continue;
-               linenum++;
-
-               /* Make a backup of it */
-               ast_copy_string(orig, inbuf, sizeof(orig));
-
-               /*
-                 Read the file line by line, split each line into a comment and command section
-                 only parse the command portion of the line
-               */
-               if (inbuf[strlen(inbuf) - 1] == '\n')
-                       inbuf[strlen(inbuf) - 1] = '\0';
-
-               if ((comment = strchr(inbuf, ';')))
-                       *comment++ = '\0'; /* Now inbuf is terminated just before the comment */
-
-               if (ast_strlen_zero(inbuf)) {
-                       fprintf(configout, "%s", orig);
-                       continue;
-               }
-
-               /* Check for a context, first '[' to first ']' */
-               if ((tmpctx = strchr(inbuf, '['))) {
-                       tmpctxend = strchr(tmpctx, ']');
-                       if (tmpctxend) {
-                               /* Valid context */
-                               ast_copy_string(currcontext, tmpctx + 1, tmpctxend - tmpctx);
-                               fprintf(configout, "%s", orig);
-                               continue;
+       /* check voicemail.conf */
+       if ((cfg = ast_config_load_with_comments(VOICEMAIL_CONFIG))) {
+               while ((category = ast_category_browse(cfg, category))) {
+                       if (!strcasecmp(category, vmu->context)) {
+                               if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
+                                       ast_log(LOG_WARNING, "We could not find the mailbox.\n");
+                                       break;
+                               }
+                               value = strstr(tmp,",");
+                               if (!value) {
+                                       ast_log(LOG_WARNING, "variable has bad format.\n");
+                                       break;
+                               }
+                               new = alloca((strlen(value)+strlen(newpassword)+1));
+                               sprintf(new,"%s%s", newpassword, value);
+                               if (!(cat = ast_category_get(cfg, category))) {
+                                       ast_log(LOG_WARNING, "Failed to get category structure.\n");
+                                       break;
+                               }
+                               ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
                        }
                }
-
-               /* This isn't a context line, check for MBX => PSWD... */
-               user = inbuf;
-               if ((pass = strchr(user, '='))) {
-                       /* We have a line in the form of aaaaa=aaaaaa */
-                       *pass++ = '\0';
-
-                       user = ast_strip(user);
-
-                       if (*pass == '>')
-                               *pass++ = '\0';
-
-                       pass = ast_skip_blanks(pass);
-
-                       /* 
-                          Since no whitespace allowed in fields, or more correctly white space
-                          inside the fields is there for a purpose, we can just terminate pass
-                          at the comma or EOL whichever comes first.
-                       */
-                       if ((rest = strchr(pass, ',')))
-                               *rest++ = '\0';
-               } else {
-                       user = NULL;
-               }                       
-
-               /* Compare user, pass AND context */
-               if (!ast_strlen_zero(user) && !strcmp(user, vmu->mailbox) &&
-                       !ast_strlen_zero(pass) && !strcmp(pass, vmu->password) &&
-                       !strcasecmp(currcontext, vmu->context)) {
-                       /* This is the line */
-                       if (rest) {
-                               fprintf(configout, "%s => %s,%s", user, newpassword, rest);
-                       } else {
-                               fprintf(configout, "%s => %s", user, newpassword);
-                       }
-                       /* If there was a comment on the line print it out */
-                       if (comment) {
-                               fprintf(configout, ";%s\n", comment);
-                       } else {
-                               fprintf(configout, "\n");
+               /* save the results */
+               reset_user_pw(vmu->context, vmu->mailbox, newpassword);
+               ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
+               config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
+       }
+       category = NULL;
+       var = NULL;
+       /* check users.conf and update the password stored for the mailbox*/
+       /* if no vmsecret entry exists create one. */
+       if ((cfg = ast_config_load_with_comments("users.conf"))) {
+               ast_debug(4, "we are looking for %s\n", vmu->mailbox);
+               while ((category = ast_category_browse(cfg, category))) {
+                       ast_debug(4, "users.conf: %s\n", category);
+                       if (!strcasecmp(category, vmu->mailbox)) {
+                               if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
+                                       ast_debug(3, "looks like we need to make vmsecret!\n");
+                                       var = ast_variable_new("vmsecret", newpassword);
+                               } 
+                               new = alloca(strlen(newpassword)+1);
+                               sprintf(new, "%s", newpassword);
+                               if (!(cat = ast_category_get(cfg, category))) {
+                                       ast_debug(4, "failed to get category!\n");
+                                       break;
+                               }
+                               if (!var)               
+                                       ast_variable_update(cat, "vmsecret", new, NULL, 0);
+                               else
+                                       ast_variable_append(cat, var);
                        }
-               } else {
-                       /* Put it back like it was */
-                       fprintf(configout, "%s", orig);
                }
+               /* save the results and clean things up */
+               reset_user_pw(vmu->context, vmu->mailbox, newpassword); 
+               ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
+               config_text_file_save("users.conf", cfg, "AppVoicemail");
        }
-       fclose(configin);
-       fclose(configout);
-
-       stat(tmpin, &statbuf);
-       chmod(tmpout, statbuf.st_mode);
-       chown(tmpout, statbuf.st_uid, statbuf.st_gid);
-       unlink(tmpin);
-       rename(tmpout, tmpin);
-       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
-       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
 }
 
 static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
@@ -930,8 +949,7 @@ static void vm_imap_delete(int msgnum, struct vm_state *vms)
                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);
+       ast_debug(3, "deleting msgnum %d, which is mailbox message %lu\n",msgnum,messageNum);
        /* delete message */
        sprintf (arg,"%lu",messageNum);
        mail_setflag (vms->mailstream,arg,"\\DELETED");
@@ -949,7 +967,7 @@ static int make_file(char *dest, int len, char *dir, int num)
  * \param context String. Ignored if is null or empty string.
  * \param ext     String. Ignored if is null or empty string.
  * \param folder  String. Ignored if is null or empty string. 
- * \return 0 on failure, 1 on success.
+ * \return -1 on failure, 0 on success.
  */
 static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
 {
@@ -959,27 +977,28 @@ static int create_dirpath(char *dest, int len, const char *context, const char *
                make_dir(dest, len, context, "", "");
                if (mkdir(dest, mode) && errno != EEXIST) {
                        ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
-                       return 0;
+                       return -1;
                }
        }
        if (!ast_strlen_zero(ext)) {
                make_dir(dest, len, context, ext, "");
                if (mkdir(dest, mode) && errno != EEXIST) {
                        ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
-                       return 0;
+                       return -1;
                }
        }
        if (!ast_strlen_zero(folder)) {
                make_dir(dest, len, context, ext, folder);
                if (mkdir(dest, mode) && errno != EEXIST) {
                        ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
-                       return 0;
+                       return -1;
                }
        }
-       return 1;
+       return 0;
 }
 
-/* only return failure if ast_lock_path returns 'timeout',
+/*! \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)
@@ -1000,10 +1019,10 @@ static int retrieve_file(char *dir, int msgnum)
        int res;
        int fd=-1;
        size_t fdlen = 0;
-       void *fdm=NULL;
+       void *fdm = MAP_FAILED;
        SQLSMALLINT colcount=0;
        SQLHSTMT stmt;
-       char sql[256];
+       char sql[PATH_MAX];
        char fmt[80]="";
        char *c;
        char coltitle[256];
@@ -1015,8 +1034,8 @@ static int retrieve_file(char *dir, int msgnum)
        SQLLEN colsize2;
        FILE *f=NULL;
        char rowdata[80];
-       char fn[256];
-       char full_fn[256];
+       char fn[PATH_MAX];
+       char full_fn[PATH_MAX];
        char msgnums[80];
        
        struct odbc_obj *obj;
@@ -1034,7 +1053,12 @@ static int retrieve_file(char *dir, int msgnum)
                else
                        ast_copy_string(fn, dir, sizeof(fn));
                snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
-               f = fopen(full_fn, "w+");
+               
+               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);
                res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
                if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
@@ -1071,7 +1095,7 @@ static int retrieve_file(char *dir, int msgnum)
                        ast_odbc_release_obj(obj);
                        goto yuck;
                }
-               fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, 0770);
+               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);
@@ -1099,7 +1123,8 @@ static int retrieve_file(char *dir, int msgnum)
                                goto yuck;
                        }
                        if (!strcasecmp(coltitle, "recording")) {
-                               res = SQLGetData(stmt, x + 1, SQL_BINARY, NULL, 0, &colsize2);
+                               off_t offset;
+                               res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
                                fdlen = colsize2;
                                if (fd > -1) {
                                        char tmp[1]="";
@@ -1109,24 +1134,26 @@ static int retrieve_file(char *dir, int msgnum)
                                                fd = -1;
                                                continue;
                                        }
-                                       if (fd > -1) {
-                                               if ((fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == -1) {
+                                       /* 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;
+                                                       }
                                                }
                                        }
-                               }
-                               if (fdm) {
-                                       memset(fdm, 0, fdlen);
-                                       res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize2);
-                                       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;
-                                       }
+                                       truncate(full_fn, fdlen);
                                }
                        } else {
                                res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
@@ -1147,8 +1174,6 @@ static int retrieve_file(char *dir, int msgnum)
 yuck:  
        if (f)
                fclose(f);
-       if (fdm)
-               munmap(fdm, fdlen);
        if (fd > -1)
                close(fd);
        return x - 1;
@@ -1156,8 +1181,8 @@ yuck:
 
 static int remove_file(char *dir, int msgnum)
 {
-       char fn[256];
-       char full_fn[256];
+       char fn[PATH_MAX];
+       char full_fn[PATH_MAX];
        char msgnums[80];
        
        if (msgnum > -1) {
@@ -1166,6 +1191,9 @@ static int remove_file(char *dir, int 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);
+       }
        snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
        unlink(full_fn);
        return 0;
@@ -1176,7 +1204,7 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir)
        int x = 0;
        int res;
        SQLHSTMT stmt;
-       char sql[256];
+       char sql[PATH_MAX];
        char rowdata[20];
        
        struct odbc_obj *obj;
@@ -1233,7 +1261,7 @@ static int message_exists(char *dir, int msgnum)
        int x = 0;
        int res;
        SQLHSTMT stmt;
-       char sql[256];
+       char sql[PATH_MAX];
        char rowdata[20];
        char msgnums[20];
        
@@ -1297,7 +1325,7 @@ static void delete_file(char *sdir, int smsg)
 {
        int res;
        SQLHSTMT stmt;
-       char sql[256];
+       char sql[PATH_MAX];
        char msgnums[20];
        
        struct odbc_obj *obj;
@@ -1389,14 +1417,14 @@ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int ms
        int x = 0;
        int res;
        int fd = -1;
-       void *fdm=NULL;
+       void *fdm = MAP_FAILED;
        size_t fdlen = -1;
        SQLHSTMT stmt;
-       SQLINTEGER len;
-       char sql[256];
+       SQLLEN len;
+       char sql[PATH_MAX];
        char msgnums[20];
-       char fn[256];
-       char full_fn[256];
+       char fn[PATH_MAX];
+       char full_fn[PATH_MAX];
        char fmt[80]="";
        char *c;
        const char *context="", *macrocontext="", *callerid="", *origtime="", *duration="";
@@ -1445,7 +1473,7 @@ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int ms
                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) {
+               if (fdm == MAP_FAILED) {
                        ast_log(LOG_WARNING, "Memory map failed!\n");
                        ast_odbc_release_obj(obj);
                        goto yuck;
@@ -1494,7 +1522,7 @@ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int ms
 yuck:  
        if (cfg)
                ast_config_destroy(cfg);
-       if (fdm)
+       if (fdm != MAP_FAILED)
                munmap(fdm, fdlen);
        if (fd > -1)
                close(fd);
@@ -1505,7 +1533,7 @@ static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxco
 {
        int res;
        SQLHSTMT stmt;
-       char sql[256];
+       char sql[PATH_MAX];
        char msgnums[20];
        char msgnumd[20];
        struct odbc_obj *obj;
@@ -1577,11 +1605,14 @@ static int count_messages(struct ast_vm_user *vmu, char *dir)
 
 static void rename_file(char *sfn, char *dfn)
 {
-       char stxt[256];
-       char dtxt[256];
+       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);
 }
 
@@ -1637,14 +1668,48 @@ static int copy(char *infile, char *outfile)
 
 static void copy_file(char *frompath, char *topath)
 {
-       char frompath2[256],topath2[256];
+       char frompath2[PATH_MAX], topath2[PATH_MAX];
+       struct ast_variable *tmp,*var = NULL;
+       char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
        ast_filecopy(frompath, topath, NULL);
        snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
        snprintf(topath2, sizeof(topath2), "%s.txt", topath);
+       if (ast_check_realtime("voicemail_data")) {
+               var = ast_load_realtime("voicemail_data", "filename", frompath, NULL);
+               /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
+               for (tmp = var; tmp; tmp = tmp->next) {
+                       if (!strcasecmp(tmp->name, "origmailbox")) {
+                               origmailbox = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "context")) {
+                               context = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "macrocontext")) {
+                               macrocontext = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "exten")) {
+                               exten = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "priority")) {
+                               priority = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "callerchan")) {
+                               callerchan = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "callerid")) {
+                               callerid = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "origdate")) {
+                               origdate = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "origtime")) {
+                               origtime = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "category")) {
+                               category = tmp->value;
+                       } else if (!strcasecmp(tmp->name, "duration")) {
+                               duration = tmp->value;
+                       }
+               }
+               ast_store_realtime("voicemail_data", "filename", topath, "origmailbox", origmailbox, "context", context, "macrocontext", macrocontext, "exten", exten, "priority", priority, "callerchan", callerchan, "callerid", callerid, "origdate", origdate, "origtime", origtime, "category", category, "duration", duration, NULL);
+       }
        copy(frompath2, topath2);
+       ast_variables_destroy(var);
 }
 #endif
-/*
+
+/*! \brief
  * A negative return value indicates an error.
  * \note Should always be called with a lock already set on dir.
  */
@@ -1685,6 +1750,9 @@ static int vm_delete(char *file)
        /* Sprintf here would safe because we alloca'd exactly the right length,
         * but trying to eliminate all sprintf's anyhow
         */
+       if (ast_check_realtime("voicemail_data")) {
+               ast_destroy_realtime("voicemail_data", "filename", file, NULL);
+       }
        snprintf(txt, txtsize, "%s.txt", file);
        unlink(txt);
        return ast_filedelete(file, NULL);
@@ -1725,14 +1793,14 @@ static int inchar(struct baseio *bio, FILE *fi)
 
 static int ochar(struct baseio *bio, int c, FILE *so)
 {
-       if (bio->linelength>=BASELINELEN) {
-               if (fputs(eol,so)==EOF)
+       if (bio->linelength >= BASELINELEN) {
+               if (fputs(eol,so) == EOF)
                        return -1;
 
                bio->linelength= 0;
        }
 
-       if (putc(((unsigned char)c),so)==EOF)
+       if (putc(((unsigned char)c),so) == EOF)
                return -1;
 
        bio->linelength++;
@@ -1755,24 +1823,24 @@ static int base_encode(char *filename, FILE *so)
                return -1;
        }
 
-       for (i= 0;i<9;i++) {
+       for (i= 0; i<9; i++) {
                dtable[i]= 'A'+i;
                dtable[i+9]= 'J'+i;
                dtable[26+i]= 'a'+i;
                dtable[26+i+9]= 'j'+i;
        }
-       for (i= 0;i<8;i++) {
+       for (i= 0; i<8; i++) {
                dtable[i+18]= 'S'+i;
                dtable[26+i+18]= 's'+i;
        }
-       for (i= 0;i<10;i++) {
+       for (i= 0; i<10; i++) {
                dtable[52+i]= '0'+i;
        }
        dtable[62]= '+';
        dtable[63]= '/';
 
        while (!hiteof){
-               unsigned char igroup[3],ogroup[4];
+               unsigned char igroup[3], ogroup[4];
                int c,n;
 
                igroup[0]= igroup[1]= igroup[2]= 0;
@@ -1788,8 +1856,8 @@ static int base_encode(char *filename, FILE *so)
 
                if (n> 0) {
                        ogroup[0]= dtable[igroup[0]>>2];
-                       ogroup[1]= dtable[((igroup[0]&3)<<4)|(igroup[1]>>4)];
-                       ogroup[2]= dtable[((igroup[1]&0xF)<<2)|(igroup[2]>>6)];
+                       ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
+                       ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
                        ogroup[3]= dtable[igroup[2]&0x3F];
 
                        if (n<3) {
@@ -1804,7 +1872,7 @@ static int base_encode(char *filename, FILE *so)
                }
        }
 
-       if (fputs(eol,so)==EOF)
+       if (fputs(eol,so) == EOF)
                return 0;
 
        fclose(fi);
@@ -1829,7 +1897,24 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu
        pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
 }
 
-/*
+static char *quote(const char *from, char *to, size_t len)
+{
+       char *ptr = to;
+       *ptr++ = '"';
+       for (; ptr < to + len - 1; from++) {
+               if (*from == '"')
+                       *ptr++ = '\\';
+               else if (*from == '\0')
+                       break;
+               *ptr++ = *from;
+       }
+       if (ptr < to + len - 1)
+               *ptr++ = '"';
+       *ptr = '\0';
+       return to;
+}
+
+/*! \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.
  */
@@ -1852,7 +1937,7 @@ static const struct tm *vmu_tm(const struct ast_vm_user *vmu, struct tm *tm)
        return tm;
 }
 
-/* same as mkstemp, but return a FILE * */
+/*! \brief same as mkstemp, but return a FILE * */
 static FILE *vm_mkftemp(char *template)
 {
        FILE *p = NULL;
@@ -1877,112 +1962,122 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
        char dur[256];
        char tmpcmd[256];
        struct tm tm;
+       char *passdata2;
+       size_t len_passdata;
+#ifdef IMAP_STORAGE
+#define ENDL "\r\n"
+#else
+#define ENDL "\n"
+#endif
 
        gethostname(host, sizeof(host)-1);
        if (strchr(srcemail, '@'))
                ast_copy_string(who, srcemail, sizeof(who));
-       else {
+       else 
                snprintf(who, sizeof(who), "%s@%s", srcemail, host);
-       }
        snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
        strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
-       fprintf(p, "Date: %s\r\n", date);
+       fprintf(p, "Date: %s" ENDL, date);
 
        /* Set date format for voicemail mail */
        strftime(date, sizeof(date), emaildateformat, &tm);
 
-       if (*fromstring) {
+       if (!ast_strlen_zero(fromstring)) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(fromstring)*3 + 200;
                        if ((passdata = alloca(vmlen))) {
                                memset(passdata, 0, vmlen);
                                prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
                                pbx_substitute_variables_helper(ast, fromstring, passdata, vmlen);
-                               fprintf(p, "From: %s <%s>\r\n",passdata,who);
+                               len_passdata = strlen(passdata) * 2 + 3;
+                               passdata2 = alloca(len_passdata);
+                               fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata), who);
                        } else
                                ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
                        ast_channel_free(ast);
                } else
                        ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
        } else
-               fprintf(p, "From: Asterisk PBX <%s>\r\n", who);
-       fprintf(p, "To: %s <%s>\r\n", vmu->fullname, vmu->email);
-       if (emailsubject) {
+               fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
+       len_passdata = strlen(vmu->fullname) * 2 + 3;
+       passdata2 = alloca(len_passdata);
+       fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata), vmu->email);
+       if (!ast_strlen_zero(emailsubject)) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
-                       int vmlen = strlen(emailsubject)*3 + 200;
+                       int vmlen = strlen(emailsubject) * 3 + 200;
                        if ((passdata = alloca(vmlen))) {
                                memset(passdata, 0, vmlen);
                                prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
                                pbx_substitute_variables_helper(ast, emailsubject, passdata, vmlen);
-                               fprintf(p, "Subject: %s\r\n", passdata);
+                               fprintf(p, "Subject: %s" ENDL, passdata);
                        } else
                                ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
                        ast_channel_free(ast);
                } else
                        ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
-       } else  if (*emailtitle) {
+       } else  if (!ast_strlen_zero(emailtitle)) {
                fprintf(p, emailtitle, msgnum + 1, mailbox) ;
-               fprintf(p,"\r\n") ;
+               fprintf(p, ENDL) ;
        } else if (ast_test_flag((&globalflags), VM_PBXSKIP))
-               fprintf(p, "Subject: New message %d in mailbox %s\r\n", msgnum + 1, mailbox);
+               fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
        else
-               fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\r\n", msgnum + 1, mailbox);
-       fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>\r\n", msgnum, (unsigned int)ast_random(), mailbox, getpid(), host);
+               fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
+       fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1, (unsigned int)ast_random(), mailbox, getpid(), host);
        if(imap) {
                /* additional information needed for IMAP searching */
-               fprintf(p, "X-Asterisk-VM-Message-Num: %d\r\n", msgnum + 1);
-               /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s\r\n", ext); */
-               fprintf(p, "X-Asterisk-VM-Server-Name: %s\r\n", fromstring);
-               fprintf(p, "X-Asterisk-VM-Context: %s\r\n", context);
-               fprintf(p, "X-Asterisk-VM-Extension: %s\r\n", mailbox);
-               fprintf(p, "X-Asterisk-VM-Priority: %d\r\n", chan->priority);
-               fprintf(p, "X-Asterisk-VM-Caller-channel: %s\r\n", chan->name);
-               fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s\r\n", cidnum);
-               fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s\r\n", cidname);
-               fprintf(p, "X-Asterisk-VM-Duration: %d\r\n", duration);
+               fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
+               /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
+               fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
+               fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
+               fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
+               fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
+               fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
+               fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, cidnum);
+               fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, cidname);
+               fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
                if (!ast_strlen_zero(category))
-                       fprintf(p, "X-Asterisk-VM-Category: %s\r\n", category);
-               fprintf(p, "X-Asterisk-VM-Orig-date: %s\r\n", date);
-               fprintf(p, "X-Asterisk-VM-Orig-time: %ld\r\n", (long)time(NULL));
+                       fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
+               fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
+               fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long)time(NULL));
        }
        if (!ast_strlen_zero(cidnum))
-               fprintf(p, "X-Asterisk-CallerID: %s\r\n", cidnum);
+               fprintf(p, "X-Asterisk-CallerID: %s" ENDL, cidnum);
        if (!ast_strlen_zero(cidname))
-               fprintf(p, "X-Asterisk-CallerIDName: %s\r\n", cidname);
-       fprintf(p, "MIME-Version: 1.0\r\n");
+               fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, cidname);
+       fprintf(p, "MIME-Version: 1.0" ENDL);
        if (attach_user_voicemail) {
                /* Something unique. */
-               snprintf(bound, sizeof(bound), "voicemail_%d%s%d%d", msgnum, mailbox, getpid(), (unsigned int)ast_random());
+               snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox, getpid(), (unsigned int)ast_random());
 
-               fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\r\n\r\n\r\n", bound);
-
-               fprintf(p, "--%s\r\n", bound);
+               fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
+               fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
+               fprintf(p, "--%s" ENDL, bound);
        }
-       fprintf(p, "Content-Type: text/plain; charset=%s\r\nContent-Transfer-Encoding: 8bit\r\n\r\n", charset);
+       fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
        if (emailbody) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(emailbody)*3 + 200;
                        if ((passdata = alloca(vmlen))) {
                                memset(passdata, 0, vmlen);
                                prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
                                pbx_substitute_variables_helper(ast, emailbody, passdata, vmlen);
-                               fprintf(p, "%s\r\n", passdata);
+                               fprintf(p, "%s" ENDL, passdata);
                        } else
                                ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
                        ast_channel_free(ast);
                } else
                        ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
        } else {
-               fprintf(p, "Dear %s:\r\n\r\n\tJust wanted to let you know you were just left a %s long message (number %d)\r\n"
+               fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a %s long message (number %d)" ENDL
 
-               "in mailbox %s from %s, on %s so you might\r\n"
-               "want to check it when you get a chance.  Thanks!\r\n\r\n\t\t\t\t--Asterisk\r\n\r\n", vmu->fullname, 
+               "in mailbox %s from %s, on %s so you might" ENDL
+               "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, 
                dur, msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
        }
        if (attach_user_voicemail) {
@@ -1994,36 +2089,28 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
                create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
                snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
                tmpfd = mkstemp(newtmp);
-               ast_log(LOG_DEBUG, "newtmp: %s\n", newtmp);
+               ast_debug(3, "newtmp: %s\n", newtmp);
                if (vmu->volgain < -.001 || vmu->volgain > .001) {
                        snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
                        ast_safe_system(tmpcmd);
                        attach = newtmp;
-                       ast_log(LOG_DEBUG, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
+                       ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
                }
-               fprintf(p, "--%s\r\n", bound);
-               fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"\r\n", ctype, format, msgnum, format);
-               fprintf(p, "Content-Transfer-Encoding: base64\r\n");
-               fprintf(p, "Content-Description: Voicemail sound attachment.\r\n");
-               fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\r\n\r\n", msgnum, format);
+               fprintf(p, "--%s" ENDL, bound);
+               fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"" ENDL, ctype, format, msgnum + 1, format);
+               fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
+               fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
+               fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"" ENDL ENDL, msgnum + 1, format);
                snprintf(fname, sizeof(fname), "%s.%s", attach, format);
                base_encode(fname, p);
-               /* only attach if necessary */
-               if (imap && strcmp(format, "gsm")) {
-                       fprintf(p, "--%s\r\n", bound);
-                       fprintf(p, "Content-Type: audio/x-gsm; name=\"msg%04d.%s\"\r\n", msgnum, format);
-                       fprintf(p, "Content-Transfer-Encoding: base64\r\n");
-                       fprintf(p, "Content-Description: Voicemail sound attachment.\r\n");
-                       fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.gsm\"\r\n\r\n", msgnum);
-                       snprintf(fname, sizeof(fname), "%s.gsm", attach);
-                       base_encode(fname, p);
-               }
-               fprintf(p, "\r\n\r\n--%s--\r\n.\r\n", bound);
+               fprintf(p, ENDL "--%s--" ENDL "." ENDL, bound);
                if (tmpfd > -1)
                        close(tmpfd);
                unlink(newtmp);
        }
+#undef ENDL
 }
+
 static int sendmail(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)
 {
        FILE *p=NULL;
@@ -2036,7 +2123,7 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
        }
        if (!strcmp(format, "wav49"))
                format = "WAV";
-       ast_log(LOG_DEBUG, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
+       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 */
        if ((p = vm_mkftemp(tmp)) == NULL) {
@@ -2047,8 +2134,7 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
                fclose(p);
                snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
                ast_safe_system(tmp2);
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
+               ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
        }
        return 0;
 }
@@ -2056,84 +2142,85 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
 static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category)
 {
        char date[256];
-       char host[MAXHOSTNAMELEN]="";
+       char host[MAXHOSTNAMELEN] = "";
        char who[256];
-       char dur[256];
+       char dur[PATH_MAX];
        char tmp[80] = "/tmp/astmail-XXXXXX";
-       char tmp2[256];
+       char tmp2[PATH_MAX];
        struct tm tm;
        FILE *p;
 
        if ((p = vm_mkftemp(tmp)) == NULL) {
                ast_log(LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
                return -1;
-       } else {
-               gethostname(host, sizeof(host)-1);
-               if (strchr(srcemail, '@'))
-                       ast_copy_string(who, srcemail, sizeof(who));
-               else {
-                       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
-               }
-               snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
-               strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
-               fprintf(p, "Date: %s\n", date);
-
-               if (*pagerfromstring) {
-                       struct ast_channel *ast;
-                       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
-                               char *passdata;
-                               int vmlen = strlen(fromstring)*3 + 200;
-                               if ((passdata = alloca(vmlen))) {
-                                       memset(passdata, 0, vmlen);
-                                       prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
-                                       pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
-                                       fprintf(p, "From: %s <%s>\n", passdata, who);
-                               } else 
-                                       ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
-                               ast_channel_free(ast);
-                       } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
-               } else
-                       fprintf(p, "From: Asterisk PBX <%s>\n", who);
-               fprintf(p, "To: %s\n", pager);
-               if (pagersubject) {
-                       struct ast_channel *ast;
-                       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
-                               char *passdata;
-                               int vmlen = strlen(pagersubject) * 3 + 200;
-                               if ((passdata = alloca(vmlen))) {
-                                       memset(passdata, 0, vmlen);
-                                       prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
-                                       pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
-                                       fprintf(p, "Subject: %s\n\n", passdata);
-                               } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
-                               ast_channel_free(ast);
-                       } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+       }
+       gethostname(host, sizeof(host)-1);
+       if (strchr(srcemail, '@'))
+               ast_copy_string(who, srcemail, sizeof(who));
+       else 
+               snprintf(who, sizeof(who), "%s@%s", srcemail, host);
+       snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
+       strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
+       fprintf(p, "Date: %s\n", date);
+
+       if (*pagerfromstring) {
+               struct ast_channel *ast;
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
+                       char *passdata;
+                       int vmlen = strlen(fromstring)*3 + 200;
+                       if ((passdata = alloca(vmlen))) {
+                               memset(passdata, 0, vmlen);
+                               prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+                               pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
+                               fprintf(p, "From: %s <%s>\n", passdata, who);
+                       } else 
+                               ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
+                       ast_channel_free(ast);
+               } else 
+                       ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+       } else
+               fprintf(p, "From: Asterisk PBX <%s>\n", who);
+       fprintf(p, "To: %s\n", pager);
+       if (pagersubject) {
+               struct ast_channel *ast;
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
+                       char *passdata;
+                       int vmlen = strlen(pagersubject) * 3 + 200;
+                       if ((passdata = alloca(vmlen))) {
+                               memset(passdata, 0, vmlen);
+                               prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+                               pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
+                               fprintf(p, "Subject: %s\n\n", passdata);
+                       } else
+                               ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
+                       ast_channel_free(ast);
                } else
-                       fprintf(p, "Subject: New VM\n\n");
-               strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
-               if (pagerbody) {
-                       struct ast_channel *ast;
-                       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
-                               char *passdata;
-                               int vmlen = strlen(pagerbody)*3 + 200;
-                               if ((passdata = alloca(vmlen))) {
-                                       memset(passdata, 0, vmlen);
-                                       prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
-                                       pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
-                                       fprintf(p, "%s\n", passdata);
-                               } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
+                       ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+       } else
+               fprintf(p, "Subject: New VM\n\n");
+
+       strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
+       if (pagerbody) {
+               struct ast_channel *ast;
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
+                       char *passdata;
+                       int vmlen = strlen(pagerbody) * 3 + 200;
+                       passdata = alloca(vmlen);
+                       memset(passdata, 0, vmlen);
+                       prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+                       pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
+                       fprintf(p, "%s\n", passdata);
                        ast_channel_free(ast);
-                       } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
-               } else {
-                       fprintf(p, "New %s long msg in box %s\n"
-                                       "from %s, on %s", dur, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
-               }
-               fclose(p);
-               snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
-               ast_safe_system(tmp2);
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Sent page to %s with command '%s'\n", pager, mailcmd);
+               } else
+                       ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+       } else {
+               fprintf(p, "New %s long msg in box %s\n"
+                               "from %s, on %s", dur, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
        }
+       fclose(p);
+       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
+       ast_safe_system(tmp2);
+       ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
        return 0;
 }
 
@@ -2149,8 +2236,16 @@ static int get_date(char *s, int len)
 static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
 {
        int res;
-       char fn[256];
+       char fn[PATH_MAX];
+       char dest[PATH_MAX];
+
        snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
+
+       if ((res = create_dirpath(dest, sizeof(dest), context, ext, "greet"))) {
+               ast_log(LOG_WARNING, "Failed to make directory(%s)\n", fn);
+               return -1;
+       }
+
        RETRIEVE(fn, -1);
        if (ast_fileexists(fn, NULL, NULL) > 0) {
                res = ast_stream_and_wait(chan, fn, ecodes);
@@ -2174,13 +2269,15 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, in
 
 static void free_user(struct ast_vm_user *vmu)
 {
-       if (ast_test_flag(vmu, VM_ALLOCED))
-               free(vmu);
+       if (!ast_test_flag(vmu, VM_ALLOCED))
+               return;
+
+       ast_free(vmu);
 }
 
 static void free_zone(struct vm_zone *z)
 {
-       free(z);
+       ast_free(z);
 }
 
 static const char *mbox(int id)
@@ -2206,9 +2303,9 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
        int x = -1;
        int res;
        SQLHSTMT stmt;
-       char sql[256];
+       char sql[PATH_MAX];
        char rowdata[20];
-       char tmp[256]="";
+       char tmp[PATH_MAX] = "";
        struct odbc_obj *obj;
        char *context;
 
@@ -2322,7 +2419,7 @@ static int messagecount(const char *context, const char *mailbox, const char *fo
        int nummsgs = 0;
        int res;
        SQLHSTMT stmt = NULL;
-       char sql[256];
+       char sql[PATH_MAX];
        char rowdata[20];
        if (!folder)
                folder = "INBOX";
@@ -2393,7 +2490,7 @@ static int has_voicemail(const char *mailbox, const char *folder)
 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[256];
+       char fn[PATH_MAX];
        char mailbox[256];
        char *stringp;
        FILE *p=NULL;
@@ -2417,34 +2514,34 @@ static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, i
 
        if (!strcmp(fmt, "wav49"))
                fmt = "WAV";
-       if(option_debug > 2)
-               ast_log(LOG_DEBUG, "Storing file '%s', format '%s'\n", fn, fmt);
+       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)) == NULL) {
+       if (!(p = vm_mkftemp(tmp))) {
                ast_log(LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
                return -1;
-       } else {
-               make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, chan->cid.cid_num, chan->cid.cid_name, 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);
-                       return -1;
-               }
-               fread(buf, len, 1, p);
-               ((char *)buf)[len] = '\0';
-               INIT(&str, mail_string, buf, len);
-               imap_mailbox_name(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);
        }
+       
+       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);
+               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, 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);
+       ast_debug(3, "%s stored\n", fn);
        return 0;
 
 }
@@ -2456,21 +2553,24 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
  
        struct ast_vm_user *vmu;
        struct vm_state *vms_p;
-       char tmp[256]="";
+       char tmp[256] = "";
        char *mb, *cur;
        char *mailboxnc; 
        char *context;
        int ret = 0;
+
        if (newmsgs)
                *newmsgs = 0;
+
        if (oldmsgs)
                *oldmsgs = 0;
  
-       if(option_debug > 2)
-               ast_log (LOG_DEBUG,"Mailbox is set to %s\n",mailbox);
+        ast_debug(3,"Mailbox is set to %s\n",mailbox);
+
        /* If no mailbox, return immediately */
        if (ast_strlen_zero(mailbox))
                return 0;
+
        if (strchr(mailbox, ',')) {
                int tmpnew, tmpold;
                ast_copy_string(tmp, mailbox, sizeof(tmp));
@@ -2490,9 +2590,10 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
                }
                return 0;
        }
+
        ast_copy_string(tmp, mailbox, sizeof(tmp));
-       context = strchr(tmp, '@');
-       if (context) {
+
+       if ((context = strchr(tmp, '@'))) {
                *context = '\0';
                mailboxnc = tmp;
                context++;
@@ -2502,92 +2603,85 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
        }
  
        /* 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, mailboxnc);
-       if (!vmu) {
-               ast_log (LOG_ERROR,"Couldn't find mailbox %s in context %s\n",mailboxnc,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;
-               }
+       /*ast_debug(1,"Before find_user, context is %s and mailbox is %s\n",context,mailbox); */
+       if (!(vmu = find_user(NULL, context, mailboxnc))) {
+               ast_log(LOG_ERROR, "Couldn't find mailbox %s in context %s\n", mailboxnc, context);
+               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(mailboxnc,1);
-       }
-       if (vms_p) {
-               if(option_debug > 2)
-                       ast_log (LOG_DEBUG,"Returning before search - user is logged in\n");
+       if ((vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1)) || (vms_p = get_vm_state_by_mailbox(mailboxnc, 1))) {
+               ast_debug(3,"Returning before search - user is logged in\n");
                *newmsgs = vms_p->newmessages;
                *oldmsgs = vms_p->oldmessages;
+               free_user(vmu);
                return 0;
        }
  
        /* 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(mailboxnc,0);
-       }
-       if (!vms_p) {
-               if(option_debug > 2)
-                       ast_log (LOG_DEBUG,"Adding new vmstate for %s\n",vmu->imapuser);
-               vms_p = (struct vm_state *)malloc(sizeof(struct vm_state));
+       if (!(vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0)) && !(vms_p = get_vm_state_by_mailbox(mailboxnc, 0))) {
+               ast_debug(3,"Adding new vmstate for %s\n",vmu->imapuser);
+               if (!(vms_p = ast_calloc(1, sizeof(*vms_p)))) {
+                       free_user(vmu);
+                       return -1;
+               }
                ast_copy_string(vms_p->imapuser,vmu->imapuser, sizeof(vms_p->imapuser));
                ast_copy_string(vms_p->username, mailboxnc, 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 > 2)
-                       ast_log (LOG_DEBUG,"Copied %s to %s\n",vmu->imapuser,vms_p->imapuser);
-               vms_p->updated = 1;
-               vms_p->interactive = 0;
-               /* set mailbox to INBOX! */
+               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(0), sizeof(vms_p->curbox));
                init_vm_state(vms_p);
                vmstate_insert(vms_p);
        }
-       if (!vms_p->mailstream)
-               ret = init_mailstream(vms_p, 0);
-       if (!vms_p->mailstream) {
+
+       /* If no mailstream exists yet and even after attempting to initialize it fails, bail out */
+       ret = init_mailstream(vms_p, 0);
+       if (!vms_p->mailstream) {
                ast_log (LOG_ERROR,"Houston we have a problem - IMAP mailstream is NULL\n");
-               return -1;
-       }
-       if (newmsgs && ret==0 && vms_p->updated==1 ) {
-               pgm = mail_newsearchpgm ();
-               hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailboxnc);
-               pgm->header = hdr;
-               pgm->unseen = 1;
-               pgm->seen = 0;
-               pgm->undeleted = 1;
-               pgm->deleted = 0;
-               vms_p->vmArrayIndex = 0;
-       
-               mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
-               *newmsgs = vms_p->vmArrayIndex;
-               vms_p->newmessages = vms_p->vmArrayIndex;
-               mail_free_searchpgm(&pgm);
-       }
-       if (oldmsgs && ret==0 && vms_p->updated==1 ) {
-               pgm = mail_newsearchpgm ();
-               hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailboxnc);
-               pgm->header = hdr;
-               pgm->unseen = 0;
-               pgm->seen = 1;
-               pgm->deleted = 0;
-               pgm->undeleted = 1;
-               vms_p->vmArrayIndex = 0;
-       
-               mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
-               *oldmsgs = vms_p->vmArrayIndex;
-               vms_p->oldmessages = vms_p->vmArrayIndex;
-               mail_free_searchpgm(&pgm);
-       }
+               free_user(vmu);
+               return -1;
+       }
+
+       if (!ret && vms_p->updated == 1) {
+               if (newmsgs) {
+                       pgm = mail_newsearchpgm();
+                       hdr = mail_newsearchheader("X-Asterisk-VM-Extension", (char *)mailboxnc);
+                       pgm->header = hdr;
+                       pgm->unseen = 1;
+                       pgm->seen = 0;
+                       pgm->undeleted = 1;
+                       pgm->deleted = 0;
+                       vms_p->vmArrayIndex = 0;
+                       mail_search_full(vms_p->mailstream, NULL, pgm, NIL);
+                       *newmsgs = vms_p->vmArrayIndex;
+                       vms_p->newmessages = vms_p->vmArrayIndex;
+                       mail_free_searchpgm(&pgm);
+               }
+               if (oldmsgs) {
+                       pgm = mail_newsearchpgm ();
+                       hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailboxnc);
+                       pgm->header = hdr;
+                       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);
+                       *oldmsgs = vms_p->vmArrayIndex;
+                       vms_p->oldmessages = vms_p->vmArrayIndex;
+                       mail_free_searchpgm(&pgm);
+               }
+       }
+
        if (vms_p->updated == 1) {  /* changes, so we did the searches above */
                vms_p->updated = 0;
        } else if (vms_p->updated > 1) {  /* decrement delay count */
@@ -2598,6 +2692,8 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
                *newmsgs = vms_p->newmessages;
                *oldmsgs = vms_p->oldmessages;
        }
+
+       free_user(vmu);
        return 0;
  }
 
@@ -2614,7 +2710,7 @@ static int has_voicemail(const char *mailbox, const char *folder)
 static int messagecount(const char *context, const char *mailbox, const char *folder)
 {
        int newmsgs, oldmsgs;
-       char tmp[256]="";
+       char tmp[256] = "";
        
        if (ast_strlen_zero(mailbox))
                return 0;
@@ -2629,18 +2725,21 @@ static int messagecount(const char *context, const char *mailbox, const char *fo
 #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)
+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[256], todir[256], frompath[256], topath[256];
+       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_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
        make_file(frompath, sizeof(frompath), fromdir, msgnum);
        make_dir(todir, sizeof(todir), recip->context, recip->mailbox, frombox);
 
@@ -2655,7 +2754,7 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i
                ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
        }
        ast_unlock_path(todir);
-       notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
+       notify_new_message(chan, recip, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
        
        return 0;
 }
@@ -2673,17 +2772,21 @@ static int __has_voicemail(const char *context, const char *mailbox, const char
        struct dirent *de;
        char fn[256];
        int ret = 0;
-       if (!folder)
-               folder = "INBOX";
+
        /* If no mailbox, return immediately */
        if (ast_strlen_zero(mailbox))
                return 0;
-       if (!context)
+
+       if (ast_strlen_zero(folder))
+               folder = "INBOX";
+       if (ast_strlen_zero(context))
                context = "default";
+
        snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
-       dir = opendir(fn);
-       if (!dir)
+
+       if (!(dir = opendir(fn)))
                return 0;
+
        while ((de = readdir(dir))) {
                if (!strncasecmp(de->d_name, "msg", 3)) {
                        if (shortcircuit) {
@@ -2693,7 +2796,9 @@ static int __has_voicemail(const char *context, const char *mailbox, const char
                                ret++;
                }
        }
+
        closedir(dir);
+
        return ret;
 }
 
@@ -2719,13 +2824,15 @@ 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 no mailbox, return immediately */
-       if (ast_strlen_zero(mailbox))
-               return 0;
+
        if (strchr(mailbox, ',')) {
                int tmpnew, tmpold;
                char *mb, *cur;
@@ -2746,17 +2853,19 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
                }
                return 0;
        }
+
        ast_copy_string(tmp, mailbox, sizeof(tmp));
-       context = strchr(tmp, '@');
-       if (context) {
-               *context = '\0';
-               context++;
-       } else
+       
+       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;
 }
 
@@ -2774,7 +2883,7 @@ static void run_externnotify(char *context, char *extension)
        else
                ast_copy_string(ext_context, extension, sizeof(ext_context));
 
-       if (!strcasecmp(externnotify, "smdi")) {
+       if (smdi_iface) {
                if (ast_app_has_voicemail(ext_context, NULL)) 
                        ast_smdi_mwi_set(smdi_iface, extension);
                else
@@ -2789,16 +2898,16 @@ static void run_externnotify(char *context, char *extension)
                        ast_log(LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
                        ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Successfully executed SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
+                       ast_debug(1, "Successfully executed SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
                }
-       } else if (!ast_strlen_zero(externnotify)) {
+       }
+
+       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);
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Executing %s\n", arguments);
+                       ast_debug(1, "Executing %s\n", arguments);
                        ast_safe_system(arguments);
                }
        }
@@ -2815,7 +2924,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
        int newmsgs, oldmsgs;
        struct vm_state *vms = NULL;
 #endif
-       char tmptxtfile[256], txtfile[256];
+       char txtfile[PATH_MAX], tmptxtfile[PATH_MAX];
        char callerid[256];
        FILE *txt;
        char date[256];
@@ -2826,23 +2935,28 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
        int ausemacro = 0;
        int ousemacro = 0;
        int ouseexten = 0;
-       char dir[256], tmpdir[260];
-       char fn[256];
-       char prefile[256]="";
-       char tempfile[256]="";
+       int rtmsgid = 0;
+       char tmpid[16];
+       char tmpdur[16];
+       char priority[16];
+       char origtime[16];
+       char dir[PATH_MAX], tmpdir[PATH_MAX];
+       char dest[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[16] = "#";
-       char tmp[256] = "", *tmpptr;
+       char tmp[1024] = "", *tmpptr;
        struct ast_vm_user *vmu;
        struct ast_vm_user svm;
        const char *category = NULL;
 
        ast_copy_string(tmp, ext, sizeof(tmp));
        ext = tmp;
-       context = strchr(tmp, '@');
-       if (context) {
+       if ((context = strchr(tmp, '@'))) {
                *context++ = '\0';
                tmpptr = strchr(context, '&');
        } else {
@@ -2854,26 +2968,29 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
 
        category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
 
-       if(option_debug > 2)
-               ast_log(LOG_DEBUG, "Before find_user\n");
+       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);
-               if (ast_test_flag(options, OPT_PRIORITY_JUMP) || ast_opt_priority_jumping)
-                       ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
                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->context, sizeof(ext_context));
-       if (ast_test_flag(options, OPT_BUSY_GREETING))
+       if (ast_test_flag(options, OPT_BUSY_GREETING)) {
+               res = create_dirpath(dest, sizeof(dest), vmu->context, ext, "busy");
                snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
-       else if (ast_test_flag(options, OPT_UNAVAIL_GREETING))
+       } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
+               res = create_dirpath(dest, sizeof(dest), vmu->context, ext, "unavail");
                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(dest, sizeof(dest), vmu->context, ext, "temp"))) {
+               ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
+               return -1;
+       }
        RETRIEVE(tempfile, -1);
        if (ast_fileexists(tempfile, NULL, NULL) > 0)
                ast_copy_string(prefile, tempfile, sizeof(prefile));
@@ -2916,14 +3033,12 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                        if (ast_streamfile(chan, prefile, chan->language) > -1) 
                                res = ast_waitstream(chan, ecodes);
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
+                       ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
                        res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
                }
                DISPOSE(prefile, -1);
                if (res < 0) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
+                       ast_debug(1, "Hang up during prefile playback\n");
                        free_user(vmu);
                        pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
                        return -1;
@@ -2992,12 +3107,11 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                /* must open stream for this user to get info! */
                vms = get_vm_state_by_mailbox(ext,0);
                if (vms) {
-                       if(option_debug > 2)
-                               ast_log(LOG_DEBUG, "Using vm_state, interactive set to %d.\n",vms->interactive);
+                       ast_debug(3, "Using vm_state, interactive set to %d.\n",vms->interactive);
                        newmsgs = vms->newmessages++;
                        oldmsgs = vms->oldmessages;
                } else {
-                       res = inboxcount(ext, &newmsgs, &oldmsgs);
+                       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
                        if(res < 0) {
                                ast_log(LOG_NOTICE,"Can not leave voicemail, unable to count messages\n");
                                return -1;
@@ -3006,23 +3120,20 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                }
                /* here is a big difference! We add one to it later */
                msgnum = newmsgs + oldmsgs;
-               if(option_debug > 2)
-                       ast_log(LOG_DEBUG, "Messagecount set to %d\n",msgnum);
+               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 */
                if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "*** QUOTA EXCEEDED!! %u >= %u\n", 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;
                }
                /* here is a big difference! We add one to it later */
                msgnum = newmsgs + oldmsgs;
-               if(option_debug > 2)
-                       ast_log(LOG_DEBUG, "Messagecount set to %d\n",msgnum);
+               ast_debug(3, "Messagecount set to %d\n",msgnum);
 
 #else
                if (count_messages(vmu, dir) >= vmu->maxmsg) {
@@ -3052,6 +3163,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                        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) {
@@ -3077,19 +3196,27 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                                chan->exten,
                                chan->priority,
                                chan->name,
-                               ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
+                               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, vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
-                               
+#ifdef IMAP_STORAGE
+               res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms);
+#else
+               res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, NULL);
+#endif
+
                if (txt) {
-                       if (duration < vmminmessage) {
+                       if (duration < vmminsecs) {
                                if (option_verbose > 2) 
-                                       ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
+                                       ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, 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);
@@ -3099,10 +3226,13 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                                        ast_filedelete(tmptxtfile, NULL);
                                        unlink(tmptxtfile);
                                } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
-                                       if (option_debug) 
-                                               ast_log(LOG_DEBUG, "The recorded media file is gone, so we should remove the .txt file too!\n");
+                                       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 {
                                        msgnum = last_message_index(vmu, dir) + 1;
                                        make_file(fn, sizeof(fn), dir, msgnum);
@@ -3119,6 +3249,11 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                                        rename(tmptxtfile, txtfile);
 
                                        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);
+                                       }
 #ifndef IMAP_STORAGE
                                        /* Are there to be more recipients of this message? */
                                        while (tmpptr) {
@@ -3132,14 +3267,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                                                        context++;
                                                }
                                                if ((recip = find_user(&recipu, context, exten))) {
-                                                       copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
+                                                       copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir);
                                                        free_user(recip);
                                                }
                                        }
 #endif
                                        if (ast_fileexists(fn, NULL, NULL)) {
                                                STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms);
-                                               notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
+                                               notify_new_message(chan, vmu, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
                                                DISPOSE(dir, msgnum);
                                        }
                                }
@@ -3150,7 +3285,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                } else if (res > 0)
                        res = 0;
 
-               if (duration < vmminmessage)
+               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
@@ -3169,8 +3304,8 @@ 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[256];
-       char dfn[256];
+       char sfn[PATH_MAX];
+       char dfn[PATH_MAX];
 
        if (vm_lock_path(dir))
                return ERROR_LOCK_PATH;
@@ -3214,8 +3349,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
        /* get the real IMAP message number for this message */
        sprintf(sequence,"%ld",vms->msgArray[msg]);
        imap_mailbox_name(dbox, vms, box, 1);
-       if (option_debug > 2)
-               ast_log(LOG_DEBUG, "Copying sequence %s to mailbox %s\n",sequence,dbox);
+       ast_debug(3, "Copying sequence %s to mailbox %s\n",sequence,dbox);
        res = mail_copy(vms->mailstream, sequence, dbox);
        if (res == 1) return 0;
        return 1;
@@ -3223,9 +3357,9 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
        char *dir = vms->curdir;
        char *username = vms->username;
        char *context = vmu->context;
-       char sfn[256];
-       char dfn[256];
-       char ddir[256];
+       char sfn[PATH_MAX];
+       char dfn[PATH_MAX];
+       char ddir[PATH_MAX];
        const char *dbox = mbox(box);
        int x;
        make_file(sfn, sizeof(sfn), dir, msg);
@@ -3364,8 +3498,7 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
        bytes += ast_adsi_voice_mode(buf + bytes, 0);
        ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
 
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Done downloading scripts...\n");
+       ast_debug(1, "Done downloading scripts...\n");
 
 #ifdef DISPLAY
        /* Add last dot */
@@ -3373,8 +3506,7 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
        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
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Restarting session...\n");
+       ast_debug(1, "Restarting session...\n");
 
        bytes = 0;
        /* Load the session now */
@@ -3487,7 +3619,7 @@ 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[256];
+       char fn2[PATH_MAX];
 
        char cid[256]="";
        char *val;
@@ -3747,7 +3879,7 @@ static int get_folder(struct ast_channel *chan, int start)
 {
        int x;
        int d;
-       char fn[256];
+       char fn[PATH_MAX];
        d = ast_play_and_wait(chan, "vm-press");        /* "Press" */
        if (d)
                return d;
@@ -3833,7 +3965,7 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu,
                                *duration += prepend_duration;
                                msg_cat = ast_category_get(msg_cfg, "message");
                                snprintf(duration_str, 11, "%ld", *duration);
-                               if (!ast_variable_update(msg_cat, "duration", duration_str, NULL)) {
+                               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, *duration, vms);
                                }
@@ -3868,22 +4000,45 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu,
        return cmd;
 }
 
+static void queue_mwi_event(const char *mbox, int new, int old)
+{
+       struct ast_event *event;
+       char *mailbox;
+
+       /* Strip off @default */
+       mailbox = ast_strdupa(mbox);
+       if (strstr(mailbox, "@default"))
+               mailbox = strsep(&mailbox, "@");
+
+       if (!(event = ast_event_new(AST_EVENT_MWI,
+                       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+                       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_END);
+}
+
 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
 {
-       char todir[256], fn[256], ext_context[256], *stringp;
+       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);
 
        if (!ast_strlen_zero(vmu->attachfmt)) {
-               if (strstr(fmt, vmu->attachfmt)) {
+               if (strstr(fmt, vmu->attachfmt))
                        fmt = vmu->attachfmt;
-               } else {
+                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 */
@@ -3891,34 +4046,33 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu,
        stringp = fmt;
        strsep(&stringp, "|");
 
+       if (!ast_strlen_zero(vmu->serveremail))
+               myserveremail = vmu->serveremail;
+
        if (!ast_strlen_zero(vmu->email)) {
-               int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
-               char *myserveremail = serveremail;
-               attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
-               if (!ast_strlen_zero(vmu->serveremail))
-                       myserveremail = vmu->serveremail;
+               int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
+               if (!attach_user_voicemail)
+                       attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
+
                /*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 (!ast_strlen_zero(vmu->pager)) {
-               char *myserveremail = serveremail;
-               if (!ast_strlen_zero(vmu->serveremail))
-                       myserveremail = vmu->serveremail;
+       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)) {
+       if (ast_test_flag(vmu, VM_DELETE))
                DELETE(todir, msgnum, fn);
-       }
 
 #ifdef IMAP_STORAGE
        DELETE(todir, msgnum, fn);
 #endif
        /* Leave voicemail for someone */
-       if (ast_app_has_voicemail(ext_context, NULL)) {
+       if (ast_app_has_voicemail(ext_context, NULL)) 
                ast_app_inboxcount(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);
        return 0;
@@ -3932,7 +4086,6 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
        char *temp;
        char todir[256];
        int todircount=0;
-       int duration;
 #endif
        char username[70]="";
        int res = 0, cmd = 0;
@@ -4071,16 +4224,19 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
 
                /* Forward VoiceMail */
                long duration = 0;
-
-               RETRIEVE(dir, curmsg);
+#ifdef IMAP_STORAGE
+               char *myserveremail = serveremail;
+               char buf[1024] = "";
+               int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
+#endif
+               RETRIEVE(dir, curmsg);
                cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, vms);
                if (!cmd) {
                        AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
 #ifdef IMAP_STORAGE
                                /* Need to get message content */
-                               if(option_debug > 2)
-                                       ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
-                               if (vms->msgArray[vms->curmsg] == 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;
                                }
@@ -4093,15 +4249,13 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
                                        return -1;
                                }
                                /* Get header info needed by sendmail */
-                               temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:");
-                               if (temp)
+                               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 */
-                               fmt = ast_strdupa(fmt);
-                               if (fmt) {
+                               if ((fmt = ast_strdupa(fmt))) {
                                        stringp = fmt;
                                        strsep(&stringp, "|");
                                } else {
@@ -4110,14 +4264,12 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
                                }
                                if (!strcasecmp(fmt, "wav49"))
                                        fmt = "WAV";
-                               if (option_debug > 2)
-                                       ast_log (LOG_DEBUG,"**** format set to %s, vmfmts set to %s\n",fmt,vmfmts);
+                               ast_debug(3,"**** format set to %s, vmfmts set to %s\n",fmt,vmfmts);
                                /* ast_copy_string(fmt, vmfmts, sizeof(fmt));*/
                                /* if (!ast_strlen_zero(fmt)) { */
                                snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
                                make_gsm_file(vms->fn, vms->imapuser, todir, vms->curmsg);
-                               if (option_debug > 2)
-                                       ast_log (LOG_DEBUG,"Before mail_fetchstructure, message number is %ld, filename is:%s\n",vms->msgArray[vms->curmsg], vms->fn);
+                               ast_debug(3,"Before mail_fetchstructure, message number is %ld, filename is:%s\n",vms->msgArray[vms->curmsg], vms->fn);
                                /*mail_fetchstructure (mailstream, vmArray[0], &body); */
                                mail_fetchstructure (vms->mailstream, vms->msgArray[vms->curmsg], &body);
                                save_body(body,vms,"3","gsm");
@@ -4126,15 +4278,14 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
  
                                STORE(todir, vmtmp->mailbox, vmtmp->context, vms->curmsg, chan, vmtmp, fmt, duration, vms);
 
-                               char *myserveremail = serveremail;
-                               if (!ast_strlen_zero(vmtmp->serveremail))
-                                       myserveremail = vmtmp->serveremail;
-                               int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
-                               attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
-                               /* NULL category for IMAP storage */
-                               sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, chan->cid.cid_num, chan->cid.cid_name, 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, 0, curmsg, duration, vmtmp, fmt);
+                               copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir);
 #endif
                                saved_messages++;
                                AST_LIST_REMOVE_CURRENT(&extensions, list);
@@ -4156,6 +4307,10 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
                        }       
                }
        }
+
+       /* 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;
 }
 
@@ -4169,7 +4324,7 @@ static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file
 
 static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file) 
 {
-       return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms);
+       return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms, NULL);
 }
 
 static int play_message_category(struct ast_channel *chan, const char *category)
@@ -4262,7 +4417,7 @@ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms,
        int res = 0;
        int i;
        char *callerid, *name;
-       char prefile[256]="";
+       char prefile[PATH_MAX] = "";
        
 
        /* If voicemail cid is not enabled, or we didn't get cid or context from the attribute file, leave now. */
@@ -4271,15 +4426,13 @@ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms,
                return res;
 
        /* Strip off caller ID number from name */
-       if (option_debug)
-               ast_log(LOG_DEBUG, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
+       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++){
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
+                       ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
                        if ((strcmp(cidinternalcontexts[i], context) == 0))
                                break;
                }
@@ -4306,9 +4459,8 @@ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms,
                        }
                }
 
-               else if (!res){
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "VM-CID: Numeric caller id: (%s)\n",callerid);
+               else if (!res) {
+                       ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
                        /* BB: 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");
@@ -4316,8 +4468,7 @@ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms,
                }
        } else {
                /* Number unknown */
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "VM-CID: From an unknown number\n");
+               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");
        }
@@ -4337,8 +4488,7 @@ static int play_message_duration(struct ast_channel *chan, struct vm_state *vms,
        durations=atoi(duration);
        durationm=(durations / 60);
 
-       if (option_debug)
-               ast_log(LOG_DEBUG, "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");
@@ -4385,14 +4535,16 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc
        char origtime[32];
        char duration[16];
        char category[32];
-       char todir[256];
+       char todir[PATH_MAX];
        int res = 0;
+       char *attachedfilefmt;
        char *temp;
+       char buf[1024];
 
        vms->starting = 0; 
-       if(option_debug > 2)
-               ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
-       if (vms->msgArray[vms->curmsg] == 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;
        }
@@ -4408,13 +4560,30 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc
        make_gsm_file(vms->fn, vms->imapuser, todir, vms->curmsg);
 
        mail_fetchstructure (vms->mailstream,vms->msgArray[vms->curmsg],&body);
-       save_body(body,vms,"3","gsm");
+       
+       /* We have the body, now we extract the file name of the first attachment. */
+       if (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)) {
@@ -4424,37 +4593,27 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc
        }
 
        /* Get info from headers!! */
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:");
-
-       if (temp)
+       if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:", buf, sizeof(buf))))
                ast_copy_string(cid, temp, sizeof(cid)); 
        else 
                cid[0] = '\0';
-
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:");
-
-       if (temp)
+       
+       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';
 
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:");
-
-       if (temp)
+       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';
 
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:");
-
-       if (temp)
+       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';
        
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Category:");
-       
-       if (temp)
+       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';
@@ -4593,8 +4752,9 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc
 #ifdef IMAP_STORAGE
 static void imap_mailbox_name(char *spec, struct vm_state *vms, int box, int use_folder)
 {
-       char tmp[256];
-       
+       char tmp[256], *t = tmp;
+       size_t left = sizeof(tmp);
+
        if (box == 1) {
                ast_copy_string(vms->curbox, mbox(0), sizeof(vms->curbox));
                sprintf(vms->vmbox, "vm-%s", mbox(1));
@@ -4603,11 +4763,20 @@ static void imap_mailbox_name(char *spec, struct vm_state *vms, int box, int use
                snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
        }
 
-       if (strlen(authuser) > 0) {
-               snprintf(tmp, sizeof(tmp), "{%s:%s/imap/authuser=%s/%s/user=%s}",imapserver,imapport,authuser,imapflags,vms->imapuser);
-       } else {
-               snprintf(tmp, sizeof(tmp), "{%s:%s/imap/%s/user=%s}",imapserver,imapport,imapflags,vms->imapuser);
-       }
+       /* 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)
                sprintf(spec, "%s%s", tmp, use_folder? imapfolder: "INBOX");
        else
@@ -4624,10 +4793,9 @@ static int init_mailstream(struct vm_state *vms, int box)
                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);
+       ast_debug(3,"vm_state user is:%s\n",vms->imapuser);
        if (vms->mailstream == NIL || !vms->mailstream) {
-               ast_log (LOG_DEBUG,"mailstream not set.\n");
+               ast_debug(1,"mailstream not set.\n");
        } else {
                stream = vms->mailstream;
        }
@@ -4639,22 +4807,22 @@ static int init_mailstream(struct vm_state *vms, int box)
 #include "linkage.c"
                /* Connect to INBOX first to get folders delimiter */
                imap_mailbox_name(tmp, vms, 0, 0);
-               stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
+               stream = mail_open(stream, tmp, debug ? OP_DEBUG : NIL);
                if (stream == NIL) {
                        ast_log (LOG_ERROR, "Can't connect to imap server %s\n", tmp);
                        return NIL;
                }
                get_mailbox_delimiter(stream);
                /* update delimiter in imapfolder */
-               for(cp = imapfolder; *cp; cp++)
+               for(cp = imapfolder; *cp; cp++) {
                        if(*cp == '/')
                                *cp = delimiter;
+               }
        }
        /* Now connect to the target folder */
        imap_mailbox_name(tmp, vms, box, 1);
-       if(option_debug > 2)
-               ast_log (LOG_DEBUG,"Before mail_open, server: %s, box:%d\n", tmp, box);
-       vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
+       ast_debug(3,"Before mail_open, server: %s, box:%d\n", tmp, box);
+       vms->mailstream = mail_open(stream, tmp, debug ? OP_DEBUG : NIL);
        if (vms->mailstream == NIL) {
                return -1;
        } else {
@@ -4670,14 +4838,13 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
        char dbox[256];
 
        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_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 (here for now to test) */
        mail_parameters(NULL, SET_QUOTA, (void *) mm_parsequota);
        imap_mailbox_name(dbox, vms, box, 1);
@@ -4686,7 +4853,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
        pgm = mail_newsearchpgm();
 
        /* Check IMAP folder for Asterisk messages only... */
-       hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", vmu->mailbox);
+       hdr = mail_newsearchheader("X-Asterisk-VM-Extension", vmu->mailbox);
        pgm->header = hdr;
        pgm->deleted = 0;
        pgm->undeleted = 1;
@@ -4700,15 +4867,13 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
                pgm->unseen = 0;
        }
 
+       ast_debug(3,"Before mail_search_full, user is %s\n",vmu->imapuser);
+
        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;
 }
 #else
@@ -4798,6 +4963,12 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
                                vms->heard[x] = 0;
                                --x;
                        } 
+               } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
+                       /* If realtime storage enabled - we should explicitly delete this message,
+                       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);
                } 
        } 
 
@@ -4810,11 +4981,12 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
        }
        ast_unlock_path(vms->curdir);
 #else
-       for (x=0;x < vmu->maxmsg;x++) { 
-               if (vms->deleted[x]) { 
-                       if(option_debug > 2)
-                               ast_log(LOG_DEBUG,"IMAP delete of %d\n",x);
-                       IMAP_DELETE(vms->curdir, x, vms->fn, vms);
+       if (vms->deleted) {
+               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);
+                       }
                }
        }
 #endif
@@ -4872,7 +5044,7 @@ static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
 {
        int cmd;
 
-       if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "fr") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) { /* Italian, Spanish, French or Portuguese syntax */
+       if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) { /* Italian, Spanish, French or Portuguese syntax */
                cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
                return cmd ? cmd : ast_play_and_wait(chan, mbox);
        } else if (!strcasecmp(chan->language, "gr")){
@@ -5345,14 +5517,14 @@ static int vm_intro_fr(struct ast_channel *chan,struct vm_state *vms)
                }
                if (!res && vms->oldmessages) {
                        res = say_and_wait(chan, vms->oldmessages, chan->language);
+                       if (!res)
+                               res = ast_play_and_wait(chan, "vm-Old");
                        if (!res) {
                                if (vms->oldmessages == 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-Old");
                }
                if (!res) {
                        if (!vms->oldmessages && !vms->newmessages) {
@@ -5710,7 +5882,7 @@ static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct
        int tries = 0;
        char newpassword[80] = "";
        char newpassword2[80] = "";
-       char prefile[256]="";
+       char prefile[PATH_MAX] = "";
        unsigned char buf[256];
        int bytes=0;
 
@@ -5756,28 +5928,46 @@ static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct
        if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
                vm_change_password_shell(vmu, newpassword);
 
-       if (option_debug)
-               ast_log(LOG_DEBUG,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
+       ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
        cmd = ast_play_and_wait(chan, vm_passchanged);
 
        /* If forcename is set, have the user record their name */      
        if (ast_test_flag(vmu, VM_FORCENAME)) {
                snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
-               cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
-               if (cmd < 0 || cmd == 't' || cmd == '#')
-                       return cmd;
+               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;
+               }
        }
 
        /* If forcegreetings is set, have the user record their greetings */
        if (ast_test_flag(vmu, VM_FORCEGREET)) {
                snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
-               cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
-               if (cmd < 0 || cmd == 't' || cmd == '#')
-                       return cmd;
+               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);
-               cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
-               if (cmd < 0 || cmd == 't' || cmd == '#')
-                       return cmd;
+               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;
+               }
        }
 
        return cmd;
@@ -5790,7 +5980,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
        int duration = 0;
        char newpassword[80] = "";
        char newpassword2[80] = "";
-       char prefile[256]="";
+       char prefile[PATH_MAX] = "";
        unsigned char buf[256];
        int bytes=0;
 
@@ -5809,15 +5999,27 @@ 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);
-                       cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
+#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);
-                       cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
+#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);
-                       cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
+#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);
@@ -5860,8 +6062,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
                        if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
                                vm_change_password_shell(vmu, newpassword);
 
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
+                       ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
                        cmd = ast_play_and_wait(chan, vm_passchanged);
                        break;
                case '*': 
@@ -5884,12 +6085,14 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
 
 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
 {
+       int res;
        int cmd = 0;
        int retries = 0;
        int duration = 0;
-       char prefile[256]="";
+       char prefile[PATH_MAX] = "";
        unsigned char buf[256];
-       int bytes=0;
+       char dest[PATH_MAX];
+       int bytes = 0;
 
        if (ast_adsi_available(chan)) {
                bytes += adsi_logo(buf + bytes);
@@ -5899,18 +6102,31 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st
                bytes += ast_adsi_voice_mode(buf + bytes, 0);
                ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
        }
+
        snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
-       while (cmd >= 0 && cmd != 't') {
+       if ((res = create_dirpath(dest, sizeof(dest), vmu->context, vms->username, "temp"))) {
+               ast_log(LOG_WARNING, "Failed to create directory (%s).\n", prefile);
+               return -1;
+       }
+       while((cmd >= 0) && (cmd != 't')) {
                if (cmd)
                        retries = 0;
                RETRIEVE(prefile, -1);
                if (ast_fileexists(prefile, NULL, NULL) <= 0) {
-                       play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
+#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':
-                               cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
+#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);
@@ -6105,8 +6321,7 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
                        ast_copy_string(mailbox, fullusername, mailbox_size);
                }
 
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Before find user for mailbox %s\n",mailbox);
+               ast_debug(1, "Before find user for mailbox %s\n",mailbox);
                vmu = find_user(&vmus, context, mailbox);
                if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
                        /* saved password is blank, so don't bother asking */
@@ -6198,8 +6413,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        memset(&vmus, 0, sizeof(vmus));
 
        if (chan->_state != AST_STATE_UP) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Before ast_answer\n");
+               ast_debug(1, "Before ast_answer\n");
                ast_answer(chan);
        }
 
@@ -6281,8 +6495,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        if (!valid)
                res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
 
-       if (option_debug)
-               ast_log(LOG_DEBUG, "After vm_authenticate\n");
+       ast_debug(1, "After vm_authenticate\n");
        if (!res) {
                valid = 1;
                if (!skipuser)
@@ -6317,21 +6530,18 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        create_dirpath(vms.curdir, sizeof(vms.curdir), vmu->context, vms.username, "");
 #endif
        /* Retrieve old and new message counts */
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Before open_mailbox\n");
+       ast_debug(1, "Before open_mailbox\n");
        res = open_mailbox(&vms, vmu, 1);
        if (res == ERROR_LOCK_PATH)
                goto out;
        vms.oldmessages = vms.lastmsg + 1;
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Number of old messages: %d\n",vms.oldmessages);
+       ast_debug(1, "Number of old messages: %d\n",vms.oldmessages);
        /* Start in INBOX */
        res = open_mailbox(&vms, vmu, 0);
        if (res == ERROR_LOCK_PATH)
                goto out;
        vms.newmessages = vms.lastmsg + 1;
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Number of new messages: %d\n",vms.newmessages);
+       ast_debug(1, "Number of new messages: %d\n",vms.newmessages);
                
        /* Select proper mailbox FIRST!! */
        if (play_auto) {
@@ -6375,10 +6585,9 @@ static int vm_execmain(struct ast_channel *chan, void *data)
                }
        }
 #ifdef IMAP_STORAGE
-               if(option_debug > 2)
-                       ast_log(LOG_DEBUG, "Checking quotas: comparing %u to %u\n",vms.quota_usage,vms.quota_limit);
+               ast_debug(3, "Checking quotas: comparing %u to %u\n",vms.quota_usage,vms.quota_limit);
                if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
-                       ast_log(LOG_DEBUG, "*** QUOTA EXCEEDED!!\n");
+                       ast_debug(1, "*** QUOTA EXCEEDED!!\n");
                        cmd = ast_play_and_wait(chan, "vm-mailboxfull");
                }
 #endif
@@ -6485,6 +6694,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
                                                cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain);
                                                if (cmd == ERROR_LOCK_PATH) {
                                                        res = cmd;
+                                                       ast_log(LOG_WARNING, "forward_message failed to lock path.\n");
                                                        goto out;
                                                }
                                        } else
@@ -6528,7 +6738,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
                        }
                        break;
                case '4':
-                       if (vms.curmsg) {
+                       if (vms.curmsg > 0) {
                                vms.curmsg--;
                                cmd = play_message(chan, vmu, &vms);
                        } else {
@@ -6544,21 +6754,24 @@ static int vm_execmain(struct ast_channel *chan, void *data)
                        }
                        break;
                case '7':
-                       vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
-                       if (useadsi)
-                               adsi_delete(chan, &vms);
-                       if (vms.deleted[vms.curmsg]) 
-                               cmd = ast_play_and_wait(chan, "vm-deleted");
-                       else
-                               cmd = ast_play_and_wait(chan, "vm-undeleted");
-                       if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
-                               if (vms.curmsg < vms.lastmsg) {
-                                       vms.curmsg++;
-                                       cmd = play_message(chan, vmu, &vms);
-                               } else {
-                                       cmd = ast_play_and_wait(chan, "vm-nomore");
+                       if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
+                               vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
+                               if (useadsi)
+                                       adsi_delete(chan, &vms);
+                               if (vms.deleted[vms.curmsg]) 
+                                       cmd = ast_play_and_wait(chan, "vm-deleted");
+                               else
+                                       cmd = ast_play_and_wait(chan, "vm-undeleted");
+                               if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
+                                       if (vms.curmsg < vms.lastmsg) {
+                                               vms.curmsg++;
+                                               cmd = play_message(chan, vmu, &vms);
+                                       } else {
+                                               cmd = ast_play_and_wait(chan, "vm-nomore");
+                                       }
                                }
-                       }
+                       } else /* Delete not valid if we haven't selected a message */
+                               cmd = 0;
 #ifdef IMAP_STORAGE
                        deleted = 1;
 #endif
@@ -6671,14 +6884,16 @@ out:
        if (vmu)
                close_mailbox(&vms, vmu);
        if (valid) {
+               int new = 0, old = 0;
                snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
                manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
                run_externnotify(vmu->context, vmu->mailbox);
+               ast_app_inboxcount(ext_context, &new, &old);
+               queue_mwi_event(ext_context, new, old);
        }
 #ifdef IMAP_STORAGE
        /* expunge message - use UID Expunge if supported on IMAP server*/
-       if(option_debug > 2)
-               ast_log(LOG_DEBUG, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n",deleted,expungeonhangup);
+       ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n",deleted,expungeonhangup);
        if (vmu && deleted == 1 && expungeonhangup == 1) {
 #ifdef HAVE_IMAP_TK2006
                if (LEVELUIDPLUS (vms.mailstream)) {
@@ -6730,7 +6945,7 @@ static int vm_exec(struct ast_channel *chan, void *data)
                                ast_module_user_remove(u);
                                return -1;
                        }
-                       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_PRIORITY_JUMP);
+                       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING);
                        if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
                                int gain;
 
@@ -6761,10 +6976,6 @@ static int vm_exec(struct ast_channel *chan, void *data)
 
        if (res == ERROR_LOCK_PATH) {
                ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
-               /*Send the call to n+101 priority, where n is the current priority*/
-               if (ast_test_flag(&leave_options, OPT_PRIORITY_JUMP) || ast_opt_priority_jumping)
-                       if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
-                               ast_log(LOG_WARNING, "Extension %s, priority %d doesn't exist.\n", chan->exten, chan->priority + 101);
                pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
                res = 0;
        }
@@ -6777,20 +6988,25 @@ static int vm_exec(struct ast_channel *chan, void *data)
 static struct ast_vm_user *find_or_create(char *context, char *mbox)
 {
        struct ast_vm_user *vmu;
+
        AST_LIST_TRAVERSE(&users, vmu, list) {
                if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mbox, vmu->mailbox))
                        break;
                if (context && (!strcasecmp(context, vmu->context)) && (!strcasecmp(mbox, vmu->mailbox)))
                        break;
        }
+
+       if (vmu)
+               return vmu;
+       
+       if (!(vmu = ast_calloc(1, sizeof(*vmu))))
+               return NULL;
+       
+       ast_copy_string(vmu->context, context, sizeof(vmu->context));
+       ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
+
+       AST_LIST_INSERT_TAIL(&users, vmu, list);
        
-       if (!vmu) {
-               if ((vmu = ast_calloc(1, sizeof(*vmu)))) {
-                       ast_copy_string(vmu->context, context, sizeof(vmu->context));
-                       ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
-                       AST_LIST_INSERT_TAIL(&users, vmu, list);
-               }
-       }
        return vmu;
 }
 
@@ -6801,24 +7017,36 @@ static int append_mailbox(char *context, char *mbox, char *data)
        char *stringp;
        char *s;
        struct ast_vm_user *vmu;
+       char *mailbox_full;
+       int new = 0, old = 0;
 
        tmp = ast_strdupa(data);
 
-       if ((vmu = find_or_create(context, mbox))) {
-               populate_defaults(vmu);
-
-               stringp = tmp;
-               if ((s = strsep(&stringp, ","))) 
-                       ast_copy_string(vmu->password, s, sizeof(vmu->password));
-               if (stringp && (s = strsep(&stringp, ","))) 
-                       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
-               if (stringp && (s = strsep(&stringp, ","))) 
-                       ast_copy_string(vmu->email, s, sizeof(vmu->email));
-               if (stringp && (s = strsep(&stringp, ","))) 
-                       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
-               if (stringp && (s = strsep(&stringp, ","))) 
-                       apply_options(vmu, s);
-       }
+       if (!(vmu = find_or_create(context, mbox)))
+               return -1;
+       
+       populate_defaults(vmu);
+
+       stringp = tmp;
+       if ((s = strsep(&stringp, ","))) 
+               ast_copy_string(vmu->password, s, sizeof(vmu->password));
+       if (stringp && (s = strsep(&stringp, ","))) 
+               ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
+       if (stringp && (s = strsep(&stringp, ","))) 
+               ast_copy_string(vmu->email, s, sizeof(vmu->email));
+       if (stringp && (s = strsep(&stringp, ","))) 
+               ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
+       if (stringp && (s = strsep(&stringp, ","))) 
+               apply_options(vmu, s);
+
+       mailbox_full = alloca(strlen(mbox) + strlen(context) + 1);
+       strcpy(mailbox_full, mbox);
+       strcat(mailbox_full, "@");
+       strcat(mailbox_full, context);
+
+       inboxcount(mailbox_full, &new, &old);
+       queue_mwi_event(mailbox_full, new, old);
+
        return 0;
 }
 
@@ -6827,7 +7055,6 @@ static int vm_box_exists(struct ast_channel *chan, void *data)
        struct ast_module_user *u;
        struct ast_vm_user svm;
        char *context, *box;
-       int priority_jump = 0;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(mbox);
                AST_APP_ARG(options);
@@ -6851,8 +7078,6 @@ static int vm_box_exists(struct ast_channel *chan, void *data)
        AST_STANDARD_APP_ARGS(args, box);
 
        if (args.options) {
-               if (strchr(args.options, 'j'))
-                       priority_jump = 1;
        }
 
        if ((context = strchr(args.mbox, '@'))) {
@@ -6862,16 +7087,13 @@ static int vm_box_exists(struct ast_channel *chan, void *data)
 
        if (find_user(&svm, context, args.mbox)) {
                pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
-               if (priority_jump || ast_opt_priority_jumping)
-                       if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) 
-                               ast_log(LOG_WARNING, "VM box %s@%s exists, but extension %s, priority %d doesn't exist\n", box, context, chan->exten, chan->priority + 101);
        } else
                pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
        ast_module_user_remove(u);
        return 0;
 }
 
-static int acf_mailbox_exists(struct ast_channel *chan, char *cmd, char *args, char *buf, size_t len)
+static int acf_mailbox_exists(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
 {
        struct ast_vm_user svm;
        AST_DECLARE_APP_ARGS(arg,
@@ -6935,60 +7157,108 @@ static int vmauthenticate(struct ast_channel *chan, void *data)
        return res;
 }
 
-static char voicemail_show_users_help[] =
+static const char voicemail_show_users_help[] =
 "Usage: voicemail show users [for <context>]\n"
 "       Lists all mailboxes currently set up\n";
 
-static char voicemail_show_zones_help[] =
+static const char voicemail_show_zones_help[] =
 "Usage: voicemail show zones\n"
 "       Lists zone message formats\n";
 
+static int show_users_realtime(int fd, const char *context)
+{
+       struct ast_config *cfg;
+       const char *cat = NULL;
+
+       if (!(cfg = ast_load_realtime_multientry("voicemail", 
+               "context", context, NULL))) {
+               return RESULT_FAILURE;
+       }
+
+       ast_cli(fd, "\n"
+                   "=============================================================\n"
+                   "=== Configured Voicemail Users ==============================\n"
+                   "=============================================================\n"
+                   "===\n");
+
+       while ((cat = ast_category_browse(cfg, cat))) {
+               struct ast_variable *var = NULL;
+               ast_cli(fd, "=== Mailbox ...\n"
+                           "===\n");
+               for (var = ast_variable_browse(cfg, cat); var; var = var->next)
+                       ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
+               ast_cli(fd, "===\n"
+                           "=== ---------------------------------------------------------\n"
+                           "===\n");
+       }
+
+       ast_cli(fd, "=============================================================\n"
+                   "\n");
+
+       return RESULT_SUCCESS;
+}
+
+/*! \brief Show a list of voicemail users in the CLI */
 static int handle_voicemail_show_users(int fd, int argc, char *argv[])
 {
        struct ast_vm_user *vmu;
        char *output_format = "%-10s %-5s %-25s %-10s %6s\n";
+       const char *context = NULL;
 
-       if ((argc < 3) || (argc > 5) || (argc == 4)) return RESULT_SHOWUSAGE;
-       else if ((argc == 5) && strcmp(argv[3],"for")) return RESULT_SHOWUSAGE;
+       if ((argc < 3) || (argc > 5) || (argc == 4))
+               return RESULT_SHOWUSAGE;
+       if (argc == 5) {
+               if (strcmp(argv[3],"for"))
+                       return RESULT_SHOWUSAGE;
+               context = argv[4];
+       }
 
-       AST_LIST_LOCK(&users);
-       if (!AST_LIST_EMPTY(&users)) {
-               if (argc == 3)
-                       ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
-               else {
-                       int count = 0;
-                       AST_LIST_TRAVERSE(&users, vmu, list) {
-                               if (!strcmp(argv[4],vmu->context))
-                                       count++;
-                       }
-                       if (count) {
-                               ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
-                       } else {
-                               ast_cli(fd, "No such voicemail context \"%s\"\n", argv[4]);
-                               AST_LIST_UNLOCK(&users);
-                               return RESULT_FAILURE;
-                       }
+       if (ast_check_realtime("voicemail")) {
+               if (!context) {
+                       ast_cli(fd, "You must specify a specific context to show users from realtime!\n");
+                       return RESULT_SHOWUSAGE;
                }
-               AST_LIST_TRAVERSE(&users, vmu, list) {
-                       int newmsgs = 0, oldmsgs = 0;
-                       char count[12], tmp[256] = "";
+               return show_users_realtime(fd, context);
+       }
 
-                       if ((argc == 3) || ((argc == 5) && !strcmp(argv[4],vmu->context))) {
-                               snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
-                               inboxcount(tmp, &newmsgs, &oldmsgs);
-                               snprintf(count,sizeof(count),"%d",newmsgs);
-                               ast_cli(fd, output_format, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
-                       }
-               }
-       } else {
+       AST_LIST_LOCK(&users);
+       if (AST_LIST_EMPTY(&users)) {
                ast_cli(fd, "There are no voicemail users currently defined\n");
                AST_LIST_UNLOCK(&users);
                return RESULT_FAILURE;
        }
+       if (argc == 3)
+               ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
+       else {
+               int count = 0;
+               AST_LIST_TRAVERSE(&users, vmu, list) {
+                       if (!strcmp(context, vmu->context))
+                               count++;
+               }
+               if (count) {
+                       ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
+               } else {
+                       ast_cli(fd, "No such voicemail context \"%s\"\n", context);
+                       AST_LIST_UNLOCK(&users);
+                       return RESULT_FAILURE;
+               }
+       }
+       AST_LIST_TRAVERSE(&users, vmu, list) {
+               int newmsgs = 0, oldmsgs = 0;
+               char count[12], tmp[256] = "";
+
+               if ((argc == 3) || ((argc == 5) && !strcmp(context, vmu->context))) {
+                       snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
+                       inboxcount(tmp, &newmsgs, &oldmsgs);
+                       snprintf(count,sizeof(count),"%d",newmsgs);
+                       ast_cli(fd, output_format, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
+               }
+       }
        AST_LIST_UNLOCK(&users);
        return RESULT_SUCCESS;
 }
 
+/*! \brief Show a list of voicemail zones in the CLI */
 static int handle_voicemail_show_zones(int fd, int argc, char *argv[])
 {
        struct vm_zone *zone;
@@ -7047,6 +7317,227 @@ static struct ast_cli_entry cli_voicemail[] = {
        voicemail_show_zones_help, NULL, NULL },
 };
 
+static void poll_subscribed_mailboxes(void)
+{
+       struct mwi_sub *mwi_sub;
+
+       AST_RWLIST_RDLOCK(&mwi_subs);
+       AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
+               int new = 0, old = 0;
+
+               if (ast_strlen_zero(mwi_sub->mailbox))
+                       continue;
+
+               inboxcount(mwi_sub->mailbox, &new, &old);
+
+               if (new != mwi_sub->old_new || old != mwi_sub->old_old) {
+                       mwi_sub->old_new = new;
+                       mwi_sub->old_old = old;
+                       queue_mwi_event(mwi_sub->mailbox, new, old);
+               }
+       }
+       AST_RWLIST_UNLOCK(&mwi_subs);
+}
+
+static void *mb_poll_thread(void *data)
+{
+       while (poll_thread_run) {
+               struct timespec ts = { 0, };
+               struct timeval tv;
+
+               tv = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
+               ts.tv_sec = tv.tv_sec;
+               ts.tv_nsec = tv.tv_usec * 1000;
+
+               ast_mutex_lock(&poll_lock);
+               ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
+               ast_mutex_unlock(&poll_lock);
+
+               if (!poll_thread_run)
+                       break;
+
+               poll_subscribed_mailboxes();
+       }
+
+       return NULL;
+}
+
+static void mwi_sub_destroy(struct mwi_sub *mwi_sub)
+{
+       free(mwi_sub);
+}
+
+static void mwi_unsub_event_cb(const struct ast_event *event, void *userdata)
+{
+       uint32_t uniqueid;
+       struct mwi_sub *mwi_sub;
+
+       if (ast_event_get_type(event) != AST_EVENT_UNSUB)
+               return;
+
+       if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
+               return;
+
+       uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
+
+       AST_RWLIST_WRLOCK(&mwi_subs);
+       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
+               if (mwi_sub->uniqueid == uniqueid) {
+                       AST_LIST_REMOVE_CURRENT(&mwi_subs, entry);
+                       break;
+               }
+       }
+       AST_RWLIST_TRAVERSE_SAFE_END
+       AST_RWLIST_UNLOCK(&mwi_subs);
+
+       if (mwi_sub)
+               mwi_sub_destroy(mwi_sub);
+}
+
+static void mwi_sub_event_cb(const struct ast_event *event, void *userdata)
+{
+       const char *mailbox;
+       uint32_t uniqueid;
+       unsigned int len;
+       struct mwi_sub *mwi_sub;
+
+       if (ast_event_get_type(event) != AST_EVENT_SUB)
+               return;
+
+       if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
+               return;
+
+       mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
+       uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
+
+       len = sizeof(*mwi_sub);
+       if (!ast_strlen_zero(mailbox))
+               len += strlen(mailbox);
+
+       if (!(mwi_sub = ast_calloc(1, len)))
+               return;
+
+       mwi_sub->uniqueid = uniqueid;
+       if (!ast_strlen_zero(mailbox))
+               strcpy(mwi_sub->mailbox, mailbox);
+
+       AST_RWLIST_WRLOCK(&mwi_subs);
+       AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
+       AST_RWLIST_UNLOCK(&mwi_subs);
+}
+
+static void start_poll_thread(void)
+{
+       pthread_attr_t attr;
+
+       mwi_sub_sub = ast_event_subscribe(AST_EVENT_SUB, mwi_sub_event_cb, NULL,
+               AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
+               AST_EVENT_IE_END);
+
+       mwi_unsub_sub = ast_event_subscribe(AST_EVENT_UNSUB, mwi_unsub_event_cb, NULL,
+               AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
+               AST_EVENT_IE_END);
+
+       if (mwi_sub_sub)
+               ast_event_report_subs(mwi_sub_sub);
+
+       poll_thread_run = 1;
+
+       pthread_attr_init(&attr);
+       ast_pthread_create(&poll_thread, &attr, mb_poll_thread, NULL);
+       pthread_attr_destroy(&attr);
+}
+
+static void stop_poll_thread(void)
+{
+       poll_thread_run = 0;
+
+       if (mwi_sub_sub) {
+               ast_event_unsubscribe(mwi_sub_sub);
+               mwi_sub_sub = NULL;
+       }
+
+       if (mwi_unsub_sub) {
+               ast_event_unsubscribe(mwi_unsub_sub);
+               mwi_unsub_sub = NULL;
+       }
+
+       ast_mutex_lock(&poll_lock);
+       ast_cond_signal(&poll_cond);
+       ast_mutex_unlock(&poll_lock);
+
+       pthread_join(poll_thread, NULL);
+
+       poll_thread = AST_PTHREADT_NULL;
+}
+
+/*! \brief Manager list voicemail users command */
+static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
+{
+       struct ast_vm_user *vmu = NULL;
+       const char *id = astman_get_header(m, "ActionID");
+       char actionid[128] = "";
+
+       if (!ast_strlen_zero(id))
+               snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
+
+       AST_LIST_LOCK(&users);
+
+       if (AST_LIST_EMPTY(&users)) {
+               astman_send_ack(s, m, "There are no voicemail users currently defined.");
+               AST_LIST_UNLOCK(&users);
+               return RESULT_SUCCESS;
+       }
+       
+       astman_send_ack(s, m, "Voicemail user list will follow\r\n");
+       
+       AST_LIST_TRAVERSE(&users, vmu, list) {
+               char dirname[256];
+               
+               make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
+               astman_append(s,
+                             "%s"
+                             "Event: VoicemailUserEntry\r\n"
+                             "VMContext: %s\r\n"
+                             "VoiceMailbox: %s\r\n"
+                             "Fullname: %s\r\n"
+                             "Email: %s\r\n"
+                             "Pager: %s\r\n"
+                             "ServerEmail: %s\r\n"
+                             "MailCommand: %s\r\n"
+                             "Language: %s\r\n"
+                             "TimeZone: %s\r\n"
+                             "Callback: %s\r\n"
+                             "Dialout: %s\r\n"
+                             "UniqueID: %s\r\n"
+                             "ExitContext: %s\r\n"
+                             "SayDurationMinimum: %d\r\n"
+                             "AttachmentFormat: %s\r\n"
+                             "VolumeGain: %.2lf\r\n"
+                             "MaxMessageCount: %d\r\n"
+                             "MaxMessageLength: %d\r\n"
+                             "NewMessageCount: %d\r\n"
+#ifdef IMAP_STORAGE
+                             "IMAPUser: %s\r\n"
+#endif
+                             "\r\n",
+                             actionid, vmu->context, vmu->mailbox, vmu->fullname, vmu->email,
+                             vmu->pager, vmu->serveremail, vmu->mailcmd, vmu->language,
+                             vmu->zonetag, vmu->callback, vmu->dialout, vmu->uniqueid,
+                             vmu->exit, vmu->saydurationm, vmu->attachfmt, vmu->volgain,
+                             vmu->maxmsg, vmu->maxsecs, count_messages(vmu, dirname)
+#ifdef IMAP_STORAGE
+                             , vmu->imapuser
+#endif
+                       );
+       }               
+       astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
+
+       AST_LIST_UNLOCK(&users);
+
+       return RESULT_SUCCESS;
+}
+
 static int load_config(void)
 {
        struct ast_vm_user *cur;
@@ -7054,51 +7545,9 @@ static int load_config(void)
        struct ast_config *cfg, *ucfg;
        char *cat;
        struct ast_variable *var;
-       const char *notifystr = NULL;
-       const char *smdistr = NULL;
-       const char *astattach;
-       const char *astsearch;
-       const char *astsaycid;
-       const char *send_voicemail;
-#ifdef IMAP_STORAGE
-       const char *imap_server;
-       const char *imap_port;
-       const char *imap_flags;
-       const char *imap_folder;
-       const char *auth_user;
-       const char *auth_password;
-       const char *expunge_on_hangup;
-#endif
-       const char *astcallop;
-       const char *astreview;
-       const char *asttempgreetwarn;
-       const char *astskipcmd;
-       const char *asthearenv;
-       const char *astsaydurationinfo;
-       const char *astsaydurationminfo;
-       const char *silencestr;
-       const char *maxmsgstr;
-       const char *astdirfwd;
-       const char *thresholdstr;
-       const char *fmt;
-       const char *astemail;
-       const char *ucontext;
-       const char *astmailcmd = SENDMAIL;
-       const char *astforcename;
-       const char *astforcegreet;
+       const char *val;
        const char *s;
-       char *q,*stringp;
-       const char *dialoutcxt = NULL;
-       const char *callbackcxt = NULL; 
-       const char *exitcxt = NULL;     
-       const char *extpc;
-       const char *emaildateformatstr;
-       const char *volgainstr;
-       const char *vm_paswd;
-       const char *vm_newpasswd;
-       const char *vm_passchange;
-       const char *vm_reenterpass;
-       const char *vm_mism;
+       char *q, *stringp;
        int x;
        int tmpadsi[4];
 
@@ -7120,99 +7569,99 @@ static int load_config(void)
        if (cfg) {
                /* General settings */
 
-               if (!(ucontext = ast_variable_retrieve(cfg, "general", "userscontext")))
-                       ucontext = "default";
-               ast_copy_string(userscontext, ucontext, sizeof(userscontext));
+               if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
+                       val = "default";
+               ast_copy_string(userscontext, val, sizeof(userscontext));
                /* Attach voice message to mail message ? */
-               if (!(astattach = ast_variable_retrieve(cfg, "general", "attach"))) 
-                       astattach = "yes";
-               ast_set2_flag((&globalflags), ast_true(astattach), VM_ATTACH);  
+               if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
+                       val = "yes";
+               ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH);        
 
-               if (!(astsearch = ast_variable_retrieve(cfg, "general", "searchcontexts")))
-                       astsearch = "no";
-               ast_set2_flag((&globalflags), ast_true(astsearch), VM_SEARCH);
+               if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
+                       val = "no";
+               ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
 
                volgain = 0.0;
-               if ((volgainstr = ast_variable_retrieve(cfg, "general", "volgain")))
-                       sscanf(volgainstr, "%lf", &volgain);
+               if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
+                       sscanf(val, "%lf", &volgain);
 
 #ifdef ODBC_STORAGE
                strcpy(odbc_database, "asterisk");
-               if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
-                       ast_copy_string(odbc_database, thresholdstr, sizeof(odbc_database));
+               if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
+                       ast_copy_string(odbc_database, val, sizeof(odbc_database));
                }
                strcpy(odbc_table, "voicemessages");
-               if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbctable"))) {
-                       ast_copy_string(odbc_table, thresholdstr, sizeof(odbc_table));
+               if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
+                       ast_copy_string(odbc_table, val, sizeof(odbc_table));
                }
 #endif         
                /* Mail command */
                strcpy(mailcmd, SENDMAIL);
-               if ((astmailcmd = ast_variable_retrieve(cfg, "general", "mailcmd")))
-                       ast_copy_string(mailcmd, astmailcmd, sizeof(mailcmd)); /* User setting */
+               if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
+                       ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
 
                maxsilence = 0;
-               if ((silencestr = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
-                       maxsilence = atoi(silencestr);
+               if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
+                       maxsilence = atoi(val);
                        if (maxsilence > 0)
                                maxsilence *= 1000;
                }
                
-               if (!(maxmsgstr = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
+               if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
                        maxmsg = MAXMSG;
                } else {
-                       maxmsg = atoi(maxmsgstr);
+                       maxmsg = atoi(val);
                        if (maxmsg <= 0) {
-                               ast_log(LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", maxmsgstr, MAXMSG);
+                               ast_log(LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
                                maxmsg = MAXMSG;
                        } else if (maxmsg > MAXMSGLIMIT) {
-                               ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, maxmsgstr);
+                               ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
                                maxmsg = MAXMSGLIMIT;
                        }
                }
 
                /* Load date format config for voicemail mail */
-               if ((emaildateformatstr = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
-                       ast_copy_string(emaildateformat, emaildateformatstr, sizeof(emaildateformat));
+               if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
+                       ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
                }
 
                /* External password changing command */
-               if ((extpc = ast_variable_retrieve(cfg, "general", "externpass"))) {
-                       ast_copy_string(ext_pass_cmd,extpc,sizeof(ext_pass_cmd));
+               if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
+                       ast_copy_string(ext_pass_cmd,val,sizeof(ext_pass_cmd));
                        pwdchange = PWDCHANGE_EXTERNAL;
-               } else if ((extpc = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
-                       ast_copy_string(ext_pass_cmd,extpc,sizeof(ext_pass_cmd));
+               } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
+                       ast_copy_string(ext_pass_cmd,val,sizeof(ext_pass_cmd));
                        pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
                }
 
 #ifdef IMAP_STORAGE
                /* IMAP server address */
-               if ((imap_server = ast_variable_retrieve(cfg, "general", "imapserver"))) {
-                       ast_copy_string(imapserver, imap_server, sizeof(imapserver));
+               if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
+                       ast_copy_string(imapserver, val, sizeof(imapserver));
                } else {
                        ast_copy_string(imapserver,"localhost", sizeof(imapserver));
                }
                /* IMAP server port */
-               if ((imap_port = ast_variable_retrieve(cfg, "general", "imapport"))) {
-                       ast_copy_string(imapport, imap_port, sizeof(imapport));
+               if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
+                       ast_copy_string(imapport, val, sizeof(imapport));
                } else {
                        ast_copy_string(imapport,"143", sizeof(imapport));
                }
                /* IMAP server flags */
-               if ((imap_flags = ast_variable_retrieve(cfg, "general", "imapflags"))) {
-                       ast_copy_string(imapflags, imap_flags, sizeof(imapflags));
+               if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
+                       ast_copy_string(imapflags, val, sizeof(imapflags));
                }
                /* IMAP server master username */
-               if ((auth_user = ast_variable_retrieve(cfg, "general", "authuser"))) {
-                       ast_copy_string(authuser, auth_user, sizeof(authuser));
+               if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
+                       ast_copy_string(authuser, val, sizeof(authuser));
                }
                /* IMAP server master password */
-               if ((auth_password = ast_variable_retrieve(cfg, "general", "authpassword"))) {
-                       ast_copy_string(authpassword, auth_password, sizeof(authpassword));
+               if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
+                       ast_copy_string(authpassword, val, sizeof(authpassword));
                }
                /* Expunge on exit */
-               if ((expunge_on_hangup = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
-                       if(ast_false(expunge_on_hangup))
+               if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
+                       if(ast_false(val))
                                expungeonhangup = 0;
                        else
                                expungeonhangup = 1;
@@ -7220,73 +7669,93 @@ static int load_config(void)
                        expungeonhangup = 1;
                }
                /* IMAP voicemail folder */
-               if ((imap_folder = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
-                       ast_copy_string(imapfolder, imap_folder, sizeof(imapfolder));
+               if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
+                       ast_copy_string(imapfolder, val, sizeof(imapfolder));
                } else {
                        ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder));
                }
 #endif
                /* External voicemail notify application */
-               
-               if ((notifystr = ast_variable_retrieve(cfg, "general", "externnotify"))) {
-                       ast_copy_string(externnotify, notifystr, sizeof(externnotify));
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "found externnotify: %s\n", externnotify);
-                       if (!strcasecmp(externnotify, "smdi")) {
-                               if (option_debug)
-                                       ast_log(LOG_DEBUG, "Using SMDI for external voicemail notification\n");
-                               if ((smdistr = ast_variable_retrieve(cfg, "general", "smdiport"))) {
-                                       smdi_iface = ast_smdi_interface_find(smdistr);
-                               } else {
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "No SMDI interface set, trying default (/dev/ttyS0)\n");
-                                       smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
-                               }
-
-                               if (!smdi_iface) {
-                                       ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling external voicemail notification\n");
-                                       externnotify[0] = '\0';
-                               } else {
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "Using SMDI port %s\n", smdi_iface->name);
-                               }
-                       }
+               if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
+                       ast_copy_string(externnotify, val, sizeof(externnotify));
+                       ast_debug(1, "found externnotify: %s\n", externnotify);
                } else {
                        externnotify[0] = '\0';
                }
 
+               /* SMDI voicemail notification */
+               if ((s = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(s)) {
+                       ast_debug(1, "Enabled SMDI voicemail notification\n");
+                       if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
+                               smdi_iface = ast_smdi_interface_find(val);
+                       } else {
+                               ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
+                               smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
+                       }
+                       if (!smdi_iface) {
+                               ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
+                       } else {
+                               ast_debug(1, "Using SMDI port %s\n", smdi_iface->name);
+                       }
+               }
+
                /* Silence treshold */
                silencethreshold = 256;
-               if ((thresholdstr = ast_variable_retrieve(cfg, "general", "silencethreshold")))
-                       silencethreshold = atoi(thresholdstr);
+               if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
+                       silencethreshold = atoi(val);
                
-               if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail"))) 
-                       astemail = ASTERISK_USERNAME;
-               ast_copy_string(serveremail, astemail, sizeof(serveremail));
+               if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
+                       val = ASTERISK_USERNAME;
+               ast_copy_string(serveremail, val, sizeof(serveremail));
                
-               vmmaxmessage = 0;
-               if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
+               vmmaxsecs = 0;
+               if ((s = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
+                       if (sscanf(s, "%d", &x) == 1) {
+                               vmmaxsecs = x;
+                       } else {
+                               ast_log(LOG_WARNING, "Invalid max message time length\n");
+                       }
+               } else if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
+                       static int maxmessage_deprecate = 0;
+                       if (maxmessage_deprecate == 0) {
+                               maxmessage_deprecate = 1;
+                               ast_log(LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
+                       }
                        if (sscanf(s, "%d", &x) == 1) {
-                               vmmaxmessage = x;
+                               vmmaxsecs = x;
                        } else {
                                ast_log(LOG_WARNING, "Invalid max message time length\n");
                        }
                }
 
-               vmminmessage = 0;
-               if ((s = ast_variable_retrieve(cfg, "general", "minmessage"))) {
+               vmminsecs = 0;
+               if ((s = ast_variable_retrieve(cfg, "general", "minsecs"))) {
+                       if (sscanf(s, "%d", &x) == 1) {
+                               vmminsecs = x;
+                               if (maxsilence <= vmminsecs)
+                                       ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
+                       } else {
+                               ast_log(LOG_WARNING, "Invalid min message time length\n");
+                       }
+               } else if ((s = ast_variable_retrieve(cfg, "general", "minmessage"))) {
+                       static int maxmessage_deprecate = 0;
+                       if (maxmessage_deprecate == 0) {
+                               maxmessage_deprecate = 1;
+                               ast_log(LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
+                       }
                        if (sscanf(s, "%d", &x) == 1) {
-                               vmminmessage = x;
-                               if (maxsilence <= vmminmessage)
+                               vmminsecs = x;
+                               if (maxsilence <= vmminsecs)
                                        ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
                        } else {
                                ast_log(LOG_WARNING, "Invalid min message time length\n");
                        }
                }
-               fmt = ast_variable_retrieve(cfg, "general", "format");
-               if (!fmt)
-                       fmt = "wav";    
-               ast_copy_string(vmfmts, fmt, sizeof(vmfmts));
+
+               val = ast_variable_retrieve(cfg, "general", "format");
+               if (!val)
+                       val = "wav";    
+               ast_copy_string(vmfmts, val, sizeof(vmfmts));
 
                skipms = 3000;
                if ((s = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
@@ -7315,18 +7784,17 @@ static int load_config(void)
                }
 
                /* Force new user to record name ? */
-               if (!(astforcename = ast_variable_retrieve(cfg, "general", "forcename"))) 
-                       astforcename = "no";
-               ast_set2_flag((&globalflags), ast_true(astforcename), VM_FORCENAME);
+               if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
+                       val = "no";
+               ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
 
                /* Force new user to record greetings ? */
-               if (!(astforcegreet = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
-                       astforcegreet = "no";
-               ast_set2_flag((&globalflags), ast_true(astforcegreet), VM_FORCEGREET);
+               if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
+                       val = "no";
+               ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
 
                if ((s = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))){
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"VM_CID Internal context string: %s\n",s);
+                       ast_debug(1,"VM_CID Internal context string: %s\n",s);
                        stringp = ast_strdupa(s);
                        for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
                                if (!ast_strlen_zero(stringp)) {
@@ -7334,121 +7802,121 @@ static int load_config(void)
                                        while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
                                                q++;
                                        ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
+                                       ast_debug(1,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
                                } else {
                                        cidinternalcontexts[x][0] = '\0';
                                }
                        }
                }
-               if (!(astreview = ast_variable_retrieve(cfg, "general", "review"))){
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"VM Review Option disabled globally\n");
-                       astreview = "no";
+               if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
+                       ast_debug(1,"VM Review Option disabled globally\n");
+                       val = "no";
                }
-               ast_set2_flag((&globalflags), ast_true(astreview), VM_REVIEW);  
+               ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW);        
 
                /*Temporary greeting reminder */
-               if (!(asttempgreetwarn = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "VM Temporary Greeting Reminder Option disabled globally\n");
-                       asttempgreetwarn = "no";
+               if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
+                       ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
+                       val = "no";
                } else {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "VM Temporary Greeting Reminder Option enabled globally\n");
+                       ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
                }
-               ast_set2_flag((&globalflags), ast_true(asttempgreetwarn), VM_TEMPGREETWARN);
+               ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
 
-               if (!(astcallop = ast_variable_retrieve(cfg, "general", "operator"))){
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"VM Operator break disabled globally\n");
-                       astcallop = "no";
+               if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
+                       ast_debug(1,"VM Operator break disabled globally\n");
+                       val = "no";
                }
-               ast_set2_flag((&globalflags), ast_true(astcallop), VM_OPERATOR);        
+               ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);      
 
-               if (!(astsaycid = ast_variable_retrieve(cfg, "general", "saycid"))) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"VM CID Info before msg disabled globally\n");
-                       astsaycid = "no";
+               if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
+                       ast_debug(1,"VM CID Info before msg disabled globally\n");
+                       val = "no";
                } 
-               ast_set2_flag((&globalflags), ast_true(astsaycid), VM_SAYCID);  
+               ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID);        
 
-               if (!(send_voicemail = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"Send Voicemail msg disabled globally\n");
-                       send_voicemail = "no";
+               if (!(val = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
+                       ast_debug(1,"Send Voicemail msg disabled globally\n");
+                       val = "no";
                }
-               ast_set2_flag((&globalflags), ast_true(send_voicemail), VM_SVMAIL);
+               ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
        
-               if (!(asthearenv = ast_variable_retrieve(cfg, "general", "envelope"))) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"ENVELOPE before msg enabled globally\n");
-                       asthearenv = "yes";
+               if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
+                       ast_debug(1,"ENVELOPE before msg enabled globally\n");
+                       val = "yes";
                }
-               ast_set2_flag((&globalflags), ast_true(asthearenv), VM_ENVELOPE);       
+               ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);      
 
-               if (!(astsaydurationinfo = ast_variable_retrieve(cfg, "general", "sayduration"))) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"Duration info before msg enabled globally\n");
-                       astsaydurationinfo = "yes";
+               if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
+                       ast_debug(1,"Duration info before msg enabled globally\n");
+                       val = "yes";
                }
-               ast_set2_flag((&globalflags), ast_true(astsaydurationinfo), VM_SAYDURATION);    
+               ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);   
 
                saydurationminfo = 2;
-               if ((astsaydurationminfo = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
-                       if (sscanf(astsaydurationminfo, "%d", &x) == 1) {
+               if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
+                       if (sscanf(val, "%d", &x) == 1) {
                                saydurationminfo = x;
                        } else {
                                ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
                        }
                }
 
-               if (!(astskipcmd = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG,"We are not going to skip to the next msg after save/delete\n");
-                       astskipcmd = "no";
+               if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
+                       ast_debug(1,"We are not going to skip to the next msg after save/delete\n");
+                       val = "no";
                }
-               ast_set2_flag((&globalflags), ast_true(astskipcmd), VM_SKIPAFTERCMD);
+               ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
 
-               if ((dialoutcxt = ast_variable_retrieve(cfg, "general", "dialout"))) {
-                       ast_copy_string(dialcontext, dialoutcxt, sizeof(dialcontext));
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "found dialout context: %s\n", dialcontext);
+               if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
+                       ast_copy_string(dialcontext, val, sizeof(dialcontext));
+                       ast_debug(1, "found dialout context: %s\n", dialcontext);
                } else {
                        dialcontext[0] = '\0';  
                }
                
-               if ((callbackcxt = ast_variable_retrieve(cfg, "general", "callback"))) {
-                       ast_copy_string(callcontext, callbackcxt, sizeof(callcontext));
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "found callback context: %s\n", callcontext);
+               if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
+                       ast_copy_string(callcontext, val, sizeof(callcontext));
+                       ast_debug(1, "found callback context: %s\n", callcontext);
                } else {
                        callcontext[0] = '\0';
                }
 
-               if ((exitcxt = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
-                       ast_copy_string(exitcontext, exitcxt, sizeof(exitcontext));
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "found operator context: %s\n", exitcontext);
+               if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
+                       ast_copy_string(exitcontext, val, sizeof(exitcontext));
+                       ast_debug(1, "found operator context: %s\n", exitcontext);
                } else {
                        exitcontext[0] = '\0';
                }
                
                /* load password sounds configuration */
-               if ((vm_paswd = ast_variable_retrieve(cfg, "general", "vm-password")))
-                       ast_copy_string(vm_password, vm_paswd, sizeof(vm_password));
-               if ((vm_newpasswd = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
-                       ast_copy_string(vm_newpassword, vm_newpasswd, sizeof(vm_newpassword));
-               if ((vm_passchange = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
-                       ast_copy_string(vm_passchanged, vm_passchange, sizeof(vm_passchanged));
-               if ((vm_reenterpass = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
-                       ast_copy_string(vm_reenterpassword, vm_reenterpass, sizeof(vm_reenterpassword));
-               if ((vm_mism = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
-                       ast_copy_string(vm_mismatch, vm_mism, sizeof(vm_mismatch));
-
-               if (!(astdirfwd = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
-                       astdirfwd = "no";
-               ast_set2_flag((&globalflags), ast_true(astdirfwd), VM_DIRECFORWARD);    
+               if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
+                       ast_copy_string(vm_password, val, sizeof(vm_password));
+               if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
+                       ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
+               if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
+                       ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
+               if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
+                       ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
+               if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
+                       ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
+
+               if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
+                       val = "no";
+               ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD);  
+
+               poll_freq = DEFAULT_POLL_FREQ;
+               if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
+                       if (sscanf(val, "%u", &poll_freq) != 1) {
+                               poll_freq = DEFAULT_POLL_FREQ;
+                               ast_log(LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
+                       }
+               }
+
+               poll_mailboxes = 0;
+               if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
+                       poll_mailboxes = ast_true(val);
+
                if ((ucfg = ast_config_load("users.conf"))) {   
                        for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
                                if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
@@ -7488,10 +7956,9 @@ static int load_config(void)
                                                                AST_LIST_UNLOCK(&zones);
                                                        } else {
                                                                ast_log(LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
-                                                               free(z);
+                                                               ast_free(z);
                                                        }
                                                } else {
-                                                       free(z);
                                                        AST_LIST_UNLOCK(&users);
                                                        ast_config_destroy(cfg);
                                                        return -1;
@@ -7502,24 +7969,24 @@ static int load_config(void)
                        }
                        cat = ast_category_browse(cfg, cat);
                }
-               memset(fromstring,0,sizeof(fromstring));
+               memset(fromstring, 0, sizeof(fromstring));
                memset(pagerfromstring,0,sizeof(pagerfromstring));
                memset(emailtitle,0,sizeof(emailtitle));
                strcpy(charset, "ISO-8859-1");
                if (emailbody) {
-                       free(emailbody);
+                       ast_free(emailbody);
                        emailbody = NULL;
                }
                if (emailsubject) {
-                       free(emailsubject);
+                       ast_free(emailsubject);
                        emailsubject = NULL;
                }
                if (pagerbody) {
-                       free(pagerbody);
+                       ast_free(pagerbody);
                        pagerbody = NULL;
                }
                if (pagersubject) {
-                       free(pagersubject);
+                       ast_free(pagersubject);
                        pagersubject = NULL;
                }
                if ((s = ast_variable_retrieve(cfg, "general", "pbxskip")))
@@ -7608,56 +8075,67 @@ static int load_config(void)
                }
                AST_LIST_UNLOCK(&users);
                ast_config_destroy(cfg);
+
+               if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
+                       start_poll_thread();
+               if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
+                       stop_poll_thread();;
+
                return 0;
        } else {
                AST_LIST_UNLOCK(&users);
-               ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
+               ast_log(LOG_WARNING, "Failed to load configuration file.\n");
                return 0;
        }
 }
 
 static int reload(void)
 {
-       return(load_config());
+       return load_config();
 }
 
 static int unload_module(void)
 {
        int res;
-       
+
        res = ast_unregister_application(app);
        res |= ast_unregister_application(app2);
        res |= ast_unregister_application(app3);
        res |= ast_unregister_application(app4);
        res |= ast_custom_function_unregister(&mailbox_exists_acf);
+       res |= ast_manager_unregister("VoicemailUsersList");
        ast_cli_unregister_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
        ast_uninstall_vm_functions();
        
        ast_module_user_hangup_all();
 
+       if (poll_thread != AST_PTHREADT_NULL)
+               stop_poll_thread();
+
        return res;
 }
 
 static int load_module(void)
 {
        int res;
+
+       /* compute the location of the voicemail spool directory */
+       snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
+
+       if ((res = load_config()))
+               return res;
+
        res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
        res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
        res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
        res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
        res |= ast_custom_function_register(&mailbox_exists_acf);
+       res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL, manager_list_voicemail_users, "List All Voicemail User Information");
        if (res)
-               return(res);
-
-       if ((res=load_config())) {
-               return(res);
-       }
+               return res;
 
        ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
 
-       /* compute the location of the voicemail spool directory */
-       snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
-
        ast_install_vm_functions(has_voicemail, inboxcount, messagecount);
 
        return res;
@@ -7728,10 +8206,11 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
 {
        int res = 0;
 #ifdef IMAP_STORAGE
-       char origtimeS[256],cidS[256],contextS[256];
-       char *header_content,*temp;
+       char origtimeS[256], cidS[256], contextS[256];
+       char *header_content, *temp;
+       char buf[1024];
 #endif
-       char filename[256];
+       char filename[PATH_MAX];
        struct ast_config *msg_cfg = NULL;
        const char *origtime, *context;
        char *cid, *name, *num;
@@ -7740,42 +8219,37 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
        vms->starting = 0; 
 #ifdef IMAP_STORAGE
        /* START HERE */
+
        /* get the message info!! */
-       if(option_debug > 2)
-               ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
-       if (vms->msgArray[vms->curmsg] == 0) {
-               ast_log (LOG_WARNING,"Trying to access unknown message\n");
+       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]);
+       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!! */
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:");
        
-       if (temp)
-               ast_copy_string(cidS,temp, sizeof(cidS));
+       /* Get info from headers!! */
+       if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:", buf, sizeof(buf))))
+               ast_copy_string(cidS, temp, sizeof(cidS));
        else
                cidS[0] = '\0';
        
        cid = &cidS[0];
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:");
-       
-       if (temp)
+
+       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];
-       temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:");
-       
-       if (temp)
+
+       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';
@@ -7924,7 +8398,8 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
                        ast_config_destroy(msg_cfg);
                        return res;
                } else {
-                       if (find_user(NULL, vmu->context, num)) {
+                       struct ast_vm_user vmu2;
+                       if (find_user(&vmu2, vmu->context, num)) {
                                struct leave_vm_options leave_options;
                                char mailbox[AST_MAX_EXTENSION * 2 + 2];
                                snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
@@ -7968,7 +8443,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
 
 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
                        int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
-                       signed char record_gain)
+                       signed char record_gain, struct vm_state *vms)
 {
        /* Record message & let caller review or re-record it, or set options if applicable */
        int res = 0;
@@ -7978,6 +8453,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
        int recorded = 0;
        int message_exists = 0;
        signed char zero_gain = 0;
+       char tempfile[PATH_MAX];
        char *acceptdtmf = "#";
        char *canceldtmf = "";
 
@@ -7989,6 +8465,11 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
                return -1;
        }
 
+       if (!outsidecaller)
+               snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
+       else
+               ast_copy_string(tempfile, recordfile, sizeof(tempfile));
+
        cmd = '3';  /* Want to start by recording */
 
        while ((cmd >= 0) && (cmd != 't')) {
@@ -8002,7 +8483,13 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
                                /* Otherwise 1 is to save the existing message */
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Saving message as is\n");
+                               if (!outsidecaller)
+                                       ast_filerename(tempfile, recordfile, NULL);
                                ast_stream_and_wait(chan, "vm-msgsaved", "");
+                               if (!outsidecaller) {
+                                       STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms);
+                                       DISPOSE(recordfile, -1);
+                               }
                                cmd = 't';
                                return res;
                        }
@@ -8010,7 +8497,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
                        /* Review */
                        if (option_verbose > 2)
                                ast_verbose(VERBOSE_PREFIX_3 "Reviewing the message\n");
-                       cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
+                       cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
                        break;
                case '3':
                        message_exists = 0;
@@ -8032,11 +8519,15 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
                                ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
                        if (ast_test_flag(vmu, VM_OPERATOR))
                                canceldtmf = "0";
-                       cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
+                       cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
                        if (record_gain)
                                ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
                        if (cmd == -1) {
-                       /* User has hung up, no options to give */
+                               /* User has hung up, no options to give */
+                               if (!outsidecaller) {
+                                       /* user was recording a greeting and they hung up, so let's delete the recording. */
+                                       vm_delete(tempfile);
+                               }
                                return cmd;
                        }
                        if (cmd == '0') {
@@ -8050,14 +8541,14 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Message too short\n");
                                cmd = ast_play_and_wait(chan, "vm-tooshort");
-                               cmd = vm_delete(recordfile);
+                               cmd = vm_delete(tempfile);
                                break;
                        }
                        else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
                                /* Message is all silence */
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Nothing recorded\n");
-                               cmd = vm_delete(recordfile);
+                               cmd = vm_delete(tempfile);
                                cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
                                if (!cmd)
                                        cmd = ast_play_and_wait(chan, "vm-speakup");
@@ -8086,7 +8577,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
                case '*':
                        /* Cancel recording, delete message, offer to take another message*/
                        cmd = ast_play_and_wait(chan, "vm-deleted");
-                       cmd = vm_delete(recordfile);
+                       cmd = vm_delete(tempfile);
                        if (outsidecaller) {
                                res = vm_exec(chan, NULL);
                                return res;
@@ -8168,19 +8659,19 @@ static void write_file(char *filename, char *buffer, unsigned long len)
 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");
+       char *mailbox = stream->mailbox, buf[1024] = "", *user;
+
+       if (!(user = get_user_by_mailbox(mailbox, buf, sizeof(buf))))
+               return;
+
+       if (!(vms = get_vm_state_by_imapuser(user, 2))) {
+               ast_log(LOG_ERROR, "No state found.\n");
+               return;
        }
+       
+       ast_debug(3, "saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vms->vmArrayIndex, vms->interactive);
+
+       vms->msgArray[vms->vmArrayIndex++] = number;
 }
 
 
@@ -8350,13 +8841,34 @@ static void status(MAILSTREAM *stream)
 }
 #endif
 
+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! */
-       if(option_debug > 3)
-               ast_log (LOG_DEBUG, "Entering EXISTS callback for message %ld\n", number);
+       ast_debug(4, "Entering EXISTS callback for message %ld\n", number);
        if (number == 0) return;
        set_update(stream);
 }
@@ -8365,8 +8877,7 @@ void mm_exists(MAILSTREAM * stream, unsigned long number)
 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);
+       ast_debug(4, "Entering EXPUNGE callback for message %ld\n", number);
        if (number == 0) return;
        set_update(stream);
 }
@@ -8375,8 +8886,7 @@ void mm_expunged(MAILSTREAM * stream, unsigned long number)
 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);
+       ast_debug(4, "Entering FLAGS callback for message %ld\n", number);
        if (number == 0) return;
        set_update(stream);
 }
@@ -8395,33 +8905,30 @@ void mm_list(MAILSTREAM * stream, int delim, char *mailbox, long attributes)
                delimiter = delim;
                ast_mutex_unlock(&delimiter_lock);
        }
-       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");
-       }
+
+       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)
 {
-       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");
-       }
+       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");
 }
 
 
@@ -8446,8 +8953,7 @@ void mm_log(char *string, long errflg)
 {
        switch ((short) errflg) {
                case NIL:
-                       if(option_debug)
-                               ast_log(LOG_DEBUG,"IMAP Info: %s\n", string);
+                       ast_debug(1,"IMAP Info: %s\n", string);
                        break;
                case PARSE:
                case WARN:
@@ -8470,20 +8976,26 @@ 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,sizeof(user));
+       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, sizeof(pwd));
+               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, sizeof(pwd));
+                               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);
+                       }
+               }
        }
 }
 
@@ -8514,10 +9026,9 @@ void mm_fatal(char *string)
 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;
+       char *mailbox = stream->mailbox, *user;
+       char buf[1024] = "";
+       unsigned long usage = 0, limit = 0;
        
        while (pquota) {
                usage = pquota->usage;
@@ -8525,72 +9036,62 @@ static void mm_parsequota(MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pqu
                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");
+       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)
+static char *get_header_by_tag(char *header, char *tag, char *buf, size_t len)
 {
-       char *start;
+       char *start, *eol_pnt;
        int taglen;
-       char *eol_pnt;
 
-       if (!header || !tag)
+       if (ast_strlen_zero(header) || ast_strlen_zero(tag))
                return NULL;
 
        taglen = strlen(tag) + 1;
        if (taglen < 1)
                return NULL;
 
-       start = strstr(header, tag);
-       if (!start)
+       if (!(start = strstr(header, tag)))
                return NULL;
 
-       ast_mutex_lock(&imaptemp_lock);
-       ast_copy_string(imaptemp, start+taglen, sizeof(imaptemp));
-       ast_mutex_unlock(&imaptemp_lock);
-       eol_pnt = strchr(imaptemp,'\n');
+       /* Since we can be called multiple times we should clear our buffer */
+       memset(buf, 0, len);
+
+       ast_copy_string(buf, start+taglen, len);
+       eol_pnt = strchr(buf,'\n');
        *eol_pnt = '\0';
-       return imaptemp;
+       return buf;
 }
 
-static char *get_user_by_mailbox(char *mailbox)
+static char *get_user_by_mailbox(char *mailbox, char *buf, size_t len)
 {
-       char *start, *quote;
-       char *eol_pnt;
+       char *start, *quote, *eol_pnt;
 
-       if (!mailbox)
+       if (ast_strlen_zero(mailbox))
                return NULL;
 
-       start = strstr(mailbox,"user=");
-       if (!start)
+       if (!(start = strstr(mailbox, "user=")))
                return NULL;
 
-       ast_mutex_lock(&imaptemp_lock);
-       ast_copy_string(imaptemp, start+5, sizeof(imaptemp));
-       ast_mutex_unlock(&imaptemp_lock);
+       ast_copy_string(buf, start+5, len);
 
-       quote = strchr(imaptemp,'\"');
-       if (!quote) {  /* if username is not in quotes */
-               eol_pnt = strchr(imaptemp,'/');
-               if (!eol_pnt) {
-                       eol_pnt = strchr(imaptemp,'}');
-               }
+       if (!(quote = strchr(buf, '\"'))) {
+               if (!(eol_pnt = strchr(buf, '/')))
+                       eol_pnt = strchr(buf,'}');
                *eol_pnt = '\0';
-               return imaptemp;
+               return buf;
        } else {
-               eol_pnt = strchr(imaptemp+1,'\"');
+               eol_pnt = strchr(buf+1,'\"');
                *eol_pnt = '\0';
-               return imaptemp+1;
+               return buf+1;
        }
 }
 
@@ -8598,61 +9099,51 @@ static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
 {
        struct vmstate *vlist = NULL;
 
-       vlist = vmstates;
-       while (vlist) {
-               if (vlist->vms) {
-                       if (vlist->vms->imapuser) {
-                               if (!strcmp(vlist->vms->imapuser,user)) {
-                                       if (interactive == 2) {
-                                               return vlist->vms;
-                                       } else if (vlist->vms->interactive == interactive) {
-                                               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);
+       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;
                }
-               vlist = vlist->next;
+
+               if (interactive == 2)
+                       return vlist->vms;
+               else if (vlist->vms->interactive == interactive)
+                       return vlist->vms;
        }
-       if(option_debug > 2)
-               ast_log(LOG_DEBUG, "%s not found in vmstates\n",user);
+
+       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;
-       
-       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");
-                                       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);
+
+       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");
+                       return vlist->vms;
                }
-               vlist = vlist->next;
        }
-       if(option_debug > 2)
-               ast_log(LOG_DEBUG, "%s not found in vmstates\n",mailbox);
+
+       ast_debug(3, "%s not found in vmstates\n", mailbox);
+
        return NULL;
 }
 
@@ -8667,17 +9158,14 @@ static void vmstate_insert(struct vm_state *vms)
        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);
+                       ast_debug(3, "Duplicate mailbox %s, copying message info...\n",vms->username);
                        vms->newmessages = altvms->newmessages;
                        vms->oldmessages = altvms->oldmessages;
-                       if(option_debug > 2)
-                               ast_log(LOG_DEBUG, "check_msgArray before memcpy\n");
+                       ast_debug(3, "check_msgArray before memcpy\n");
                        check_msgArray(vms);
                        /* memcpy(vms->msgArray, altvms->msgArray, sizeof(long)*256); */
                        copy_msgArray(vms, altvms);
-                       if(option_debug > 2)
-                               ast_log(LOG_DEBUG, "check_msgArray after memcpy\n");
+                       ast_debug(3, "check_msgArray after memcpy\n");
                        check_msgArray(vms);
                        vms->vmArrayIndex = altvms->vmArrayIndex;
                        vms->lastmsg = altvms->lastmsg;
@@ -8690,78 +9178,65 @@ static void vmstate_insert(struct vm_state *vms)
                }
        }
 
-       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);
+       if (!(v = ast_calloc(1, sizeof(*v))))
+               return;
+       
        v->vms = vms;
-       v->next = vmstates;
-       vmstates = v;
-       ast_mutex_unlock(&vmstate_lock);
+
+       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, *vf = NULL, *vl = NULL;
-       struct vm_state *altvms;
+       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;
-               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 = 2;
-               }
+       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 = 2;
        }
-
-       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) {
+       
+       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) {
-                       vf = vc;
-                       if (vl)
-                               vl->next = vc->next;
-                       else
-                               vmstates = vc->next;
+                       AST_LIST_REMOVE_CURRENT(&vmstates, list);
                        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 {
-               free(vf);
        }
-       ast_mutex_unlock(&vmstate_lock);
+       AST_LIST_TRAVERSE_SAFE_END
+       AST_LIST_UNLOCK(&vmstates);
+       
+       if (vc)
+               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;
-       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 = 2; /* set updated flag since mailbox changed */
-       } else {
-               if(option_debug > 2)
-                       ast_log (LOG_WARNING, "User %s mailbox not found for update.\n",user);
+       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 = 2; /* Set updated flag since mailbox changed */
 }
 
 static void init_vm_state(struct vm_state *vms) 
@@ -8778,8 +9253,7 @@ static void check_msgArray(struct vm_state *vms)
        int x;
        for (x = 0; x<256; x++) {
                if (vms->msgArray[x]!=0) {
-                       if(option_debug)
-                               ast_log (LOG_DEBUG, "Item %d set to %ld\n",x,vms->msgArray[x]);
+                       ast_debug(1, "Item %d set to %ld\n",x,vms->msgArray[x]);
                }
        }
 }
@@ -8806,7 +9280,7 @@ static int save_body(BODY *body, struct vm_state *vms, char *section, char *form
        body_content = mail_fetchbody (vms->mailstream, vms->msgArray[vms->curmsg], section, &len);
        if (body_content != NIL) {
                sprintf(filename,"%s.%s", vms->fn, format);
-               /* ast_log (LOG_DEBUG,body_content); */
+               /* ast_debug(1,body_content); */
                body_decoded = rfc822_base64 ((unsigned char *)body_content, len, &newlen);
                write_file (filename, (char *) body_decoded, newlen);
        }