aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/app_queue.c11
-rw-r--r--apps/app_speech_utils.c1
-rw-r--r--apps/app_voicemail.c184
-rw-r--r--apps/app_waitforsilence.c29
4 files changed, 185 insertions, 40 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 98238620a..516664e66 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3057,6 +3057,7 @@ struct queue_transfer_ds {
struct queue_ent *qe;
struct member *member;
int starttime;
+ int callcompletedinsl;
};
static void queue_transfer_destroy(void *data)
@@ -3088,11 +3089,14 @@ static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struc
struct queue_ent *qe = qtds->qe;
struct member *member = qtds->member;
int callstart = qtds->starttime;
+ int callcompletedinsl = qtds->callcompletedinsl;
struct ast_datastore *datastore;
ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld",
new_chan->exten, new_chan->context, (long) (callstart - qe->start),
(long) (time(NULL) - callstart));
+
+ update_queue(qe->parent, member, callcompletedinsl);
if (!(datastore = ast_channel_datastore_find(new_chan, &queue_transfer_info, NULL))) {
ast_log(LOG_WARNING, "Can't find the queue_transfer datastore.\n");
@@ -3116,7 +3120,7 @@ static int attended_transfer_occurred(struct ast_channel *chan)
/*! \brief create a datastore for storing relevant info to log attended transfers in the queue_log
*/
-static void setup_transfer_datastore(struct queue_ent *qe, struct member *member, int starttime)
+static void setup_transfer_datastore(struct queue_ent *qe, struct member *member, int starttime, int callcompletedinsl)
{
struct ast_datastore *ds;
struct queue_transfer_ds *qtds = ast_calloc(1, sizeof(*qtds));
@@ -3137,6 +3141,7 @@ static void setup_transfer_datastore(struct queue_ent *qe, struct member *member
/* This member is refcounted in try_calling, so no need to add it here, too */
qtds->member = member;
qtds->starttime = starttime;
+ qtds->callcompletedinsl = callcompletedinsl;
ds->data = qtds;
ast_channel_datastore_add(qe->chan, ds);
ast_channel_unlock(qe->chan);
@@ -3814,7 +3819,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
time(&callstart);
- setup_transfer_datastore(qe, member, callstart);
+ setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
/* If the queue member did an attended transfer, then the TRANSFER already was logged in the queue_log
@@ -3843,11 +3848,11 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
ast_channel_datastore_free(transfer_ds);
}
ast_channel_unlock(qe->chan);
+ update_queue(qe->parent, member, callcompletedinsl);
}
if (bridge != AST_PBX_NO_HANGUP_PEER)
ast_hangup(peer);
- update_queue(qe->parent, member, callcompletedinsl);
res = bridge ? bridge : 1;
ao2_ref(member, -1);
}
diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c
index 221d2eb5c..6ba68c3b4 100644
--- a/apps/app_speech_utils.c
+++ b/apps/app_speech_utils.c
@@ -727,6 +727,7 @@ static int speech_background(struct ast_channel *chan, void *data)
speech->results->text = ast_strdup(dtmf);
speech->results->grammar = ast_strdup("dtmf");
}
+ ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
}
/* See if it was because they hung up */
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 41c51f709..e06ca84b1 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -3230,7 +3230,8 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu
pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
- pbx_builtin_setvar_helper(ast, "VM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
+ pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
+ ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
pbx_builtin_setvar_helper(ast, "VM_DATE", date);
@@ -3277,6 +3278,90 @@ static const struct ast_tm *vmu_tm(const struct ast_vm_user *vmu, struct ast_tm
return tm;
}
+/*!\brief Check if the string would need encoding within the MIME standard, to
+ * avoid confusing certain mail software that expects messages to be 7-bit
+ * clean.
+ */
+static int check_mime(const char *str)
+{
+ for (; *str; str++) {
+ if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*!\brief Encode a string according to the MIME rules for encoding strings
+ * that are not 7-bit clean or contain control characters.
+ *
+ * Additionally, if the encoded string would exceed the MIME limit of 76
+ * characters per line, then the encoding will be broken up into multiple
+ * sections, separated by a space character, in order to facilitate
+ * breaking up the associated header across multiple lines.
+ *
+ * \param start A string to be encoded
+ * \param end An expandable buffer for holding the result
+ * \param preamble The length of the first line already used for this string,
+ * to ensure that each line maintains a maximum length of 76 chars.
+ * \param postamble the length of any additional characters appended to the
+ * line, used to ensure proper field wrapping.
+ * \retval The encoded string.
+ */
+static char *encode_mime_str(const char *start, char *end, size_t endsize, size_t preamble, size_t postamble)
+{
+ char tmp[80];
+ int first_section = 1;
+ size_t endlen = 0, tmplen = 0;
+ *end = '\0';
+
+ tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
+ for (; *start; start++) {
+ int need_encoding = 0;
+ if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
+ need_encoding = 1;
+ }
+ if ((first_section && need_encoding && preamble + tmplen > 70) ||
+ (first_section && !need_encoding && preamble + tmplen > 72) ||
+ (!first_section && need_encoding && tmplen > 70) ||
+ (!first_section && !need_encoding && tmplen > 72)) {
+ /* Start new line */
+ endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
+ tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
+ first_section = 0;
+ }
+ if (need_encoding && *start == ' ') {
+ tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
+ } else if (need_encoding) {
+ tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
+ } else {
+ tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
+ }
+ }
+ snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
+ return end;
+}
+
+/*!
+ * \brief Creates the email file to be sent to indicate a new voicemail exists for a user.
+ * \param p The output file to generate the email contents into.
+ * \param srcemail The email address to send the email to, presumably the email address for the owner of the mailbox.
+ * \param vmu The voicemail user who is sending the voicemail.
+ * \param msgnum The message index in the mailbox folder.
+ * \param context
+ * \param mailbox The voicemail box to read the voicemail to be notified in this email.
+ * \param cidnum The caller ID number.
+ * \param cidname The caller ID name.
+ * \param attach the name of the sound file to be attached to the email, if attach_user_voicemail == 1.
+ * \param format The message sound file format. i.e. .wav
+ * \param duration The time of the message content, in seconds.
+ * \param attach_user_voicemail if 1, the sound file is attached to the email.
+ * \param chan
+ * \param category
+ * \param imap if == 1, indicates the target folder for the email notification to be sent to will be an IMAP mailstore. This causes additional mailbox headers to be set, which would facilitate searching for the email in the destination IMAP folder.
+ *
+ * The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.
+ */
static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap)
{
char date[256];
@@ -3288,8 +3373,8 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
char tmpcmd[256];
struct ast_tm tm;
char enc_cidnum[256] = "", enc_cidname[256] = "";
- char *passdata2;
- size_t len_passdata;
+ char *passdata = NULL, *passdata2;
+ size_t len_passdata = 0, len_passdata2, tmplen;
char *greeting_attachment;
#ifdef IMAP_STORAGE
@@ -3298,6 +3383,17 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
#define ENDL "\n"
#endif
+ /* One alloca for multiple fields */
+ len_passdata2 = strlen(vmu->fullname);
+ if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
+ len_passdata2 = tmplen;
+ }
+ if ((tmplen = strlen(fromstring)) > len_passdata2) {
+ len_passdata2 = tmplen;
+ }
+ len_passdata2 = len_passdata2 * 3 + 200;
+ passdata2 = alloca(len_passdata2);
+
if (!ast_strlen_zero(cidnum)) {
strip_control(cidnum, enc_cidnum, sizeof(enc_cidnum));
}
@@ -3325,15 +3421,25 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
if (!ast_strlen_zero(fromstring)) {
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
- char *passdata;
- int vmlen = strlen(fromstring) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata, vmlen, category);
- pbx_substitute_variables_helper(ast, fromstring, passdata, vmlen);
- len_passdata = strlen(passdata) * 2 + 3;
- passdata2 = alloca(len_passdata);
- fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata), who);
+ char *ptr;
+ memset(passdata2, 0, len_passdata2);
+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category);
+ pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
+ len_passdata = strlen(passdata2) * 3 + 300;
+ passdata = alloca(len_passdata);
+ if (check_mime(passdata2)) {
+ int first_line = 1;
+ encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
+ while ((ptr = strchr(passdata, ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
+ first_line = 0;
+ passdata = ptr + 1;
+ }
+ fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
+ } else {
+ fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata2), who);
+ }
ast_channel_free(ast);
} else {
ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
@@ -3341,19 +3447,48 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
} else {
fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
}
- len_passdata = strlen(vmu->fullname) * 2 + 3;
- passdata2 = alloca(len_passdata);
- fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata), vmu->email);
+
+ if (check_mime(vmu->fullname)) {
+ int first_line = 1;
+ char *ptr;
+ encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
+ while ((ptr = strchr(passdata2, ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
+ first_line = 0;
+ passdata2 = ptr + 1;
+ }
+ fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
+ } else {
+ fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
+ }
if (!ast_strlen_zero(emailsubject)) {
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
- char *passdata;
int vmlen = strlen(emailsubject) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata, vmlen, category);
- pbx_substitute_variables_helper(ast, emailsubject, passdata, vmlen);
- fprintf(p, "Subject: %s" ENDL, passdata);
+ /* Only allocate more space if the previous was not large enough */
+ if (vmlen > len_passdata) {
+ passdata = alloca(vmlen);
+ len_passdata = vmlen;
+ }
+
+ memset(passdata, 0, len_passdata);
+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, len_passdata, category);
+ pbx_substitute_variables_helper(ast, emailsubject, passdata, len_passdata);
+ if (check_mime(passdata)) {
+ int first_line = 1;
+ char *ptr;
+ encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
+ while ((ptr = strchr(passdata2, ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
+ first_line = 0;
+ passdata2 = ptr + 1;
+ }
+ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
+ } else {
+ fprintf(p, "Subject: %s" ENDL, passdata);
+ }
ast_channel_free(ast);
} else {
ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
@@ -6894,8 +7029,11 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm
/* Notify the user that the temp greeting is set and give them the option to remove it */
snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
- if (ast_fileexists(prefile, NULL, NULL) > 0)
+ RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
+ if (ast_fileexists(prefile, NULL, NULL) > 0) {
ast_play_and_wait(chan, "vm-tempgreetactive");
+ }
+ DISPOSE(prefile, -1);
}
/* Play voicemail intro - syntax is different for different languages */
@@ -7186,9 +7324,11 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
default:
cmd = 0;
snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
+ RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
if (ast_fileexists(prefile, NULL, NULL)) {
cmd = ast_play_and_wait(chan, "vm-tmpexists");
}
+ DISPOSE(prefile, -1);
if (!cmd) {
cmd = ast_play_and_wait(chan, "vm-options");
}
diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c
index e45f24344..38d98fa5d 100644
--- a/apps/app_waitforsilence.c
+++ b/apps/app_waitforsilence.c
@@ -69,7 +69,7 @@ static char *descrip =
"TIMEOUT - if exited without silence detected after timeout\n";
static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstart, int timeout) {
- struct ast_frame *f;
+ struct ast_frame *f = NULL;
int dspsilence = 0;
static int silencethreshold = 128;
int rfmt = 0;
@@ -78,48 +78,47 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
time_t now;
rfmt = chan->readformat; /* Set to linear mode */
- res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
- if (res < 0) {
+ if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
return -1;
}
- sildet = ast_dsp_new(); /* Create the silence detector */
- if (!sildet) {
+ /* Create the silence detector */
+ if (!(sildet = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
return -1;
}
ast_dsp_set_threshold(sildet, silencethreshold);
/* Await silence... */
- f = NULL;
- for(;;) {
+ for (;;) {
/* Start with no silence received */
dspsilence = 0;
res = ast_waitfor(chan, silencereqd);
/* Must have gotten a hangup; let's exit */
- if (res <= 0) {
- f = NULL;
+ if (res < 0) {
+ pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
break;
}
/* We waited and got no frame; sounds like digital silence or a muted digital channel */
- if (!res) {
+ if (res == 0) {
dspsilence = silencereqd;
} else {
/* Looks like we did get a frame, so let's check it out */
- f = ast_read(chan);
- if (!f)
+ if (!(f = ast_read(chan))) {
+ pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
break;
- if (f && f->frametype == AST_FRAME_VOICE) {
+ }
+ if (f->frametype == AST_FRAME_VOICE) {
ast_dsp_silence(sildet, f, &dspsilence);
- ast_frfree(f);
}
+ ast_frfree(f);
}
- ast_verb(3, "Got %dms silence< %dms required\n", dspsilence, silencereqd);
+ ast_verb(6, "Got %dms silence< %dms required\n", dspsilence, silencereqd);
if (dspsilence >= silencereqd) {
ast_verb(3, "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd);