summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/app_confbridge.c15
-rw-r--r--apps/app_followme.c107
-rw-r--r--apps/app_voicemail.c226
-rw-r--r--apps/confbridge/conf_config_parser.c19
-rw-r--r--apps/confbridge/include/confbridge.h1
5 files changed, 270 insertions, 98 deletions
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index b3609b673..82204c48f 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -1256,9 +1256,17 @@ void conf_handle_second_active(struct confbridge_conference *conference)
void conf_ended(struct confbridge_conference *conference)
{
+ struct pbx_find_info q = { .stacklen = 0 };
+
/* Called with a reference to conference */
ao2_unlink(conference_bridges, conference);
send_conf_end_event(conference);
+ if (!ast_strlen_zero(conference->b_profile.regcontext) &&
+ pbx_find_extension(NULL, NULL, &q, conference->b_profile.regcontext,
+ conference->name, 1, NULL, "", E_MATCH)) {
+ ast_context_remove_extension(conference->b_profile.regcontext,
+ conference->name, 1, NULL);
+ }
ao2_lock(conference);
conf_stop_record(conference);
ao2_unlock(conference);
@@ -1363,6 +1371,13 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
}
send_conf_start_event(conference);
+
+ if (!ast_strlen_zero(conference->b_profile.regcontext)) {
+ if (!ast_exists_extension(NULL, conference->b_profile.regcontext, conference->name, 1, NULL)) {
+ ast_add_extension(conference->b_profile.regcontext, 1, conference->name, 1, NULL, NULL, "Noop", NULL, NULL, "ConfBridge");
+ }
+ }
+
ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
}
diff --git a/apps/app_followme.c b/apps/app_followme.c
index 668753417..a955843bc 100644
--- a/apps/app_followme.c
+++ b/apps/app_followme.c
@@ -66,6 +66,8 @@ ASTERISK_REGISTER_FILE()
#include "asterisk/stasis_channels.h"
#include "asterisk/max_forwards.h"
+#define REC_FORMAT "sln"
+
/*** DOCUMENTATION
<application name="FollowMe" language="en_US">
<synopsis>
@@ -166,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 */
@@ -196,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];
@@ -266,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";
@@ -311,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));
@@ -341,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"))
@@ -396,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;
@@ -428,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));
}
@@ -649,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)) {
@@ -785,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:
@@ -928,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;
@@ -1366,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));
@@ -1424,7 +1456,7 @@ static int app_exec(struct ast_channel *chan, const char *data)
snprintf(targs->namerecloc, sizeof(targs->namerecloc), "%s/followme.%s",
ast_config_AST_SPOOL_DIR, ast_channel_uniqueid(chan));
- if (ast_play_and_record(chan, "vm-rec-name", targs->namerecloc, 5, "sln", &duration,
+ if (ast_play_and_record(chan, "vm-rec-name", targs->namerecloc, 5, REC_FORMAT, &duration,
NULL, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL) < 0) {
goto outrun;
}
@@ -1525,7 +1557,18 @@ outrun:
ast_free(nm);
}
if (!ast_strlen_zero(targs->namerecloc)) {
- unlink(targs->namerecloc);
+ int ret;
+ char fn[PATH_MAX];
+
+ snprintf(fn, sizeof(fn), "%s.%s", targs->namerecloc,
+ REC_FORMAT);
+ ret = unlink(fn);
+ if (ret != 0) {
+ ast_log(LOG_NOTICE, "Failed to delete recorded name file %s: %d (%s)\n",
+ fn, errno, strerror(errno));
+ } else {
+ ast_debug(2, "deleted recorded prompt %s.\n", fn);
+ }
}
ast_free((char *) targs->predial_callee);
ast_party_connected_line_free(&targs->connected_in);
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");
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index a33c6a12a..69d6f69ea 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -339,6 +339,22 @@ ASTERISK_REGISTER_FILE()
unescaped to <variable>X</variable>. All variables will be evaluated at the time ConfBridge is called.
</para></description>
</configOption>
+ <configOption name="regcontext">
+ <synopsis>The name of the context into which to register the name of the conference bridge as NoOP() at priority 1</synopsis>
+ <description><para>
+ When set this will cause the name of the created conference to be registered
+ into the named context at priority 1 with an operation of NoOP(). This can
+ then be used in other parts of the dialplan to test for the existence of a
+ specific conference bridge.
+ You should be aware that there are potential races between testing for the
+ existence of a bridge, and taking action upon that information, consider
+ for example two callers executing the check simultaniously, and then taking
+ special action as "first caller" into the bridge. The same for exiting,
+ directly after the check the bridge can be destroyed before the new caller
+ enters (creating a new bridge), for example, and the "first member" actions
+ could thus be missed.
+ </para></description>
+ </configOption>
<configOption name="video_mode">
<synopsis>Sets how confbridge handles video distribution to the conference participants</synopsis>
<description><para>
@@ -1595,6 +1611,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
ast_cli(a->fd,"Max Members: No Limit\n");
}
+ ast_cli(a->fd,"Registration context: %s\n", b_profile.regcontext);
+
switch (b_profile.flags
& (BRIDGE_OPT_VIDEO_SRC_LAST_MARKED | BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
| BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
@@ -2163,6 +2181,7 @@ int conf_load_config(void)
aco_option_register(&cfg_info, "record_file", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_file));
aco_option_register(&cfg_info, "record_options", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_options));
aco_option_register(&cfg_info, "record_command", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, rec_command));
+ aco_option_register(&cfg_info, "regcontext", ACO_EXACT, bridge_types, NULL, OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, regcontext));
aco_option_register(&cfg_info, "language", ACO_EXACT, bridge_types, "en", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct bridge_profile, language));
aco_option_register_custom(&cfg_info, "^sound_", ACO_REGEX, bridge_types, NULL, sound_option_handler, 0);
/* This option should only be used with the CONFBRIDGE dialplan function */
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index 539b9961b..5ae042113 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -210,6 +210,7 @@ struct bridge_profile {
unsigned int internal_sample_rate; /*!< The internal sample rate of the bridge. 0 when set to auto adjust mode. */
unsigned int mix_interval; /*!< The internal mixing interval used by the bridge. When set to 0 the bridgewill use a default interval. */
struct bridge_profile_sounds *sounds;
+ char regcontext[AST_MAX_CONTEXT];
};
/*! \brief The structure that represents a conference bridge */