]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Version 0.1.11 from FTP
authorMark Spencer <markster@digium.com>
Fri, 1 Mar 2002 16:54:59 +0000 (16:54 +0000)
committerMark Spencer <markster@digium.com>
Fri, 1 Mar 2002 16:54:59 +0000 (16:54 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@417 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_voicemail.c

index 76f69c132a97997868859e5a6319074309b67c64..cc2efe6e22f0b8abc06f570e1579bb881ad3cb50 100755 (executable)
 
 #define VM_SPOOL_DIR AST_SPOOL_DIR "/vm"
 
+#define BASEMAXINLINE 256
+
+#define BASELINELEN 72
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define BASEMAXINLINE 256
+#define BASELINELEN 72
+#define eol "\r\n"
+
+int iocp;
+int iolen;
+int linelength;
+int ateof;
+unsigned char iobuf[BASEMAXINLINE];
 
 static char *tdesc = "Comedian Mail (Voicemail System)";
 
@@ -106,6 +123,7 @@ static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
 {
        char *fn;
        int res;
+
        res = ast_streamfile(chan, "vm-message", chan->language);
        if (!res) {
                res = ast_waitstream(chan, AST_DIGIT_ANY);
@@ -126,15 +144,141 @@ static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
 }
 #endif
 
-static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *mailbox, char *callerid)
+static int
+inbuf(FILE *fi)
+{
+       int l;
+
+       if(ateof)
+               return 0;
+
+       if ( (l = fread(iobuf,1,BASEMAXINLINE,fi)) <= 0) {
+               if(ferror(fi))
+                       return -1;
+
+               ateof = 1;
+               return 0;
+       }
+
+       iolen= l;
+       iocp= 0;
+
+       return 1;
+}
+
+static int 
+inchar(FILE *fi)
+{
+       if(iocp>=iolen)
+               if(!inbuf(fi))
+                       return EOF;
+
+       return iobuf[iocp++];
+}
+
+static int
+ochar(int c, FILE *so)
+{
+       if(linelength>=BASELINELEN) {
+               if(fputs(eol,so)==EOF)
+                       return -1;
+
+               linelength= 0;
+       }
+
+       if(putc(((unsigned char)c),so)==EOF)
+               return -1;
+
+       linelength++;
+
+       return 1;
+}
+
+static int base_encode(char *filename, FILE *so)
+{
+       unsigned char dtable[BASEMAXINLINE];
+       int i,hiteof= 0;
+       FILE *fi;
+
+       linelength = 0;
+       iocp = BASEMAXINLINE;
+       iolen = 0;
+       ateof = 0;
+
+       if ( !(fi = fopen(filename, "rb"))) {
+               ast_log(LOG_WARNING, "Failed to open log file: %s: %s\n", filename, strerror(errno));
+               return -1;
+       }
+
+       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++){
+               dtable[i+18]= 'S'+i;
+               dtable[26+i+18]= 's'+i;
+       }
+       for(i= 0;i<10;i++){
+               dtable[52+i]= '0'+i;
+       }
+       dtable[62]= '+';
+       dtable[63]= '/';
+
+       while(!hiteof){
+               unsigned char igroup[3],ogroup[4];
+               int c,n;
+
+               igroup[0]= igroup[1]= igroup[2]= 0;
+
+               for(n= 0;n<3;n++){
+                       if ( (c = inchar(fi)) == EOF) {
+                               hiteof= 1;
+                               break;
+                       }
+
+                       igroup[n]= (unsigned char)c;
+               }
+
+               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[3]= dtable[igroup[2]&0x3F];
+
+                       if(n<3) {
+                               ogroup[3]= '=';
+
+                               if(n<2)
+                                       ogroup[2]= '=';
+                       }
+
+                       for(i= 0;i<4;i++)
+                               ochar(ogroup[i], so);
+               }
+       }
+
+       if(fputs(eol,so)==EOF)
+               return 0;
+
+       fclose(fi);
+
+       return 1;
+}
+
+static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *mailbox, char *callerid, char *attach, char *format)
 {
        FILE *p;
        char date[256];
        char host[256];
        char who[256];
+       char bound[256];
+       char fname[256];
        time_t t;
        struct tm *tm;
        p = popen(SENDMAIL, "w");
+
        if (p) {
                if (strchr(srcemail, '@'))
                        strncpy(who, srcemail, sizeof(who)-1);
@@ -146,16 +290,35 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
                tm = localtime(&t);
                strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", tm);
                fprintf(p, "Date: %s\n", date);
-               fprintf(p, "Message-ID: <Asterisk-%d-%s-%d@%s>\n", msgnum, mailbox, getpid(), host);
                fprintf(p, "From: Asterisk PBX <%s>\n", who);
                fprintf(p, "To: %s <%s>\n", name, email);
-               fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n\n", msgnum, mailbox);
+               fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n", msgnum, mailbox);
+               fprintf(p, "Message-ID: <Asterisk-%d-%s-%d@%s>\n", msgnum, mailbox, getpid(), host);
+               fprintf(p, "MIME-Version: 1.0\n");
+
+               // Something unique.
+               snprintf(bound, sizeof(bound), "Boundary=%d%s%d", msgnum, mailbox, getpid());
+
+               fprintf(p, "Content-Type: MULTIPART/MIXED; BOUNDARY=\"%s\"\n\n\n", bound);
+
+               fprintf(p, "--%s\n", bound);
+               fprintf(p, "Content-Type: TEXT/PLAIN; charset=US-ASCII\n\n");
                strftime(date, sizeof(date), "%A, %B %d, %Y at %r", tm);
                fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a message (number %d)\n"
+
                           "in mailbox %s from %s, on %s so you might\n"
-                                  "want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n", name, 
+                                  "want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n\n", name, 
                        msgnum, mailbox, (callerid ? callerid : "an unknown caller"), date);
-               fprintf(p, ".\n");
+
+               fprintf(p, "--%s\n", bound);
+               fprintf(p, "Content-Type: TEXT/PLAIN; charset=US-ASCII; name=\"msg%04d\"\n", msgnum);
+               fprintf(p, "Content-Transfer-Encoding: BASE64\n");
+               fprintf(p, "Content-Description: Voicemail sound attachment.\n");
+               fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\n\n", msgnum, format);
+
+               snprintf(fname, sizeof(fname), "%s.%s", attach, format);
+               base_encode(fname, p);
+               fprintf(p, "\n\n--%s--\n.\n", bound);
                pclose(p);
        } else {
                ast_log(LOG_WARNING, "Unable to launch '%s'\n", SENDMAIL);
@@ -207,13 +370,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
        int res = -1, fmtcnt=0, x;
        int msgnum;
        int outmsg=0;
+       int wavother=0;
        struct ast_frame *f;
        char date[256];
        char dir[256];
        char fn[256];
        char prefile[256]="";
        char *astemail;
-       
+
        cfg = ast_load(VOICEMAIL_CONFIG);
        if (!cfg) {
                ast_log(LOG_WARNING, "No such configuration file %s\n", VOICEMAIL_CONFIG);
@@ -241,7 +405,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
                        ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
                /* Play the beginning intro if desired */
                if (strlen(prefile)) {
-                       if (ast_fileexists(prefile, NULL, NULL) < 0) {
+                       if (ast_fileexists(prefile, NULL, NULL) > 0) {
                                if (ast_streamfile(chan, prefile, chan->language) > -1) 
                                    silent = ast_waitstream(chan, "#");
                        } else {
@@ -333,6 +497,8 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
                                                                        free(sfmt[y]);
                                                                break;
                                                        }
+                                                       if(!strcasecmp(sfmt[x], "wav"))
+                                                               wavother++;
                                                        free(sfmt[x]);
                                                }
                                                if (x == fmtcnt) {
@@ -340,7 +506,22 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
                                                           we read a # or get a hangup */
                                                        if (option_verbose > 2) 
                                                                ast_verbose( VERBOSE_PREFIX_3 "Recording to %s\n", fn);
-                                                       while((f = ast_read(chan))) {
+                                                       f = NULL;
+                                                       for(;;) {
+                                                               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);
@@ -378,6 +559,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
                                                        ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", fn, sfmt[x]); 
                                                        free(sfmt[x]);
                                                }
+
                                                ast_closestream(writer);
                                                for (x=0;x<fmtcnt;x++) {
                                                        if (!others[x])
@@ -391,8 +573,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
                                                                ast_waitstream(chan, "");
                                                        }
                                                        /* Send e-mail if applicable */
-                                                       if (email) 
-                                                               sendmail(astemail, email, name, msgnum, ext, chan->callerid);
+                                                               sendmail(astemail, email, name, msgnum, ext, chan->callerid, fn, wavother ? "wav" : fmts);
                                                }
                                        } else {
                                                if (msgnum < MAXMSG)
@@ -1014,6 +1195,45 @@ static int get_folder(struct ast_channel *chan, int start)
        return d;
 }
 
+static int
+forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int curmsg)
+{
+       char username[70];
+       char sys[256];
+       char todir[256];
+       int todircount=0;
+
+       while(1) {
+               ast_streamfile(chan, "vm-extension", chan->language);
+
+               if (ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0)
+                       return 0;
+               if (ast_variable_retrieve(cfg, NULL, username)) {
+                       printf("Got %d\n", atoi(username));
+                       if (play_and_wait(chan, "vm-savedto"))
+                               break;
+
+                       snprintf(todir, sizeof(todir), "%s/%s/INBOX", VM_SPOOL_DIR, username);
+                       snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir);
+                       puts(sys);
+                       system(sys);
+
+                       todircount = count_messages(todir);
+
+                       snprintf(sys, sizeof(sys), "cp %s/msg%04d.gsm %s/msg%04d.gsm\n", dir, curmsg, todir, todircount);
+                       puts(sys);
+                       system(sys);
+
+                       break;
+               } else {
+                       if ( play_and_wait(chan, "pbx-invalid"))
+                               break;
+               }
+       }
+
+       return 0;
+}
+
 #define WAITCMD(a) do { \
        d = (a); \
        if (d < 0) \
