diff options
Diffstat (limited to 'apps/app_minivm.c')
-rw-r--r-- | apps/app_minivm.c | 490 |
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(); |