summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/app_dial.c5
-rw-r--r--apps/app_followme.c93
-rw-r--r--apps/app_queue.c4
-rw-r--r--apps/app_voicemail.c226
4 files changed, 232 insertions, 96 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 11591bdfb..5e034d3eb 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -872,6 +872,8 @@ static void do_forward(struct chanlist *o, struct cause_args *num,
/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", ast_channel_name(in), tech, stuff);
+ ast_channel_publish_dial_forward(in, original, NULL, NULL, "CANCEL",
+ ast_channel_call_forward(original));
c = o->chan = NULL;
cause = AST_CAUSE_BUSY;
} else {
@@ -1385,6 +1387,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
pa->sentringing++;
}
}
+ ast_channel_publish_dial(in, c, NULL, "RINGING");
break;
case AST_CONTROL_PROGRESS:
ast_verb(3, "%s is making progress passing it to %s\n", ast_channel_name(c), ast_channel_name(in));
@@ -1404,6 +1407,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
dtmf_progress);
ast_dtmf_stream(c, in, dtmf_progress, 250, 0);
}
+ ast_channel_publish_dial(in, c, NULL, "PROGRESS");
break;
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
@@ -1476,6 +1480,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
}
if (!ast_test_flag64(outgoing, OPT_RINGBACK))
ast_indicate(in, AST_CONTROL_PROCEEDING);
+ ast_channel_publish_dial(in, c, NULL, "PROCEEDING");
break;
case AST_CONTROL_HOLD:
/* XXX this should be saved like AST_CONTROL_CONNECTED_LINE for !single || caller_entertained */
diff --git a/apps/app_followme.c b/apps/app_followme.c
index 106902043..a955843bc 100644
--- a/apps/app_followme.c
+++ b/apps/app_followme.c
@@ -168,6 +168,8 @@ struct call_followme {
char context[AST_MAX_CONTEXT]; /*!< Context to dial from */
unsigned int active; /*!< Profile is active (1), or disabled (0). */
int realtime; /*!< Cached from realtime */
+ /*! Allow callees to accept/reject the forwarded call */
+ unsigned int enable_callee_prompt:1;
char takecall[MAX_YN_STRING]; /*!< Digit mapping to take a call */
char nextindp[MAX_YN_STRING]; /*!< Digit mapping to decline a call */
char callfromprompt[PATH_MAX]; /*!< Sound prompt name and path */
@@ -198,6 +200,8 @@ struct fm_args {
unsigned int pending_out_connected_update:1;
/*! TRUE if caller has a pending hold request for the winning call. */
unsigned int pending_hold:1;
+ /*! TRUE if callees will be prompted to answer */
+ unsigned int enable_callee_prompt:1;
/*! Music On Hold Class suggested by caller hold for winning call. */
char suggested_moh[MAX_MUSICCLASS];
char context[AST_MAX_CONTEXT];
@@ -268,6 +272,7 @@ static const char *defaultmoh = "default"; /*!< Default Music-On-Hold Class
static char takecall[MAX_YN_STRING] = "1";
static char nextindp[MAX_YN_STRING] = "2";
+static int enable_callee_prompt = 1;
static char callfromprompt[PATH_MAX] = "followme/call-from";
static char norecordingprompt[PATH_MAX] = "followme/no-recording";
static char optionsprompt[PATH_MAX] = "followme/options";
@@ -313,6 +318,7 @@ static struct call_followme *alloc_profile(const char *fmname)
ast_copy_string(f->name, fmname, sizeof(f->name));
f->moh[0] = '\0';
f->context[0] = '\0';
+ f->enable_callee_prompt = enable_callee_prompt;
ast_copy_string(f->takecall, takecall, sizeof(f->takecall));
ast_copy_string(f->nextindp, nextindp, sizeof(f->nextindp));
ast_copy_string(f->callfromprompt, callfromprompt, sizeof(f->callfromprompt));
@@ -343,6 +349,8 @@ static void profile_set_param(struct call_followme *f, const char *param, const
ast_copy_string(f->moh, val, sizeof(f->moh));
else if (!strcasecmp(param, "context"))
ast_copy_string(f->context, val, sizeof(f->context));
+ else if (!strcasecmp(param, "enable_callee_prompt"))
+ f->enable_callee_prompt = ast_true(val);
else if (!strcasecmp(param, "takecall"))
ast_copy_string(f->takecall, val, sizeof(f->takecall));
else if (!strcasecmp(param, "declinecall"))
@@ -398,6 +406,7 @@ static int reload_followme(int reload)
char *numberstr;
int timeout;
int numorder;
+ const char* enable_callee_prompt_str;
const char *takecallstr;
const char *declinecallstr;
const char *tmpstr;
@@ -430,6 +439,12 @@ static int reload_followme(int reload)
featuredigittimeout = 5000;
}
+ if ((enable_callee_prompt_str = ast_variable_retrieve(cfg, "general",
+ "enable_callee_prompt")) &&
+ !ast_strlen_zero(enable_callee_prompt_str)) {
+ enable_callee_prompt = ast_true(enable_callee_prompt_str);
+ }
+
if ((takecallstr = ast_variable_retrieve(cfg, "general", "takecall")) && !ast_strlen_zero(takecallstr)) {
ast_copy_string(takecall, takecallstr, sizeof(takecall));
}
@@ -651,26 +666,30 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
if (tmpuser->digts && (tmpuser->digts > featuredigittimeout)) {
ast_verb(3, "<%s> We've been waiting for digits longer than we should have.\n",
ast_channel_name(tmpuser->ochan));
- if (!ast_strlen_zero(tpargs->namerecloc)) {
- tmpuser->state = 1;
- tmpuser->digts = 0;
- if (!ast_streamfile(tmpuser->ochan, callfromname, ast_channel_language(tmpuser->ochan))) {
- ast_sched_runq(ast_channel_sched(tmpuser->ochan));
+ if (tpargs->enable_callee_prompt) {
+ if (!ast_strlen_zero(tpargs->namerecloc)) {
+ tmpuser->state = 1;
+ tmpuser->digts = 0;
+ if (!ast_streamfile(tmpuser->ochan, callfromname, ast_channel_language(tmpuser->ochan))) {
+ ast_sched_runq(ast_channel_sched(tmpuser->ochan));
+ } else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
+ clear_caller(tmpuser);
+ continue;
+ }
} else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
- clear_caller(tmpuser);
- continue;
+ tmpuser->state = 2;
+ tmpuser->digts = 0;
+ if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, ast_channel_language(tmpuser->ochan)))
+ ast_sched_runq(ast_channel_sched(tmpuser->ochan));
+ else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
+ clear_caller(tmpuser);
+ continue;
+ }
}
} else {
- tmpuser->state = 2;
- tmpuser->digts = 0;
- if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, ast_channel_language(tmpuser->ochan)))
- ast_sched_runq(ast_channel_sched(tmpuser->ochan));
- else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
- clear_caller(tmpuser);
- continue;
- }
+ tmpuser->state = 3;
}
}
if (ast_channel_stream(tmpuser->ochan)) {
@@ -787,23 +806,28 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
/* If call has been answered, then the eventual hangup is likely to be normal hangup */
ast_channel_hangupcause_set(winner, AST_CAUSE_NORMAL_CLEARING);
ast_channel_hangupcause_set(caller, AST_CAUSE_NORMAL_CLEARING);
- ast_verb(3, "Starting playback of %s\n", callfromname);
- if (!ast_strlen_zero(tpargs->namerecloc)) {
- if (!ast_streamfile(winner, callfromname, ast_channel_language(winner))) {
- ast_sched_runq(ast_channel_sched(winner));
- tmpuser->state = 1;
+ if (tpargs->enable_callee_prompt) {
+ ast_verb(3, "Starting playback of %s\n", callfromname);
+ if (!ast_strlen_zero(tpargs->namerecloc)) {
+ if (!ast_streamfile(winner, callfromname, ast_channel_language(winner))) {
+ ast_sched_runq(ast_channel_sched(winner));
+ tmpuser->state = 1;
+ } else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
+ clear_caller(tmpuser);
+ }
} else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
- clear_caller(tmpuser);
+ tmpuser->state = 2;
+ if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, ast_channel_language(tmpuser->ochan)))
+ ast_sched_runq(ast_channel_sched(tmpuser->ochan));
+ else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
+ clear_caller(tmpuser);
+ }
}
} else {
+ ast_verb(3, "Skip playback of caller name / norecording\n");
tmpuser->state = 2;
- if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, ast_channel_language(tmpuser->ochan)))
- ast_sched_runq(ast_channel_sched(tmpuser->ochan));
- else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
- clear_caller(tmpuser);
- }
}
break;
case AST_CONTROL_BUSY:
@@ -824,9 +848,11 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
break;
case AST_CONTROL_RINGING:
ast_verb(3, "%s is ringing\n", ast_channel_name(winner));
+ ast_channel_publish_dial(caller, winner, NULL, "RINGING");
break;
case AST_CONTROL_PROGRESS:
ast_verb(3, "%s is making progress\n", ast_channel_name(winner));
+ ast_channel_publish_dial(caller, winner, NULL, "PROGRESS");
break;
case AST_CONTROL_VIDUPDATE:
ast_verb(3, "%s requested a video update\n", ast_channel_name(winner));
@@ -836,6 +862,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
break;
case AST_CONTROL_PROCEEDING:
ast_verb(3, "%s is proceeding\n", ast_channel_name(winner));
+ ast_channel_publish_dial(caller, winner, NULL, "PROCEEDING");
break;
case AST_CONTROL_HOLD:
ast_verb(3, "%s placed call on hold\n", ast_channel_name(winner));
@@ -927,6 +954,11 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
break;
}
}
+ if (!tpargs->enable_callee_prompt && tmpuser) {
+ ast_debug(1, "Taking call with no prompt\n");
+ ast_frfree(f);
+ return tmpuser->ochan;
+ }
if (tmpuser && tmpuser->state == 3 && f->frametype == AST_FRAME_DTMF) {
int cmp_len;
@@ -1365,6 +1397,7 @@ static int app_exec(struct ast_channel *chan, const char *data)
/* Lock the profile lock and copy out everything we need to run with before unlocking it again */
ast_mutex_lock(&f->lock);
+ targs->enable_callee_prompt = f->enable_callee_prompt;
targs->mohclass = ast_strdupa(f->moh);
ast_copy_string(targs->context, f->context, sizeof(targs->context));
ast_copy_string(targs->takecall, f->takecall, sizeof(targs->takecall));
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 8171d11cb..165924e0c 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -4846,6 +4846,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
/* Before processing channel, go ahead and check for forwarding */
if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
+ ast_channel_publish_dial_forward(qe->chan, o->chan, NULL, NULL,
+ "CANCEL", ast_channel_call_forward(o->chan));
numnochan++;
do_hang(o);
winner = NULL;
@@ -5052,6 +5054,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
case AST_CONTROL_RINGING:
ast_verb(3, "%s is ringing\n", ochan_name);
+ ast_channel_publish_dial(qe->chan, o->chan, on, "RINGING");
+
/* Start ring indication when the channel is ringing, if specified */
if (qe->ring_when_ringing) {
ast_moh_stop(qe->chan);
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index e7de8a2b2..1d5b2dcb3 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -1088,7 +1088,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir,
- signed char record_gain, struct vm_state *vms, char *flag, const char *msg_id);
+ signed char record_gain, struct vm_state *vms, char *flag, const char *msg_id, int forwardintro);
static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname, const char *flag);
@@ -2174,6 +2174,7 @@ static int imap_retrieve_greeting(const char *dir, const int msgnum, struct ast_
{
struct vm_state *vms_p;
char *file, *filename;
+ char dest[PATH_MAX];
char *attachment;
int i;
BODY *body;
@@ -2237,6 +2238,7 @@ static int imap_retrieve_greeting(const char *dir, const int msgnum, struct ast_
if (!strcmp(filename, file)) {
ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
vms_p->msgArray[vms_p->curmsg] = i + 1;
+ create_dirpath(dest, sizeof(dest), vmu->context, vms_p->username, "");
save_body(body, vms_p, "2", attachment, 0);
ret = 0;
break;
@@ -2369,7 +2371,8 @@ static int imap_retrieve_file(const char *dir, const int msgnum, const char *mai
snprintf(text_file, sizeof(text_file), "%s.%s", vms->fn, "txt");
if (!(text_file_ptr = fopen(text_file, "w"))) {
- ast_log(LOG_WARNING, "Unable to open/create file %s: %s\n", text_file, strerror(errno));
+ ast_log(LOG_ERROR, "Unable to open/create file %s: %s\n", text_file, strerror(errno));
+ goto exit;
}
fprintf(text_file_ptr, "%s\n", "[message]");
@@ -2709,8 +2712,8 @@ static int imap_store_file(const char *dir, const char *mailboxuser, const char
}
make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, "INBOX",
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
- S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
+ chan ? S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL) : NULL,
+ chan ? S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL) : NULL,
fn, introfn, fmt, duration, 1, chan, NULL, 1, flag, msg_id);
/* read mail file to memory */
len = ftell(p);
@@ -3018,6 +3021,10 @@ static int init_mailstream(struct vm_state *vms, int box)
ast_mutex_lock(&vms->lock);
ast_mutex_lock(&mail_open_lock);
vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
+ /* Create the folder if it dosn't exist */
+ if (vms->mailstream && !mail_status(vms->mailstream, tmp, SA_UIDNEXT)) {
+ mail_create(vms->mailstream, tmp);
+ }
ast_mutex_unlock(&mail_open_lock);
ast_mutex_unlock(&vms->lock);
if (vms->mailstream == NIL) {
@@ -3112,7 +3119,15 @@ static void write_file(char *filename, char *buffer, unsigned long len)
{
FILE *output;
- output = fopen (filename, "w");
+ if (!filename || !buffer) {
+ return;
+ }
+
+ if (!(output = fopen(filename, "w"))) {
+ ast_log(LOG_ERROR, "Unable to open/create file %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
if (fwrite(buffer, len, 1, output) != 1) {
if (ferror(output)) {
ast_log(LOG_ERROR, "Short write while writing e-mail body: %s.\n", strerror(errno));
@@ -3247,18 +3262,30 @@ void mm_lsub(MAILSTREAM * stream, int delim, char *mailbox, long attributes)
void mm_status(MAILSTREAM * stream, char *mailbox, MAILSTATUS * status)
{
- ast_log(AST_LOG_NOTICE, " Mailbox %s", mailbox);
- if (status->flags & SA_MESSAGES)
- ast_log(AST_LOG_NOTICE, ", %lu messages", status->messages);
- if (status->flags & SA_RECENT)
- ast_log(AST_LOG_NOTICE, ", %lu recent", status->recent);
- if (status->flags & SA_UNSEEN)
- ast_log(AST_LOG_NOTICE, ", %lu unseen", status->unseen);
- if (status->flags & SA_UIDVALIDITY)
- ast_log(AST_LOG_NOTICE, ", %lu UID validity", status->uidvalidity);
- if (status->flags & SA_UIDNEXT)
- ast_log(AST_LOG_NOTICE, ", %lu next UID", status->uidnext);
- ast_log(AST_LOG_NOTICE, "\n");
+ struct ast_str *str;
+ if (!DEBUG_ATLEAST(5) || !(str = ast_str_create(MAX_OBJECT_FIELD))) {
+ return;
+ }
+
+ ast_str_append(&str, 0, " Mailbox %s", mailbox);
+ if (status->flags & SA_MESSAGES) {
+ ast_str_append(&str, 0, ", %lu messages", status->messages);
+ }
+ if (status->flags & SA_RECENT) {
+ ast_str_append(&str, 0, ", %lu recent", status->recent);
+ }
+ if (status->flags & SA_UNSEEN) {
+ ast_str_append(&str, 0, ", %lu unseen", status->unseen);
+ }
+ if (status->flags & SA_UIDVALIDITY) {
+ ast_str_append(&str, 0, ", %lu UID validity", status->uidvalidity);
+ }
+ if (status->flags & SA_UIDNEXT) {
+ ast_str_append(&str, 0, ", %lu next UID", status->uidnext);
+ }
+ ast_log(LOG_DEBUG, "%s\n", ast_str_buffer(str));
+
+ ast_free(str);
}
@@ -3446,8 +3473,9 @@ static struct vm_state *get_vm_state_by_imapuser(const char *user, int interacti
if (interactive) {
struct vm_state *vms;
pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
- vms = pthread_getspecific(ts_vmstate.key);
- return vms;
+ if ((vms = pthread_getspecific(ts_vmstate.key)) && vms->imapuser && !strcmp(vms->imapuser, user)) {
+ return vms;
+ }
}
AST_LIST_LOCK(&vmstates);
@@ -3485,8 +3513,10 @@ static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, const char
if (interactive) {
struct vm_state *vms;
pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
- vms = pthread_getspecific(ts_vmstate.key);
- return vms;
+ if ((vms = pthread_getspecific(ts_vmstate.key)) && vms->username && vms->context &&
+ !strcmp(vms->username,mailbox) && !strcmp(vms->context, local_context)) {
+ return vms;
+ }
}
AST_LIST_LOCK(&vmstates);
@@ -5133,7 +5163,9 @@ static void make_email_file(FILE *p,
first_line = 0;
}
- if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
+ if (msgnum <= -1) {
+ fprintf(p, "Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
+ } else if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
struct ast_channel *ast;
if ((ast = ast_dummy_channel_alloc())) {
@@ -5186,9 +5218,8 @@ static void make_email_file(FILE *p,
fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
#endif
/* flag added for Urgent */
- fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
+ fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, S_OR(flag, ""));
fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan ? ast_channel_priority(chan) : 0);
- fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan ? ast_channel_name(chan) : "");
fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
@@ -5219,7 +5250,11 @@ static void make_email_file(FILE *p,
fprintf(p, "--%s" ENDL, bound);
}
fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
- if (emailbody || vmu->emailbody) {
+ if (msgnum <= -1) {
+ fprintf(p, "This message is to let you know that your greeting '%s' was changed on %s." ENDL
+ "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
+ greeting_attachment, date);
+ } else if (emailbody || vmu->emailbody) {
char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
struct ast_channel *ast;
if ((ast = ast_dummy_channel_alloc())) {
@@ -5245,7 +5280,7 @@ static void make_email_file(FILE *p,
} else {
ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
}
- } else if (msgnum > -1) {
+ } else {
if (strcmp(vmu->mailbox, mailbox)) {
/* Forwarded type */
struct ast_config *msg_cfg;
@@ -5290,9 +5325,6 @@ plain_message:
ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
(cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
}
- } else {
- fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
- "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
}
if (imap || attach_user_voicemail) {
@@ -6851,7 +6883,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
goto leave_vm_out;
}
- res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id);
+ res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id, 0);
if (txt) {
fprintf(txt, "flag=%s\n", flag);
@@ -7055,6 +7087,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
char sequence[10];
char mailbox[256];
int res;
+ int curr_mbox;
/* get the real IMAP message number for this message */
snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
@@ -7064,26 +7097,35 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
/* if save to Old folder, put in INBOX as read */
if (box == OLD_FOLDER) {
mail_setflag(vms->mailstream, sequence, "\\Seen");
- mail_clearflag(vms->mailstream, sequence, "\\Unseen");
} else if (box == NEW_FOLDER) {
- mail_setflag(vms->mailstream, sequence, "\\Unseen");
mail_clearflag(vms->mailstream, sequence, "\\Seen");
}
if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
ast_mutex_unlock(&vms->lock);
return 0;
}
- /* Create the folder if it don't exist */
+
+ /* get the current mailbox so that we can point the mailstream back to it later */
+ curr_mbox = get_folder_by_name(vms->curbox);
+
+ /* Create the folder if it dosn't exist */
imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
- ast_debug(5, "Checking if folder exists: %s\n", mailbox);
- if (mail_create(vms->mailstream, mailbox) == NIL)
- ast_debug(5, "Folder exists.\n");
- else
- ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
- if (move) {
- res = !mail_move(vms->mailstream, sequence, (char *) mbox(vmu, box));
+ if (vms->mailstream && !mail_status(vms->mailstream, mailbox, SA_UIDNEXT)) {
+ if (mail_create(vms->mailstream, mailbox) != NIL) {
+ ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
+ }
+ }
+
+ /* restore previous mbox stream */
+ if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
+ ast_log(AST_LOG_ERROR, "IMAP mailstream is NULL or can't init_mailstream\n");
+ res = -1;
} else {
- res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
+ if (move) {
+ res = !mail_move(vms->mailstream, sequence, (char *) mbox(vmu, box));
+ } else {
+ res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
+ }
}
ast_mutex_unlock(&vms->lock);
return res;
@@ -7814,9 +7856,9 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu,
}
make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
strncat(vms->introfn, "intro", sizeof(vms->introfn));
- ast_play_and_wait(chan, INTRO);
+ ast_play_and_wait(chan, "vm-record-prepend");
ast_play_and_wait(chan, "beep");
- cmd = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag, msg_id);
+ cmd = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag, msg_id, 1);
if (cmd == -1) {
break;
}
@@ -8085,6 +8127,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
char *stringp;
const char *s;
+ const char mailbox_context[256];
int saved_messages = 0;
int valid_extensions = 0;
char *dir;
@@ -8193,20 +8236,44 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
/* start optimistic */
valid_extensions = 1;
while (s) {
+ snprintf((char*)mailbox_context, sizeof(mailbox_context), "%s@%s", s, context ? context : "default");
if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
int oldmsgs;
int newmsgs;
int capacity;
- if (inboxcount(s, &newmsgs, &oldmsgs)) {
- ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
+
+ if (inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
+ ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
/* Shouldn't happen, but allow trying another extension if it does */
res = ast_play_and_wait(chan, "pbx-invalid");
valid_extensions = 0;
break;
}
+#ifdef IMAP_STORAGE
+ if (!(dstvms = get_vm_state_by_mailbox(s, context, 0))) {
+ if (!(dstvms = create_vm_state_from_user(receiver))) {
+ ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
+ /* Shouldn't happen, but allow trying another extension if it does */
+ res = ast_play_and_wait(chan, "pbx-invalid");
+ valid_extensions = 0;
+ break;
+ }
+ }
+ check_quota(dstvms, imapfolder);
+ if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
+ ast_log(LOG_NOTICE, "Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
+ res = ast_play_and_wait(chan, "vm-mailboxfull");
+ valid_extensions = 0;
+ while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
+ inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
+ free_user(vmtmp);
+ }
+ break;
+ }
+#endif
capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
if ((newmsgs + oldmsgs) >= capacity) {
- ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
+ ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
res = ast_play_and_wait(chan, "vm-mailboxfull");
valid_extensions = 0;
while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
@@ -8226,7 +8293,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
free_user(receiver);
}
- ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
+ ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", mailbox_context);
/* "I am sorry, that's not a valid extension. Please try again." */
res = ast_play_and_wait(chan, "pbx-invalid");
valid_extensions = 0;
@@ -8306,7 +8373,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
if (!dstvms->mailstream) {
ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
} else {
- copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
+ copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str);
}
} else {
@@ -8342,10 +8409,6 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
res = ast_play_and_wait(chan, "vm-messages");
if (!res)
res = ast_play_and_wait(chan, "vm-saved"); */
-#ifdef IMAP_STORAGE
- /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
- if (ast_strlen_zero(vmstmp.introfn))
-#endif
res = ast_play_and_wait(chan, "vm-msgforwarded");
}
#ifndef IMAP_STORAGE
@@ -8814,6 +8877,7 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
char arg[10];
int i;
BODY* body;
+ int curr_mbox;
file = strrchr(ast_strdupa(dir), '/');
if (file) {
@@ -8824,6 +8888,16 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
}
ast_mutex_lock(&vms->lock);
+
+ /* get the current mailbox so that we can point the mailstream back to it later */
+ curr_mbox = get_folder_by_name(vms->curbox);
+
+ if (init_mailstream(vms, GREETINGS_FOLDER) || !vms->mailstream) {
+ ast_log(AST_LOG_ERROR, "IMAP mailstream is NULL or can't init_mailstream\n");
+ ast_mutex_unlock(&vms->lock);
+ return -1;
+ }
+
for (i = 0; i < vms->mailstream->nmsgs; i++) {
mail_fetchstructure(vms->mailstream, i + 1, &body);
/* We have the body, now we extract the file name of the first attachment. */
@@ -8841,6 +8915,14 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
}
}
mail_expunge(vms->mailstream);
+
+ if (curr_mbox != -1) {
+ /* restore previous mbox stream */
+ if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
+ ast_log(AST_LOG_ERROR, "IMAP mailstream is NULL or can't init_mailstream\n");
+ }
+ }
+
ast_mutex_unlock(&vms->lock);
return 0;
}
@@ -10348,7 +10430,7 @@ static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct
if (ast_test_flag(vmu, VM_FORCENAME)) {
snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_fileexists(prefile, NULL, NULL) < 1) {
- cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
}
@@ -10358,14 +10440,14 @@ static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct
if (ast_test_flag(vmu, VM_FORCEGREET)) {
snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_fileexists(prefile, NULL, NULL) < 1) {
- cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
}
snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_fileexists(prefile, NULL, NULL) < 1) {
- cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
if (cmd < 0 || cmd == 't' || cmd == '#')
return cmd;
}
@@ -10447,15 +10529,15 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
switch (cmd) {
case '1': /* Record your unavailable message */
snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
- cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
break;
case '2': /* Record your busy message */
snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
- cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
break;
case '3': /* Record greeting */
snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
- cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
break;
case '4': /* manage the temporary greeting */
cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
@@ -10589,7 +10671,7 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st
retries = 0;
RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
if (ast_fileexists(prefile, NULL, NULL) <= 0) {
- cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
if (cmd == -1) {
break;
}
@@ -10597,7 +10679,7 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st
} else {
switch (cmd) {
case '1':
- cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL);
+ cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
break;
case '2':
DELETE(prefile, -1, prefile, vmu);
@@ -11876,7 +11958,13 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
if (useadsi)
adsi_status(chan, &vms);
- break;
+ /* Reopen play_folder */
+ res = open_mailbox(&vms, vmu, play_folder);
+ if (res < 0) {
+ goto out;
+ }
+ vms.starting = 1;
+ break;
default: /* Nothing */
ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
@@ -15109,7 +15197,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir,
- signed char record_gain, struct vm_state *vms, char *flag, const char *msg_id)
+ signed char record_gain, struct vm_state *vms, char *flag, const char *msg_id, int forwardintro)
{
/* Record message & let caller review or re-record it, or set options if applicable */
int res = 0;
@@ -15151,7 +15239,9 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
ast_verb(3, "Saving message as is\n");
if (!outsidecaller)
ast_filerename(tempfile, recordfile, NULL);
- ast_stream_and_wait(chan, "vm-msgsaved", "");
+ if (!forwardintro) {
+ ast_stream_and_wait(chan, "vm-msgsaved", "");
+ }
if (!outsidecaller) {
/* Saves to IMAP server only if imapgreeting=yes */
STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id);
@@ -15174,7 +15264,11 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
ast_verb(3, "Recording the message\n");
if (recorded && outsidecaller) {
- cmd = ast_play_and_wait(chan, INTRO);
+ if (forwardintro) {
+ cmd = ast_play_and_wait(chan, "vm-record-prepend");
+ } else {
+ cmd = ast_play_and_wait(chan, INTRO);
+ }
cmd = ast_play_and_wait(chan, "beep");
}
recorded = 1;
@@ -15295,10 +15389,10 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
}
return cmd;
default:
- /* If the caller is an ouside caller, and the review option is enabled,
+ /* If the caller is an ouside caller and the review option is enabled or it's forward intro
allow them to review the message, but let the owner of the box review
their OGM's */
- if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
+ if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro)
return cmd;
if (msg_exists) {
cmd = ast_play_and_wait(chan, "vm-review");