summaryrefslogtreecommitdiff
path: root/apps/app_minivm.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/app_minivm.c')
-rw-r--r--apps/app_minivm.c490
1 files changed, 311 insertions, 179 deletions
diff --git a/apps/app_minivm.c b/apps/app_minivm.c
index 9148ee130..fffa714e0 100644
--- a/apps/app_minivm.c
+++ b/apps/app_minivm.c
@@ -483,11 +483,12 @@ AST_APP_OPTIONS(minivm_accmess_options, {
AST_APP_OPTION('n', OPT_NAME_GREETING),
});
-/*! \brief Structure for linked list of Mini-Voicemail users: \ref minivm_accounts */
+/*!\internal
+ * \brief Structure for linked list of Mini-Voicemail users: \ref minivm_accounts */
struct minivm_account {
char username[AST_MAX_CONTEXT]; /*!< Mailbox username */
char domain[AST_MAX_CONTEXT]; /*!< Voicemail domain */
-
+
char pincode[10]; /*!< Secret pin code, numbers only */
char fullname[120]; /*!< Full name, for directory app */
char email[80]; /*!< E-mail address - override */
@@ -502,18 +503,20 @@ struct minivm_account {
char attachfmt[80]; /*!< Format for voicemail audio file attachment */
char etemplate[80]; /*!< Pager template */
char ptemplate[80]; /*!< Voicemail format */
- unsigned int flags; /*!< MVM_ flags */
+ unsigned int flags; /*!< MVM_ flags */
struct ast_variable *chanvars; /*!< Variables for e-mail template */
double volgain; /*!< Volume gain for voicemails sent via e-mail */
- AST_LIST_ENTRY(minivm_account) list;
+ AST_LIST_ENTRY(minivm_account) list;
};
-/*! \brief The list of e-mail accounts */
+/*!\internal
+ * \brief The list of e-mail accounts */
static AST_LIST_HEAD_STATIC(minivm_accounts, minivm_account);
-/*! \brief Linked list of e-mail templates in various languages
- These are used as templates for e-mails, pager messages and jabber messages
- \ref message_templates
+/*!\internal
+ * \brief Linked list of e-mail templates in various languages
+ * These are used as templates for e-mails, pager messages and jabber messages
+ * \ref message_templates
*/
struct minivm_template {
char name[80]; /*!< Template name */
@@ -588,11 +591,11 @@ static char default_vmformat[80];
static struct ast_flags globalflags = {0}; /*!< Global voicemail flags */
static int global_saydurationminfo;
-static char global_charset[32]; /*!< Global charset in messages */
static double global_volgain; /*!< Volume gain for voicmemail via e-mail */
-/*! \brief Default dateformat, can be overridden in configuration file */
+/*!\internal
+ * \brief Default dateformat, can be overridden in configuration file */
#define DEFAULT_DATEFORMAT "%A, %B %d, %Y at %r"
#define DEFAULT_CHARSET "ISO-8859-1"
@@ -603,7 +606,8 @@ static int create_vmaccount(char *name, struct ast_variable *var, int realtime);
static struct minivm_account *find_user_realtime(const char *domain, const char *username);
static char *handle_minivm_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
-/*! \brief Create message template */
+/*!\internal
+ * \brief Create message template */
static struct minivm_template *message_template_create(const char *name)
{
struct minivm_template *template;
@@ -622,7 +626,8 @@ static struct minivm_template *message_template_create(const char *name)
return template;
}
-/*! \brief Release memory allocated by message template */
+/*!\internal
+ * \brief Release memory allocated by message template */
static void message_template_free(struct minivm_template *template)
{
if (template->body)
@@ -631,7 +636,8 @@ static void message_template_free(struct minivm_template *template)
ast_free (template);
}
-/*! \brief Build message template from configuration */
+/*!\internal
+ * \brief Build message template from configuration */
static int message_template_build(const char *name, struct ast_variable *var)
{
struct minivm_template *template;
@@ -693,7 +699,8 @@ static int message_template_build(const char *name, struct ast_variable *var)
return error;
}
-/*! \brief Find named template */
+/*!\internal
+ * \brief Find named template */
static struct minivm_template *message_template_find(const char *name)
{
struct minivm_template *this, *res = NULL;
@@ -714,18 +721,21 @@ static struct minivm_template *message_template_find(const char *name)
}
-/*! \brief Clear list of templates */
+/*!\internal
+ * \brief Clear list of templates */
static void message_destroy_list(void)
{
struct minivm_template *this;
AST_LIST_LOCK(&message_templates);
- while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list)))
+ while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) {
message_template_free(this);
-
+ }
+
AST_LIST_UNLOCK(&message_templates);
}
-/*! \brief read buffer from file (base64 conversion) */
+/*!\internal
+ * \brief read buffer from file (base64 conversion) */
static int b64_inbuf(struct b64_baseio *bio, FILE *fi)
{
int l;
@@ -747,7 +757,8 @@ static int b64_inbuf(struct b64_baseio *bio, FILE *fi)
return 1;
}
-/*! \brief read character from file to buffer (base64 conversion) */
+/*!\internal
+ * \brief read character from file to buffer (base64 conversion) */
static int b64_inchar(struct b64_baseio *bio, FILE *fi)
{
if (bio->iocp >= bio->iolen) {
@@ -758,7 +769,8 @@ static int b64_inchar(struct b64_baseio *bio, FILE *fi)
return bio->iobuf[bio->iocp++];
}
-/*! \brief write buffer to file (base64 conversion) */
+/*!\internal
+ * \brief write buffer to file (base64 conversion) */
static int b64_ochar(struct b64_baseio *bio, int c, FILE *so)
{
if (bio->linelength >= B64_BASELINELEN) {
@@ -776,7 +788,8 @@ static int b64_ochar(struct b64_baseio *bio, int c, FILE *so)
return 1;
}
-/*! \brief Encode file to base64 encoding for email attachment (base64 conversion) */
+/*!\internal
+ * \brief Encode file to base64 encoding for email attachment (base64 conversion) */
static int base_encode(char *filename, FILE *so)
{
unsigned char dtable[B64_BASEMAXINLINE];
@@ -859,7 +872,8 @@ static int get_date(char *s, int len)
}
-/*! \brief Free user structure - if it's allocated */
+/*!\internal
+ * \brief Free user structure - if it's allocated */
static void free_user(struct minivm_account *vmu)
{
if (vmu->chanvars)
@@ -869,8 +883,9 @@ static void free_user(struct minivm_account *vmu)
-/*! \brief Prepare for voicemail template by adding channel variables
- to the channel
+/*!\internal
+ * \brief Prepare for voicemail template by adding channel variables
+ * to the channel
*/
static void prep_email_sub_vars(struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
{
@@ -899,7 +914,8 @@ static void prep_email_sub_vars(struct ast_channel *channel, const struct minivm
pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
}
-/*! \brief Set default values for Mini-Voicemail users */
+/*!\internal
+ * \brief Set default values for Mini-Voicemail users */
static void populate_defaults(struct minivm_account *vmu)
{
ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
@@ -907,26 +923,8 @@ static void populate_defaults(struct minivm_account *vmu)
vmu->volgain = global_volgain;
}
-/*! \brief Fix quote of mail headers for non-ascii characters */
-static char *mailheader_quote(const char *from, char *to, size_t len)
-{
- char *ptr = to;
- *ptr++ = '"';
- for (; ptr < to + len - 1; from++) {
- if (*from == '"')
- *ptr++ = '\\';
- else if (*from == '\0')
- break;
- *ptr++ = *from;
- }
- if (ptr < to + len - 1)
- *ptr++ = '"';
- *ptr = '\0';
- return to;
-}
-
-
-/*! \brief Allocate new vm user and set default values */
+/*!\internal
+ * \brief Allocate new vm user and set default values */
static struct minivm_account *mvm_user_alloc(void)
{
struct minivm_account *new;
@@ -940,7 +938,8 @@ static struct minivm_account *mvm_user_alloc(void)
}
-/*! \brief Clear list of users */
+/*!\internal
+ * \brief Clear list of users */
static void vmaccounts_destroy_list(void)
{
struct minivm_account *this;
@@ -951,7 +950,8 @@ static void vmaccounts_destroy_list(void)
}
-/*! \brief Find user from static memory object list */
+/*!\internal
+ * \brief Find user from static memory object list */
static struct minivm_account *find_account(const char *domain, const char *username, int createtemp)
{
struct minivm_account *vmu = NULL, *cur;
@@ -992,8 +992,9 @@ static struct minivm_account *find_account(const char *domain, const char *usern
return vmu;
}
-/*! \brief Find user in realtime storage
- Returns pointer to minivm_account structure
+/*!\internal
+ * \brief Find user in realtime storage
+ * \return pointer to minivm_account structure
*/
static struct minivm_account *find_user_realtime(const char *domain, const char *username)
{
@@ -1023,7 +1024,102 @@ static struct minivm_account *find_user_realtime(const char *domain, const char
return retval;
}
-/*! \brief Send voicemail with audio file as an attachment */
+/*!\internal
+ * \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;
+}
+
+/*!\internal
+ * \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 end An expandable buffer for holding the result
+ * \param maxlen \see ast_str
+ * \param charset Character set in which the result should be encoded
+ * \param start A string to be encoded
+ * \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.
+ * \return The encoded string.
+ */
+static const char *ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
+{
+ struct ast_str *tmp = ast_str_alloca(80);
+ int first_section = 1;
+ *end = '\0';
+
+ ast_str_reset(*end);
+ ast_str_set(&tmp, -1, "=?%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 + ast_str_strlen(tmp) > 70) ||
+ (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
+ (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
+ (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
+ /* Start new line */
+ ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
+ ast_str_set(&tmp, -1, "=?%s?Q?", charset);
+ first_section = 0;
+ }
+ if (need_encoding && *start == ' ') {
+ ast_str_append(&tmp, -1, "_");
+ } else if (need_encoding) {
+ ast_str_append(&tmp, -1, "=%hhX", *start);
+ } else {
+ ast_str_append(&tmp, -1, "%c", *start);
+ }
+ }
+ ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
+ return ast_str_buffer(*end);
+}
+
+/*!\internal
+ * \brief Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
+ * \param from The string to work with.
+ * \param buf The destination buffer to write the modified quoted string.
+ * \param maxlen Always zero. \see ast_str
+ *
+ * \return The destination string with quotes wrapped on it (the to field).
+ */
+static const char *ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
+{
+ const char *ptr;
+
+ /* We're only ever passing 0 to maxlen, so short output isn't possible */
+ ast_str_set(buf, maxlen, "\"");
+ for (ptr = from; *ptr; ptr++) {
+ if (*ptr == '"' || *ptr == '\\') {
+ ast_str_append(buf, maxlen, "\\%c", *ptr);
+ } else {
+ ast_str_append(buf, maxlen, "%c", *ptr);
+ }
+ }
+ ast_str_append(buf, maxlen, "\"");
+
+ return ast_str_buffer(*buf);
+}
+
+/*!\internal
+ * \brief Send voicemail with audio file as an attachment */
static int sendmail(struct minivm_template *template, struct minivm_account *vmu, char *cidnum, char *cidname, const char *filename, char *format, int duration, int attach_user_voicemail, enum mvm_messagetype type, const char *counter)
{
FILE *p = NULL;
@@ -1039,14 +1135,18 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
struct timeval now;
struct ast_tm tm;
struct minivm_zone *the_zone = NULL;
- int len_passdata;
struct ast_channel *ast;
char *finalfilename;
- char *passdata = NULL;
- char *passdata2 = NULL;
+ struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
char *fromaddress;
char *fromemail;
+ if (!str1 || !str2) {
+ ast_free(str1);
+ ast_free(str2);
+ return -1;
+ }
+
if (type == MVM_MESSAGE_EMAIL) {
if (vmu && !ast_strlen_zero(vmu->email)) {
ast_copy_string(email, vmu->email, sizeof(email));
@@ -1160,51 +1260,71 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
if (ast_strlen_zero(fromaddress)) {
fprintf(p, "From: Asterisk PBX <%s>\n", who);
} else {
- /* Allocate a buffer big enough for variable substitution */
- int vmlen = strlen(fromaddress) * 3 + 200;
-
ast_debug(4, "Fromaddress template: %s\n", fromaddress);
- if ((passdata = alloca(vmlen))) {
- pbx_substitute_variables_helper(ast, fromaddress, passdata, vmlen);
- len_passdata = strlen(passdata) * 2 + 3;
- passdata2 = alloca(len_passdata);
- fprintf(p, "From: %s <%s>\n", mailheader_quote(passdata, passdata2, len_passdata), who);
- } else {
- ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
- fclose(p);
- return -1;
+ ast_str_substitute_variables(&str1, 0, ast, fromaddress);
+ if (check_mime(ast_str_buffer(str1))) {
+ int first_line = 1;
+ char *ptr;
+ ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
+ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s\n", first_line ? "From:" : "", ast_str_buffer(str2));
+ first_line = 0;
+ /* Substring is smaller, so this will never grow */
+ ast_str_set(&str2, 0, "%s", ptr + 1);
+ }
+ fprintf(p, "%s %s <%s>\n", first_line ? "From:" : "", ast_str_buffer(str2), who);
+ } else {
+ fprintf(p, "From: %s <%s>\n", ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
}
}
- ast_debug(4, "Fromstring now: %s\n", ast_strlen_zero(passdata) ? "-default-" : passdata);
fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
- len_passdata = strlen(vmu->fullname) * 2 + 3;
- passdata2 = alloca(len_passdata);
- if (!ast_strlen_zero(vmu->email))
- fprintf(p, "To: %s <%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->email);
- else
- fprintf(p, "To: %s <%s@%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->username, vmu->domain);
+
+ if (ast_strlen_zero(vmu->email)) {
+ snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
+ } else {
+ ast_copy_string(email, vmu->email, sizeof(email));
+ }
+
+ if (check_mime(vmu->fullname)) {
+ int first_line = 1;
+ char *ptr;
+ ast_str_encode_mime(&str2, 0, template->charset, vmu->fullname, strlen("To: "), strlen(email) + 3);
+ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s\n", first_line ? "To:" : "", ast_str_buffer(str2));
+ first_line = 0;
+ /* Substring is smaller, so this will never grow */
+ ast_str_set(&str2, 0, "%s", ptr + 1);
+ }
+ fprintf(p, "%s %s <%s>\n", first_line ? "To:" : "", ast_str_buffer(str2), email);
+ } else {
+ fprintf(p, "To: %s <%s>\n", ast_str_quote(&str2, 0, vmu->fullname), email);
+ }
if (!ast_strlen_zero(template->subject)) {
- char *pass_data;
- int vmlen = strlen(template->subject) * 3 + 200;
- if ((pass_data = alloca(vmlen))) {
- pbx_substitute_variables_helper(ast, template->subject, pass_data, vmlen);
- fprintf(p, "Subject: %s\n", pass_data);
+ ast_str_substitute_variables(&str1, 0, ast, template->subject);
+ if (check_mime(ast_str_buffer(str1))) {
+ int first_line = 1;
+ char *ptr;
+ ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("Subject: "), 0);
+ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
+ first_line = 0;
+ /* Substring is smaller, so this will never grow */
+ ast_str_set(&str2, 0, "%s", ptr + 1);
+ }
+ fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
} else {
- ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
- fclose(p);
- return -1;
+ fprintf(p, "Subject: %s\n", ast_str_buffer(str1));
}
-
- ast_debug(4, "Subject now: %s\n", pass_data);
-
- } else {
+ } else {
fprintf(p, "Subject: New message in mailbox %s@%s\n", vmu->username, vmu->domain);
ast_debug(1, "Using default subject for this email \n");
}
-
if (option_debug > 2)
fprintf(p, "X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->username, vmu->domain);
fprintf(p, "MIME-Version: 1.0\n");
@@ -1215,19 +1335,13 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
fprintf(p, "--%s\n", bound);
- fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", global_charset);
+ fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", template->charset);
if (!ast_strlen_zero(template->body)) {
- char *pass_data;
- int vmlen = strlen(template->body)*3 + 200;
- if ((pass_data = alloca(vmlen))) {
- pbx_substitute_variables_helper(ast, template->body, pass_data, vmlen);
- ast_debug(3, "Message now: %s\n-----\n", pass_data);
- fprintf(p, "%s\n", pass_data);
- } else
- ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
+ ast_str_substitute_variables(&str1, 0, ast, template->body);
+ ast_debug(3, "Message now: %s\n-----\n", ast_str_buffer(str1));
+ fprintf(p, "%s\n", ast_str_buffer(str1));
} else {
fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
-
"in mailbox %s from %s, on %s so you might\n"
"want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname,
dur, vmu->username, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
@@ -1239,7 +1353,7 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
ast_debug(3, "Attaching file to message: %s\n", fname);
if (!strcasecmp(format, "ogg"))
ctype = "application/";
-
+
fprintf(p, "--%s\n", bound);
fprintf(p, "Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
fprintf(p, "Content-Transfer-Encoding: base64\n");
@@ -1257,16 +1371,20 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
if (ast) {
ast = ast_channel_release(ast);
}
+ ast_free(str1);
+ ast_free(str2);
return 0;
}
-/*! \brief Create directory based on components */
+/*!\internal
+ * \brief Create directory based on components */
static int make_dir(char *dest, int len, const char *domain, const char *username, const char *folder)
{
return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
}
-/*! \brief Checks if directory exists. Does not create directory, but builds string in dest
+/*!\internal
+ * \brief Checks if directory exists. Does not create directory, but builds string in dest
* \param dest String. base directory.
* \param len Int. Length base directory string.
* \param domain String. Ignored if is null or empty string.
@@ -1284,11 +1402,12 @@ static int check_dirpath(char *dest, int len, char *domain, char *username, char
return TRUE;
}
-/*! \brief basically mkdir -p $dest/$domain/$username/$folder
+/*!\internal
+ * \brief basically mkdir -p $dest/$domain/$username/$folder
* \param dest String. base directory.
* \param len Length of directory string
* \param domain String. Ignored if is null or empty string.
- * \param folder String. Ignored if is null or empty string.
+ * \param folder String. Ignored if is null or empty string.
* \param username String. Ignored if is null or empty string.
* \return -1 on failure, 0 on success.
*/
@@ -1305,8 +1424,9 @@ static int create_dirpath(char *dest, int len, char *domain, char *username, cha
}
-/*! \brief Play intro message before recording voicemail
-*/
+/*!\internal
+ * \brief Play intro message before recording voicemail
+ */
static int invent_message(struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
{
int res;
@@ -1328,7 +1448,7 @@ static int invent_message(struct ast_channel *chan, char *domain, char *username
char *i = username;
ast_debug(2, "No personal prompts. Using default prompt set for language\n");
-
+
while (*i) {
ast_debug(2, "Numeric? Checking %c\n", *i);
if (!isdigit(*i)) {
@@ -1339,16 +1459,16 @@ static int invent_message(struct ast_channel *chan, char *domain, char *username
}
if (numericusername) {
- if(ast_streamfile(chan, "vm-theperson", chan->language))
+ if (ast_streamfile(chan, "vm-theperson", chan->language))
return -1;
if ((res = ast_waitstream(chan, ecodes)))
return res;
-
+
res = ast_say_digit_str(chan, username, ecodes, chan->language);
if (res)
return res;
} else {
- if(ast_streamfile(chan, "vm-theextensionis", chan->language))
+ if (ast_streamfile(chan, "vm-theextensionis", chan->language))
return -1;
if ((res = ast_waitstream(chan, ecodes)))
return res;
@@ -1362,7 +1482,8 @@ static int invent_message(struct ast_channel *chan, char *domain, char *username
return res;
}
-/*! \brief Delete media files and attribute file */
+/*!\internal
+ * \brief Delete media files and attribute file */
static int vm_delete(char *file)
{
int res;
@@ -1375,30 +1496,31 @@ static int vm_delete(char *file)
}
-/*! \brief Record voicemail message & let caller review or re-record it, or set options if applicable */
+/*!\internal
+ * \brief Record voicemail message & let caller review or re-record it, or set options if applicable */
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
int outsidecaller, struct minivm_account *vmu, int *duration, const char *unlockdir,
signed char record_gain)
{
- int cmd = 0;
- int max_attempts = 3;
- int attempts = 0;
- int recorded = 0;
- int message_exists = 0;
+ int cmd = 0;
+ int max_attempts = 3;
+ int attempts = 0;
+ int recorded = 0;
+ int message_exists = 0;
signed char zero_gain = 0;
char *acceptdtmf = "#";
char *canceldtmf = "";
- /* Note that urgent and private are for flagging messages as such in the future */
-
+ /* Note that urgent and private are for flagging messages as such in the future */
+
/* barf if no pointer passed to store duration in */
if (duration == NULL) {
ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
return -1;
}
- cmd = '3'; /* Want to start by recording */
-
+ cmd = '3'; /* Want to start by recording */
+
while ((cmd >= 0) && (cmd != 't')) {
switch (cmd) {
case '1':
@@ -1406,23 +1528,23 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
ast_stream_and_wait(chan, "vm-msgsaved", "");
cmd = 't';
break;
- case '2':
- /* Review */
+ case '2':
+ /* Review */
ast_verb(3, "Reviewing the message\n");
- ast_streamfile(chan, recordfile, chan->language);
- cmd = ast_waitstream(chan, AST_DIGIT_ANY);
- break;
- case '3':
- message_exists = 0;
- /* Record */
- if (recorded == 1)
+ ast_streamfile(chan, recordfile, chan->language);
+ cmd = ast_waitstream(chan, AST_DIGIT_ANY);
+ break;
+ case '3':
+ message_exists = 0;
+ /* Record */
+ if (recorded == 1)
ast_verb(3, "Re-recording the message\n");
- else
+ else
ast_verb(3, "Recording the message\n");
if (recorded && outsidecaller)
- cmd = ast_play_and_wait(chan, "beep");
- recorded = 1;
- /* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */
+ cmd = ast_play_and_wait(chan, "beep");
+ recorded = 1;
+ /* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */
if (record_gain)
ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
if (ast_test_flag(vmu, MVM_OPERATOR))
@@ -1430,10 +1552,10 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
if (record_gain)
ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
- if (cmd == -1) /* User has hung up, no options to give */
- return cmd;
- if (cmd == '0')
- break;
+ if (cmd == -1) /* User has hung up, no options to give */
+ return cmd;
+ if (cmd == '0')
+ break;
else if (cmd == '*')
break;
else {
@@ -1484,7 +1606,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
if (!cmd)
cmd = ast_waitfordigit(chan, 600);
}
-
+
if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
cmd = ast_play_and_wait(chan, "vm-reachoper");
if (!cmd)
@@ -1500,7 +1622,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
}
}
}
- if (outsidecaller)
+ if (outsidecaller)
ast_play_and_wait(chan, "vm-goodbye");
if (cmd == 't')
cmd = 0;
@@ -1521,10 +1643,11 @@ static void run_externnotify(struct ast_channel *chan, struct minivm_account *vm
chan->cid.cid_name, chan->cid.cid_num);
ast_debug(1, "Executing: %s\n", arguments);
- ast_safe_system(arguments);
+ ast_safe_system(arguments);
}
-/*! \brief Send message to voicemail account owner */
+/*!\internal
+ * \brief Send message to voicemail account owner */
static int notify_new_message(struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
{
char *stringp;
@@ -1537,8 +1660,9 @@ static int notify_new_message(struct ast_channel *chan, const char *templatename
if (!ast_strlen_zero(vmu->attachfmt)) {
if (strstr(format, vmu->attachfmt)) {
format = vmu->attachfmt;
- } else
+ } else {
ast_log(LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'. Falling back to default format for '%s@%s'.\n", vmu->attachfmt, format, vmu->username, vmu->domain);
+ }
}
etemplate = message_template_find(vmu->etemplate);
@@ -1595,13 +1719,15 @@ static int notify_new_message(struct ast_channel *chan, const char *templatename
run_externnotify(chan, vmu); /* Run external notification */
- if (etemplate->locale)
+ if (etemplate->locale) {
setlocale(LC_TIME, oldlocale); /* Rest to old locale */
+ }
return res;
}
-/*! \brief Record voicemail message, store into file prepared for sending e-mail */
+/*!\internal
+ * \brief Record voicemail message, store into file prepared for sending e-mail */
static int leave_voicemail(struct ast_channel *chan, char *username, struct leave_vm_options *options)
{
char tmptxtfile[PATH_MAX];
@@ -1663,7 +1789,6 @@ static int leave_voicemail(struct ast_channel *chan, char *username, struct leav
snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
-
/* XXX This file needs to be in temp directory */
txtdes = mkstemp(tmptxtfile);
@@ -1700,7 +1825,7 @@ static int leave_voicemail(struct ast_channel *chan, char *username, struct leav
get_date(date, sizeof(date));
ast_localtime(&now, &tm, NULL);
ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
-
+
snprintf(logbuf, sizeof(logbuf),
/* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
"%s:%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
@@ -1751,12 +1876,14 @@ static int leave_voicemail(struct ast_channel *chan, char *username, struct leav
}
global_stats.lastreceived = ast_tvnow();
global_stats.receivedmessages++;
-// /* Go ahead and delete audio files from system, they're not needed any more */
-// if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
-// ast_filedelete(tmptxtfile, NULL);
-// /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
-// ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
-// }
+#if 0
+ /* Go ahead and delete audio files from system, they're not needed any more */
+ if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
+ ast_filedelete(tmptxtfile, NULL);
+ /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
+ ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
+ }
+#endif
if (res > 0)
res = 0;
@@ -1768,7 +1895,8 @@ static int leave_voicemail(struct ast_channel *chan, char *username, struct leav
return res;
}
-/*! \brief Queue a message waiting event */
+/*!\internal
+ * \brief Queue a message waiting event */
static void queue_mwi_event(const char *mbx, const char *ctx, int urgent, int new, int old)
{
struct ast_event *event;
@@ -1792,7 +1920,8 @@ static void queue_mwi_event(const char *mbx, const char *ctx, int urgent, int ne
ast_event_queue_and_cache(event);
}
-/*! \brief Send MWI using interal Asterisk event subsystem */
+/*!\internal
+ * \brief Send MWI using interal Asterisk event subsystem */
static int minivm_mwi_exec(struct ast_channel *chan, void *data)
{
int argc;
@@ -1803,37 +1932,38 @@ static int minivm_mwi_exec(struct ast_channel *chan, void *data)
char *mailbox;
char *domain;
if (ast_strlen_zero(data)) {
- ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
- return -1;
- }
- tmpptr = ast_strdupa((char *)data);
- if (!tmpptr) {
- ast_log(LOG_ERROR, "Out of memory\n");
- return -1;
- }
- argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
+ ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
+ return -1;
+ }
+ tmpptr = ast_strdupa((char *)data);
+ if (!tmpptr) {
+ ast_log(LOG_ERROR, "Out of memory\n");
+ return -1;
+ }
+ argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
if (argc < 4) {
ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
return -1;
}
- ast_copy_string(tmp, argv[0], sizeof(tmp));
- mailbox = tmp;
- domain = strchr(tmp, '@');
- if (domain) {
- *domain = '\0';
- domain++;
- }
- if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
- ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
- return -1;
- }
+ ast_copy_string(tmp, argv[0], sizeof(tmp));
+ mailbox = tmp;
+ domain = strchr(tmp, '@');
+ if (domain) {
+ *domain = '\0';
+ domain++;
+ }
+ if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
+ ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
+ return -1;
+ }
queue_mwi_event(mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
return res;
}
-/*! \brief Notify voicemail account owners - either generic template or user specific */
+/*!\internal
+ * \brief Notify voicemail account owners - either generic template or user specific */
static int minivm_notify_exec(struct ast_channel *chan, void *data)
{
int argc;
@@ -1848,7 +1978,7 @@ static int minivm_notify_exec(struct ast_channel *chan, void *data)
const char *filename;
const char *format;
const char *duration_string;
-
+
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
return -1;
@@ -1912,7 +2042,8 @@ static int minivm_notify_exec(struct ast_channel *chan, void *data)
}
-/*! \brief Dialplan function to record voicemail */
+/*!\internal
+ * \brief Dialplan function to record voicemail */
static int minivm_record_exec(struct ast_channel *chan, void *data)
{
int res = 0;
@@ -1922,7 +2053,7 @@ static int minivm_record_exec(struct ast_channel *chan, void *data)
char *argv[2];
struct ast_flags flags = { 0 };
char *opts[OPT_ARG_ARRAY_SIZE];
-
+
memset(&leave_options, 0, sizeof(leave_options));
/* Answer channel if it's not already answered */
@@ -1968,7 +2099,8 @@ static int minivm_record_exec(struct ast_channel *chan, void *data)
return res;
}
-/*! \brief Play voicemail prompts - either generic or user specific */
+/*!\internal
+ * \brief Play voicemail prompts - either generic or user specific */
static int minivm_greet_exec(struct ast_channel *chan, void *data)
{
struct leave_vm_options leave_options = { 0, '\0'};
@@ -2154,12 +2286,13 @@ static int minivm_greet_exec(struct ast_channel *chan, void *data)
}
-/*! \brief Dialplan application to delete voicemail */
+/*!\internal
+ * \brief Dialplan application to delete voicemail */
static int minivm_delete_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char filename[BUFSIZ];
-
+
if (!ast_strlen_zero(data)) {
ast_copy_string(filename, (char *) data, sizeof(filename));
} else {
@@ -2609,7 +2742,6 @@ static int load_config(int reload)
ast_copy_string(default_vmformat, "wav", sizeof(default_vmformat));
ast_set2_flag((&globalflags), FALSE, MVM_REVIEW);
ast_set2_flag((&globalflags), FALSE, MVM_OPERATOR);
- strcpy(global_charset, "ISO-8859-1");
/* Reset statistics */
memset(&global_stats, 0, sizeof(global_stats));
global_stats.reset = ast_tvnow();