@@ -1132,7 +1352,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        int box;
        int useadsi = 0;
        struct ast_config *cfg;
-       
+
        LOCAL_USER_ADD(u);
        cfg = ast_load(VOICEMAIL_CONFIG);
        if (!cfg) {
@@ -1155,7 +1375,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
        
        do {
                /* Prompt for, and read in the username */
-               if (ast_readstring(chan, username, sizeof(username), 2000, 10000, "#") < 0) {
+               if (ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0) {
                        ast_log(LOG_WARNING, "Couldn't read username\n");
                        goto out;
                }                       
@@ -1171,7 +1391,7 @@ 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), 2000, 10000, "#") < 0) {
+               if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
                        ast_log(LOG_WARNING, "Unable to read password\n");
                        goto out;
                }
@@ -1219,6 +1439,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
                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 {
@@ -1339,6 +1560,11 @@ cmd:
                        else
                                WAITCMD(play_and_wait(chan, "vm-undeleted"));
                        goto instructions;
+               case '8':
+                       if(lastmsg > -1)
+                               if(forward_message(chan, cfg, curdir, curmsg) < 0)
+                                       goto out;
+                       goto instructions;
                case '9':
                        if (useadsi)
                                adsi_folders(chan, 1, "Save to folder...");
@@ -1406,6 +1632,7 @@ static int vm_exec(struct ast_channel *chan, void *data)
        struct localuser *u;
        char *ext = (char *)data;
        
+
        if (!data) {
                ast_log(LOG_WARNING, "vm requires an argument (extension)\n");
                return -1;