Merge in ast_strftime branch, which changes timestamps to be accurate to the microsec...
[asterisk/asterisk.git] / apps / app_voicemail.c
index a33d9a7..4c051dc 100644 (file)
@@ -370,7 +370,7 @@ struct ast_vm_user {
        char uniqueid[20];               /*!< Unique integer identifier */
        char exit[80];
        char attachfmt[20];              /*!< Attachment format */
-       unsigned int flags;              /*!< VM_ flags */      
+       uint64_t 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 */
@@ -495,7 +495,7 @@ static char *descrip_vm =
        "           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";
+       "    u    - Play the 'unavailable' greeting.\n";
 
 static char *synopsis_vmain = "Check Voicemail messages";
 
@@ -619,9 +619,9 @@ static struct ast_flags globalflags = {0};
 
 static int saydurationminfo;
 
-static char dialcontext[AST_MAX_CONTEXT];
-static char callcontext[AST_MAX_CONTEXT];
-static char exitcontext[AST_MAX_CONTEXT];
+static char dialcontext[AST_MAX_CONTEXT] = "";
+static char callcontext[AST_MAX_CONTEXT] = "";
+static char exitcontext[AST_MAX_CONTEXT] = "";
 
 static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64];
 
@@ -665,12 +665,9 @@ static void populate_defaults(struct ast_vm_user *vmu)
        ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);     
        if (saydurationminfo)
                vmu->saydurationm = saydurationminfo;
-       if (callcontext)
-               ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
-       if (dialcontext)
-               ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
-       if (exitcontext)
-               ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
+       ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
+       ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
+       ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
        if (vmmaxsecs)
                vmu->maxsecs = vmmaxsecs;
        if (maxmsg)
@@ -1967,10 +1964,10 @@ static char *quote(const char *from, char *to, size_t len)
  * fill in *tm for current time according to the proper timezone, if any.
  * Return tm so it can be used as a function argument.
  */
-static const struct tm *vmu_tm(const struct ast_vm_user *vmu, struct tm *tm)
+static const struct ast_tm *vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
 {
        const struct vm_zone *z = NULL;
-       time_t t = time(NULL);
+       struct timeval t = ast_tvnow();
 
        /* Does this user have a timezone specified? */
        if (!ast_strlen_zero(vmu->zonetag)) {
@@ -2010,7 +2007,7 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
        char fname[256];
        char dur[256];
        char tmpcmd[256];
-       struct tm tm;
+       struct ast_tm tm;
        char *passdata2;
        size_t len_passdata;
        char *greeting_attachment;
@@ -2032,11 +2029,11 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
                *greeting_attachment++ = '\0';
 
        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));
+       ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
        fprintf(p, "Date: %s" ENDL, date);
 
        /* Set date format for voicemail mail */
-       strftime(date, sizeof(date), emaildateformat, &tm);
+       ast_strftime(date, sizeof(date), emaildateformat, &tm);
 
        if (!ast_strlen_zero(fromstring)) {
                struct ast_channel *ast;
@@ -2193,7 +2190,7 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
        }
        if (!strcmp(format, "wav49"))
                format = "WAV";
-       ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
+       ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %lld\n", attach, format, attach_user_voicemail, (unsigned long long)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) {
@@ -2217,7 +2214,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
        char dur[PATH_MAX];
        char tmp[80] = "/tmp/astmail-XXXXXX";
        char tmp2[PATH_MAX];
-       struct tm tm;
+       struct ast_tm tm;
        FILE *p;
 
        if ((p = vm_mkftemp(tmp)) == NULL) {
@@ -2230,7 +2227,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
        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));
+       ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
        fprintf(p, "Date: %s\n", date);
 
        if (*pagerfromstring) {
@@ -2269,7 +2266,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
        } else
                fprintf(p, "Subject: New VM\n\n");
 
-       strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
+       ast_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))) {
@@ -2296,11 +2293,10 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
 
 static int get_date(char *s, int len)
 {
-       struct tm tm;
-       time_t t;
-       t = time(0);
+       struct ast_tm tm;
+       struct timeval t = ast_tvnow();
        ast_localtime(&t, &tm, NULL);
-       return strftime(s, len, "%a %b %e %r %Z %Y", &tm);
+       return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
 }
 
 static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
@@ -2991,7 +2987,7 @@ static void run_externnotify(char *context, char *extension)
 }
 
 struct leave_vm_options {
-       unsigned int flags;
+       uint64_t flags;
        signed char record_gain;
 };
 
@@ -4176,6 +4172,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
        char *temp;
        char todir[256];
        int todircount=0;
+       struct vm_state *dstvms;
 #endif
        char username[70]="";
        int res = 0, cmd = 0;
@@ -4366,7 +4363,19 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
                                /* should not assume "fmt" here! */
                                save_body(body,vms,"2",fmt);
  
-                               STORE(todir, vmtmp->mailbox, vmtmp->context, vms->curmsg, chan, vmtmp, fmt, duration, vms);
+                               /* get destination mailbox */
+                               dstvms = get_vm_state_by_mailbox(vmtmp->mailbox,0);
+                               if (dstvms) {
+                                       init_mailstream(dstvms, 0);
+                                       if (!dstvms->mailstream) {
+                                               ast_log (LOG_ERROR,"IMAP mailstream for %s is NULL\n",vmtmp->mailbox);
+                                       } else {
+                                               STORE(todir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms);
+                                               run_externnotify(vmtmp->context, vmtmp->mailbox); 
+                                       }
+                               } else {
+                                       ast_log (LOG_ERROR,"Could not find state information for mailbox %s\n",vmtmp->mailbox);
+                               }
 
                                if (!ast_strlen_zero(vmtmp->serveremail))
                                        myserveremail = vmtmp->serveremail;
