From 5aa87dbfa7a3c287006b6c383f836efc00b22661 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Fri, 9 May 2003 05:53:17 +0000 Subject: [PATCH] Commit changes to app_voicemail2 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@984 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_voicemail2.c | 1442 +++++++++++++++++++++-------------------- 1 file changed, 731 insertions(+), 711 deletions(-) diff --git a/apps/app_voicemail2.c b/apps/app_voicemail2.c index 0b8348430f..dcc504b656 100755 --- a/apps/app_voicemail2.c +++ b/apps/app_voicemail2.c @@ -65,11 +65,13 @@ #define BASELINELEN 72 #define eol "\r\n" -static int iocp; -static int iolen; -static int linelength; -static int ateof; -static unsigned char iobuf[BASEMAXINLINE]; +struct baseio { + int iocp; + int iolen; + int linelength; + int ateof; + unsigned char iobuf[BASEMAXINLINE]; +}; static char *tdesc = "Comedian Mail (Voicemail System)"; @@ -202,51 +204,51 @@ static int vm_change_password(char *username, char *password, char *newpassword) } static int -inbuf(FILE *fi) +inbuf(struct baseio *bio, FILE *fi) { int l; - if(ateof) + if(bio->ateof) return 0; - if ( (l = fread(iobuf,1,BASEMAXINLINE,fi)) <= 0) { + if ( (l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) { if(ferror(fi)) return -1; - ateof = 1; + bio->ateof = 1; return 0; } - iolen= l; - iocp= 0; + bio->iolen= l; + bio->iocp= 0; return 1; } static int -inchar(FILE *fi) +inchar(struct baseio *bio, FILE *fi) { - if(iocp>=iolen) - if(!inbuf(fi)) + if(bio->iocp>=bio->iolen) + if(!inbuf(bio, fi)) return EOF; - return iobuf[iocp++]; + return bio->iobuf[bio->iocp++]; } static int -ochar(int c, FILE *so) +ochar(struct baseio *bio, int c, FILE *so) { - if(linelength>=BASELINELEN) { + if(bio->linelength>=BASELINELEN) { if(fputs(eol,so)==EOF) return -1; - linelength= 0; + bio->linelength= 0; } if(putc(((unsigned char)c),so)==EOF) return -1; - linelength++; + bio->linelength++; return 1; } @@ -256,11 +258,10 @@ static int base_encode(char *filename, FILE *so) unsigned char dtable[BASEMAXINLINE]; int i,hiteof= 0; FILE *fi; + struct baseio bio; - linelength = 0; - iocp = BASEMAXINLINE; - iolen = 0; - ateof = 0; + memset(&bio, 0, sizeof(bio)); + bio.iocp = BASEMAXINLINE; if ( !(fi = fopen(filename, "rb"))) { ast_log(LOG_WARNING, "Failed to open log file: %s: %s\n", filename, strerror(errno)); @@ -290,7 +291,7 @@ static int base_encode(char *filename, FILE *so) igroup[0]= igroup[1]= igroup[2]= 0; for(n= 0;n<3;n++){ - if ( (c = inchar(fi)) == EOF) { + if ( (c = inchar(&bio, fi)) == EOF) { hiteof= 1; break; } @@ -312,7 +313,7 @@ static int base_encode(char *filename, FILE *so) } for(i= 0;i<4;i++) - ochar(ogroup[i], so); + ochar(&bio, ogroup[i], so); } } @@ -473,21 +474,159 @@ static int invent_message(struct ast_channel *chan, char *ext, int busy, char *e return res; } +static int play_and_wait(struct ast_channel *chan, char *fn) +{ + int d; + d = ast_streamfile(chan, fn, chan->language); + if (d) + return d; + d = ast_waitstream(chan, AST_DIGIT_ANY); + return d; +} + +static int play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt) +{ + char d, *fmts; + char comment[256]; + int x, fmtcnt=1, res=-1,outmsg=0; + struct ast_frame *f; + struct ast_filestream *others[MAX_OTHER_FORMATS]; + char *sfmt[MAX_OTHER_FORMATS]; + char *stringp=NULL; + time_t start, end; + + + ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "", recordfile, fmt); + snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "", recordfile, chan->name); + + if (playfile) { + d = play_and_wait(chan, playfile); + if (!d) + d = ast_streamfile(chan, "beep",chan->language); + if (!d) + d = ast_waitstream(chan,""); + if (d < 0) + return -1; + } + + fmts = strdupa(fmt); + + stringp=fmts; + strsep(&stringp, "|"); + ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); + sfmt[0] = strdupa(fmts); + + while((fmt = strsep(&stringp, "|"))) { + if (fmtcnt > MAX_OTHER_FORMATS - 1) { + ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); + break; + } + sfmt[fmtcnt++] = strdupa(fmt); + } + + if (maxtime) + time(&start); + for (x=0;xname); + res = -1; + } + } + + if (res < 0) { + f = NULL; + break; + } + f = ast_read(chan); + if (!f) + break; + if (f->frametype == AST_FRAME_VOICE) { + /* write each format */ + for (x=0;xframetype == AST_FRAME_DTMF) { + if (f->subclass == '#') { + if (option_verbose > 2) + ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); + res = '#'; + outmsg = 2; + ast_frfree(f); + break; + } + } + if (maxtime) { + time(&end); + if (maxtime < (end - start)) { + if (option_verbose > 2) + ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); + res = 't'; + ast_frfree(f); + break; + } + } + ast_frfree(f); + } + if (!f) { + if (option_verbose > 2) + ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); + res = -1; + outmsg=1; + } + } else { + ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); + } + + for (x=0;x 1) { + /* Let them know it worked */ + ast_streamfile(chan, "vm-msgsaved", chan->language); + ast_waitstream(chan, ""); + } + } + + + return res; +} + static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int busy, int unavail) { struct ast_config *cfg; - char *copy, *name, *passwd, *email, *pager, *fmt, *fmts; + char *copy, *name=NULL, *passwd=NULL, *email=NULL, *pager=NULL, *fmt; char comment[256]; - struct ast_filestream *writer=NULL, *others[MAX_OTHER_FORMATS]; - char *sfmt[MAX_OTHER_FORMATS]; char txtfile[256]; FILE *txt; - int res = -1, fmtcnt=0, x; + int res = 0, x; int msgnum; - int outmsg=0; - int wavother=0; int maxmessage=0; - struct ast_frame *f; char date[256]; char dir[256]; char fn[256]; @@ -497,14 +636,16 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int char *s; time_t start; time_t end; + int silence = 0; /* amount of silence to allow */ +#if 0 + /* XXX Need to be moved to play_and_record */ struct ast_dsp *sildet; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; - int silence = 0; /* amount of silence to allow */ int gotsilence = 0; /* did we timeout for silence? */ +#endif char *silencestr; char *thresholdstr; - int rfmt; int threshold = 128; cfg = ast_load(VOICEMAIL_CONFIG); @@ -537,12 +678,15 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int else if (unavail) snprintf(prefile, sizeof(prefile), "vm/%s/unavail", ext); /* Make sure they have an entry in the config */ - copy = strdup(copy); + copy = strdupa(copy); stringp=copy; passwd = strsep(&stringp, ","); - name = strsep(&stringp, ","); - email = strsep(&stringp, ","); - pager = strsep(&stringp, ","); + if (passwd) + name = strsep(&stringp, ","); + if (name) + email = strsep(&stringp, ","); + if (email) + pager = strsep(&stringp, ","); make_dir(dir, sizeof(dir), ext, ""); /* It's easier just to try to make it than to check for its existence */ if (mkdir(dir, 0700) && (errno != EEXIST)) @@ -556,75 +700,67 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int if (strlen(prefile)) { if (ast_fileexists(prefile, NULL, NULL) > 0) { if (ast_streamfile(chan, prefile, chan->language) > -1) - silent = ast_waitstream(chan, "#0"); + res = ast_waitstream(chan, "#0"); } else { ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile); - silent = invent_message(chan, ext, busy, ecodes); + res = invent_message(chan, ext, busy, ecodes); } - if (silent < 0) { + if (res < 0) { ast_log(LOG_DEBUG, "Hang up during prefile playback\n"); - free(copy); return -1; } } - /* If they hit "#" we should still play the beep sound */ - if (silent == '#') { - if (!ast_streamfile(chan, "beep", chan->language) < 0) + if (res == '#') { + /* On a '#' we skip the instructions */ + silent = 1; + res = 0; + } + if (!res && !silent) { + res = ast_streamfile(chan, INTRO, chan->language); + if (!res) + res = ast_waitstream(chan, ecodes); + if (res == '#') { silent = 1; - if (ast_waitstream(chan, "") <0) { - ast_log(LOG_DEBUG, "Hangup during beep\n"); - free(copy); - return -1; + res = 0; } - } else if (silent == '0') { + } + /* Check for a '0' here */ + if (res == '0') { strncpy(chan->exten, "o", sizeof(chan->exten) - 1); if (strlen(chan->macrocontext)) strncpy(chan->context, chan->macrocontext, sizeof(chan->context) - 1); chan->priority = 0; - free(copy); return 0; } - /* Stream an info message */ - if (silent || !ast_streamfile(chan, INTRO, chan->language)) { - /* Wait for the message to finish */ - if (silent || !ast_waitstream(chan, "")) { - if (!ast_streamfile(chan, "beep", chan->language) < 0) - silent = 1; - if (ast_waitstream(chan, "") <0) { - ast_log(LOG_DEBUG, "Hangup during beep\n"); - free(copy); - return -1; - } - fmt = ast_variable_retrieve(cfg, "general", "format"); - if (fmt) { - char *stringp=NULL; - fmts = strdup(fmt); - stringp=fmts; - fmt = strsep(&stringp, "|"); - msgnum = 0; - do { - make_file(fn, sizeof(fn), dir, msgnum); - snprintf(comment, sizeof(comment), "Voicemail from %s to %s (%s) on %s\n", - (chan->callerid ? chan->callerid : "Unknown"), - name, ext, chan->name); - if (ast_fileexists(fn, NULL, chan->language) > 0) { - msgnum++; - continue; - } - writer = ast_writefile(fn, fmt, comment, O_EXCL, 1 /* check for other formats */, 0700); - if (!writer) - break; - msgnum++; - } while(!writer && (msgnum < MAXMSG)); - if (writer) { - char *stringp=NULL; - /* Store information */ - snprintf(txtfile, sizeof(txtfile), "%s.txt", fn); - txt = fopen(txtfile, "w+"); - if (txt) { - get_date(date, sizeof(date)); - time(&start); - fprintf(txt, + if (!res && (silent < 2)) { + /* Unless we're *really* silent, try to send the beep */ + res = ast_streamfile(chan, "beep", chan->language); + if (!res) + res = ast_waitstream(chan, ""); + } + if (res < 0) + return -1; + /* The meat of recording the message... All the announcements and beeps have been played*/ + fmt = ast_variable_retrieve(cfg, "general", "format"); + if (fmt) { + msgnum = 0; + do { + make_file(fn, sizeof(fn), dir, msgnum); + snprintf(comment, sizeof(comment), "Voicemail from %s to %s (%s) on %s\n", + (chan->callerid ? chan->callerid : "Unknown"), + name, ext, chan->name); + if (ast_fileexists(fn, NULL, chan->language) <= 0) + break; + msgnum++; + } while(msgnum < MAXMSG); + if (msgnum < MAXMSG) { + /* Store information */ + snprintf(txtfile, sizeof(txtfile), "%s.txt", fn); + txt = fopen(txtfile, "w+"); + if (txt) { + get_date(date, sizeof(date)); + time(&start); + fprintf(txt, ";\n" "; Message Information file\n" ";\n" @@ -644,38 +780,29 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int chan->name, chan->callerid ? chan->callerid : "Unknown", date, time(NULL)); - fclose(txt); - } else - ast_log(LOG_WARNING, "Error opening text file for output\n"); + fclose(txt); + } else + ast_log(LOG_WARNING, "Error opening text file for output\n"); + res = play_and_record(chan, NULL, fn, maxmessage, fmt); + txt = fopen(txtfile, "a"); + if (txt) { + time(&end); + fprintf(txt, "duration=%ld\n", end-start); + fclose(txt); + } + stringp = fmt; + strsep(&stringp, "|"); + /* Send e-mail if applicable */ + if (email) + sendmail(astemail, email, name, msgnum, ext, chan->callerid, fn, fmt, end - start); + if (pager) + sendpage(astemail, pager, msgnum, ext, chan->callerid, end - start); + } else + ast_log(LOG_WARNING, "No more messages possible\n"); + } else + ast_log(LOG_WARNING, "No format for saving voicemail?\n"); - /* We need to reset these values */ - free(fmts); - fmt = ast_variable_retrieve(cfg, "general", "format"); - fmts = strdup(fmt); - stringp=fmts; - strsep(&stringp, "|"); - while((fmt = strsep(&stringp, "|"))) { - if (fmtcnt > MAX_OTHER_FORMATS - 1) { - ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); - break; - } - sfmt[fmtcnt++] = strdup(fmt); - } - for (x=0;x 0) { rfmt = chan->readformat; @@ -690,148 +817,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int } ast_dsp_set_threshold(sildet, 50); } - - if (x == fmtcnt) { - /* Loop forever, writing the packets we read to the writer(s), until - we read a # or get a hangup */ - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "Recording to %s\n", fn); - f = NULL; - for(;;) { - res = ast_waitfor(chan, 2000); - if (!res) { - ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); - /* Try one more time in case of masq */ - res = ast_waitfor(chan, 2000); - if (!res) { - ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); - res = -1; - } - } - - if (res < 0) { - f = NULL; - break; - } - - f = ast_read(chan); - if (!f) - break; - if (f->frametype == AST_FRAME_VOICE) { - /* Write the primary format */ - res = ast_writestream(writer, f); - if (res) { - ast_log(LOG_WARNING, "Error writing primary frame\n"); - break; - } - /* And each of the others */ - for (x=0;x 0) { - dspsilence = 0; - ast_dsp_silence(sildet, f, &dspsilence); - if (dspsilence) { - totalsilence = dspsilence; - } else { - totalsilence = 0; - } - if (totalsilence > silence) { - /* Ended happily with silence */ - outmsg=2; - ast_frfree(f); - gotsilence = 1; - res = 0; - break; - } - } - - } else if (f->frametype == AST_FRAME_DTMF) { - if (f->subclass == '#') { - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); - outmsg=2; - ast_frfree(f); - res = 0; - break; - } - } - ast_frfree(f); - time(&end); - if (maxmessage && (end - start > maxmessage)) { - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "Message is too long, ending it now...\n"); - outmsg = 2; - res = 0; - break; - } - } - if (!f) { - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); - res = -1; - outmsg=1; - } - if (gotsilence) { - ast_stream_rewind(writer, silence-1000); - ast_truncstream(writer); - - /* And each of the others */ - for (x=0;x 1) { - /* Let them know it worked */ - ast_streamfile(chan, "vm-msgsaved", chan->language); - ast_waitstream(chan, ""); - } - txt = fopen(txtfile, "a"); - if (txt) { - time(&end); - fprintf(txt, "duration=%ld\n", end-start); - fclose(txt); - } - /* Send e-mail if applicable */ - if (email) - sendmail(astemail, email, name, msgnum, ext, chan->callerid, fn, wavother ? "wav" : fmts, end - start); - if (pager) - sendpage(astemail, pager, msgnum, ext, chan->callerid, end - start); - } - } else { - if (msgnum < MAXMSG) - ast_log(LOG_WARNING, "Error writing to mailbox %s\n", ext); - else - ast_log(LOG_WARNING, "Too many messages in mailbox %s\n", ext); - } - free(fmts); - } else - ast_log(LOG_WARNING, "No format to save messages in \n"); - } - } else - ast_log(LOG_WARNING, "Unable to playback instructions\n"); - - free(copy); +#endif } else ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext); ast_destroy(cfg); @@ -880,16 +866,6 @@ static int count_messages(char *dir) return x; } -static int play_and_wait(struct ast_channel *chan, char *fn) -{ - int d; - d = ast_streamfile(chan, fn, chan->language); - if (d) - return d; - d = ast_waitstream(chan, AST_DIGIT_ANY); - return d; -} - static int say_and_wait(struct ast_channel *chan, int num) { int d; @@ -1456,6 +1432,17 @@ static int get_folder(struct ast_channel *chan, int start) return d; } +static int get_folder2(struct ast_channel *chan, char *fn, int start) +{ + int res = 0; + res = play_and_wait(chan, fn); + while (((res < '0') || (res > '9')) && + (res != '#') && (res > 0)) { + res = get_folder(chan, 0); + } + return res; +} + static int forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int curmsg, char* myusername) { @@ -1471,12 +1458,14 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int char *astemail; char fn[256]; char callerid[512]; + int res = 0; - while(1) { - ast_streamfile(chan, "vm-extension", chan->language); - - if (ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0) - return 0; + while(!res) { + res = ast_streamfile(chan, "vm-extension", chan->language); + if (res) + break; + if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0)) + break; if (ast_variable_retrieve(cfg, NULL, username)) { printf("Got %d\n", atoi(username)); /* if (play_and_wait(chan, "vm-savedto")) @@ -1553,18 +1542,37 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int } /* give confirmatopm that the message was saved */ - if (play_and_wait(chan, "vm-message")) break; - if (play_and_wait(chan, "vm-saved")) break; - + res = play_and_wait(chan, "vm-message"); + if (!res) + res = play_and_wait(chan, "vm-saved"); break; } else { - if ( play_and_wait(chan, "pbx-invalid")) - break; + res = play_and_wait(chan, "pbx-invalid"); } } - return 0; + return res; } +struct vm_state { + char curbox[80]; + char username[80]; + char curdir[256]; + char vmbox[256]; + char fn[256]; + char fn2[256]; + char password[80]; + int deleted[MAXMSG]; + int heard[MAXMSG]; + int curmsg; + int skipms; + int lastmsg; + int newmessages; + int oldmessages; + int starting; + int repeats; + int maxgreet; +}; + #define WAITCMD(a) do { \ d = (a); \ if (d < 0) \ @@ -1656,151 +1664,265 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int snprintf(vmbox, sizeof(vmbox), "vm-%s", curbox); \ } while (0) -static int play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime) + +static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file) { - char d, *fmt, *fmts; - char comment[256]; - int x, fmtcnt=1, res=-1,outmsg=0, wavother=0; - struct ast_frame *f; - struct ast_config *cfg; - struct ast_filestream *others[MAX_OTHER_FORMATS]; - char *sfmt[MAX_OTHER_FORMATS]; - char *stringp=NULL; - time_t start, end; - - - ast_log(LOG_DEBUG,"play_and_record: %s, %s\n", playfile, recordfile); - snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile, recordfile, chan->name); - - d = play_and_wait(chan, playfile); - if (d < 0) - return -1; - ast_streamfile(chan, "beep",chan->language); - ast_waitstream(chan,""); - cfg = ast_load(VOICEMAIL_CONFIG); - - fmt = ast_variable_retrieve(cfg, "general", "format"); - ast_log(LOG_DEBUG,"Recording Formats: fmt=%s\n", fmt); - - fmts = strdup(fmt); - - ast_destroy(cfg); + int res; + if ((res = ast_streamfile(chan, file, chan->language))) + ast_log(LOG_WARNING, "Unable to play message %s\n", file); + if (!res) + res = ast_waitstream(chan, AST_DIGIT_ANY); + return res; +} - stringp=fmts; - strsep(&stringp, "|"); - ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); - sfmt[0] = strdup(fmts); +static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file) +{ + int res; + if ((res = ast_streamfile(chan, file, chan->language))) + ast_log(LOG_WARNING, "Unable to play message %s\n", file); + if (!res) + res = ast_waitstream_fr(chan, AST_DIGIT_ANY, "#", "*",vms->skipms); + return res; +} + +static int play_message(struct ast_channel *chan, struct vm_state *vms, int msg) +{ + int res = 0; + vms->starting = 0; \ + make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg); + adsi_message(chan, vms->curbox, msg, vms->lastmsg, vms->deleted[msg], vms->fn); + if (!msg) + res = wait_file2(chan, vms, "vm-first"); + else if (msg == vms->lastmsg) + res = wait_file2(chan, vms, "vm-last"); + if (!res) { + res = wait_file2(chan, vms, "vm-message"); + if (msg && (msg != vms->lastmsg)) { + if (!res) + res = ast_say_number(chan, msg + 1, AST_DIGIT_ANY, chan->language); + } + } - while((fmt = strsep(&stringp, "|"))) { - if (fmtcnt > MAX_OTHER_FORMATS - 1) { - ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); - break; + if (!res) { + make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg); + vms->heard[msg] = 1; + res = wait_file(chan, vms, vms->fn); + } + return res; +} + +static void open_mailbox(struct vm_state *vms, int box) +{ + strncpy(vms->curbox, mbox(box), sizeof(vms->curbox) - 1); + make_dir(vms->curdir, sizeof(vms->curdir), vms->username, vms->curbox); + vms->lastmsg = count_messages(vms->curdir) - 1; + snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox); +} + +static void close_mailbox(struct vm_state *vms) +{ + int x; + char ntxt[256] = ""; + char txt[256] = ""; + if (vms->lastmsg > -1) { + /* Get the deleted messages fixed */ + vms->curmsg = -1; + for (x=0;x<=vms->lastmsg;x++) { + if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) { + /* Save this message. It's not in INBOX or hasn't been heard */ + vms->curmsg++; + make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); + make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg); + if (strcmp(vms->fn, vms->fn2)) { + snprintf(txt, sizeof(txt), "%s.txt", vms->fn); + snprintf(ntxt, sizeof(ntxt), "%s.txt", vms->fn2); + ast_filerename(vms->fn, vms->fn2, NULL); + rename(txt, ntxt); + } + } else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) { + /* Move to old folder before deleting */ + save_to_folder(vms->curdir, x, vms->username, 1); + } + } + for (x = vms->curmsg + 1; x<=vms->lastmsg; x++) { + make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); + snprintf(txt, sizeof(txt), "%s.txt", vms->fn); + ast_filedelete(vms->fn, NULL); + unlink(txt); + } + } + memset(vms->deleted, 0, sizeof(vms->deleted)); + memset(vms->heard, 0, sizeof(vms->heard)); +} + +static int vm_intro(struct ast_channel *chan,struct vm_state *vms) +{ + /* Introduce messages they have */ + int res; + res = play_and_wait(chan, "vm-youhave"); + if (!res) { + if (vms->newmessages) { + res = say_and_wait(chan, vms->newmessages); + if (!res) + res = play_and_wait(chan, "vm-INBOX"); + if (vms->oldmessages && !res) + res = play_and_wait(chan, "vm-and"); + else if (!res) { + if ((vms->newmessages == 1)) + res = play_and_wait(chan, "vm-message"); + else + res = play_and_wait(chan, "vm-messages"); } - sfmt[fmtcnt++] = strdup(fmt); + } - - if (maxtime) - time(&start); - for (x=0;xoldmessages) { + res = say_and_wait(chan, vms->oldmessages); + if (!res) + res = play_and_wait(chan, "vm-Old"); + if (!res) { + if (vms->oldmessages == 1) + res = play_and_wait(chan, "vm-message"); + else + res = play_and_wait(chan, "vm-messages"); } - if(!strcasecmp(sfmt[x], "wav")) - wavother++; - free(sfmt[x]); + } + if (!res) { + if (!vms->oldmessages && !vms->newmessages) { + res = play_and_wait(chan, "vm-no"); + if (!res) + res = play_and_wait(chan, "vm-messages"); } - if (x == fmtcnt) { - /* Loop forever, writing the packets we read to the writer(s), until - we read a # or get a hangup */ - f = NULL; - for(;;) { - res = ast_waitfor(chan, 2000); - if (!res) { - ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); - /* Try one more time in case of masq */ - res = ast_waitfor(chan, 2000); - if (!res) { - ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); - res = -1; - } - } - - if (res < 0) { - f = NULL; - break; - } + } + } + return res; +} - f = ast_read(chan); - if (!f) - break; - if (f->frametype == AST_FRAME_VOICE) { - /* write each format */ - for (x=0;xframetype == AST_FRAME_DTMF) { - if (f->subclass == '#') { - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); - outmsg=2; - break; - } - } - if (maxtime) { - time(&end); - if (maxtime < (end - start)) { - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); - outmsg=2; - break; - } - } - ast_frfree(f); +static int vm_instructions(struct ast_channel *chan, struct vm_state *vms) +{ + int res = 0; + /* Play instructions and wait for new command */ + while(!res) { + if (vms->starting) { + if (vms->lastmsg > -1) { + res = play_and_wait(chan, "vm-onefor"); + if (!res) + res = play_and_wait(chan, vms->vmbox); + if (!res) + res = play_and_wait(chan, "vm-messages"); } - if (!f) { - if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); - res = -1; - outmsg=1; - } - } else { - ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); - free(sfmt[x]); - } - - for (x=0;x 1) { - /* Let them know it worked */ - ast_streamfile(chan, "vm-msgsaved", chan->language); - ast_waitstream(chan, ""); - } - } - - - return 0; + if (!res) + res = play_and_wait(chan, "vm-opts"); + } else { + if (vms->curmsg) + res = play_and_wait(chan, "vm-prev"); + if (!res) + res = play_and_wait(chan, "vm-repeat"); + if (!res && (vms->curmsg != vms->lastmsg)) + res = play_and_wait(chan, "vm-next"); + if (!res) { + if (!vms->deleted[vms->curmsg]) + res = play_and_wait(chan, "vm-delete"); + else + res = play_and_wait(chan, "vm-undelete"); + if (!res) + res = play_and_wait(chan, "vm-toforward"); + if (!res) + res = play_and_wait(chan, "vm-savemessage"); + } + } + if (!res) + res = play_and_wait(chan, "vm-helpexit"); + if (!res) + res = ast_waitfordigit(chan, 6000); + if (!res) { + vms->repeats++; + if (vms->repeats > 2) { + res = play_and_wait(chan, "vm-goodbye"); + if (!res) + res = 't'; + } + } + } + return res; } +static int vm_options(struct ast_channel *chan, struct vm_state *vms, char *fmtc) +{ + int cmd = 0; + int retries = 0; + char newpassword[80] = ""; + char newpassword2[80] = ""; + char prefile[256]=""; + while((cmd >= 0) && (cmd != 't')) { + if (cmd) + retries = 0; + switch (cmd) { + case '1': + snprintf(prefile,sizeof(prefile),"vm/%s/unavail",vms->username); + cmd = play_and_record(chan,"vm-rec-unv",prefile, vms->maxgreet, fmtc); + /* Ignore DTMF */ + if (cmd >0) + cmd = 0; + break; + case '2': + snprintf(prefile,sizeof(prefile),"vm/%s/busy",vms->username); + cmd = play_and_record(chan,"vm-rec-busy",prefile, vms->maxgreet, fmtc); + /* Ignore DTMF */ + if (cmd >0) + cmd = 0; + break; + case '3': + snprintf(prefile,sizeof(prefile),"vm/%s/greet",vms->username); + cmd = play_and_record(chan,"vm-rec-name",prefile, vms->maxgreet, fmtc); + /* Ignore DTMF */ + if (cmd >0) + cmd = 0; + break; + case '4': + newpassword[1] = '\0'; + newpassword[0] = cmd = play_and_wait(chan,"vm-newpassword"); + if (cmd < 0) + break; + if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) { + break; + } + newpassword2[1] = '\0'; + newpassword2[0] = cmd = play_and_wait(chan,"vm-reenterpassword"); + if (cmd < 0) + break; - + if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#"))) { + break; + } + if (strcmp(newpassword, newpassword2)) { + ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2); + cmd = play_and_wait(chan, "vm-mismatch"); + break; + } + if (vm_change_password(vms->username,vms->password,newpassword) < 0) + { + ast_log(LOG_DEBUG,"Failed to set new password of user %s\n",vms->username); + } else + ast_log(LOG_DEBUG,"User %s set password to %s of length %i\n",vms->username,newpassword,strlen(newpassword)); + cmd = play_and_wait(chan,"vm-passchanged"); + break; + case '*': + cmd = 't'; + break; + default: + cmd = play_and_wait(chan,"vm-options"); + if (!cmd) + cmd = ast_waitfordigit(chan,6000); + if (!cmd) + retries++; + if (retries > 3) + cmd = 't'; + } + } + if (cmd == 't') + cmd = 0; + return cmd; +} static int vm_execmain(struct ast_channel *chan, void *data) { @@ -1810,41 +1932,24 @@ static int vm_execmain(struct ast_channel *chan, void *data) int res=-1; int valid = 0; int prefix = 0; - char d; + int cmd=0; struct localuser *u; - char username[80] =""; char prefixstr[80] =""; char empty[80] = ""; - char password[80] = "", *copy; - char newpassword[80] = ""; - char newpassword2[80] = ""; - char curbox[80] = ""; - char curdir[256] = ""; - char vmbox[256] = ""; - char fn[256] = ""; - char fn2[256] = ""; - char prefile[256]=""; + char *copy; int x; - char ntxt[256] = ""; - char txt[256] = ""; - int deleted[MAXMSG] = { 0, }; - int heard[MAXMSG] = { 0, }; - int newmessages; - int oldmessages; - int repeats = 0; - int curmsg = 0; - int lastmsg = 0; - int starting = 1; int box; int useadsi = 0; int skipuser = 0; char *s; - int ms = 3000; - int maxgreet = 0; char tmp[256], *ext; + char fmtc[256] = ""; struct ast_config *cfg; + struct vm_state vms; LOCAL_USER_ADD(u); + memset(&vms, 0, sizeof(vms)); + vms.skipms = 3000; cfg = ast_load(VOICEMAIL_CONFIG); if (!cfg) { ast_log(LOG_WARNING, "No voicemail configuration\n"); @@ -1852,11 +1957,21 @@ static int vm_execmain(struct ast_channel *chan, void *data) } if ((s = ast_variable_retrieve(cfg, "general", "maxgreet"))) { if (sscanf(s, "%d", &x) == 1) { - maxgreet = x; + vms.maxgreet = x; } else { ast_log(LOG_WARNING, "Invalid max message greeting length\n"); } } + if ((s = ast_variable_retrieve(cfg, "general", "skipms"))) { + if (sscanf(s, "%d", &x) == 1) { + vms.skipms = x; + } else { + ast_log(LOG_WARNING, "Invalid skipms value\n"); + } + } + if ((s = ast_variable_retrieve(cfg, "general", "format"))) { + strncpy(fmtc, s, sizeof(fmtc) - 1); + } if (chan->_state != AST_STATE_UP) ast_answer(chan); @@ -1881,9 +1996,9 @@ static int vm_execmain(struct ast_channel *chan, void *data) if (prefix) strncpy(prefixstr, ext, sizeof(prefixstr) - 1); else - strncpy(username, ext, sizeof(username) - 1); + strncpy(vms.username, ext, sizeof(vms.username) - 1); /* make sure username passed as an option is valid */ - if (ast_variable_retrieve(cfg, NULL, username)) + if (ast_variable_retrieve(cfg, NULL, vms.username)) skipuser++; else valid = 0; @@ -1903,11 +2018,11 @@ static int vm_execmain(struct ast_channel *chan, void *data) while (!valid) { /* Prompt for, and read in the username */ - if (!skipuser && ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0) { + if (!skipuser && ast_readstring(chan, vms.username, sizeof(vms.username) - 1, 2000, 10000, "#") < 0) { ast_log(LOG_WARNING, "Couldn't read username\n"); goto out; } - if (!strlen(username)) { + if (!strlen(vms.username)) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n"); res = 0; @@ -1919,35 +2034,35 @@ static int vm_execmain(struct ast_channel *chan, void *data) ast_log(LOG_WARNING, "Unable to stream password file\n"); goto out; } - if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) { + if (ast_readstring(chan, vms.password, sizeof(vms.password) - 1, 2000, 10000, "#") < 0) { ast_log(LOG_WARNING, "Unable to read password\n"); goto out; } if (prefix) { char fullusername[80] = ""; strncpy(fullusername, prefixstr, sizeof(fullusername) - 1); - strncat(fullusername, username, sizeof(fullusername) - 1); - strncpy(username, fullusername, sizeof(username) - 1); + strncat(fullusername, vms.username, sizeof(fullusername) - 1); + strncpy(vms.username, fullusername, sizeof(vms.username) - 1); } - copy = ast_variable_retrieve(cfg, NULL, username); + copy = ast_variable_retrieve(cfg, NULL, vms.username); if (copy) { char *stringp=NULL; copy = strdup(copy); stringp=copy; strsep(&stringp, ","); - if (!strcmp(password,copy)) + if (!strcmp(vms.password,copy)) valid++; else { if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s'\n", password, username); + ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s'\n", vms.password, vms.username); if (prefix) - strncpy(username, empty, sizeof(username) -1); + strncpy(vms.username, empty, sizeof(vms.username) -1); } free(copy); } else { skipuser = 0; if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_3 "No such user '%s' in config file\n", username); + ast_verbose( VERBOSE_PREFIX_3 "No such user '%s' in config file\n", vms.username); } if (!valid) { if (useadsi) @@ -1962,275 +2077,177 @@ static int vm_execmain(struct ast_channel *chan, void *data) } if (valid) { - snprintf(curdir, sizeof(curdir), "%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,"vm", username); - mkdir(curdir, 0700); - OPEN_MAILBOX(1); - oldmessages = lastmsg + 1; + snprintf(vms.curdir, sizeof(vms.curdir), "%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,"vm", vms.username); + mkdir(vms.curdir, 0700); + /* Retrieve old and new message counts */ + open_mailbox(&vms, 1); + vms.oldmessages = vms.lastmsg + 1; /* Start in INBOX */ - OPEN_MAILBOX(0); - newmessages = lastmsg + 1; + open_mailbox(&vms, 0); + vms.newmessages = vms.lastmsg + 1; /* Select proper mailbox FIRST!! */ - if (!newmessages && oldmessages) { + if (!vms.newmessages && vms.oldmessages) { /* If we only have old messages start here */ - OPEN_MAILBOX(1); + open_mailbox(&vms, 1); } if (useadsi) - adsi_status(chan, newmessages, oldmessages, lastmsg); - - WAITCMD(play_and_wait(chan, "vm-youhave")); - if (newmessages) { - WAITCMD(say_and_wait(chan, newmessages)); - WAITCMD(play_and_wait(chan, "vm-INBOX")); - - if (oldmessages) - WAITCMD(play_and_wait(chan, "vm-and")); - else { - if (newmessages == 1) - WAITCMD(play_and_wait(chan, "vm-message")); + adsi_status(chan, vms.newmessages, vms.oldmessages, vms.lastmsg); + res = 0; + cmd = vm_intro(chan, &vms); + vms.repeats = 0; + vms.starting = 1; + while((cmd > -1) && (cmd != 't') && (cmd != '#')) { + /* Run main menu */ + switch(cmd) { + case '1': + vms.curmsg = 0; + /* Fall through */ + case '5': + if (vms.lastmsg > -1) { + cmd = play_message(chan, &vms, vms.curmsg); + } else { + cmd = play_and_wait(chan, "vm-youhave"); + if (!cmd) + cmd = play_and_wait(chan, "vm-no"); + if (!cmd) { + snprintf(vms.fn, sizeof(vms.fn), "vm-%s", vms.curbox); + cmd = play_and_wait(chan, vms.fn); + } + if (!cmd) + cmd = play_and_wait(chan, "vm-messages"); + } + break; + case '2': /* Change folders */ + if (useadsi) + adsi_folders(chan, 0, "Change to folder..."); + if (cmd == '#') { + cmd = 0; + } else if (cmd > 0) { + cmd = cmd - '0'; + close_mailbox(&vms); + open_mailbox(&vms, cmd); + cmd = 0; + } + if (useadsi) + adsi_status2(chan, vms.curbox, vms.lastmsg + 1); + if (!cmd) + cmd = play_and_wait(chan, vms.vmbox); + if (!cmd) + cmd = play_and_wait(chan, "vm-messages"); + vms.starting = 1; + break; + case '4': + if (vms.curmsg) { + vms.curmsg--; + cmd = play_message(chan, &vms, vms.curmsg); + } else { + cmd = play_and_wait(chan, "vm-nomore"); + } + break; + case '6': + if (vms.curmsg < vms.lastmsg) { + vms.curmsg++; + cmd = play_message(chan, &vms, vms.curmsg); + } else { + cmd = play_and_wait(chan, "vm-nomore"); + } + break; + case '7': + vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg]; + if (useadsi) + adsi_delete(chan, vms.curmsg, vms.lastmsg, vms.deleted[vms.curmsg]); + if (vms.deleted[vms.curmsg]) + cmd = play_and_wait(chan, "vm-deleted"); else - WAITCMD(play_and_wait(chan, "vm-messages")); - } - - } - if (oldmessages) { - WAITCMD(say_and_wait(chan, oldmessages)); - WAITCMD(play_and_wait(chan, "vm-Old")); - if (oldmessages == 1) - WAITCMD(play_and_wait(chan, "vm-message")); - else - WAITCMD(play_and_wait(chan, "vm-messages")); - } - if (!oldmessages && !newmessages) { - WAITCMD(play_and_wait(chan, "vm-no")); - WAITCMD(play_and_wait(chan, "vm-messages")); - } - repeats = 0; - starting = 1; -instructions: - if (starting) { - if (lastmsg > -1) { - WAITCMD(play_and_wait(chan, "vm-onefor")); - WAITCMD(play_and_wait(chan, vmbox)); - WAITCMD(play_and_wait(chan, "vm-messages")); - } - WAITCMD(play_and_wait(chan, "vm-opts")); - } else { - if (curmsg) - WAITCMD(play_and_wait(chan, "vm-prev")); - WAITCMD(play_and_wait(chan, "vm-repeat")); - if (curmsg != lastmsg) - WAITCMD(play_and_wait(chan, "vm-next")); - if (!deleted[curmsg]) - WAITCMD(play_and_wait(chan, "vm-delete")); - else - WAITCMD(play_and_wait(chan, "vm-undelete")); - WAITCMD(play_and_wait(chan, "vm-toforward")); - WAITCMD(play_and_wait(chan, "vm-savemessage")); - } - WAITCMD(play_and_wait(chan, "vm-helpexit")); - d = ast_waitfordigit(chan, 6000); - if (d < 0) - goto out; - if (!d) { - repeats++; - if (repeats > 2) { - play_and_wait(chan, "vm-goodbye"); - goto out; + cmd = play_and_wait(chan, "vm-undeleted"); + break; + case '8': + if(vms.lastmsg > -1) + cmd = forward_message(chan, cfg, vms.curdir, vms.curmsg, vms.username); + break; + case '9': + if (useadsi) + adsi_folders(chan, 1, "Save to folder..."); + cmd = get_folder2(chan, "vm-savefolder", 1); + box = 0; /* Shut up compiler */ + if (cmd == '#') { + cmd = 0; + break; + } else if (cmd > 0) { + box = cmd = cmd - '0'; + cmd = save_to_folder(vms.curdir, vms.curmsg, vms.username, cmd); + vms.deleted[vms.curmsg]=1; + } + make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg); + if (useadsi) + adsi_message(chan, vms.curbox, vms.curmsg, vms.lastmsg, vms.deleted[vms.curmsg], vms.fn); + if (!cmd) + cmd = play_and_wait(chan, "vm-message"); + if (!cmd) + cmd = say_and_wait(chan, vms.curmsg + 1); + if (!cmd) + cmd = play_and_wait(chan, "vm-savedto"); + if (!cmd) { + snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box)); + cmd = play_and_wait(chan, vms.fn); + } + if (!cmd) + cmd = play_and_wait(chan, "vm-messages"); + break; + case '*': + if (!vms.starting) { + cmd = play_and_wait(chan, "vm-onefor"); + if (!cmd) + cmd = play_and_wait(chan, vms.vmbox); + if (!cmd) + cmd = play_and_wait(chan, "vm-messages"); + if (!cmd) + cmd = play_and_wait(chan, "vm-opts"); + } else + cmd = 0; + break; + case '0': + cmd = vm_options(chan, &vms, fmtc); + break; + case '#': + ast_stopstream(chan); + adsi_goodbye(chan); + cmd = play_and_wait(chan, "vm-goodbye"); + if (cmd > 0) + cmd = '#'; + break; + default: /* Nothing */ + cmd = vm_instructions(chan, &vms); + break; } - goto instructions; } -cmd: - switch(d) { - case '2': - if (useadsi) - adsi_folders(chan, 0, "Change to folder..."); - box = play_and_wait(chan, "vm-changeto"); - if (box < 0) - goto out; - while((box < '0') || (box > '9')) { - box = get_folder(chan, 0); - if (box < 0) - goto out; - if (box == '#') - goto instructions; - } - box = box - '0'; - CLOSE_MAILBOX; - OPEN_MAILBOX(box); - if (useadsi) - adsi_status2(chan, curbox, lastmsg + 1); - WAITCMD(play_and_wait(chan, vmbox)); - WAITCMD(play_and_wait(chan, "vm-messages")); - starting = 1; - goto instructions; - case '4': - if (curmsg) { - curmsg--; - PLAYMSG(curmsg); - } else { - WAITCMD(play_and_wait(chan, "vm-nomore")); - goto instructions; - } - case '1': - curmsg = 0; - /* Fall through */ - case '5': - if (lastmsg > -1) { - PLAYMSG(curmsg); - } else { - WAITCMD(play_and_wait(chan, "vm-youhave")); - WAITCMD(play_and_wait(chan, "vm-no")); - snprintf(fn, sizeof(fn), "vm-%s", curbox); - WAITCMD(play_and_wait(chan, fn)); - WAITCMD(play_and_wait(chan, "vm-messages")); - goto instructions; - } - case '6': - if (curmsg < lastmsg) { - curmsg++; - PLAYMSG(curmsg); - } else { - WAITCMD(play_and_wait(chan, "vm-nomore")); - goto instructions; - } - case '7': - deleted[curmsg] = !deleted[curmsg]; - if (useadsi) - adsi_delete(chan, curmsg, lastmsg, deleted[curmsg]); - if (deleted[curmsg]) - WAITCMD(play_and_wait(chan, "vm-deleted")); - else - WAITCMD(play_and_wait(chan, "vm-undeleted")); - goto instructions; - case '8': - if(lastmsg > -1) - if(forward_message(chan, cfg, curdir, curmsg, username) < 0) - goto out; - goto instructions; - case '9': - if (useadsi) - adsi_folders(chan, 1, "Save to folder..."); - box = play_and_wait(chan, "vm-savefolder"); - if (box < 0) - goto out; - while((box < '1') || (box > '9')) { - box = get_folder(chan, 1); - if (box < 0) - goto out; - if (box == '#') - goto instructions; - } - box = box - '0'; - if (option_debug) - ast_log(LOG_DEBUG, "Save to folder: %s (%d)\n", mbox(box), box); - if (save_to_folder(curdir, curmsg, username, box)) - goto out; - deleted[curmsg]=1; - make_file(fn, sizeof(fn), curdir, curmsg); - if (useadsi) - adsi_message(chan, curbox, curmsg, lastmsg, deleted[curmsg], fn); - WAITCMD(play_and_wait(chan, "vm-message")); - WAITCMD(say_and_wait(chan, curmsg + 1) ); - WAITCMD(play_and_wait(chan, "vm-savedto")); - snprintf(fn, sizeof(fn), "vm-%s", mbox(box)); - WAITCMD(play_and_wait(chan, fn)); - WAITCMD(play_and_wait(chan, "vm-messages")); - goto instructions; - case '*': - if (!starting) { - WAITCMD(play_and_wait(chan, "vm-onefor")); - WAITCMD(play_and_wait(chan, vmbox)); - WAITCMD(play_and_wait(chan, "vm-messages")); - WAITCMD(play_and_wait(chan, "vm-opts")); - } - goto instructions; - case '#': - ast_stopstream(chan); - adsi_goodbye(chan); - play_and_wait(chan, "vm-goodbye"); + if (cmd == 't') { + /* Timeout */ res = 0; - goto out2; - - case '0': - goto vm_options; - - default: - goto instructions; + } else { + /* Hangup */ + res = -1; } } out: - adsi_goodbye(chan); -out2: - CLOSE_MAILBOX; - ast_stopstream(chan); + if ((res > -1) && (cmd != '#')) { + ast_stopstream(chan); + adsi_goodbye(chan); + if (useadsi) + adsi_unload_session(chan); + } + close_mailbox(&vms); if (cfg) ast_destroy(cfg); - if (useadsi) - adsi_unload_session(chan); if (valid) { - manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", username, ast_app_has_voicemail(username)); + manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", vms.username, ast_app_has_voicemail(vms.username)); } LOCAL_USER_REMOVE(u); return res; -vm_options: - d = play_and_wait(chan,"vm-options"); - if (!d) - d = ast_waitfordigit(chan,6000); - if (d < 0) - goto out; - switch (d) { - - case '1': - snprintf(prefile,sizeof(prefile),"vm/%s/unavail",username); - play_and_record(chan,"vm-rec-unv",prefile, maxgreet); - break; - case '2': - snprintf(prefile,sizeof(prefile),"vm/%s/busy",username); - play_and_record(chan,"vm-rec-busy",prefile, maxgreet); - break; - case '3': - snprintf(prefile,sizeof(prefile),"vm/%s/greet",username); - play_and_record(chan,"vm-rec-name",prefile, maxgreet); - break; - case '4': - newpassword[1] = '\0'; - newpassword[0] = play_and_wait(chan,"vm-newpassword"); - if (ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#") < 0) { - play_and_wait(chan, "vm-sorry"); - ast_log(LOG_NOTICE,"Unable to read new password\n"); - goto vm_options; - } - newpassword2[1] = '\0'; - newpassword2[0] = play_and_wait(chan,"vm-reenterpassword"); - - if (ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#") < 0) { - play_and_wait(chan, "vm-sorry"); - ast_log(LOG_NOTICE,"Unable to read re-entered password\n"); - goto vm_options; - } - if (strcmp(newpassword, newpassword2)) { - ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", username, newpassword, newpassword2); - play_and_wait(chan, "vm-mismatch"); - goto vm_options; - } - if (vm_change_password(username,password,newpassword) < 0) - { - ast_log(LOG_DEBUG,"Failed to set new password of user %s\n",username); - } else - ast_log(LOG_DEBUG,"User %s set password to %s of length %i\n",username,newpassword,strlen(newpassword)); - play_and_wait(chan,"vm-passchanged"); - break; - case '*': - goto instructions; - - default: - goto vm_options; - } - goto vm_options; } static int vm_exec(struct ast_channel *chan, void *data) @@ -2252,15 +2269,18 @@ static int vm_exec(struct ast_channel *chan, void *data) return 0; } ext = tmp; - if (*ext == 's') { - silent++; - ext++; - } else if (*ext == 'b') { - busy++; - ext++; - } else if (*ext == 'u') { - unavail++; - ext++; + while(*ext) { + if (*ext == 's') { + silent = 2; + ext++; + } else if (*ext == 'b') { + busy=1; + ext++; + } else if (*ext == 'u') { + unavail=1; + ext++; + } else + break; } res = leave_voicemail(chan, ext, silent, busy, unavail); LOCAL_USER_REMOVE(u);