Applications no longer need to call ast_module_user_add and ast_module_user_remove...
[asterisk/asterisk.git] / apps / app_voicemail.c
index 4ec85b6..b700e76 100644 (file)
@@ -35,7 +35,7 @@ c-client (http://www.washington.edu/imap/
  *
  *
  *
- * \note  This file is now almost impossible to work with, due to all #ifdefs.
+ * \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.
  */
@@ -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";
 
@@ -2311,7 +2311,7 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, in
 
        snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
 
-       if ((res = create_dirpath(dest, sizeof(dest), context, ext, "greet"))) {
+       if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
                ast_log(LOG_WARNING, "Failed to make directory(%s)\n", fn);
                return -1;
        }
@@ -2647,7 +2647,7 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
         ast_debug(3,"Mailbox is set to %s\n",mailbox);
 
        /* If no mailbox, return immediately */
-       if (ast_strlen_zero(mailbox))
+       if (ast_strlen_zero(mailbox)) 
                return 0;
 
        if (strchr(mailbox, ',')) {
@@ -2694,7 +2694,7 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
                free_user(vmu);
                return -1;
        }
+
        /* check if someone is accessing this box right now... */
        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");
@@ -2703,7 +2703,7 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
                free_user(vmu);
                return 0;
        }
+
        /* add one if not there... */
        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);
@@ -3018,7 +3018,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
        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] = "";
@@ -3055,16 +3054,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
        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));
+               ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
        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)) {
-               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"))) {
+       if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
                ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
                return -1;
        }
@@ -3074,7 +3071,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
        DISPOSE(tempfile, -1);
        /* It's easier just to try to make it than to check for its existence */
        create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
-       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp");
 
        /* Check current or macro-calling context for special extensions */
        if (ast_test_flag(vmu, VM_OPERATOR)) {
@@ -3187,8 +3183,25 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                        ast_log(LOG_NOTICE,"Can not leave voicemail, unable to count messages\n");
                        return -1;
                }
-               if((vms = get_vm_state_by_mailbox(ext,0))) 
-                       vms->newmessages++; /*still need to increment new message count*/
+               if(!(vms = get_vm_state_by_mailbox(ext,0))) {
+               /*It is possible under certain circumstances that inboxcount did not create a vm_state when it was needed. This is a catchall which will
+                * rarely be used*/
+                       if (!(vms = ast_calloc(1, sizeof(*vms)))) {
+                               ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
+                               return -1;
+                       }
+                       ast_copy_string(vms->imapuser, vmu->imapuser, sizeof(vms->imapuser));
+                       ast_copy_string(vms->username, ext, sizeof(vms->username));
+                       vms->mailstream = NIL;
+                       ast_debug(3, "Copied %s to %s\n", vmu->imapuser, vms->imapuser);
+                       vms->updated=1;
+                       ast_copy_string(vms->curbox, mbox(0), sizeof(vms->curbox));
+                       init_vm_state(vms);
+                       vmstate_insert(vms);
+                       vms = get_vm_state_by_mailbox(ext,0);
+               }
+               vms->newmessages++;
+               
                /* here is a big difference! We add one to it later */
                msgnum = newmsgs + oldmsgs;
                ast_debug(3, "Messagecount set to %d\n",msgnum);
@@ -3320,6 +3333,11 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
                                        ast_filerename(tmptxtfile, fn, NULL);
                                        rename(tmptxtfile, txtfile);
 
+                                       /* Properly set permissions on voicemail text descriptor file.
+                                          Unfortunately mkstemp() makes this file 0600 on most unix systems. */
+                                       if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
+                                               ast_log(LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
+
                                        ast_unlock_path(dir);
                                        if (ast_check_realtime("voicemail_data")) {
                                                snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
@@ -4158,6 +4176,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;
@@ -4348,7 +4367,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;
@@ -5031,8 +5062,7 @@ static int imap_retrieve_file (char *dir, int msgnum, char *mailbox, char *conte
                return -1;
        }
 
-       for (i = 0; i < vms_p->mailstream->nmsgs; i++)
-       {
+       for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
                mail_fetchstructure(vms_p->mailstream, i + 1, &body);
                /* We have the body, now we extract the file name of the first attachment. */
                if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
@@ -5042,8 +5072,7 @@ static int imap_retrieve_file (char *dir, int msgnum, char *mailbox, char *conte
                        return -1;
                }
                filename = strsep(&attachment, ".");
-               if (!strcmp(filename, file))
-               {
+               if (!strcmp(filename, file)) {
                        ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
                        vms_p->msgArray[vms_p->curmsg] = i + 1;
                        save_body(body, vms_p, "2", attachment);
@@ -5083,8 +5112,7 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
                        return -1;
                }
                filename = strsep(&attachment, ".");
-               if (!strcmp(filename, file))
-               {
+               if (!strcmp(filename, file)) {
                        sprintf (arg,"%d", i+1);
                        mail_setflag (vms->mailstream,arg,"\\DELETED");
                }
@@ -6380,13 +6408,11 @@ 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[PATH_MAX] = "";
        unsigned char buf[256];
-       char dest[PATH_MAX];
        int bytes = 0;
 
        if (ast_adsi_available(chan)) {
@@ -6399,10 +6425,6 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st
        }
 
        snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
-       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;
@@ -6705,7 +6727,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;
@@ -6722,7 +6743,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));
@@ -6748,16 +6768,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;
@@ -7247,7 +7264,6 @@ out:
                free(vms.deleted);
        if (vms.heard)
                free(vms.heard);
-       ast_module_user_remove(u);
 
        return res;
 }
@@ -7255,7 +7271,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 };
@@ -7264,8 +7279,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));
 
@@ -7276,17 +7289,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;
@@ -7296,14 +7306,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);
        }
 
@@ -7314,8 +7320,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;
 }
@@ -7387,7 +7391,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,
@@ -7401,8 +7404,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);
@@ -7424,7 +7425,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;
 }
 
@@ -7454,14 +7455,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);
@@ -7488,7 +7486,6 @@ static int vmauthenticate(struct ast_channel *chan, void *data)
                res = 0;
        }
 
-       ast_module_user_remove(u);
        return res;
 }
 
@@ -8479,8 +8476,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();
@@ -8637,7 +8632,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
 
        make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
        snprintf(filename,sizeof(filename), "%s.txt", vms->fn2);
-       RETRIEVE(vms->curdir, vms->curms, vmu->mailbox, vmu->context);
+       RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
        msg_cfg = ast_config_load(filename);
        DISPOSE(vms->curdir, vms->curmsg);
        if (!msg_cfg) {
@@ -9495,7 +9490,7 @@ static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
                        continue;
                }
 
-               if (interactive == 2 || vlist->vms->interactive == interactive) {
+               if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
                        AST_LIST_UNLOCK(&vmstates);
                        return vlist->vms;
                }