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 __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = ASTERISK_GPL_KEY , .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_INIT_VALUE |
FILE * | minivmlogfile |
static ast_mutex_t | minivmloglock = AST_MUTEX_INIT_VALUE |
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 __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = ASTERISK_GPL_KEY , .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_INIT_VALUE [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_INIT_VALUE [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.