@@ -4462,8 +4471,7 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v
        /* Set the DIFF_* variables */
        ast_localtime(&t, &time_now, NULL);
        tv_now = ast_tvnow();
-       tnow = tv_now.tv_sec;
-       ast_localtime(&tnow, &time_then, NULL);
+       ast_localtime(&tv_now, &time_then, NULL);
 
        /* Day difference */
        if (time_now.tm_year == time_then.tm_year)
@@ -6714,7 +6722,6 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        int res=-1;
        int cmd=0;
        int valid = 0;
-       struct ast_module_user *u;
        char prefixstr[80] ="";
        char ext_context[256]="";
        int box;
@@ -6731,7 +6738,6 @@ static int vm_execmain(struct ast_channel *chan, void *data)
 #ifdef IMAP_STORAGE
        int deleted = 0;
 #endif
-       u = ast_module_user_add(chan);
 
        /* Add the vm_state to the active list and keep it active */
        memset(&vms, 0, sizeof(vms));
@@ -6757,16 +6763,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
                AST_STANDARD_APP_ARGS(args, parse);
 
                if (args.argc == 2) {
-                       if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
-                               ast_module_user_remove(u);
+                       if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
                                return -1;
-                       }
                        if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
                                int gain;
                                if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
                                        if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
                                                ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
-                                               ast_module_user_remove(u);
                                                return -1;
                                        } else {
                                                record_gain = (signed char) gain;
@@ -7256,7 +7259,6 @@ out:
                free(vms.deleted);
        if (vms.heard)
                free(vms.heard);
-       ast_module_user_remove(u);
 
        return res;
 }
@@ -7264,7 +7266,6 @@ out:
 static int vm_exec(struct ast_channel *chan, void *data)
 {
        int res = 0;
-       struct ast_module_user *u;
        char *tmp;
        struct leave_vm_options leave_options;
        struct ast_flags flags = { 0 };
@@ -7273,8 +7274,6 @@ static int vm_exec(struct ast_channel *chan, void *data)
                AST_APP_ARG(argv0);
                AST_APP_ARG(argv1);
        );
-
-       u = ast_module_user_add(chan);
        
        memset(&leave_options, 0, sizeof(leave_options));
 
@@ -7285,17 +7284,14 @@ static int vm_exec(struct ast_channel *chan, void *data)
                tmp = ast_strdupa(data);
                AST_STANDARD_APP_ARGS(args, tmp);
                if (args.argc == 2) {
-                       if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
-                               ast_module_user_remove(u);
+                       if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
                                return -1;
-                       }
                        ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING);
                        if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
                                int gain;
 
                                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
                                        ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
-                                       ast_module_user_remove(u);
                                        return -1;
                                } else {
                                        leave_options.record_gain = (signed char) gain;
@@ -7305,14 +7301,10 @@ static int vm_exec(struct ast_channel *chan, void *data)
        } else {
                char tmp[256];
                res = ast_app_getdata(chan, "vm-whichbox", tmp, sizeof(tmp) - 1, 0);
-               if (res < 0) {
-                       ast_module_user_remove(u);
+               if (res < 0)
                        return res;
-               }
-               if (ast_strlen_zero(tmp)) {
-                       ast_module_user_remove(u);
+               if (ast_strlen_zero(tmp))
                        return 0;
-               }
                args.argv0 = ast_strdupa(tmp);
        }
 
@@ -7323,8 +7315,6 @@ static int vm_exec(struct ast_channel *chan, void *data)
                pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
                res = 0;
        }
-       
-       ast_module_user_remove(u);
 
        return res;
 }
@@ -7396,7 +7386,6 @@ static int append_mailbox(char *context, char *mbox, char *data)
 
 static int vm_box_exists(struct ast_channel *chan, void *data) 
 {
-       struct ast_module_user *u;
        struct ast_vm_user svm;
        char *context, *box;
        AST_DECLARE_APP_ARGS(args,
@@ -7410,8 +7399,6 @@ static int vm_box_exists(struct ast_channel *chan, void *data)
                return -1;
        }
 
-       u = ast_module_user_add(chan);
-
        if (!dep_warning) {
                dep_warning = 1;
                ast_log(LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
@@ -7433,7 +7420,7 @@ static int vm_box_exists(struct ast_channel *chan, void *data)
                pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
        } else
                pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
-       ast_module_user_remove(u);
+
        return 0;
 }
 
@@ -7463,14 +7450,11 @@ static struct ast_custom_function mailbox_exists_acf = {
 
 static int vmauthenticate(struct ast_channel *chan, void *data)
 {
-       struct ast_module_user *u;
        char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
        struct ast_vm_user vmus;
        char *options = NULL;
        int silent = 0, skipuser = 0;
        int res = -1;
-
-       u = ast_module_user_add(chan);
        
        if (s) {
                s = ast_strdupa(s);
@@ -7497,7 +7481,6 @@ static int vmauthenticate(struct ast_channel *chan, void *data)
                res = 0;
        }
 
-       ast_module_user_remove(u);
        return res;
 }
 
@@ -8488,8 +8471,6 @@ static int unload_module(void)
        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();