dect
/
asterisk
Archived
13
0
Fork 0

Version 0.1.9 from FTP

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@349 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
markster 2001-08-05 21:46:13 +00:00
parent 384c0bdcf3
commit e3b8316f38
3 changed files with 496 additions and 246 deletions

View File

@ -30,11 +30,12 @@ static char *app = "Directory";
static char *synopsis = "Provide directory of voicemail extensions";
static char *descrip =
" Directory(context): Presents the user with a directory of extensions from which\n"
" they may select by name. The list of names and extensions is discovered from\n"
" voicemail.conf. The context argument is required, and specifies the context\n"
" in which to interpret the extensions\n. Returns 0 unless the user hangs up. It\n"
" also sets up the channel on exit to enter the extension the user selected.\n";
" Directory(context): Presents the user with a directory of extensions from\n"
"which they may select by name. The list of names and extensions is\n"
"discovered from voicemail.conf. The context argument is required, and\n"
"specifies the context in which to interpret the extensions\n. Returns 0\n"
"unless the user hangs up. It also sets up the channel on exit to enter the\n"
"extension the user selected.\n";
/* For simplicity, I'm keeping the format compatible with the voicemail config,
but i'm open to suggestions for isolating it */
@ -129,7 +130,8 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
char fn[256];
memset(ext, 0, sizeof(ext));
ext[0] = digit;
res = ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#");
res = 0;
if (ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#") < 0) res = -1;
if (!res) {
/* Search for all names which start with those digits */
v = ast_variable_browse(cfg, context);

View File

@ -37,10 +37,6 @@
#define VOICEMAIL_CONFIG "voicemail.conf"
#define ASTERISK_USERNAME "asterisk"
/*
#define HOSTNAME_OVERRIDE "linux-support.net"
*/
#define SENDMAIL "/usr/sbin/sendmail -t"
#define INTRO "vm-intro"
@ -58,10 +54,10 @@ static char *synopsis_vm =
"Leave a voicemail message";
static char *descrip_vm =
" VoiceMail([s]extension): Leaves voicemail for a given extension (must be configured in\n"
" voicemail.conf). If the extension is preceeded by an 's' then instructions for leaving\n"
" the message will be skipped. Returns -1 on error or mailbox not found, or if the user\n"
" hangs up. Otherwise, it returns 0. \n";
" VoiceMail([s]extension): Leaves voicemail for a given extension (must be\n"
"configured in voicemail.conf). If the extension is preceeded by an 's' then\n"
"instructions for leaving the message will be skipped. Returns -1 on error\n"
"or mailbox not found, or if the user hangs up. Otherwise, it returns 0. \n";
static char *synopsis_vmain =
"Enter voicemail system";
@ -80,19 +76,18 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char *get_dir(char *ext, char *mailbox)
static int make_dir(char *dest, int len, char *ext, char *mailbox)
{
char *tmp = malloc(strlen(ext) + strlen(VM_SPOOL_DIR) + 3 + strlen(mailbox));
sprintf(tmp, "%s/%s/%s", VM_SPOOL_DIR, ext, mailbox);
return tmp;
return snprintf(dest, len, "%s/%s/%s", VM_SPOOL_DIR, ext, mailbox);
}
static char *get_fn(char *dir, int num)
static int make_file(char *dest, int len, char *dir, int num)
{
char *tmp = malloc(strlen(dir) + 10);
sprintf(tmp, "%s/msg%04d", dir, num);
return tmp;
return snprintf(dest, len, "%s/msg%04d", dir, num);
}
#if 0
static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
{
char *fn;
@ -115,34 +110,37 @@ static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
ast_log(LOG_WARNING, "Unable to announce message\n");
return res;
}
static int sendmail(char *email, char *name, int msgnum, char *mailbox)
#endif
static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *mailbox, char *callerid)
{
FILE *p;
char date[256];
char host[256];
char who[256];
time_t t;
struct tm *tm;
p = popen(SENDMAIL, "w");
if (p) {
gethostname(host, sizeof(host));
if (strchr(srcemail, '@'))
strncpy(who, srcemail, sizeof(who));
else {
gethostname(host, sizeof(host));
snprintf(who, sizeof(who), "%s@%s", srcemail, host);
}
time(&t);
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@%s>\n", ASTERISK_USERNAME,
#ifdef HOSTNAME_OVERRIDE
HOSTNAME_OVERRIDE
#else
host
#endif
);
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);
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, 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, msgnum, mailbox, date);
"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,
msgnum, mailbox, (callerid ? callerid : "an unknown caller"), date);
fprintf(p, ".\n");
pclose(p);
} else {
@ -164,7 +162,7 @@ static int get_date(char *s, int len)
static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
{
struct ast_config *cfg;
char *copy, *name, *passwd, *email, *dir, *fmt, *fmts, *fn=NULL;
char *copy, *name, *passwd, *email, *fmt, *fmts;
char comment[256];
struct ast_filestream *writer=NULL, *others[MAX_OTHER_FORMATS];
char *sfmt[MAX_OTHER_FORMATS];
@ -175,23 +173,28 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
int outmsg=0;
struct ast_frame *f;
char date[256];
char dir[256];
char fn[256];
char *astemail;
cfg = ast_load(VOICEMAIL_CONFIG);
if (!cfg) {
ast_log(LOG_WARNING, "No such configuration file %s\n", VOICEMAIL_CONFIG);
return -1;
}
if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
astemail = ASTERISK_USERNAME;
if ((copy = ast_variable_retrieve(cfg, NULL, ext))) {
/* Make sure they have an entry in the config */
copy = strdup(copy);
passwd = strtok(copy, ",");
name = strtok(NULL, ",");
email = strtok(NULL, ",");
dir = get_dir(ext, "");
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))
ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
dir = get_dir(ext, "INBOX");
make_dir(dir, sizeof(dir), ext, "INBOX");
if (mkdir(dir, 0700) && (errno != EEXIST))
ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
/* Stream an info message */
@ -204,9 +207,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
fmt = strtok(fmts, "|");
msgnum = 0;
do {
if (fn)
free(fn);
fn = get_fn(dir, msgnum);
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);
@ -328,7 +329,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
}
/* Send e-mail if applicable */
if (email)
sendmail(email, name, msgnum, ext);
sendmail(astemail, email, name, msgnum, ext, chan->callerid);
}
} else {
if (msgnum < MAXMSG)
@ -336,8 +337,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
else
ast_log(LOG_WARNING, "Too many messages in mailbox %s\n", ext);
}
if (fn)
free(fn);
free(fmts);
} else
ast_log(LOG_WARNING, "No format to save messages in \n");
@ -345,7 +344,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
} else
ast_log(LOG_WARNING, "Unable to playback instructions\n");
free(dir);
free(copy);
} else
ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
@ -354,25 +352,276 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
return res;
}
static char *mbox(int id)
{
switch(id) {
case 0:
return "INBOX";
case 1:
return "Old";
case 2:
return "Work";
case 3:
return "Family";
case 4:
return "Friends";
case 5:
return "Cust1";
case 6:
return "Cust2";
case 7:
return "Cust3";
case 8:
return "Cust4";
case 9:
return "Cust5";
default:
return "Unknown";
}
}
static int count_messages(char *dir)
{
int x;
char fn[256];
for (x=0;x<MAXMSG;x++) {
make_file(fn, sizeof(fn), dir, x);
if (ast_fileexists(fn, NULL, NULL) < 1)
break;
}
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;
d = ast_say_number(chan, num, chan->language);
return d;
}
static int copy(char *infile, char *outfile)
{
int ifd;
int ofd;
int res;
int len;
char buf[4096];
if ((ifd = open(infile, O_RDONLY)) < 0) {
ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
return -1;
}
if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
close(ifd);
return -1;
}
do {
len = read(ifd, buf, sizeof(buf));
if (len < 0) {
ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
close(ifd);
close(ofd);
unlink(outfile);
}
if (len) {
res = write(ofd, buf, len);
if (res != len) {
ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
close(ifd);
close(ofd);
unlink(outfile);
}
}
} while(len);
close(ifd);
close(ofd);
return 0;
}
static int save_to_folder(char *dir, int msg, char *username, int box)
{
char sfn[256];
char dfn[256];
char ddir[256];
char txt[256];
char ntxt[256];
char *dbox = mbox(box);
int x;
make_file(sfn, sizeof(sfn), dir, msg);
make_dir(ddir, sizeof(ddir), username, dbox);
mkdir(ddir, 0700);
for (x=0;x<MAXMSG;x++) {
make_file(dfn, sizeof(dfn), ddir, x);
if (ast_fileexists(dfn, NULL, NULL) < 0)
break;
}
if (x >= MAXMSG)
return -1;
ast_filecopy(sfn, dfn, NULL);
if (strcmp(sfn, dfn)) {
snprintf(txt, sizeof(txt), "%s.txt", sfn);
snprintf(ntxt, sizeof(ntxt), "%s.txt", dfn);
copy(txt, ntxt);
}
return 0;
}
static int get_folder(struct ast_channel *chan, int start)
{
int x;
int d;
char fn[256];
d = play_and_wait(chan, "vm-press");
if (d)
return d;
for (x = start; x< 5; x++) {
if ((d = ast_say_number(chan, x, chan->language)))
return d;
d = play_and_wait(chan, "vm-for");
if (d)
return d;
snprintf(fn, sizeof(fn), "vm-%s", mbox(x));
d = play_and_wait(chan, fn);
if (d)
return d;
d = play_and_wait(chan, "vm-messages");
if (d)
return d;
d = ast_waitfordigit(chan, 500);
if (d)
return d;
}
d = play_and_wait(chan, "vm-tocancel");
if (d)
return d;
d = ast_waitfordigit(chan, 4000);
return d;
}
#define WAITCMD(a) do { \
d = (a); \
if (d < 0) \
goto out; \
if (d) \
goto cmd; \
} while(0)
#define WAITFILE2(file) do { \
if (ast_streamfile(chan, file, chan->language)) \
ast_log(LOG_WARNING, "Unable to play message %s\n", file); \
d = ast_waitstream(chan, AST_DIGIT_ANY); \
if (d < 0) { \
goto out; \
}\
} while(0)
#define WAITFILE(file) do { \
if (ast_streamfile(chan, file, chan->language)) \
ast_log(LOG_WARNING, "Unable to play message %s\n", file); \
d = ast_waitstream(chan, AST_DIGIT_ANY); \
if (!d) { \
repeats = 0; \
goto instructions; \
} else if (d < 0) { \
goto out; \
} else goto cmd;\
} while(0)
#define PLAYMSG(a) do { \
starting = 0; \
if (!a) \
WAITFILE2("vm-first"); \
else if (a == lastmsg) \
WAITFILE2("vm-last"); \
WAITFILE2("vm-message"); \
if (a && (a != lastmsg)) { \
d = ast_say_number(chan, a + 1, chan->language); \
if (d < 0) goto out; \
if (d) goto cmd; \
} \
make_file(fn, sizeof(fn), curdir, a); \
heard[a] = 1; \
WAITFILE(fn); \
} while(0)
#define CLOSE_MAILBOX do { \
if (lastmsg > -1) { \
/* Get the deleted messages fixed */ \
curmsg = -1; \
for (x=0;x<=lastmsg;x++) { \
if (!deleted[x] && (strcasecmp(curbox, "INBOX") || !heard[x])) { \
/* Save this message. It's not in INBOX or hasn't been heard */ \
curmsg++; \
make_file(fn, sizeof(fn), curdir, x); \
make_file(fn2, sizeof(fn2), curdir, curmsg); \
if (strcmp(fn, fn2)) { \
snprintf(txt, sizeof(txt), "%s.txt", fn); \
snprintf(ntxt, sizeof(ntxt), "%s.txt", fn2); \
ast_filerename(fn, fn2, NULL); \
rename(txt, ntxt); \
} \
} else if (!strcasecmp(curbox, "INBOX") && heard[x] && !deleted[x]) { \
/* Move to old folder before deleting */ \
save_to_folder(curdir, x, username, 1); \
} \
} \
for (x = curmsg + 1; x<=lastmsg; x++) { \
make_file(fn, sizeof(fn), curdir, x); \
snprintf(txt, sizeof(txt), "%s.txt", fn); \
ast_filedelete(fn, NULL); \
unlink(txt); \
} \
} \
memset(deleted, 0, sizeof(deleted)); \
memset(heard, 0, sizeof(heard)); \
} while(0)
#define OPEN_MAILBOX(a) do { \
strcpy(curbox, mbox(a)); \
make_dir(curdir, sizeof(curdir), username, curbox); \
lastmsg = count_messages(curdir) - 1; \
snprintf(vmbox, sizeof(vmbox), "vm-%s", curbox); \
} while (0)
static int vm_execmain(struct ast_channel *chan, void *data)
{
/* XXX This is, admittedly, some pretty horrendus code XXX */
/* XXX This is, admittedly, some pretty horrendus code. For some
reason it just seemed a lot easier to do with GOTO's. I feel
like I'm back in my GWBASIC days. XXX */
int res=-1;
int valid = 0;
int curmsg = 0;
int maxmsg = 0;
int x;
char *fn, *nfn;
char d;
struct localuser *u;
char username[80];
char password[80], *copy;
int deleted[MAXMSG];
char curbox[80];
char curdir[256];
char vmbox[256];
char fn[256];
char fn2[256];
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;
struct ast_config *cfg;
int state;
char *dir=NULL;
LOCAL_USER_ADD(u);
cfg = ast_load(VOICEMAIL_CONFIG);
@ -386,9 +635,12 @@ static int vm_execmain(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "Couldn't stream login file\n");
goto out;
}
/* Authenticate them and get their mailbox/password */
do {
/* Prompt for, and read in the username */
if (ast_readstring(chan, username, sizeof(username), 2000, 10000, "#")) {
if (ast_readstring(chan, username, sizeof(username), 2000, 10000, "#") < 0) {
ast_log(LOG_WARNING, "Couldn't read username\n");
goto out;
}
@ -402,7 +654,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, "#")) {
if (ast_readstring(chan, password, sizeof(password), 2000, 10000, "#") < 0) {
ast_log(LOG_WARNING, "Unable to read password\n");
goto out;
}
@ -424,208 +676,175 @@ static int vm_execmain(struct ast_channel *chan, void *data)
break;
}
} while (!valid);
if (valid) {
dir = get_dir(username, "INBOX");
if (!dir)
goto out;
deleted[0] = 0;
/* Find out how many messages are there, mark all as
not deleted. */
do {
fn = get_fn(dir, maxmsg);
if ((res = ast_fileexists(fn, NULL, chan->language))>0) {
maxmsg++;
deleted[maxmsg] = 0;
}
free(fn);
} while(res > 0);
if (ast_streamfile(chan, "vm-youhave", chan->language))
goto out;
if ((d=ast_waitstream(chan, AST_DIGIT_ANY)) < 0)
goto out;
ast_stopstream(chan);
if (!d) {
/* If they haven't interrupted us, play the message count */
if (maxmsg > 0) {
if ((d = ast_say_number(chan, maxmsg, chan->language)) < 0)
goto out;
} else {
if (ast_streamfile(chan, "vm-no", chan->language))
goto out;
if ((d=ast_waitstream(chan, AST_DIGIT_ANY)) < 0)
goto out;
ast_stopstream(chan);
}
if (!d) {
/* And if they still haven't, give them the last word */
if (ast_streamfile(chan, ((maxmsg == 1) ? "vm-message" : "vm-messages"), chan->language))
goto out;
if (ast_waitstream(chan, AST_DIGIT_ANY) < 0)
goto out;
ast_stopstream(chan);
}
}
res = -1;
if (valid) {
OPEN_MAILBOX(1);
oldmessages = lastmsg + 1;
/* Start in INBOX */
OPEN_MAILBOX(0);
newmessages = lastmsg + 1;
WAITCMD(play_and_wait(chan, "vm-youhave"));
if (newmessages) {
WAITCMD(say_and_wait(chan, newmessages));
WAITCMD(play_and_wait(chan, "vm-INBOX"));
if (newmessages == 1)
WAITCMD(play_and_wait(chan, "vm-message"));
else
WAITCMD(play_and_wait(chan, "vm-messages"));
#define STATE_STARTING 1
#define STATE_MESSAGE 2
#define STATE_MESSAGE_PLAYING 3
state = STATE_STARTING;
ast_log(LOG_EVENT, "User '%s' logged in on channel '%s' with %d message(s).\n", username, chan->name, maxmsg);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "User '%s' logged in on channel %s with %d messages\n", username, chan->name, maxmsg);
if (!ast_streamfile(chan, "vm-instructions", chan->language)) {
for(;;) {
if (chan->stream) {
d = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
if (!d && (state == STATE_MESSAGE_PLAYING)) {
state = STATE_MESSAGE;
/* If it runs out playing a message, then give directions */
if (!(d = ast_streamfile(chan, "vm-msginstruct", chan->language)))
d = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
}
if (!d)
d = ast_waitfordigit(chan, COMMAND_TIMEOUT);
} else
d = ast_waitfordigit(chan, COMMAND_TIMEOUT);
if (d < 0)
if (oldmessages)
WAITCMD(play_and_wait(chan, "vm-and"));
}
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"));
}
if (!newmessages && oldmessages) {
/* If we only have old messages start here */
OPEN_MAILBOX(1);
}
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;
}
goto instructions;
}
cmd:
switch(d) {
case '2':
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;
restart:
if (!d || (d == '*')) {
/* If they don't say anything, play back a message. We'll decide which one is
best based up on where they are. Ditto if they press the '*' key. */
switch(state) {
case STATE_STARTING:
if (ast_streamfile(chan, "vm-instructions", chan->language))
goto out;
break;
case STATE_MESSAGE:
case STATE_MESSAGE_PLAYING:
if (ast_streamfile(chan, "vm-msginstruct", chan->language))
goto out;
break;
default:
ast_log(LOG_WARNING, "What do I do when they timeout/* in state %d?\n", state);
}
} else {
/* XXX Should we be command-compatible with Meridian mail? Their system seems
very confusing, but also widely used XXX */
/* They've entered (or started to enter) a command */
switch(d) {
case '0':
if (curmsg < maxmsg) {
deleted[curmsg] = !deleted[curmsg];
if (deleted[curmsg]) {
if (ast_streamfile(chan, "vm-deleted", chan->language))
goto out;
} else {
if (ast_streamfile(chan, "vm-undeleted", chan->language))
goto out;
}
} else {
if (ast_streamfile(chan, "vm-nomore", chan->language))
goto out;
}
break;
case '1':
curmsg = 0;
if (maxmsg > 0) {
/* Yuck */
if ((d = announce_message(chan, dir, curmsg)) > 0)
goto restart;
else if (d < 0)
goto out;
} else {
if (ast_streamfile(chan, "vm-nomore", chan->language))
goto out;
}
state = STATE_MESSAGE_PLAYING;
break;
case '4':
if (curmsg > 0)
curmsg--;
/* Yuck */
if ((d = announce_message(chan, dir, curmsg)) > 0)
goto restart;
else if (d < 0)
goto out;
state = STATE_MESSAGE_PLAYING;
break;
case '5':
if ((d = announce_message(chan, dir, curmsg)) > 0)
goto restart;
else if (d < 0)
goto out;
state = STATE_MESSAGE_PLAYING;
break;
case '6':
if (curmsg < maxmsg - 1) {
curmsg++;
if ((d = announce_message(chan, dir, curmsg)) > 0)
goto restart;
else if (d < 0)
goto out;
} else {
if (ast_streamfile(chan, "vm-nomore", chan->language))
goto out;
}
state = STATE_MESSAGE_PLAYING;
break;
/* XXX Message compose? It's easy! Just read their # and, assuming it's in the config,
call the routine as if it were called from the PBX proper XXX */
case '#':
if (ast_streamfile(chan, "vm-goodbye", chan->language))
goto out;
if (ast_waitstream(chan, ""))
goto out;
res = 0;
goto out;
break;
default:
/* Double yuck */
d = '*';
goto restart;
}
}
if (box == '#')
goto instructions;
}
box = box - '0';
CLOSE_MAILBOX;
OPEN_MAILBOX(box);
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;
}
}
}
out:
ast_stopstream(chan);
if (maxmsg) {
/* Get the deleted messages fixed */
curmsg = -1;
for (x=0;x<maxmsg;x++) {
if (!deleted[x]) {
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++;
fn = get_fn(dir, x);
nfn = get_fn(dir, curmsg);
if (strcmp(fn, nfn)) {
snprintf(txt, sizeof(txt), "%s.txt", fn);
snprintf(ntxt, sizeof(ntxt), "%s.txt", nfn);
ast_filerename(fn, nfn, NULL);
rename(txt, ntxt);
}
free(fn);
free(nfn);
PLAYMSG(curmsg);
} else {
WAITCMD(play_and_wait(chan, "vm-nomore"));
goto instructions;
}
}
for (x = curmsg + 1; x<maxmsg; x++) {
fn = get_fn(dir, x);
if (fn) {
snprintf(txt, sizeof(txt), "%s.txt", fn);
ast_filedelete(fn, NULL);
unlink(txt);
free(fn);
case '7':
deleted[curmsg] = !deleted[curmsg];
if (deleted[curmsg])
WAITCMD(play_and_wait(chan, "vm-deleted"));
else
WAITCMD(play_and_wait(chan, "vm-undeleted"));
goto instructions;
case '9':
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';
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;
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 '#':
play_and_wait(chan, "vm-goodbye");
goto out;
default:
goto instructions;
}
}
if (dir)
free(dir);
out:
CLOSE_MAILBOX;
ast_stopstream(chan);
if (cfg)
ast_destroy(cfg);
LOCAL_USER_REMOVE(u);
@ -647,6 +866,8 @@ static int vm_exec(struct ast_channel *chan, void *data)
silent++;
ext++;
}
if (chan->state != AST_STATE_UP)
ast_answer(chan);
res = leave_voicemail(chan, ext, silent);
LOCAL_USER_REMOVE(u);
return res;

27
include/asterisk/app.h Executable file
View File

@ -0,0 +1,27 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Application convenience functions, designed to give consistent
* look and feel to asterisk apps.
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#ifndef _ASTERISK_APP_H
#define _ASTERISK_APP_H
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
extern int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif