aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_voicemail.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2004-06-23 18:00:50 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2004-06-23 18:00:50 +0000
commit83dc4d51088942df3bae3b6da37e544e8db04ee2 (patch)
tree33d4fa4dbacb300bef77eaf0cf137ea082ca82d0 /apps/app_voicemail.c
parentcb8eee8b42a73eaa5c7c746b0deb317b891de9af (diff)
Merge Tilghman's voicemail broadcast improvements (thanks!)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3287 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_voicemail.c')
-rwxr-xr-xapps/app_voicemail.c307
1 files changed, 201 insertions, 106 deletions
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index e1d29430b..f5f242a85 100755
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -85,8 +85,6 @@ static inline void sql_close(void) { }
#define MAX_DATETIME_FORMAT 512
#define MAX_NUM_CID_CONTEXTS 10
-#define DIGITS_DIR AST_SOUNDS "/digits/"
-
struct baseio {
int iocp;
@@ -111,6 +109,7 @@ struct ast_vm_user {
char dialout[80];
char exit[80];
int attach;
+ int delete;
int alloced;
int saycid;
int review;
@@ -163,8 +162,8 @@ static char *synopsis_vm =
"Leave a voicemail message";
static char *descrip_vm =
-" VoiceMail([s|u|b]extension[@context]): Leaves voicemail for a given\n"
-"extension (must be configured in voicemail.conf).\n"
+" VoiceMail([s|u|b]extension[@context][&extension[@context]][...]): Leaves"
+"voicemail for a given extension (must be configured in voicemail.conf).\n"
" If the extension is preceded by \n"
"* 's' then instructions for leaving the message will be skipped.\n"
"* 'u' then the \"unavailable\" message will be played.\n"
@@ -176,6 +175,8 @@ static char *descrip_vm =
"extension 'a' in the current context.\n"
"If the requested mailbox does not exist, and there exists a priority\n"
"n + 101, then that priority will be taken next.\n"
+"When multiple mailboxes are specified, the unavailable or busy message\n"
+"will be taken from the first mailbox specified.\n"
"Returns -1 on error or mailbox not found, or if the user hangs up.\n"
"Otherwise, it returns 0.\n";
@@ -288,6 +289,8 @@ static void apply_options(struct ast_vm_user *vmu, char *options)
strncpy(vmu->serveremail, value, sizeof(vmu->serveremail) - 1);
} else if (!strcasecmp(var, "tz")) {
strncpy(vmu->zonetag, value, sizeof(vmu->zonetag) - 1);
+ } else if (!strcasecmp(var, "delete")) {
+ vmu->delete = ast_true(value);
} else if (!strcasecmp(var, "saycid")){
if(ast_true(value))
vmu->saycid = 1;
@@ -1499,6 +1502,128 @@ static void free_zone(struct vm_zone *z)
free(z);
}
+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 copy(char *infile, char *outfile)
+{
+ int ifd;
+ int ofd;
+ int res;
+ int len;
+ char buf[4096];
+
+#ifdef HARDLINK_WHEN_POSSIBLE
+ /* Hard link if possible; saves disk space & is faster */
+ if (link(infile, outfile)) {
+#endif
+ 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;
+#ifdef HARDLINK_WHEN_POSSIBLE
+ } else {
+ /* Hard link succeeded */
+ return 0;
+ }
+#endif
+}
+
+static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *callerid);
+
+static void copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt)
+{
+ char fromdir[256], todir[256], frompath[256], topath[256];
+ char *frombox = mbox(imbox);
+ int recipmsgnum;
+
+ ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
+
+ make_dir(todir, sizeof(todir), recip->context, "", "");
+ /* It's easier just to try to make it than to check for its existence */
+ if (mkdir(todir, 0700) && (errno != EEXIST))
+ ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", todir, strerror(errno));
+ make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "");
+ /* It's easier just to try to make it than to check for its existence */
+ if (mkdir(todir, 0700) && (errno != EEXIST))
+ ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", todir, strerror(errno));
+ make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
+ if (mkdir(todir, 0700) && (errno != EEXIST))
+ ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", todir, strerror(errno));
+
+ make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
+ make_file(frompath, sizeof(frompath), fromdir, msgnum);
+ recipmsgnum = 0;
+ do {
+ make_file(topath, sizeof(topath), todir, recipmsgnum);
+ if (ast_fileexists(topath, NULL, chan->language) <= 0)
+ break;
+ recipmsgnum++;
+ } while(recipmsgnum < MAXMSG);
+ if (recipmsgnum < MAXMSG) {
+ char frompath2[256],topath2[256];
+ ast_filecopy(frompath, topath, NULL);
+ snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
+ snprintf(topath2, sizeof(topath2), "%s.txt", topath);
+ copy(frompath2, topath2);
+ } else {
+ ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
+ }
+
+ notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->callerid);
+}
+
static void run_externnotify(char *context, char *extension, int numvoicemails)
{
char arguments[255];
@@ -1514,7 +1639,6 @@ static void run_externnotify(char *context, char *extension, int numvoicemails)
static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int busy, int unavail)
{
- char comment[256];
char txtfile[256];
FILE *txt;
int res = 0;
@@ -1529,18 +1653,24 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
char fmt[80];
char *context;
char ecodes[16] = "#";
- char *stringp;
- char tmp[256] = "";
+ char tmp[256] = "", *tmpptr;
struct ast_vm_user *vmu;
struct ast_vm_user svm;
-
strncpy(tmp, ext, sizeof(tmp) - 1);
ext = tmp;
context = strchr(tmp, '@');
if (context) {
*context = '\0';
context++;
+ tmpptr = strchr(context, '&');
+ } else {
+ tmpptr = strchr(ext, '&');
+ }
+
+ if (tmpptr) {
+ *tmpptr = '\0';
+ tmpptr++;
}
if ((vmu = find_user(&svm, context, ext))) {
@@ -1641,9 +1771,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
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"),
- vmu->fullname, ext, chan->name);
if (ast_fileexists(fn, NULL, chan->language) <= 0)
break;
msgnum++;
@@ -1697,24 +1824,23 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
vm_delete(fn);
goto leave_vm_out;
}
- stringp = fmt;
- strsep(&stringp, "|");
- /* Send e-mail if applicable */
- if (strlen(vmu->email)) {
- int attach_user_voicemail = attach_voicemail;
- char *myserveremail = serveremail;
- if (vmu->attach > -1)
- attach_user_voicemail = vmu->attach;
- if (strlen(vmu->serveremail))
- myserveremail = vmu->serveremail;
- sendmail(myserveremail, vmu, msgnum, ext, chan->callerid, fn, fmt, duration, attach_user_voicemail);
- }
- if (strlen(vmu->pager)) {
- char *myserveremail = serveremail;
- if (strlen(vmu->serveremail))
- myserveremail = vmu->serveremail;
- sendpage(myserveremail, vmu->pager, msgnum, ext, chan->callerid, duration, vmu);
+ /* Are there to be more recipients of this message? */
+ while (tmpptr) {
+ struct ast_vm_user recipu, *recip;
+ char *exten, *context;
+
+ exten = strsep(&tmpptr, "&");
+ context = strchr(exten, '@');
+ if (context) {
+ *context = '\0';
+ context++;
+ }
+ if ((recip = find_user(&recipu, context, exten))) {
+ copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
+ free_user(recip);
+ }
}
+ notify_new_message(chan, vmu, msgnum, duration, fmt, chan->callerid);
} else {
res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
if (!res)
@@ -1722,52 +1848,19 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
ast_log(LOG_WARNING, "No more messages possible\n");
}
} else
- ast_log(LOG_WARNING, "No format for saving voicemail?\n");
+ ast_log(LOG_WARNING, "No format for saving voicemail?\n");
leave_vm_out:
free_user(vmu);
} else {
ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
- /*Send the call to n+101 priority, where n is the current priority*/
- if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
- chan->priority+=100;
+ /*Send the call to n+101 priority, where n is the current priority*/
+ if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
+ chan->priority+=100;
}
- /* Leave voicemail for someone */
- manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, ast_app_has_voicemail(ext_context));
-
- /* If an external program is specified to be run after leaving a voicemail */
- run_externnotify(chan->context, ext_context, ast_app_has_voicemail(ext_context));
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;
@@ -1787,45 +1880,6 @@ static int say_and_wait(struct ast_channel *chan, int num)
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 *context, char *username, int box)
{
char sfn[256];
@@ -2422,6 +2476,49 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu,
return cmd;
}
+static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *callerid)
+{
+ char todir[256], fn[256], *stringp;
+
+ make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
+ make_file(fn, sizeof(fn), todir, msgnum);
+
+ /* Attach only the first format */
+ fmt = ast_strdupa(fmt);
+ if (fmt) {
+ stringp = fmt;
+ strsep(&stringp, "|");
+
+ if (strlen(vmu->email)) {
+ int attach_user_voicemail = attach_voicemail;
+ char *myserveremail = serveremail;
+ if (vmu->attach > -1)
+ attach_user_voicemail = vmu->attach;
+ if (strlen(vmu->serveremail))
+ myserveremail = vmu->serveremail;
+ sendmail(myserveremail, vmu, msgnum, vmu->mailbox, callerid, fn, fmt, duration, attach_user_voicemail);
+ }
+
+ if (strlen(vmu->pager)) {
+ char *myserveremail = serveremail;
+ if (strlen(vmu->serveremail))
+ myserveremail = vmu->serveremail;
+ sendpage(myserveremail, vmu->pager, msgnum, vmu->mailbox, callerid, duration, vmu);
+ }
+ } else {
+ ast_log(LOG_ERROR, "Out of memory\n");
+ }
+
+ if (vmu->delete) {
+ vm_delete(fn);
+ }
+
+ /* Leave voicemail for someone */
+ manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", vmu->mailbox, ast_app_has_voicemail(vmu->mailbox));
+ run_externnotify(chan->context, vmu->mailbox, ast_app_has_voicemail(vmu->mailbox));
+ return 0;
+}
+
static int forward_message(struct ast_channel *chan, char *context, char *dir, int curmsg, struct ast_vm_user *sender, char *fmt)
{
char username[70];
@@ -3363,12 +3460,10 @@ out:
snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, ast_app_has_voicemail(ext_context));
run_externnotify(chan->context, ext_context, ast_app_has_voicemail(ext_context));
-
}
LOCAL_USER_REMOVE(u);
return res;
-
}
static int vm_exec(struct ast_channel *chan, void *data)