MiniVoiceMail - A Minimal Voicemail System for Asterisk. More...
#include "asterisk.h"#include <ctype.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/mman.h>#include <time.h>#include <dirent.h>#include <locale.h>#include "asterisk/paths.h"#include "asterisk/lock.h"#include "asterisk/file.h"#include "asterisk/channel.h"#include "asterisk/pbx.h"#include "asterisk/config.h"#include "asterisk/say.h"#include "asterisk/module.h"#include "asterisk/app.h"#include "asterisk/manager.h"#include "asterisk/dsp.h"#include "asterisk/localtime.h"#include "asterisk/cli.h"#include "asterisk/utils.h"#include "asterisk/linkedlists.h"#include "asterisk/callerid.h"#include "asterisk/event.h"
Go to the source code of this file.
Data Structures | |
| struct | b64_baseio |
| Structure for base64 encoding. More... | |
| struct | leave_vm_options |
| Options for leaving voicemail with the voicemail() application. More... | |
| struct | message_templates |
| The list of e-mail templates. More... | |
| struct | minivm_account |
| Structure for linked list of Mini-Voicemail users: minivm_accounts. More... | |
| struct | minivm_accounts |
| The list of e-mail accounts. More... | |
| struct | minivm_stats |
| Structure for gathering statistics. More... | |
| struct | minivm_template |
| Linked list of e-mail templates in various languages These are used as templates for e-mails, pager messages and jabber messages message_templates. More... | |
| struct | minivm_zone |
| Voicemail time zones. More... | |
| struct | minivm_zones |
| The list of e-mail time zones. More... | |
Defines | |
| #define | ASTERISK_USERNAME "asterisk" |
| #define | B64_BASELINELEN 72 |
| #define | B64_BASEMAXINLINE 256 |
| #define | DEFAULT_CHARSET "ISO-8859-1" |
| #define | DEFAULT_DATEFORMAT "%A, %B %d, %Y at %r" |
| Default dateformat, can be overridden in configuration file. | |
| #define | EOL "\r\n" |
| #define | ERROR_LOCK_PATH -100 |
| #define | FALSE 0 |
| #define | HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n" |
| #define | HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n" |
| #define | HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n" |
| #define | MAX_DATETIME_FORMAT 512 |
| #define | MAX_NUM_CID_CONTEXTS 10 |
| #define | MVM_ALLOCED (1 << 13) |
| #define | MVM_ENVELOPE (1 << 4) |
| #define | MVM_OPERATOR (1 << 1) |
| #define | MVM_PBXSKIP (1 << 9) |
| #define | MVM_REALTIME (1 << 2) |
| #define | MVM_REVIEW (1 << 0) |
| #define | MVM_SVMAIL (1 << 3) |
| #define | SENDMAIL "/usr/sbin/sendmail -t" |
| Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail.conf. | |
| #define | SOUND_INTRO "vm-intro" |
| #define | TRUE 1 |
| #define | VOICEMAIL_CONFIG "minivm.conf" |
| #define | VOICEMAIL_DIR_MODE 0700 |
Enumerations | |
| enum | { OPT_SILENT = (1 << 0), OPT_BUSY_GREETING = (1 << 1), OPT_UNAVAIL_GREETING = (1 << 2), OPT_TEMP_GREETING = (1 << 3), OPT_NAME_GREETING = (1 << 4), OPT_RECORDGAIN = (1 << 5) } |
| enum | { OPT_ARG_RECORDGAIN = 0, OPT_ARG_ARRAY_SIZE = 1 } |
| enum | mvm_messagetype { MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE } |
| Message types for notification. More... | |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | access_counter_file (char *directory, char *countername, int value, int operand) |
| Access counter file, lock directory, read and possibly write it again changed. | |
| static int | apply_general_options (struct ast_variable *var) |
| Apply general configuration options. | |
| static int | b64_inbuf (struct b64_baseio *bio, FILE *fi) |
| read buffer from file (base64 conversion) | |
| static int | b64_inchar (struct b64_baseio *bio, FILE *fi) |
| read character from file to buffer (base64 conversion) | |
| static int | b64_ochar (struct b64_baseio *bio, int c, FILE *so) |
| write buffer to file (base64 conversion) | |
| static int | base_encode (char *filename, FILE *so) |
| Encode file to base64 encoding for email attachment (base64 conversion) | |
| static int | check_dirpath (char *dest, int len, char *domain, char *username, char *folder) |
| Checks if directory exists. Does not create directory, but builds string in dest. | |
| static char * | complete_minivm_show_users (const char *line, const char *word, int pos, int state) |
| static int | create_dirpath (char *dest, int len, char *domain, char *username, char *folder) |
| basically mkdir -p $dest/$domain/$username/$folder | |
| static int | create_vmaccount (char *name, struct ast_variable *var, int realtime) |
| Append new mailbox to mailbox list from configuration file. | |
| static struct minivm_account * | find_account (const char *domain, const char *username, int createtemp) |
| Find user from static memory object list. | |
| static struct minivm_account * | find_user_realtime (const char *domain, const char *username) |
| Find user in realtime storage Returns pointer to minivm_account structure. | |
| static void | free_user (struct minivm_account *vmu) |
| Free user structure - if it's allocated. | |
| static void | free_zone (struct minivm_zone *z) |
| Free Mini Voicemail timezone. | |
| static int | get_date (char *s, int len) |
| static char * | handle_minivm_list_templates (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI routine for listing templates. | |
| static char * | handle_minivm_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Reload cofiguration. | |
| static char * | handle_minivm_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI Show settings. | |
| static char * | handle_minivm_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show stats. | |
| static char * | handle_minivm_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command to list voicemail accounts. | |
| static char * | handle_minivm_show_zones (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show a list of voicemail zones in the CLI. | |
| static int | invent_message (struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes) |
| Play intro message before recording voicemail. | |
| static int | leave_voicemail (struct ast_channel *chan, char *username, struct leave_vm_options *options) |
| Record voicemail message, store into file prepared for sending e-mail. | |
| static int | load_config (int reload) |
| Load minivoicemail configuration. | |
| static int | load_module (void) |
| Load mini voicemail module. | |
| static char * | mailheader_quote (const char *from, char *to, size_t len) |
| Fix quote of mail headers for non-ascii characters. | |
| static int | make_dir (char *dest, int len, const char *domain, const char *username, const char *folder) |
| Create directory based on components. | |
| static void | message_destroy_list (void) |
| Clear list of templates. | |
| static int | message_template_build (const char *name, struct ast_variable *var) |
| Build message template from configuration. | |
| static struct minivm_template * | message_template_create (const char *name) |
| Create message template. | |
| static struct minivm_template * | message_template_find (const char *name) |
| Find named template. | |
| static void | message_template_free (struct minivm_template *template) |
| Release memory allocated by message template. | |
| static char * | message_template_parse_emailbody (const char *configuration) |
| Parse emailbody template from configuration file. | |
| static char * | message_template_parse_filebody (const char *filename) |
| Read message template from file. | |
| static int | minivm_accmess_exec (struct ast_channel *chan, void *data) |
| Record specific messages for voicemail account. | |
| static int | minivm_account_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| ${MINIVMACCOUNT()} Dialplan function - reads account data | |
| static int | minivm_counter_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| ${MINIVMCOUNTER()} Dialplan function - read counters | |
| static int | minivm_counter_func_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
| ${MINIVMCOUNTER()} Dialplan function - changes counter data | |
| static int | minivm_delete_exec (struct ast_channel *chan, void *data) |
| Dialplan application to delete voicemail. | |
| static int | minivm_greet_exec (struct ast_channel *chan, void *data) |
| Play voicemail prompts - either generic or user specific. | |
| static int | minivm_mwi_exec (struct ast_channel *chan, void *data) |
| Send MWI using interal Asterisk event subsystem. | |
| static int | minivm_notify_exec (struct ast_channel *chan, void *data) |
| Notify voicemail account owners - either generic template or user specific. | |
| static int | minivm_record_exec (struct ast_channel *chan, void *data) |
| Dialplan function to record voicemail. | |
| static struct minivm_account * | mvm_user_alloc (void) |
| Allocate new vm user and set default values. | |
| 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) |
| Send message to voicemail account owner. | |
| 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) |
| Record voicemail message & let caller review or re-record it, or set options if applicable. | |
| static void | populate_defaults (struct minivm_account *vmu) |
| Set default values for Mini-Voicemail users. | |
| 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) |
| Prepare for voicemail template by adding channel variables to the channel. | |
| static void | queue_mwi_event (const char *mbx, const char *ctx, int urgent, int new, int old) |
| Queue a message waiting event. | |
| static int | reload (void) |
| Reload mini voicemail module. | |
| static void | run_externnotify (struct ast_channel *chan, struct minivm_account *vmu) |
| Run external notification for voicemail message. | |
| 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) |
| Send voicemail with audio file as an attachment. | |
| static int | timezone_add (const char *zonename, const char *config) |
| Add time zone to memory list. | |
| static void | timezone_destroy_list (void) |
| Clear list of timezones. | |
| static int | unload_module (void) |
| Unload mini voicemail module. | |
| static int | vm_delete (char *file) |
| Delete media files and attribute file. | |
| static int | vm_lock_path (const char *path) |
| lock directory | |
| static void | vmaccounts_destroy_list (void) |
| Clear list of users. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| static char * | app_minivm_accmess = "MinivmAccMess" |
| static char * | app_minivm_delete = "MinivmDelete" |
| static char * | app_minivm_greet = "MinivmGreet" |
| static char * | app_minivm_mwi = "MinivmMWI" |
| static char * | app_minivm_notify = "MinivmNotify" |
| static char * | app_minivm_record = "MinivmRecord" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_cli_entry | cli_minivm [] |
| CLI commands for Mini-voicemail. | |
| static char | default_vmformat [80] |
| static char | global_charset [32] |
| static char | global_externnotify [160] |
| static char | global_logfile [PATH_MAX] |
| static char | global_mailcmd [160] |
| static int | global_maxgreet |
| static int | global_maxsilence |
| static int | global_saydurationminfo |
| static int | global_silencethreshold = 128 |
| static struct minivm_stats | global_stats |
| Statistics for voicemail. | |
| static int | global_vmmaxmessage |
| static int | global_vmminmessage |
| static double | global_volgain |
| static struct ast_flags | globalflags = {0} |
| static struct message_templates | message_templates |
| static struct ast_app_option | minivm_accmess_options [128] = { [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 't' ] = { .flag = OPT_TEMP_GREETING }, [ 'n' ] = { .flag = OPT_NAME_GREETING },} |
| static struct ast_custom_function | minivm_account_function |
| static struct minivm_accounts | minivm_accounts |
| static struct ast_app_option | minivm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 },} |
| static struct ast_custom_function | minivm_counter_function |
| enum { ... } | minivm_option_args |
| enum { ... } | minivm_option_flags |
| static struct minivm_zones | minivm_zones |
| static ast_mutex_t | minivmlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| FILE * | minivmlogfile |
| static ast_mutex_t | minivmloglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static char | MVM_SPOOL_DIR [PATH_MAX] |
MiniVoiceMail - A Minimal Voicemail System for Asterisk.
A voicemail system in small building blocks, working together based on the Comedian Mail voicemail system (app_voicemail.c).
Definition in file app_minivm.c.
| #define ASTERISK_USERNAME "asterisk" |
Default username for sending mail is asterisk@localhost
Definition at line 437 of file app_minivm.c.
| #define B64_BASELINELEN 72 |
Line length for Base 64 endoded messages
Definition at line 427 of file app_minivm.c.
Referenced by b64_ochar().
| #define B64_BASEMAXINLINE 256 |
Buffer size for Base 64 attachment encoding
Definition at line 426 of file app_minivm.c.
Referenced by b64_inbuf(), and base_encode().
| #define DEFAULT_CHARSET "ISO-8859-1" |
Definition at line 597 of file app_minivm.c.
Referenced by message_template_create().
| #define DEFAULT_DATEFORMAT "%A, %B %d, %Y at %r" |
Default dateformat, can be overridden in configuration file.
Definition at line 596 of file app_minivm.c.
Referenced by message_template_create().
| #define EOL "\r\n" |
Definition at line 428 of file app_minivm.c.
Referenced by b64_ochar(), and base_encode().
| #define ERROR_LOCK_PATH -100 |
Definition at line 433 of file app_minivm.c.
Referenced by minivm_record_exec().
| #define FALSE 0 |
Definition at line 409 of file app_minivm.c.
Referenced by ast_tzset(), check_dirpath(), invent_message(), load_config(), minivm_accmess_exec(), minivm_counter_func_read(), minivm_counter_func_write(), rcvfax_exec(), show_console(), sndfax_exec(), time1(), time2(), time2sub(), transmit_audio(), transmit_t38(), tzload(), and tzparse().
| #define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n" |
Referenced by handle_minivm_show_users().
| #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n" |
Referenced by handle_minivm_show_zones().
| #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n" |
Referenced by handle_minivm_list_templates().
| #define MAX_DATETIME_FORMAT 512 |
Definition at line 430 of file app_minivm.c.
| #define MAX_NUM_CID_CONTEXTS 10 |
Definition at line 431 of file app_minivm.c.
| #define MVM_ALLOCED (1 << 13) |
Definition at line 419 of file app_minivm.c.
Referenced by find_account(), leave_voicemail(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), and minivm_notify_exec().
| #define MVM_ENVELOPE (1 << 4) |
Definition at line 417 of file app_minivm.c.
| #define MVM_OPERATOR (1 << 1) |
Operator exit during voicemail recording
Definition at line 414 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), minivm_greet_exec(), and play_record_review().
| #define MVM_PBXSKIP (1 << 9) |
Definition at line 418 of file app_minivm.c.
| #define MVM_REALTIME (1 << 2) |
This user is a realtime account
Definition at line 415 of file app_minivm.c.
| #define MVM_REVIEW (1 << 0) |
Review message
Definition at line 413 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and play_record_review().
| #define MVM_SVMAIL (1 << 3) |
Definition at line 416 of file app_minivm.c.
| #define SENDMAIL "/usr/sbin/sendmail -t" |
Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail.conf.
Definition at line 423 of file app_minivm.c.
Referenced by load_config().
| #define SOUND_INTRO "vm-intro" |
Definition at line 425 of file app_minivm.c.
Referenced by minivm_greet_exec().
| #define TRUE 1 |
Definition at line 406 of file app_minivm.c.
Referenced by ast_tzset(), check_dirpath(), cli_activate(), find_account(), find_user_realtime(), gmtload(), leave_voicemail(), load_config(), message_template_create(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), minivm_notify_exec(), rcvfax_exec(), show_console(), sndfax_exec(), time1(), time2(), time2sub(), transmit_audio(), transmit_t38(), tzload(), and tzparse().
| #define VOICEMAIL_CONFIG "minivm.conf" |
Definition at line 436 of file app_minivm.c.
Referenced by load_config().
| #define VOICEMAIL_DIR_MODE 0700 |
Definition at line 434 of file app_minivm.c.
| anonymous enum |
| OPT_SILENT | |
| OPT_BUSY_GREETING | |
| OPT_UNAVAIL_GREETING | |
| OPT_TEMP_GREETING | |
| OPT_NAME_GREETING | |
| OPT_RECORDGAIN |
Definition at line 458 of file app_minivm.c.
{
OPT_SILENT = (1 << 0),
OPT_BUSY_GREETING = (1 << 1),
OPT_UNAVAIL_GREETING = (1 << 2),
OPT_TEMP_GREETING = (1 << 3),
OPT_NAME_GREETING = (1 << 4),
OPT_RECORDGAIN = (1 << 5),
} minivm_option_flags;
| anonymous enum |
Definition at line 467 of file app_minivm.c.
{
OPT_ARG_RECORDGAIN = 0,
OPT_ARG_ARRAY_SIZE = 1,
} minivm_option_args;
| enum mvm_messagetype |
Message types for notification.
Definition at line 440 of file app_minivm.c.
{
MVM_MESSAGE_EMAIL,
MVM_MESSAGE_PAGE
/* For trunk: MVM_MESSAGE_JABBER, */
};
| static void __reg_module | ( | void | ) | [static] |
Definition at line 3350 of file app_minivm.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 3350 of file app_minivm.c.
| static int access_counter_file | ( | char * | directory, |
| char * | countername, | ||
| int | value, | ||
| int | operand | ||
| ) | [static] |
Access counter file, lock directory, read and possibly write it again changed.
| directory | Directory to crate file in |
| countername | filename |
| value | If set to zero, we only read the variable |
| operand | 0 to read, 1 to set new value, 2 to change |
Definition at line 3036 of file app_minivm.c.
References ast_debug, ast_log(), ast_unlock_path(), errno, LOG_ERROR, and vm_lock_path().
Referenced by minivm_counter_func_read(), and minivm_counter_func_write().
{
char filename[BUFSIZ];
char readbuf[BUFSIZ];
FILE *counterfile;
int old = 0, counter = 0;
/* Lock directory */
if (vm_lock_path(directory)) {
return -1; /* Could not lock directory */
}
snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
if (operand != 1) {
counterfile = fopen(filename, "r");
if (counterfile) {
if(fgets(readbuf, sizeof(readbuf), counterfile)) {
ast_debug(3, "Read this string from counter file: %s\n", readbuf);
old = counter = atoi(readbuf);
}
fclose(counterfile);
}
}
switch (operand) {
case 0: /* Read only */
ast_unlock_path(directory);
ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
return counter;
break;
case 1: /* Set new value */
counter = value;
break;
case 2: /* Change value */
counter += value;
if (counter < 0) /* Don't allow counters to fall below zero */
counter = 0;
break;
}
/* Now, write the new value to the file */
counterfile = fopen(filename, "w");
if (!counterfile) {
ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
ast_unlock_path(directory);
return -1; /* Could not open file for writing */
}
fprintf(counterfile, "%d\n\n", counter);
fclose(counterfile);
ast_unlock_path(directory);
ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
return counter;
}
| static int apply_general_options | ( | struct ast_variable * | var | ) | [static] |
Apply general configuration options.
Definition at line 2515 of file app_minivm.c.
References ast_config_AST_LOG_DIR, ast_copy_string(), ast_log(), ast_set2_flag, ast_strlen_zero(), ast_true(), default_vmformat, global_externnotify, global_logfile, global_mailcmd, global_maxgreet, global_maxsilence, global_silencethreshold, global_vmmaxmessage, global_vmminmessage, globalflags, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by load_config().
{
int error = 0;
while (var) {
/* Mail command */
if (!strcmp(var->name, "mailcmd")) {
ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
} else if (!strcmp(var->name, "maxgreet")) {
global_maxgreet = atoi(var->value);
} else if (!strcmp(var->name, "maxsilence")) {
global_maxsilence = atoi(var->value);
if (global_maxsilence > 0)
global_maxsilence *= 1000;
} else if (!strcmp(var->name, "logfile")) {
if (!ast_strlen_zero(var->value) ) {
if(*(var->value) == '/')
ast_copy_string(global_logfile, var->value, sizeof(global_logfile));
else
snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
}
} else if (!strcmp(var->name, "externnotify")) {
/* External voicemail notify application */
ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
} else if (!strcmp(var->name, "silencetreshold")) {
/* Silence treshold */
global_silencethreshold = atoi(var->value);
} else if (!strcmp(var->name, "maxmessage")) {
int x;
if (sscanf(var->value, "%30d", &x) == 1) {
global_vmmaxmessage = x;
} else {
error ++;
ast_log(LOG_WARNING, "Invalid max message time length\n");
}
} else if (!strcmp(var->name, "minmessage")) {
int x;
if (sscanf(var->value, "%30d", &x) == 1) {
global_vmminmessage = x;
if (global_maxsilence <= global_vmminmessage)
ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
} else {
error ++;
ast_log(LOG_WARNING, "Invalid min message time length\n");
}
} else if (!strcmp(var->name, "format")) {
ast_copy_string(default_vmformat, var->value, sizeof(default_vmformat));
} else if (!strcmp(var->name, "review")) {
ast_set2_flag((&globalflags), ast_true(var->value), MVM_REVIEW);
} else if (!strcmp(var->name, "operator")) {
ast_set2_flag((&globalflags), ast_true(var->value), MVM_OPERATOR);
}
var = var->next;
}
return error;
}
| static int b64_inbuf | ( | struct b64_baseio * | bio, |
| FILE * | fi | ||
| ) | [static] |
read buffer from file (base64 conversion)
Definition at line 729 of file app_minivm.c.
References b64_baseio::ateof, B64_BASEMAXINLINE, b64_baseio::iobuf, b64_baseio::iocp, and b64_baseio::iolen.
Referenced by b64_inchar().
| static int b64_inchar | ( | struct b64_baseio * | bio, |
| FILE * | fi | ||
| ) | [static] |
read character from file to buffer (base64 conversion)
Definition at line 751 of file app_minivm.c.
References b64_inbuf(), b64_baseio::iobuf, b64_baseio::iocp, and b64_baseio::iolen.
Referenced by base_encode().
| static int b64_ochar | ( | struct b64_baseio * | bio, |
| int | c, | ||
| FILE * | so | ||
| ) | [static] |
write buffer to file (base64 conversion)
Definition at line 762 of file app_minivm.c.
References B64_BASELINELEN, EOL, and b64_baseio::linelength.
Referenced by base_encode().
{
if (bio->linelength >= B64_BASELINELEN) {
if (fputs(EOL,so) == EOF)
return -1;
bio->linelength= 0;
}
if (putc(((unsigned char) c), so) == EOF)
return -1;
bio->linelength++;
return 1;
}
| static int base_encode | ( | char * | filename, |
| FILE * | so | ||
| ) | [static] |
Encode file to base64 encoding for email attachment (base64 conversion)
Definition at line 780 of file app_minivm.c.
References ast_log(), B64_BASEMAXINLINE, b64_inchar(), b64_ochar(), EOL, errno, b64_baseio::iocp, and LOG_WARNING.
Referenced by sendmail().
{
unsigned char dtable[B64_BASEMAXINLINE];
int i,hiteof= 0;
FILE *fi;
struct b64_baseio bio;
memset(&bio, 0, sizeof(bio));
bio.iocp = B64_BASEMAXINLINE;
if (!(fi = fopen(filename, "rb"))) {
ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
return -1;
}
for (i= 0; i<9; i++) {
dtable[i]= 'A'+i;
dtable[i+9]= 'J'+i;
dtable[26+i]= 'a'+i;
dtable[26+i+9]= 'j'+i;
}
for (i= 0; i < 8; i++) {
dtable[i+18]= 'S'+i;
dtable[26+i+18]= 's'+i;
}
for (i= 0; i < 10; i++) {
dtable[52+i]= '0'+i;
}
dtable[62]= '+';
dtable[63]= '/';
while (!hiteof){
unsigned char igroup[3], ogroup[4];
int c,n;
igroup[0]= igroup[1]= igroup[2]= 0;
for (n= 0; n < 3; n++) {
if ((c = b64_inchar(&bio, fi)) == EOF) {
hiteof= 1;
break;
}
igroup[n]= (unsigned char)c;
}
if (n> 0) {
ogroup[0]= dtable[igroup[0]>>2];
ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
ogroup[3]= dtable[igroup[2]&0x3F];
if (n<3) {
ogroup[3]= '=';
if (n<2)
ogroup[2]= '=';
}
for (i= 0;i<4;i++)
b64_ochar(&bio, ogroup[i], so);
}
}
/* Put end of line - line feed */
if (fputs(EOL, so) == EOF)
return 0;
fclose(fi);
return 1;
}
| static int check_dirpath | ( | char * | dest, |
| int | len, | ||
| char * | domain, | ||
| char * | username, | ||
| char * | folder | ||
| ) | [static] |
Checks if directory exists. Does not create directory, but builds string in dest.
| dest | String. base directory. |
| len | Int. Length base directory string. |
| domain | String. Ignored if is null or empty string. |
| username | String. Ignored if is null or empty string. |
| folder | String. Ignored if is null or empty string. |
Definition at line 1276 of file app_minivm.c.
References FALSE, make_dir(), and TRUE.
Referenced by leave_voicemail(), minivm_account_func_read(), and minivm_greet_exec().
| static char* complete_minivm_show_users | ( | const char * | line, |
| const char * | word, | ||
| int | pos, | ||
| int | state | ||
| ) | [static] |
Definition at line 2755 of file app_minivm.c.
References AST_LIST_TRAVERSE, ast_strdup, and minivm_account::domain.
Referenced by handle_minivm_show_users().
{
int which = 0;
int wordlen;
struct minivm_account *vmu;
const char *domain = "";
/* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
if (pos > 4)
return NULL;
if (pos == 3)
return (state == 0) ? ast_strdup("for") : NULL;
wordlen = strlen(word);
AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
if (!strncasecmp(word, vmu->domain, wordlen)) {
if (domain && strcmp(domain, vmu->domain) && ++which > state)
return ast_strdup(vmu->domain);
/* ignore repeated domains ? */
domain = vmu->domain;
}
}
return NULL;
}
| static int create_dirpath | ( | char * | dest, |
| int | len, | ||
| char * | domain, | ||
| char * | username, | ||
| char * | folder | ||
| ) | [static] |
basically mkdir -p $dest/$domain/$username/$folder
| dest | String. base directory. |
| len | Length of directory string |
| domain | String. Ignored if is null or empty string. |
| folder | String. Ignored if is null or empty string. |
| username | String. Ignored if is null or empty string. |
Definition at line 1294 of file app_minivm.c.
References ast_debug, ast_log(), ast_mkdir(), LOG_WARNING, and make_dir().
Referenced by leave_voicemail(), minivm_counter_func_read(), and minivm_counter_func_write().
| static int create_vmaccount | ( | char * | name, |
| struct ast_variable * | var, | ||
| int | realtime | ||
| ) | [static] |
Append new mailbox to mailbox list from configuration file.
Definition at line 2299 of file app_minivm.c.
References minivm_account::accountcode, ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), minivm_account::chanvars, minivm_account::domain, minivm_account::email, minivm_account::etemplate, minivm_account::externnotify, minivm_account::fullname, global_stats, minivm_account::language, LOG_ERROR, ast_variable::name, ast_variable::next, minivm_account::pager, minivm_account::pincode, populate_defaults(), minivm_account::ptemplate, minivm_account::serveremail, minivm_account::username, ast_variable::value, minivm_stats::voicemailaccounts, minivm_account::volgain, and minivm_account::zonetag.
Referenced by find_user_realtime(), and load_config().
{
struct minivm_account *vmu;
char *domain;
char *username;
char accbuf[BUFSIZ];
ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
ast_copy_string(accbuf, name, sizeof(accbuf));
username = accbuf;
domain = strchr(accbuf, '@');
if (domain) {
*domain = '\0';
domain++;
}
if (ast_strlen_zero(domain)) {
ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
return 0;
}
ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
/* Allocate user account */
vmu = ast_calloc(1, sizeof(*vmu));
if (!vmu)
return 0;
ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
ast_copy_string(vmu->username, username, sizeof(vmu->username));
populate_defaults(vmu);
ast_debug(3, "...Configuring account %s\n", name);
while (var) {
ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
if (!strcasecmp(var->name, "serveremail")) {
ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
} else if (!strcasecmp(var->name, "email")) {
ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
} else if (!strcasecmp(var->name, "accountcode")) {
ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
} else if (!strcasecmp(var->name, "pincode")) {
ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
} else if (!strcasecmp(var->name, "domain")) {
ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
} else if (!strcasecmp(var->name, "language")) {
ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
} else if (!strcasecmp(var->name, "timezone")) {
ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
} else if (!strcasecmp(var->name, "externnotify")) {
ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
} else if (!strcasecmp(var->name, "etemplate")) {
ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
} else if (!strcasecmp(var->name, "ptemplate")) {
ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
} else if (!strcasecmp(var->name, "fullname")) {
ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
} else if (!strcasecmp(var->name, "setvar")) {
char *varval;
char *varname = ast_strdupa(var->value);
struct ast_variable *tmpvar;
if (varname && (varval = strchr(varname, '='))) {
*varval = '\0';
varval++;
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
tmpvar->next = vmu->chanvars;
vmu->chanvars = tmpvar;
}
}
} else if (!strcasecmp(var->name, "pager")) {
ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
} else if (!strcasecmp(var->name, "volgain")) {
sscanf(var->value, "%30lf", &vmu->volgain);
} else {
ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
}
var = var->next;
}
ast_debug(3, "...Linking account %s\n", name);
AST_LIST_LOCK(&minivm_accounts);
AST_LIST_INSERT_TAIL(&minivm_accounts, vmu, list);
AST_LIST_UNLOCK(&minivm_accounts);
global_stats.voicemailaccounts++;
ast_debug(2, "MVM :: Created account %s@%s - tz %s etemplate %s %s\n", username, domain, ast_strlen_zero(vmu->zonetag) ? "" : vmu->zonetag, ast_strlen_zero(vmu->etemplate) ? "" : vmu->etemplate, realtime ? "(realtime)" : "");
return 0;
}
| static struct minivm_account* find_account | ( | const char * | domain, |
| const char * | username, | ||
| int | createtemp | ||
| ) | [static, read] |
Find user from static memory object list.
Definition at line 955 of file app_minivm.c.
References ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set2_flag, ast_strlen_zero(), minivm_account::domain, find_user_realtime(), LOG_NOTICE, MVM_ALLOCED, mvm_user_alloc(), TRUE, and minivm_account::username.
Referenced by leave_voicemail(), minivm_accmess_exec(), minivm_account_func_read(), minivm_counter_func_read(), minivm_counter_func_write(), minivm_greet_exec(), and minivm_notify_exec().
{
struct minivm_account *vmu = NULL, *cur;
if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
ast_log(LOG_NOTICE, "No username or domain? \n");
return NULL;
}
ast_debug(3, "Looking for voicemail user %s in domain %s\n", username, domain);
AST_LIST_LOCK(&minivm_accounts);
AST_LIST_TRAVERSE(&minivm_accounts, cur, list) {
/* Is this the voicemail account we're looking for? */
if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
break;
}
AST_LIST_UNLOCK(&minivm_accounts);
if (cur) {
ast_debug(3, "Found account for %s@%s\n", username, domain);
vmu = cur;
} else
vmu = find_user_realtime(domain, username);
if (createtemp && !vmu) {
/* Create a temporary user, send e-mail and be gone */
vmu = mvm_user_alloc();
ast_set2_flag(vmu, TRUE, MVM_ALLOCED);
if (vmu) {
ast_copy_string(vmu->username, username, sizeof(vmu->username));
ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
ast_debug(1, "Created temporary account\n");
}
}
return vmu;
}
| static struct minivm_account * find_user_realtime | ( | const char * | domain, |
| const char * | username | ||
| ) | [static, read] |
Find user in realtime storage Returns pointer to minivm_account structure.
Definition at line 998 of file app_minivm.c.
References ast_copy_string(), ast_free, ast_load_realtime(), ast_variables_destroy(), create_vmaccount(), MAXHOSTNAMELEN, mvm_user_alloc(), populate_defaults(), SENTINEL, TRUE, minivm_account::username, and var.
Referenced by find_account().
{
struct ast_variable *var;
struct minivm_account *retval;
char name[MAXHOSTNAMELEN];
retval = mvm_user_alloc();
if (!retval)
return NULL;
if (username)
ast_copy_string(retval->username, username, sizeof(retval->username));
populate_defaults(retval);
var = ast_load_realtime("minivm", "username", username, "domain", domain, SENTINEL);
if (!var) {
ast_free(retval);
return NULL;
}
snprintf(name, sizeof(name), "%s@%s", username, domain);
create_vmaccount(name, var, TRUE);
ast_variables_destroy(var);
return retval;
}
| static void free_user | ( | struct minivm_account * | vmu | ) | [static] |
Free user structure - if it's allocated.
Definition at line 863 of file app_minivm.c.
References ast_free, ast_variables_destroy(), and minivm_account::chanvars.
Referenced by leave_voicemail(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), and minivm_notify_exec().
{
if (vmu->chanvars)
ast_variables_destroy(vmu->chanvars);
ast_free(vmu);
}
| static void free_zone | ( | struct minivm_zone * | z | ) | [static] |
Free Mini Voicemail timezone.
Definition at line 2393 of file app_minivm.c.
References ast_free.
Referenced by timezone_destroy_list().
{
ast_free(z);
}
| static int get_date | ( | char * | s, |
| int | len | ||
| ) | [static] |
Definition at line 852 of file app_minivm.c.
References ast_localtime(), ast_strftime(), and ast_tvnow().
Referenced by leave_voicemail().
{
struct ast_tm tm;
struct timeval now = ast_tvnow();
ast_localtime(&now, &tm, NULL);
return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
}
| static char* handle_minivm_list_templates | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
CLI routine for listing templates.
Definition at line 2714 of file app_minivm.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HVLT_OUTPUT_FORMAT, and ast_cli_entry::usage.
{
struct minivm_template *this;
#define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
int count = 0;
switch (cmd) {
case CLI_INIT:
e->command = "minivm list templates";
e->usage =
"Usage: minivm list templates\n"
" Lists message templates for e-mail, paging and IM\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc > 3)
return CLI_SHOWUSAGE;
AST_LIST_LOCK(&message_templates);
if (AST_LIST_EMPTY(&message_templates)) {
ast_cli(a->fd, "There are no message templates defined\n");
AST_LIST_UNLOCK(&message_templates);
return CLI_FAILURE;
}
ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
AST_LIST_TRAVERSE(&message_templates, this, list) {
ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name,
this->charset ? this->charset : "-",
this->locale ? this->locale : "-",
this->attachment ? "Yes" : "No",
this->subject ? this->subject : "-");
count++;
}
AST_LIST_UNLOCK(&message_templates);
ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
return CLI_SUCCESS;
}
| static char * handle_minivm_reload | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Reload cofiguration.
Definition at line 3303 of file app_minivm.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, reload, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "minivm reload";
e->usage =
"Usage: minivm reload\n"
" Reload mini-voicemail configuration and reset statistics\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
reload();
ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
return CLI_SUCCESS;
}
| static char* handle_minivm_show_settings | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
CLI Show settings.
Definition at line 2865 of file app_minivm.c.
References ast_cli(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, default_vmformat, ast_cli_args::fd, global_externnotify, global_logfile, global_mailcmd, global_maxsilence, global_silencethreshold, global_vmmaxmessage, global_vmminmessage, globalflags, MVM_OPERATOR, MVM_REVIEW, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "minivm show settings";
e->usage =
"Usage: minivm show settings\n"
" Display Mini-Voicemail general settings\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
ast_cli(a->fd, "* Mini-Voicemail general settings\n");
ast_cli(a->fd, " -------------------------------\n");
ast_cli(a->fd, "\n");
ast_cli(a->fd, " Mail command (shell): %s\n", global_mailcmd);
ast_cli(a->fd, " Max silence: %d\n", global_maxsilence);
ast_cli(a->fd, " Silence threshold: %d\n", global_silencethreshold);
ast_cli(a->fd, " Max message length (secs): %d\n", global_vmmaxmessage);
ast_cli(a->fd, " Min message length (secs): %d\n", global_vmminmessage);
ast_cli(a->fd, " Default format: %s\n", default_vmformat);
ast_cli(a->fd, " Extern notify (shell): %s\n", global_externnotify);
ast_cli(a->fd, " Logfile: %s\n", global_logfile[0] ? global_logfile : "<disabled>");
ast_cli(a->fd, " Operator exit: %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
ast_cli(a->fd, " Message review: %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
ast_cli(a->fd, "\n");
return CLI_SUCCESS;
}
| static char* handle_minivm_show_stats | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Show stats.
Definition at line 2897 of file app_minivm.c.
References ast_cli(), ast_localtime(), ast_strftime(), buf, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, global_stats, minivm_stats::lastreceived, minivm_stats::receivedmessages, minivm_stats::reset, minivm_stats::templates, minivm_stats::timezones, ast_cli_entry::usage, and minivm_stats::voicemailaccounts.
{
struct ast_tm timebuf;
char buf[BUFSIZ];
switch (cmd) {
case CLI_INIT:
e->command = "minivm show stats";
e->usage =
"Usage: minivm show stats\n"
" Display Mini-Voicemail counters\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
ast_cli(a->fd, "* Mini-Voicemail statistics\n");
ast_cli(a->fd, " -------------------------\n");
ast_cli(a->fd, "\n");
ast_cli(a->fd, " Voicemail accounts: %5d\n", global_stats.voicemailaccounts);
ast_cli(a->fd, " Templates: %5d\n", global_stats.templates);
ast_cli(a->fd, " Timezones: %5d\n", global_stats.timezones);
if (global_stats.receivedmessages == 0) {
ast_cli(a->fd, " Received messages since last reset: <none>\n");
} else {
ast_cli(a->fd, " Received messages since last reset: %d\n", global_stats.receivedmessages);
ast_localtime(&global_stats.lastreceived, &timebuf, NULL);
ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
ast_cli(a->fd, " Last received voicemail: %s\n", buf);
}
ast_localtime(&global_stats.reset, &timebuf, NULL);
ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
ast_cli(a->fd, " Last reset: %s\n", buf);
ast_cli(a->fd, "\n");
return CLI_SUCCESS;
}
| static char* handle_minivm_show_users | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
CLI command to list voicemail accounts.
Definition at line 2780 of file app_minivm.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, minivm_account::attachfmt, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_minivm_show_users(), minivm_account::domain, minivm_account::etemplate, ast_cli_args::fd, minivm_account::fullname, HMSU_OUTPUT_FORMAT, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, minivm_account::ptemplate, ast_cli_entry::usage, minivm_account::username, ast_cli_args::word, and minivm_account::zonetag.
{
struct minivm_account *vmu;
#define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
int count = 0;
switch (cmd) {
case CLI_INIT:
e->command = "minivm list accounts";
e->usage =
"Usage: minivm list accounts\n"
" Lists all mailboxes currently set up\n";
return NULL;
case CLI_GENERATE:
return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
}
if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
return CLI_SHOWUSAGE;
if ((a->argc == 5) && strcmp(a->argv[3],"for"))
return CLI_SHOWUSAGE;
AST_LIST_LOCK(&minivm_accounts);
if (AST_LIST_EMPTY(&minivm_accounts)) {
ast_cli(a->fd, "There are no voicemail users currently defined\n");
AST_LIST_UNLOCK(&minivm_accounts);
return CLI_FAILURE;
}
ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
char tmp[256] = "";
if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
count++;
snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, vmu->etemplate ? vmu->etemplate : "-",
vmu->ptemplate ? vmu->ptemplate : "-",
vmu->zonetag ? vmu->zonetag : "-",
vmu->attachfmt ? vmu->attachfmt : "-",
vmu->fullname);
}
}
AST_LIST_UNLOCK(&minivm_accounts);
ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
return CLI_SUCCESS;
}
| static char* handle_minivm_show_zones | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Show a list of voicemail zones in the CLI.
Definition at line 2828 of file app_minivm.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HMSZ_OUTPUT_FORMAT, minivm_zone::msg_format, minivm_zone::name, minivm_zone::timezone, and ast_cli_entry::usage.
{
struct minivm_zone *zone;
#define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
char *res = CLI_SUCCESS;
switch (cmd) {
case CLI_INIT:
e->command = "minivm list zones";
e->usage =
"Usage: minivm list zones\n"
" Lists zone message formats\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
AST_LIST_LOCK(&minivm_zones);
if (!AST_LIST_EMPTY(&minivm_zones)) {
ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
AST_LIST_TRAVERSE(&minivm_zones, zone, list) {
ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
}
} else {
ast_cli(a->fd, "There are no voicemail zones currently defined\n");
res = CLI_FAILURE;
}
AST_LIST_UNLOCK(&minivm_zones);
return res;
}
| static int invent_message | ( | struct ast_channel * | chan, |
| char * | domain, | ||
| char * | username, | ||
| int | busy, | ||
| char * | ecodes | ||
| ) | [static] |
Play intro message before recording voicemail.
Definition at line 1309 of file app_minivm.c.
References ast_debug, ast_fileexists(), ast_say_digit_str(), ast_streamfile(), ast_waitstream(), FALSE, ast_channel::language, and minivm_account::username.
Referenced by minivm_greet_exec().
{
int res;
char fn[PATH_MAX];
ast_debug(2, "Still preparing to play message ...\n");
snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
if (ast_fileexists(fn, NULL, NULL) > 0) {
res = ast_streamfile(chan, fn, chan->language);
if (res)
return -1;
res = ast_waitstream(chan, ecodes);
if (res)
return res;
} else {
int numericusername = 1;
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)) {
numericusername = FALSE;
break;
}
i++;
}
if (numericusername) {
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))
return -1;
if ((res = ast_waitstream(chan, ecodes)))
return res;
}
}
res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", chan->language);
if (res)
return -1;
res = ast_waitstream(chan, ecodes);
return res;
}
| static int leave_voicemail | ( | struct ast_channel * | chan, |
| char * | username, | ||
| struct leave_vm_options * | options | ||
| ) | [static] |
Record voicemail message, store into file prepared for sending e-mail.
Definition at line 1604 of file app_minivm.c.
References minivm_account::accountcode, ast_callerid_merge(), ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_localtime(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_streamfile(), ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_tvnow(), ast_verb, ast_waitstream(), minivm_account::attachfmt, check_dirpath(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, create_dirpath(), default_vmformat, minivm_account::domain, errno, ast_channel::exten, find_account(), free_user(), get_date(), global_stats, global_vmmaxmessage, global_vmminmessage, ast_channel::language, minivm_stats::lastreceived, LOG_ERROR, LOG_WARNING, ast_channel::macrocontext, minivmlogfile, minivmloglock, MVM_ALLOCED, ast_channel::name, pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, minivm_stats::receivedmessages, leave_vm_options::record_gain, and TRUE.
Referenced by minivm_record_exec().
{
char tmptxtfile[PATH_MAX];
char callerid[256];
FILE *txt;
int res = 0, txtdes;
int msgnum;
int duration = 0;
char date[256];
char tmpdir[PATH_MAX];
char ext_context[256] = "";
char fmt[80];
char *domain;
char tmp[256] = "";
struct minivm_account *vmu;
int userdir;
ast_copy_string(tmp, username, sizeof(tmp));
username = tmp;
domain = strchr(tmp, '@');
if (domain) {
*domain = '\0';
domain++;
}
if (!(vmu = find_account(domain, username, TRUE))) {
/* We could not find user, let's exit */
ast_log(LOG_ERROR, "Can't allocate temporary account for '%s@%s'\n", username, domain);
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
return 0;
}
/* Setup pre-file if appropriate */
if (strcmp(vmu->domain, "localhost"))
snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
else
ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
/* The meat of recording the message... All the announcements and beeps have been played*/
if (ast_strlen_zero(vmu->attachfmt))
ast_copy_string(fmt, default_vmformat, sizeof(fmt));
else
ast_copy_string(fmt, vmu->attachfmt, sizeof(fmt));
if (ast_strlen_zero(fmt)) {
ast_log(LOG_WARNING, "No format for saving voicemail? Default %s\n", default_vmformat);
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
return res;
}
msgnum = 0;
userdir = check_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
/* If we have no user directory, use generic temporary directory */
if (!userdir) {
create_dirpath(tmpdir, sizeof(tmpdir), "0000_minivm_temp", "mediafiles", "");
ast_debug(3, "Creating temporary directory %s\n", tmpdir);
}
snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
/* XXX This file needs to be in temp directory */
txtdes = mkstemp(tmptxtfile);
if (txtdes < 0) {
ast_log(LOG_ERROR, "Unable to create message file %s: %s\n", tmptxtfile, strerror(errno));
res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
if (!res)
res = ast_waitstream(chan, "");
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
return res;
}
if (res >= 0) {
/* Unless we're *really* silent, try to send the beep */
res = ast_streamfile(chan, "beep", chan->language);
if (!res)
res = ast_waitstream(chan, "");
}
/* OEJ XXX Maybe this can be turned into a log file? Hmm. */
/* Store information */
ast_debug(2, "Open file for metadata: %s\n", tmptxtfile);
res = play_record_review(chan, NULL, tmptxtfile, global_vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
txt = fdopen(txtdes, "w+");
if (!txt) {
ast_log(LOG_WARNING, "Error opening text file for output\n");
} else {
struct ast_tm tm;
struct timeval now = ast_tvnow();
char timebuf[30];
char logbuf[BUFSIZ];
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",
username,
chan->context,
chan->macrocontext,
chan->exten,
chan->priority,
chan->name,
ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
date,
timebuf,
duration,
duration < global_vmminmessage ? "IGNORED" : "OK",
vmu->accountcode
);
fprintf(txt, "%s", logbuf);
if (minivmlogfile) {
ast_mutex_lock(&minivmloglock);
fprintf(minivmlogfile, "%s", logbuf);
ast_mutex_unlock(&minivmloglock);
}
if (duration < global_vmminmessage) {
ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, global_vmminmessage);
fclose(txt);
ast_filedelete(tmptxtfile, NULL);
unlink(tmptxtfile);
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
return 0;
}
fclose(txt); /* Close log file */
if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
unlink(tmptxtfile);
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
return 0;
}
/* Set channel variables for the notify application */
pbx_builtin_setvar_helper(chan, "MVM_FILENAME", tmptxtfile);
snprintf(timebuf, sizeof(timebuf), "%d", duration);
pbx_builtin_setvar_helper(chan, "MVM_DURATION", timebuf);
pbx_builtin_setvar_helper(chan, "MVM_FORMAT", fmt);
}
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 (res > 0)
res = 0;
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
return res;
}
| static int load_config | ( | int | reload | ) | [static] |
Load minivoicemail configuration.
Definition at line 2573 of file app_minivm.c.
References apply_general_options(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set2_flag, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), ast_variable_retrieve(), chanvar, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, create_vmaccount(), default_vmformat, errno, FALSE, global_charset, global_externnotify, global_logfile, global_mailcmd, global_maxgreet, global_maxsilence, global_saydurationminfo, global_silencethreshold, global_stats, global_vmmaxmessage, global_vmminmessage, globalflags, LOG_ERROR, LOG_WARNING, message_destroy_list(), message_template_build(), message_template_find(), message_template_parse_emailbody(), minivmlock, minivmlogfile, MVM_OPERATOR, MVM_REVIEW, ast_variable::name, ast_variable::next, minivm_stats::reset, SENDMAIL, THRESHOLD_SILENCE, timezone_add(), timezone_destroy_list(), TRUE, ast_variable::value, var, vmaccounts_destroy_list(), and VOICEMAIL_CONFIG.
Referenced by load_module(), and reload().
{
struct ast_config *cfg;
struct ast_variable *var;
char *cat;
const char *chanvar;
int error = 0;
struct minivm_template *template;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
} else if (cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
return 0;
}
ast_mutex_lock(&minivmlock);
/* Destroy lists to reconfigure */
message_destroy_list(); /* Destroy list of voicemail message templates */
timezone_destroy_list(); /* Destroy list of timezones */
vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
ast_debug(2, "Destroyed memory objects...\n");
/* First, set some default settings */
global_externnotify[0] = '\0';
global_logfile[0] = '\0';
global_vmmaxmessage = 2000;
global_maxgreet = 2000;
global_vmminmessage = 0;
strcpy(global_mailcmd, SENDMAIL);
global_maxsilence = 0;
global_saydurationminfo = 2;
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();
global_silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
/* Make sure we could load configuration file */
if (!cfg) {
ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
ast_mutex_unlock(&minivmlock);
return 0;
}
ast_debug(2, "Loaded configuration file, now parsing\n");
/* General settings */
cat = ast_category_browse(cfg, NULL);
while (cat) {
ast_debug(3, "Found configuration section [%s]\n", cat);
if (!strcasecmp(cat, "general")) {
/* Nothing right now */
error += apply_general_options(ast_variable_browse(cfg, cat));
} else if (!strncasecmp(cat, "template-", 9)) {
/* Template */
char *name = cat + 9;
/* Now build and link template to list */
error += message_template_build(name, ast_variable_browse(cfg, cat));
} else {
var = ast_variable_browse(cfg, cat);
if (!strcasecmp(cat, "zonemessages")) {
/* Timezones in this context */
while (var) {
timezone_add(var->name, var->value);
var = var->next;
}
} else {
/* Create mailbox from this */
error += create_vmaccount(cat, var, FALSE);
}
}
/* Find next section in configuration file */
cat = ast_category_browse(cfg, cat);
}
/* Configure the default email template */
message_template_build("email-default", NULL);
template = message_template_find("email-default");
/* Load date format config for voicemail mail */
if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat")))
ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
ast_copy_string(template->charset, chanvar, sizeof(template->charset));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject")))
ast_copy_string(template->subject, chanvar, sizeof(template->subject));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody")))
template->body = message_template_parse_emailbody(chanvar);
template->attachment = TRUE;
message_template_build("pager-default", NULL);
template = message_template_find("pager-default");
if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
ast_copy_string(template->charset, chanvar, sizeof(template->charset));
if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
ast_copy_string(template->subject, chanvar,sizeof(template->subject));
if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody")))
template->body = message_template_parse_emailbody(chanvar);
template->attachment = FALSE;
if (error)
ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
ast_mutex_unlock(&minivmlock);
ast_config_destroy(cfg);
/* Close log file if it's open and disabled */
if(minivmlogfile)
fclose(minivmlogfile);
/* Open log file if it's enabled */
if(!ast_strlen_zero(global_logfile)) {
minivmlogfile = fopen(global_logfile, "a");
if(!minivmlogfile)
ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
if (minivmlogfile)
ast_debug(3, "Opened log file %s \n", global_logfile);
}
return 0;
}
| static int load_module | ( | void | ) | [static] |
Load mini voicemail module.
Definition at line 3269 of file app_minivm.c.
References ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_register_application_xml, cli_minivm, load_config(), minivm_accmess_exec(), minivm_account_function, minivm_counter_function, minivm_delete_exec(), minivm_greet_exec(), minivm_mwi_exec(), minivm_notify_exec(), and minivm_record_exec().
{
int res;
res = ast_register_application_xml(app_minivm_record, minivm_record_exec);
res = ast_register_application_xml(app_minivm_greet, minivm_greet_exec);
res = ast_register_application_xml(app_minivm_notify, minivm_notify_exec);
res = ast_register_application_xml(app_minivm_delete, minivm_delete_exec);
res = ast_register_application_xml(app_minivm_accmess, minivm_accmess_exec);
res = ast_register_application_xml(app_minivm_mwi, minivm_mwi_exec);
ast_custom_function_register(&minivm_account_function);
ast_custom_function_register(&minivm_counter_function);
if (res)
return(res);
if ((res = load_config(0)))
return(res);
ast_cli_register_multiple(cli_minivm, ARRAY_LEN(cli_minivm));
/* compute the location of the voicemail spool directory */
snprintf(MVM_SPOOL_DIR, sizeof(MVM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
return res;
}
| static char* mailheader_quote | ( | const char * | from, |
| char * | to, | ||
| size_t | len | ||
| ) | [static] |
Fix quote of mail headers for non-ascii characters.
Definition at line 911 of file app_minivm.c.
Referenced by sendmail().
{
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;
}
| static int make_dir | ( | char * | dest, |
| int | len, | ||
| const char * | domain, | ||
| const char * | username, | ||
| const char * | folder | ||
| ) | [static] |
Create directory based on components.
Definition at line 1263 of file app_minivm.c.
References ast_strlen_zero().
Referenced by check_dirpath(), and create_dirpath().
{
return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
}
| static void message_destroy_list | ( | void | ) | [static] |
Clear list of templates.
Definition at line 718 of file app_minivm.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and message_template_free().
Referenced by load_config(), and unload_module().
{
struct minivm_template *this;
AST_LIST_LOCK(&message_templates);
while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list)))
message_template_free(this);
AST_LIST_UNLOCK(&message_templates);
}
| static int message_template_build | ( | const char * | name, |
| struct ast_variable * | var | ||
| ) | [static] |
Build message template from configuration.
Definition at line 635 of file app_minivm.c.
References ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_true(), global_stats, LOG_ERROR, message_template_create(), message_template_parse_emailbody(), message_template_parse_filebody(), ast_variable::name, ast_variable::next, minivm_stats::templates, and ast_variable::value.
Referenced by load_config().
{
struct minivm_template *template;
int error = 0;
template = message_template_create(name);
if (!template) {
ast_log(LOG_ERROR, "Out of memory, can't allocate message template object %s.\n", name);
return -1;
}
while (var) {
ast_debug(3, "Configuring template option %s = \"%s\" for template %s\n", var->name, var->value, name);
if (!strcasecmp(var->name, "fromaddress")) {
ast_copy_string(template->fromaddress, var->value, sizeof(template->fromaddress));
} else if (!strcasecmp(var->name, "fromemail")) {
ast_copy_string(template->serveremail, var->value, sizeof(template->serveremail));
} else if (!strcasecmp(var->name, "subject")) {
ast_copy_string(template->subject, var->value, sizeof(template->subject));
} else if (!strcasecmp(var->name, "locale")) {
ast_copy_string(template->locale, var->value, sizeof(template->locale));
} else if (!strcasecmp(var->name, "attachmedia")) {
template->attachment = ast_true(var->value);
} else if (!strcasecmp(var->name, "dateformat")) {
ast_copy_string(template->dateformat, var->value, sizeof(template->dateformat));
} else if (!strcasecmp(var->name, "charset")) {
ast_copy_string(template->charset, var->value, sizeof(template->charset));
} else if (!strcasecmp(var->name, "templatefile")) {
if (template->body)
ast_free(template->body);
template->body = message_template_parse_filebody(var->value);
if (!template->body) {
ast_log(LOG_ERROR, "Error reading message body definition file %s\n", var->value);
error++;
}
} else if (!strcasecmp(var->name, "messagebody")) {
if (template->body)
ast_free(template->body);
template->body = message_template_parse_emailbody(var->value);
if (!template->body) {
ast_log(LOG_ERROR, "Error parsing message body definition:\n %s\n", var->value);
error++;
}
} else {
ast_log(LOG_ERROR, "Unknown message template configuration option \"%s=%s\"\n", var->name, var->value);
error++;
}
var = var->next;
}
if (error)
ast_log(LOG_ERROR, "-- %d errors found parsing message template definition %s\n", error, name);
AST_LIST_LOCK(&message_templates);
AST_LIST_INSERT_TAIL(&message_templates, template, list);
AST_LIST_UNLOCK(&message_templates);
global_stats.templates++;
return error;
}
| static struct minivm_template* message_template_create | ( | const char * | name | ) | [static, read] |
Create message template.
Definition at line 607 of file app_minivm.c.
References ast_calloc, ast_copy_string(), DEFAULT_CHARSET, DEFAULT_DATEFORMAT, and TRUE.
Referenced by message_template_build().
{
struct minivm_template *template;
template = ast_calloc(1, sizeof(*template));
if (!template)
return NULL;
/* Set some defaults for templates */
ast_copy_string(template->name, name, sizeof(template->name));
ast_copy_string(template->dateformat, DEFAULT_DATEFORMAT, sizeof(template->dateformat));
ast_copy_string(template->charset, DEFAULT_CHARSET, sizeof(template->charset));
ast_copy_string(template->subject, "New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}", sizeof(template->subject));
template->attachment = TRUE;
return template;
}
| static struct minivm_template* message_template_find | ( | const char * | name | ) | [static, read] |
Find named template.
Definition at line 697 of file app_minivm.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_strlen_zero().
Referenced by load_config(), and notify_new_message().
{
struct minivm_template *this, *res = NULL;
if (ast_strlen_zero(name))
return NULL;
AST_LIST_LOCK(&message_templates);
AST_LIST_TRAVERSE(&message_templates, this, list) {
if (!strcasecmp(this->name, name)) {
res = this;
break;
}
}
AST_LIST_UNLOCK(&message_templates);
return res;
}
| static void message_template_free | ( | struct minivm_template * | template | ) | [static] |
Release memory allocated by message template.
Definition at line 626 of file app_minivm.c.
References ast_free.
Referenced by message_destroy_list().
| static char * message_template_parse_emailbody | ( | const char * | body | ) | [static] |
Parse emailbody template from configuration file.
Definition at line 2488 of file app_minivm.c.
References ast_log(), ast_strdup, emailbody, len(), and LOG_NOTICE.
Referenced by load_config(), and message_template_build().
{
char *tmpread, *tmpwrite;
char *emailbody = ast_strdup(configuration);
/* substitute strings \t and \n into the apropriate characters */
tmpread = tmpwrite = emailbody;
while ((tmpwrite = strchr(tmpread,'\\'))) {
int len = strlen("\n");
switch (tmpwrite[1]) {
case 'n':
memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
strncpy(tmpwrite, "\n", len);
break;
case 't':
memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
strncpy(tmpwrite, "\t", len);
break;
default:
ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
}
tmpread = tmpwrite + len;
}
return emailbody;
}
| static char * message_template_parse_filebody | ( | const char * | filename | ) | [static] |
Read message template from file.
Definition at line 2448 of file app_minivm.c.
References ast_calloc, ast_config_AST_CONFIG_DIR, ast_copy_string(), ast_debug, ast_log(), ast_strlen_zero(), buf, and LOG_ERROR.
Referenced by message_template_build().
{
char buf[BUFSIZ * 6];
char readbuf[BUFSIZ];
char filenamebuf[BUFSIZ];
char *writepos;
char *messagebody;
FILE *fi;
int lines = 0;
if (ast_strlen_zero(filename))
return NULL;
if (*filename == '/')
ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
else
snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
if (!(fi = fopen(filenamebuf, "r"))) {
ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
return NULL;
}
writepos = buf;
while (fgets(readbuf, sizeof(readbuf), fi)) {
lines ++;
if (writepos != buf) {
*writepos = '\n'; /* Replace EOL with new line */
writepos++;
}
ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
writepos += strlen(readbuf) - 1;
}
fclose(fi);
messagebody = ast_calloc(1, strlen(buf + 1));
ast_copy_string(messagebody, buf, strlen(buf) + 1);
ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
return messagebody;
}
| static int minivm_accmess_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Record specific messages for voicemail account.
Definition at line 2195 of file app_minivm.c.
References ast_channel::_state, ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args(), ast_copy_string(), ast_debug, ast_log(), AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, default_vmformat, minivm_account::domain, FALSE, find_account(), minivm_account::flags, free_user(), global_maxgreet, LOG_ERROR, LOG_WARNING, minivm_accmess_options, MVM_ALLOCED, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_NAME_GREETING, OPT_TEMP_GREETING, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), play_record_review(), prompt, TRUE, and minivm_account::username.
Referenced by load_module().
{
int argc = 0;
char *argv[2];
char filename[PATH_MAX];
char tmp[PATH_MAX];
char *domain;
char *tmpptr = NULL;
struct minivm_account *vmu;
char *username = argv[0];
struct ast_flags flags = { 0 };
char *opts[OPT_ARG_ARRAY_SIZE];
int error = FALSE;
char *message = NULL;
char *prompt = NULL;
int duration;
int cmd;
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
error = TRUE;
} else
tmpptr = ast_strdupa((char *)data);
if (!error) {
if (!tmpptr) {
ast_log(LOG_ERROR, "Out of memory\n");
error = TRUE;
} else
argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
}
if (argc <=1) {
ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
error = TRUE;
}
if (!error && strlen(argv[1]) > 1) {
ast_log(LOG_ERROR, "MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
error = TRUE;
}
if (!error && ast_app_parse_options(minivm_accmess_options, &flags, opts, argv[1])) {
ast_log(LOG_ERROR, "Can't parse option %s\n", argv[1]);
error = TRUE;
}
if (error) {
pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
return -1;
}
ast_copy_string(tmp, argv[0], sizeof(tmp));
username = tmp;
domain = strchr(tmp, '@');
if (domain) {
*domain = '\0';
domain++;
}
if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
return -1;
}
if(!(vmu = find_account(domain, username, TRUE))) {
/* We could not find user, let's exit */
ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
return -1;
}
/* Answer channel if it's not already answered */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
/* Here's where the action is */
if (ast_test_flag(&flags, OPT_BUSY_GREETING)) {
message = "busy";
prompt = "vm-rec-busy";
} else if (ast_test_flag(&flags, OPT_UNAVAIL_GREETING)) {
message = "unavailable";
prompt = "vm-rec-unv";
} else if (ast_test_flag(&flags, OPT_TEMP_GREETING)) {
message = "temp";
prompt = "vm-rec-temp";
} else if (ast_test_flag(&flags, OPT_NAME_GREETING)) {
message = "greet";
prompt = "vm-rec-name";
}
snprintf(filename,sizeof(filename), "%s%s/%s/%s", MVM_SPOOL_DIR, vmu->domain, vmu->username, message);
/* Maybe we should check the result of play_record_review ? */
cmd = play_record_review(chan, prompt, filename, global_maxgreet, default_vmformat, 0, vmu, &duration, NULL, FALSE);
ast_debug(1, "Recorded new %s message in %s (duration %d)\n", message, filename, duration);
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "SUCCESS");
/* Ok, we're ready to rock and roll. Return to dialplan */
return 0;
}
| static int minivm_account_func_read | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| char * | buf, | ||
| size_t | len | ||
| ) | [static] |
${MINIVMACCOUNT()} Dialplan function - reads account data
Definition at line 2937 of file app_minivm.c.
References minivm_account::accountcode, ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, minivm_account::chanvars, check_dirpath(), minivm_account::domain, minivm_account::email, minivm_account::etemplate, find_account(), free_user(), minivm_account::fullname, minivm_account::language, LOG_ERROR, MVM_ALLOCED, ast_variable::name, ast_variable::next, minivm_account::pager, minivm_account::pincode, minivm_account::ptemplate, TRUE, minivm_account::username, ast_variable::value, var, and minivm_account::zonetag.
{
struct minivm_account *vmu;
char *username, *domain, *colname;
if (!(username = ast_strdupa(data))) {
ast_log(LOG_ERROR, "Memory Error!\n");
return -1;
}
if ((colname = strchr(username, ':'))) {
*colname = '\0';
colname++;
} else {
colname = "path";
}
if ((domain = strchr(username, '@'))) {
*domain = '\0';
domain++;
}
if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
return 0;
}
if (!(vmu = find_account(domain, username, TRUE)))
return 0;
if (!strcasecmp(colname, "hasaccount")) {
ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
} else if (!strcasecmp(colname, "fullname")) {
ast_copy_string(buf, vmu->fullname, len);
} else if (!strcasecmp(colname, "email")) {
if (!ast_strlen_zero(vmu->email))
ast_copy_string(buf, vmu->email, len);
else
snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
} else if (!strcasecmp(colname, "pager")) {
ast_copy_string(buf, vmu->pager, len);
} else if (!strcasecmp(colname, "etemplate")) {
if (!ast_strlen_zero(vmu->etemplate))
ast_copy_string(buf, vmu->etemplate, len);
else
ast_copy_string(buf, "email-default", len);
} else if (!strcasecmp(colname, "language")) {
ast_copy_string(buf, vmu->language, len);
} else if (!strcasecmp(colname, "timezone")) {
ast_copy_string(buf, vmu->zonetag, len);
} else if (!strcasecmp(colname, "ptemplate")) {
if (!ast_strlen_zero(vmu->ptemplate))
ast_copy_string(buf, vmu->ptemplate, len);
else
ast_copy_string(buf, "email-default", len);
} else if (!strcasecmp(colname, "accountcode")) {
ast_copy_string(buf, vmu->accountcode, len);
} else if (!strcasecmp(colname, "pincode")) {
ast_copy_string(buf, vmu->pincode, len);
} else if (!strcasecmp(colname, "path")) {
check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
} else { /* Look in channel variables */
struct ast_variable *var;
int found = 0;
for (var = vmu->chanvars ; var ; var = var->next)
if (!strcmp(var->name, colname)) {
ast_copy_string(buf, var->value, len);
found = 1;
break;
}
}
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
return 0;
}
| static int minivm_counter_func_read | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| char * | buf, | ||
| size_t | len | ||
| ) | [static] |
${MINIVMCOUNTER()} Dialplan function - read counters
Definition at line 3089 of file app_minivm.c.
References access_counter_file(), ast_log(), ast_strdupa, ast_strlen_zero(), create_dirpath(), minivm_account::domain, FALSE, find_account(), LOG_ERROR, LOG_WARNING, and minivm_account::username.
{
char *username, *domain, *countername;
struct minivm_account *vmu = NULL;
char userpath[BUFSIZ];
int res;
*buf = '\0';
if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
ast_log(LOG_WARNING, "Memory error!\n");
return -1;
}
if ((countername = strchr(username, ':'))) {
*countername = '\0';
countername++;
}
if ((domain = strchr(username, '@'))) {
*domain = '\0';
domain++;
}
/* If we have neither username nor domain now, let's give up */
if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
ast_log(LOG_ERROR, "No account given\n");
return -1;
}
if (ast_strlen_zero(countername)) {
ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
return -1;
}
/* We only have a domain, no username */
if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
domain = username;
username = NULL;
}
/* If we can't find account or if the account is temporary, return. */
if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
return 0;
}
create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
/* We have the path, now read the counter file */
res = access_counter_file(userpath, countername, 0, 0);
if (res >= 0)
snprintf(buf, len, "%d", res);
return 0;
}
| static int minivm_counter_func_write | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| const char * | value | ||
| ) | [static] |
${MINIVMCOUNTER()} Dialplan function - changes counter data
Definition at line 3145 of file app_minivm.c.
References access_counter_file(), ast_log(), ast_strdupa, ast_strlen_zero(), create_dirpath(), minivm_account::domain, FALSE, find_account(), LOG_ERROR, LOG_WARNING, and minivm_account::username.
{
char *username, *domain, *countername, *operand;
char userpath[BUFSIZ];
struct minivm_account *vmu;
int change = 0;
int operation = 0;
if(!value)
return -1;
change = atoi(value);
if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
ast_log(LOG_WARNING, "Memory error!\n");
return -1;
}
if ((countername = strchr(username, ':'))) {
*countername = '\0';
countername++;
}
if ((operand = strchr(countername, ':'))) {
*operand = '\0';
operand++;
}
if ((domain = strchr(username, '@'))) {
*domain = '\0';
domain++;
}
/* If we have neither username nor domain now, let's give up */
if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
ast_log(LOG_ERROR, "No account given\n");
return -1;
}
/* We only have a domain, no username */
if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
domain = username;
username = NULL;
}
if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
return -1;
}
/* If we can't find account or if the account is temporary, return. */
if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
return 0;
}
create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
/* Now, find out our operator */
if (*operand == 'i') /* Increment */
operation = 2;
else if (*operand == 'd') {
change = change * -1;
operation = 2;
} else if (*operand == 's')
operation = 1;
else {
ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
return -1;
}
/* We have the path, now read the counter file */
access_counter_file(userpath, countername, change, operation);
return 0;
}
| static int minivm_delete_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Dialplan application to delete voicemail.
Definition at line 2157 of file app_minivm.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_fileexists(), ast_log(), ast_strlen_zero(), LOG_ERROR, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and vm_delete().
Referenced by load_module().
{
int res = 0;
char filename[BUFSIZ];
if (!ast_strlen_zero(data)) {
ast_copy_string(filename, (char *) data, sizeof(filename));
} else {
ast_channel_lock(chan);
ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
ast_channel_unlock(chan);
}
if (ast_strlen_zero(filename)) {
ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
return res;
}
/* Go ahead and delete audio files from system, they're not needed any more */
/* We should look for both audio and text files here */
if (ast_fileexists(filename, NULL, NULL) > 0) {
res = vm_delete(filename);
if (res) {
ast_debug(2, "Can't delete file: %s\n", filename);
pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
} else {
ast_debug(2, "Deleted voicemail file :: %s \n", filename);
pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
}
} else {
ast_debug(2, "Filename does not exist: %s\n", filename);
pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
}
return res;
}
| static int minivm_greet_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Play voicemail prompts - either generic or user specific.
Definition at line 1971 of file app_minivm.c.
References ast_channel::_state, ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args(), ast_copy_flags, ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), ast_play_and_wait(), ast_set_flag, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), check_dirpath(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, minivm_account::domain, minivm_account::exit, ast_channel::exten, find_account(), minivm_account::flags, free_user(), invent_message(), ast_channel::language, LOG_ERROR, ast_channel::macrocontext, minivm_app_options, MVM_ALLOCED, MVM_OPERATOR, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), ast_channel::priority, SOUND_INTRO, TRUE, and minivm_account::username.
Referenced by load_module().
{
struct leave_vm_options leave_options = { 0, '\0'};
int argc;
char *argv[2];
struct ast_flags flags = { 0 };
char *opts[OPT_ARG_ARRAY_SIZE];
int res = 0;
int ausemacro = 0;
int ousemacro = 0;
int ouseexten = 0;
char tmp[PATH_MAX];
char dest[PATH_MAX];
char prefile[PATH_MAX] = "";
char tempfile[PATH_MAX] = "";
char ext_context[256] = "";
char *domain;
char ecodes[16] = "#";
char *tmpptr;
struct minivm_account *vmu;
char *username = argv[0];
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));
if (argc == 2) {
if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1]))
return -1;
ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
}
ast_copy_string(tmp, argv[0], sizeof(tmp));
username = tmp;
domain = strchr(tmp, '@');
if (domain) {
*domain = '\0';
domain++;
}
if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument: %s\n", argv[0]);
return -1;
}
ast_debug(1, "Trying to find configuration for user %s in domain %s\n", username, domain);
if (!(vmu = find_account(domain, username, TRUE))) {
ast_log(LOG_ERROR, "Could not allocate memory. \n");
return -1;
}
/* Answer channel if it's not already answered */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
/* Setup pre-file if appropriate */
if (strcmp(vmu->domain, "localhost"))
snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
else
ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
if (res)
snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
} else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
if (res)
snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
}
/* Check for temporary greeting - it overrides busy and unavail */
snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
if (!(res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
ast_debug(2, "Temporary message directory does not exist, using default (%s)\n", tempfile);
ast_copy_string(prefile, tempfile, sizeof(prefile));
}
ast_debug(2, "Preparing to play message ...\n");
/* Check current or macro-calling context for special extensions */
if (ast_test_flag(vmu, MVM_OPERATOR)) {
if (!ast_strlen_zero(vmu->exit)) {
if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
ouseexten = 1;
}
} else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
ouseexten = 1;
}
else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
ousemacro = 1;
}
}
if (!ast_strlen_zero(vmu->exit)) {
if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
} else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
ausemacro = 1;
}
res = 0; /* Reset */
/* Play the beginning intro if desired */
if (!ast_strlen_zero(prefile)) {
if (ast_streamfile(chan, prefile, chan->language) > -1)
res = ast_waitstream(chan, ecodes);
} else {
ast_debug(2, "%s doesn't exist, doing what we can\n", prefile);
res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
}
if (res < 0) {
ast_debug(2, "Hang up during prefile playback\n");
pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
return -1;
}
if (res == '#') {
/* On a '#' we skip the instructions */
ast_set_flag(&leave_options, OPT_SILENT);
res = 0;
}
if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
res = ast_streamfile(chan, SOUND_INTRO, chan->language);
if (!res)
res = ast_waitstream(chan, ecodes);
if (res == '#') {
ast_set_flag(&leave_options, OPT_SILENT);
res = 0;
}
}
if (res > 0)
ast_stopstream(chan);
/* Check for a '*' here in case the caller wants to escape from voicemail to something
other than the operator -- an automated attendant or mailbox login for example */
if (res == '*') {
chan->exten[0] = 'a';
chan->exten[1] = '\0';
if (!ast_strlen_zero(vmu->exit)) {
ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
} else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
}
chan->priority = 0;
pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
res = 0;
} else if (res == '0') { /* Check for a '0' here */
if(ouseexten || ousemacro) {
chan->exten[0] = 'o';
chan->exten[1] = '\0';
if (!ast_strlen_zero(vmu->exit)) {
ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
} else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
}
ast_play_and_wait(chan, "transfer");
chan->priority = 0;
pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
}
res = 0;
} else if (res < 0) {
pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
res = -1;
} else
pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "SUCCESS");
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
/* Ok, we're ready to rock and roll. Return to dialplan */
return res;
}
| static int minivm_mwi_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Send MWI using interal Asterisk event subsystem.
Definition at line 1795 of file app_minivm.c.
References ARRAY_LEN, ast_app_separate_args(), ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), minivm_account::domain, LOG_ERROR, mailbox, and queue_mwi_event().
Referenced by load_module().
{
int argc;
char *argv[4];
int res = 0;
char *tmpptr;
char tmp[PATH_MAX];
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));
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;
}
queue_mwi_event(mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
return res;
}
| static int minivm_notify_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Notify voicemail account owners - either generic template or user specific.
Definition at line 1836 of file app_minivm.c.
References ARRAY_LEN, ast_app_separate_args(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, minivm_account::domain, find_account(), format, free_user(), LOG_ERROR, LOG_WARNING, MVM_ALLOCED, notify_new_message(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), TRUE, and minivm_account::username.
Referenced by load_module().
{
int argc;
char *argv[2];
int res = 0;
char tmp[PATH_MAX];
char *domain;
char *tmpptr;
struct minivm_account *vmu;
char *username = argv[0];
const char *template = "";
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;
}
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 == 2 && !ast_strlen_zero(argv[1]))
template = argv[1];
ast_copy_string(tmp, argv[0], sizeof(tmp));
username = tmp;
domain = strchr(tmp, '@');
if (domain) {
*domain = '\0';
domain++;
}
if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
return -1;
}
if(!(vmu = find_account(domain, username, TRUE))) {
/* We could not find user, let's exit */
ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
return -1;
}
ast_channel_lock(chan);
if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
filename = ast_strdupa(filename);
}
ast_channel_unlock(chan);
/* Notify of new message to e-mail and pager */
if (!ast_strlen_zero(filename)) {
ast_channel_lock(chan);
if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
format = ast_strdupa(format);
}
if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
duration_string = ast_strdupa(duration_string);
}
ast_channel_unlock(chan);
res = notify_new_message(chan, template, vmu, filename, atoi(duration_string), format, chan->cid.cid_num, chan->cid.cid_name);
}
pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
if(ast_test_flag(vmu, MVM_ALLOCED))
free_user(vmu);
/* Ok, we're ready to rock and roll. Return to dialplan */
return res;
}
| static int minivm_record_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Dialplan function to record voicemail.
Definition at line 1915 of file app_minivm.c.
References ast_channel::_state, ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args(), ast_copy_flags, ast_log(), AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, minivm_account::flags, leave_voicemail(), LOG_ERROR, LOG_WARNING, minivm_app_options, OPT_ARG_ARRAY_SIZE, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and leave_vm_options::record_gain.
Referenced by load_module().
{
int res = 0;
char *tmp;
struct leave_vm_options leave_options;
int argc;
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 */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
return -1;
}
tmp = ast_strdupa((char *)data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory\n");
return -1;
}
argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
if (argc == 2) {
if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
return -1;
}
ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
int gain;
if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
return -1;
} else
leave_options.record_gain = (signed char) gain;
}
}
/* Now run the appliation and good luck to you! */
res = leave_voicemail(chan, argv[0], &leave_options);
if (res == ERROR_LOCK_PATH) {
ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
res = 0;
}
pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
return res;
}
| static struct minivm_account* mvm_user_alloc | ( | void | ) | [static, read] |
Allocate new vm user and set default values.
Definition at line 930 of file app_minivm.c.
References ast_calloc, and populate_defaults().
Referenced by find_account(), and find_user_realtime().
{
struct minivm_account *new;
new = ast_calloc(1, sizeof(*new));
if (!new)
return NULL;
populate_defaults(new);
return new;
}
| 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 | ||
| ) | [static] |
Send message to voicemail account owner.
Definition at line 1527 of file app_minivm.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), minivm_account::attachfmt, minivm_template::attachment, minivm_account::domain, minivm_account::etemplate, EVENT_FLAG_CALL, minivm_template::locale, LOG_WARNING, manager_event, message_template_find(), MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_account::pager, pbx_builtin_getvar_helper(), minivm_account::ptemplate, run_externnotify(), sendmail(), strsep(), and minivm_account::username.
Referenced by minivm_notify_exec().
{
char *stringp;
struct minivm_template *etemplate;
char *messageformat;
int res = 0;
char oldlocale[100];
const char *counter;
if (!ast_strlen_zero(vmu->attachfmt)) {
if (strstr(format, vmu->attachfmt)) {
format = vmu->attachfmt;
} 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);
if (!etemplate)
etemplate = message_template_find(templatename);
if (!etemplate)
etemplate = message_template_find("email-default");
/* Attach only the first format */
stringp = messageformat = ast_strdupa(format);
strsep(&stringp, "|");
if (!ast_strlen_zero(etemplate->locale)) {
char *new_locale;
ast_copy_string(oldlocale, setlocale(LC_TIME, NULL), sizeof(oldlocale));
ast_debug(2, "Changing locale from %s to %s\n", oldlocale, etemplate->locale);
new_locale = setlocale(LC_TIME, etemplate->locale);
if (new_locale == NULL) {
ast_log(LOG_WARNING, "-_-_- Changing to new locale did not work. Locale: %s\n", etemplate->locale);
}
}
/* Read counter if available */
ast_channel_lock(chan);
if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
counter = ast_strdupa(counter);
}
ast_channel_unlock(chan);
if (ast_strlen_zero(counter)) {
ast_debug(2, "MVM_COUNTER not found\n");
} else {
ast_debug(2, "MVM_COUNTER found - will use it with value %s\n", counter);
}
res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_EMAIL, counter);
if (res == 0 && !ast_strlen_zero(vmu->pager)) {
/* Find template for paging */
etemplate = message_template_find(vmu->ptemplate);
if (!etemplate)
etemplate = message_template_find("pager-default");
if (etemplate->locale) {
ast_copy_string(oldlocale, setlocale(LC_TIME, ""), sizeof(oldlocale));
setlocale(LC_TIME, etemplate->locale);
}
res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_PAGE, counter);
}
manager_event(EVENT_FLAG_CALL, "MiniVoiceMail", "Action: SentNotification\rn\nMailbox: %s@%s\r\nCounter: %s\r\n", vmu->username, vmu->domain, counter);
run_externnotify(chan, vmu); /* Run external notification */
if (etemplate->locale)
setlocale(LC_TIME, oldlocale); /* Rest to old locale */
return res;
}
| 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 | ||
| ) | [static] |
Record voicemail message & let caller review or re-record it, or set options if applicable.
Definition at line 1378 of file app_minivm.c.
References acceptdtmf, ast_channel_setoption(), AST_DIGIT_ANY, ast_log(), AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_stream_and_wait(), ast_streamfile(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_waitstream(), global_maxsilence, global_silencethreshold, ast_channel::language, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, and vm_delete().
Referenced by leave_voicemail(), and minivm_accmess_exec().
{
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 */
/* 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 */
while ((cmd >= 0) && (cmd != 't')) {
switch (cmd) {
case '1':
ast_verb(3, "Saving message as is\n");
ast_stream_and_wait(chan, "vm-msgsaved", "");
cmd = 't';
break;
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_verb(3, "Re-recording the message\n");
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 */
if (record_gain)
ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
if (ast_test_flag(vmu, MVM_OPERATOR))
canceldtmf = "0";
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;
else if (cmd == '*')
break;
else {
/* If all is well, a message exists */
message_exists = 1;
cmd = 0;
}
break;
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '*':
case '#':
cmd = ast_play_and_wait(chan, "vm-sorry");
break;
case '0':
if(!ast_test_flag(vmu, MVM_OPERATOR)) {
cmd = ast_play_and_wait(chan, "vm-sorry");
break;
}
if (message_exists || recorded) {
cmd = ast_play_and_wait(chan, "vm-saveoper");
if (!cmd)
cmd = ast_waitfordigit(chan, 3000);
if (cmd == '1') {
ast_play_and_wait(chan, "vm-msgsaved");
cmd = '0';
} else {
ast_play_and_wait(chan, "vm-deleted");
vm_delete(recordfile);
cmd = '0';
}
}
return cmd;
default:
/* If the caller is an ouside caller, and the review option is enabled,
allow them to review the message, but let the owner of the box review
their OGM's */
if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
return cmd;
if (message_exists) {
cmd = ast_play_and_wait(chan, "vm-review");
} else {
cmd = ast_play_and_wait(chan, "vm-torerecord");
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)
cmd = ast_waitfordigit(chan, 600);
}
if (!cmd)
cmd = ast_waitfordigit(chan, 6000);
if (!cmd) {
attempts++;
}
if (attempts > max_attempts) {
cmd = 't';
}
}
}
if (outsidecaller)
ast_play_and_wait(chan, "vm-goodbye");
if (cmd == 't')
cmd = 0;
return cmd;
}
| static void populate_defaults | ( | struct minivm_account * | vmu | ) | [static] |
Set default values for Mini-Voicemail users.
Definition at line 903 of file app_minivm.c.
References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, minivm_account::attachfmt, default_vmformat, global_volgain, globalflags, and minivm_account::volgain.
Referenced by create_vmaccount(), find_user_realtime(), and mvm_user_alloc().
{
ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
ast_copy_string(vmu->attachfmt, default_vmformat, sizeof(vmu->attachfmt));
vmu->volgain = global_volgain;
}
| 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 | ||
| ) | [static] |
Prepare for voicemail template by adding channel variables to the channel.
Definition at line 875 of file app_minivm.c.
References ast_callerid_merge(), ast_log(), ast_strlen_zero(), minivm_account::chanvars, minivm_account::domain, minivm_account::fullname, LOG_ERROR, ast_variable::name, ast_variable::next, pbx_builtin_setvar_helper(), minivm_account::username, ast_variable::value, and var.
Referenced by sendmail().
{
char callerid[256];
struct ast_variable *var;
if (!channel) {
ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
return;
}
for (var = vmu->chanvars ; var ; var = var->next) {
pbx_builtin_setvar_helper(channel, var->name, var->value);
}
/* Prepare variables for substition in email body and subject */
pbx_builtin_setvar_helper(channel, "MVM_NAME", vmu->fullname);
pbx_builtin_setvar_helper(channel, "MVM_DUR", dur);
pbx_builtin_setvar_helper(channel, "MVM_DOMAIN", vmu->domain);
pbx_builtin_setvar_helper(channel, "MVM_USERNAME", vmu->username);
pbx_builtin_setvar_helper(channel, "MVM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
pbx_builtin_setvar_helper(channel, "MVM_CIDNAME", (cidname ? cidname : "an unknown caller"));
pbx_builtin_setvar_helper(channel, "MVM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
pbx_builtin_setvar_helper(channel, "MVM_DATE", date);
if (!ast_strlen_zero(counter))
pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
}
| static void queue_mwi_event | ( | const char * | mbx, |
| const char * | ctx, | ||
| int | urgent, | ||
| int | new, | ||
| int | old | ||
| ) | [static] |
Queue a message waiting event.
Definition at line 1771 of file app_minivm.c.
References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_strdupa, ast_strlen_zero(), context, and mailbox.
Referenced by minivm_mwi_exec().
{
struct ast_event *event;
char *mailbox, *context;
mailbox = ast_strdupa(mbx);
context = ast_strdupa(ctx);
if (ast_strlen_zero(context)) {
context = "default";
}
if (!(event = ast_event_new(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
AST_EVENT_IE_END))) {
return;
}
ast_event_queue_and_cache(event);
}
| static int reload | ( | void | ) | [static] |
Reload mini voicemail module.
Definition at line 3297 of file app_minivm.c.
References load_config().
{
return(load_config(1));
}
| static void run_externnotify | ( | struct ast_channel * | chan, |
| struct minivm_account * | vmu | ||
| ) | [static] |
Run external notification for voicemail message.
Definition at line 1510 of file app_minivm.c.
References ast_debug, ast_safe_system(), ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, minivm_account::domain, minivm_account::externnotify, global_externnotify, and minivm_account::username.
Referenced by notify_new_message().
{
char arguments[BUFSIZ];
if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify))
return;
snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&",
ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify,
vmu->username, vmu->domain,
chan->cid.cid_name, chan->cid.cid_num);
ast_debug(1, "Executing: %s\n", arguments);
ast_safe_system(arguments);
}
| 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 | ||
| ) | [static] |
Send voicemail with audio file as an attachment.
Definition at line 1027 of file app_minivm.c.
References ast_channel_alloc(), ast_channel_free(), ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_random(), ast_safe_system(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_tvnow(), base_encode(), minivm_account::domain, minivm_account::email, minivm_account::fullname, global_charset, global_mailcmd, LOG_WARNING, mailheader_quote(), MAXHOSTNAMELEN, MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_zone::name, option_debug, minivm_account::pager, pbx_substitute_variables_helper(), prep_email_sub_vars(), minivm_account::serveremail, minivm_zone::timezone, minivm_account::username, minivm_account::volgain, and minivm_account::zonetag.
Referenced by notify_new_message().
{
FILE *p = NULL;
int pfd;
char email[256] = "";
char who[256] = "";
char date[256];
char bound[256];
char fname[PATH_MAX];
char dur[PATH_MAX];
char tmp[80] = "/tmp/astmail-XXXXXX";
char tmp2[PATH_MAX];
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;
char *fromaddress;
char *fromemail;
if (type == MVM_MESSAGE_EMAIL) {
if (vmu && !ast_strlen_zero(vmu->email)) {
ast_copy_string(email, vmu->email, sizeof(email));
} else if (!ast_strlen_zero(vmu->username) && !ast_strlen_zero(vmu->domain))
snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
} else if (type == MVM_MESSAGE_PAGE) {
ast_copy_string(email, vmu->pager, sizeof(email));
}
if (ast_strlen_zero(email)) {
ast_log(LOG_WARNING, "No address to send message to.\n");
return -1;
}
ast_debug(3, "Sending mail to %s@%s - Using template %s\n", vmu->username, vmu->domain, template->name);
if (!strcmp(format, "wav49"))
format = "WAV";
/* If we have a gain option, process it now with sox */
if (type == MVM_MESSAGE_EMAIL && (vmu->volgain < -.001 || vmu->volgain > .001) ) {
char newtmp[PATH_MAX];
char tmpcmd[PATH_MAX];
int tmpfd;
ast_copy_string(newtmp, "/tmp/XXXXXX", sizeof(newtmp));
ast_debug(3, "newtmp: %s\n", newtmp);
tmpfd = mkstemp(newtmp);
snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, filename, format, newtmp, format);
ast_safe_system(tmpcmd);
finalfilename = newtmp;
ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->volgain, vmu->username);
} else {
finalfilename = ast_strdupa(filename);
}
/* Create file name */
snprintf(fname, sizeof(fname), "%s.%s", finalfilename, format);
if (template->attachment)
ast_debug(1, "Attaching file '%s', format '%s', uservm is '%d'\n", finalfilename, format, attach_user_voicemail);
/* Make a temporary file instead of piping directly to sendmail, in case the mail
command hangs */
pfd = mkstemp(tmp);
if (pfd > -1) {
p = fdopen(pfd, "w");
if (!p) {
close(pfd);
pfd = -1;
}
ast_debug(1, "Opening temp file for e-mail: %s\n", tmp);
}
if (!p) {
ast_log(LOG_WARNING, "Unable to open temporary file '%s'\n", tmp);
return -1;
}
/* Allocate channel used for chanvar substitution */
ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
/* Does this user have a timezone specified? */
if (!ast_strlen_zero(vmu->zonetag)) {
/* Find the zone in the list */
struct minivm_zone *z;
AST_LIST_LOCK(&minivm_zones);
AST_LIST_TRAVERSE(&minivm_zones, z, list) {
if (strcmp(z->name, vmu->zonetag))
continue;
the_zone = z;
}
AST_LIST_UNLOCK(&minivm_zones);
}
now = ast_tvnow();
ast_localtime(&now, &tm, the_zone ? the_zone->timezone : NULL);
ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
/* Start printing the email to the temporary file */
fprintf(p, "Date: %s\n", date);
/* Set date format for voicemail mail */
ast_strftime(date, sizeof(date), template->dateformat, &tm);
/* Populate channel with channel variables for substitution */
prep_email_sub_vars(ast, vmu, cidnum, cidname, dur, date, counter);
/* Find email address to use */
/* If there's a server e-mail adress in the account, user that, othterwise template */
fromemail = ast_strlen_zero(vmu->serveremail) ? template->serveremail : vmu->serveremail;
/* Find name to user for server e-mail */
fromaddress = ast_strlen_zero(template->fromaddress) ? "" : template->fromaddress;
/* If needed, add hostname as domain */
if (ast_strlen_zero(fromemail))
fromemail = "asterisk";
if (strchr(fromemail, '@'))
ast_copy_string(who, fromemail, sizeof(who));
else {
char host[MAXHOSTNAMELEN];
gethostname(host, sizeof(host)-1);
snprintf(who, sizeof(who), "%s@%s", fromemail, host);
}
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_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(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);
} else {
ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
fclose(p);
return -1;
}
ast_debug(4, "Subject now: %s\n", pass_data);
} 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");
/* Something unique. */
snprintf(bound, sizeof(bound), "voicemail_%s%d%d", vmu->username, (int)getpid(), (unsigned int)ast_random());
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);
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");
} 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);
ast_debug(3, "Using default message body (no template)\n-----\n");
}
/* Eww. We want formats to tell us their own MIME type */
if (template->attachment) {
char *ctype = "audio/x-";
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");
fprintf(p, "Content-Description: Voicemail sound attachment.\n");
fprintf(p, "Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter : "", format);
base_encode(fname, p);
fprintf(p, "\n\n--%s--\n.\n", bound);
}
fclose(p);
snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", global_mailcmd, tmp, tmp);
ast_safe_system(tmp2);
ast_debug(1, "Sent message to %s with command '%s' - %s\n", vmu->email, global_mailcmd, template->attachment ? "(media attachment)" : "");
ast_debug(3, "Actual command used: %s\n", tmp2);
if (ast)
ast_channel_free(ast);
return 0;
}
| static int timezone_add | ( | const char * | zonename, |
| const char * | config | ||
| ) | [static] |
Add time zone to memory list.
Definition at line 2411 of file app_minivm.c.
References ast_calloc, ast_copy_string(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strdupa, global_stats, LOG_WARNING, minivm_zone::msg_format, minivm_zone::name, strsep(), minivm_zone::timezone, and minivm_stats::timezones.
Referenced by load_config().
{
struct minivm_zone *newzone;
char *msg_format, *timezone_str;
newzone = ast_calloc(1, sizeof(*newzone));
if (newzone == NULL)
return 0;
msg_format = ast_strdupa(config);
if (msg_format == NULL) {
ast_log(LOG_WARNING, "Out of memory.\n");
ast_free(newzone);
return 0;
}
timezone_str = strsep(&msg_format, "|");
if (!msg_format) {
ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
ast_free(newzone);
return 0;
}
ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
AST_LIST_LOCK(&minivm_zones);
AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
AST_LIST_UNLOCK(&minivm_zones);
global_stats.timezones++;
return 0;
}
| static void timezone_destroy_list | ( | void | ) | [static] |
Clear list of timezones.
Definition at line 2399 of file app_minivm.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and free_zone().
Referenced by load_config(), and unload_module().
{
struct minivm_zone *this;
AST_LIST_LOCK(&minivm_zones);
while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list)))
free_zone(this);
AST_LIST_UNLOCK(&minivm_zones);
}
| static int unload_module | ( | void | ) | [static] |
Unload mini voicemail module.
Definition at line 3323 of file app_minivm.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_unregister_application(), cli_minivm, message_destroy_list(), minivm_account_function, minivm_counter_function, timezone_destroy_list(), and vmaccounts_destroy_list().
{
int res;
res = ast_unregister_application(app_minivm_record);
res |= ast_unregister_application(app_minivm_greet);
res |= ast_unregister_application(app_minivm_notify);
res |= ast_unregister_application(app_minivm_delete);
res |= ast_unregister_application(app_minivm_accmess);
res |= ast_unregister_application(app_minivm_mwi);
ast_cli_unregister_multiple(cli_minivm, ARRAY_LEN(cli_minivm));
ast_custom_function_unregister(&minivm_account_function);
ast_custom_function_unregister(&minivm_counter_function);
message_destroy_list(); /* Destroy list of voicemail message templates */
timezone_destroy_list(); /* Destroy list of timezones */
vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
return res;
}
| static int vm_delete | ( | char * | file | ) | [static] |
Delete media files and attribute file.
Definition at line 1365 of file app_minivm.c.
References ast_debug, and ast_filedelete().
Referenced by minivm_delete_exec(), and play_record_review().
{
int res;
ast_debug(1, "Deleting voicemail file %s\n", file);
res = unlink(file); /* Remove the meta data file */
res |= ast_filedelete(file, NULL); /* remove the media file */
return res;
}
| static int vm_lock_path | ( | const char * | path | ) | [static] |
lock directory
only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason
Definition at line 3019 of file app_minivm.c.
References ast_lock_path(), and AST_LOCK_TIMEOUT.
Referenced by access_counter_file().
{
switch (ast_lock_path(path)) {
case AST_LOCK_TIMEOUT:
return -1;
default:
return 0;
}
}
| static void vmaccounts_destroy_list | ( | void | ) | [static] |
Clear list of users.
Definition at line 944 of file app_minivm.c.
References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.
Referenced by load_config(), and unload_module().
{
struct minivm_account *this;
AST_LIST_LOCK(&minivm_accounts);
while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list)))
ast_free(this);
AST_LIST_UNLOCK(&minivm_accounts);
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3350 of file app_minivm.c.
char* app_minivm_accmess = "MinivmAccMess" [static] |
Definition at line 453 of file app_minivm.c.
char* app_minivm_delete = "MinivmDelete" [static] |
Definition at line 452 of file app_minivm.c.
char* app_minivm_greet = "MinivmGreet" [static] |
Definition at line 450 of file app_minivm.c.
char* app_minivm_mwi = "MinivmMWI" [static] |
Definition at line 454 of file app_minivm.c.
char* app_minivm_notify = "MinivmNotify" [static] |
Definition at line 451 of file app_minivm.c.
char* app_minivm_record = "MinivmRecord" [static] |
Definition at line 449 of file app_minivm.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3350 of file app_minivm.c.
struct ast_cli_entry cli_minivm[] [static] |
CLI commands for Mini-voicemail.
Definition at line 3220 of file app_minivm.c.
Referenced by load_module(), and unload_module().
char default_vmformat[80] [static] |
Definition at line 587 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), leave_voicemail(), load_config(), minivm_accmess_exec(), and populate_defaults().
char global_charset[32] [static] |
Global charset in messages
Definition at line 591 of file app_minivm.c.
Referenced by load_config(), and sendmail().
char global_externnotify[160] [static] |
External notification application
Definition at line 585 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and run_externnotify().
char global_logfile[PATH_MAX] [static] |
Global log file for messages
Definition at line 586 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), and load_config().
char global_mailcmd[160] [static] |
Configurable mail cmd
Definition at line 584 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and sendmail().
int global_maxgreet [static] |
Maximum length of prompts
Definition at line 582 of file app_minivm.c.
Referenced by apply_general_options(), load_config(), and minivm_accmess_exec().
int global_maxsilence [static] |
Maximum silence during recording
Definition at line 581 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and play_record_review().
int global_saydurationminfo [static] |
Definition at line 590 of file app_minivm.c.
Referenced by load_config().
int global_silencethreshold = 128 [static] |
Definition at line 583 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and play_record_review().
struct minivm_stats global_stats [static] |
Statistics for voicemail.
Definition at line 572 of file app_minivm.c.
Referenced by create_vmaccount(), handle_minivm_show_stats(), leave_voicemail(), load_config(), message_template_build(), and timezone_add().
int global_vmmaxmessage [static] |
Maximum duration of message
Definition at line 580 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), leave_voicemail(), and load_config().
int global_vmminmessage [static] |
Minimum duration of messages
Definition at line 579 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), leave_voicemail(), and load_config().
double global_volgain [static] |
Volume gain for voicmemail via e-mail
Definition at line 593 of file app_minivm.c.
Referenced by populate_defaults().
struct ast_flags globalflags = {0} [static] |
Global voicemail flags
Definition at line 589 of file app_minivm.c.
Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and populate_defaults().
struct message_templates message_templates [static] |
struct ast_app_option minivm_accmess_options[128] = { [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 't' ] = { .flag = OPT_TEMP_GREETING }, [ 'n' ] = { .flag = OPT_NAME_GREETING },} [static] |
Definition at line 484 of file app_minivm.c.
Referenced by minivm_accmess_exec().
struct ast_custom_function minivm_account_function [static] |
Definition at line 3248 of file app_minivm.c.
Referenced by load_module(), and unload_module().
struct minivm_accounts minivm_accounts [static] |
struct ast_app_option minivm_app_options[128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 },} [static] |
Definition at line 477 of file app_minivm.c.
Referenced by minivm_greet_exec(), and minivm_record_exec().
struct ast_custom_function minivm_counter_function [static] |
Definition at line 3229 of file app_minivm.c.
Referenced by load_module(), and unload_module().
| enum { ... } minivm_option_args |
| enum { ... } minivm_option_flags |
struct minivm_zones minivm_zones [static] |
ast_mutex_t minivmlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Lock to protect voicemail system
Definition at line 574 of file app_minivm.c.
Referenced by load_config().
| FILE* minivmlogfile |
The minivm log file
Definition at line 577 of file app_minivm.c.
Referenced by leave_voicemail(), and load_config().
ast_mutex_t minivmloglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Lock to protect voicemail system log file
Definition at line 575 of file app_minivm.c.
Referenced by leave_voicemail().
char MVM_SPOOL_DIR[PATH_MAX] [static] |
Definition at line 446 of file app_minivm.c.