Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Enumerations | Functions | Variables
app_minivm.c File Reference

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/mwi.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/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
Include dependency graph for app_minivm.c:

Go to the source code of this file.

Data Structures

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
 
struct  minivm_accounts
 
struct  minivm_stats
 Structure for gathering statistics. More...
 
struct  minivm_template
 
struct  minivm_zone
 Voicemail time zones. More...
 
struct  minivm_zones
 The list of e-mail time zones. More...
 

Macros

#define ASTERISK_USERNAME   "asterisk"
 
#define DEFAULT_CHARSET   "ISO-8859-1"
 
#define DEFAULT_DATEFORMAT   "%A, %B %d, %Y at %r"
 
#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. More...
 
#define SOUND_INTRO   "vm-intro"
 
#define TRUE   1
 
#define VOICEMAIL_CONFIG   "minivm.conf"
 
#define VOICEMAIL_DIR_MODE   0700
 

Enumerations

enum  minivm_option_args { OPT_ARG_RECORDGAIN = 0 , OPT_ARG_ARRAY_SIZE = 1 }
 
enum  minivm_option_flags {
  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  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. More...
 
static int apply_general_options (struct ast_variable *var)
 Apply general configuration options. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static const char * ast_str_encode_mime (struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
 
static const char * ast_str_quote (struct ast_str **buf, ssize_t maxlen, const char *from)
 
static int check_dirpath (char *dest, int len, char *domain, char *username, char *folder)
 
static int check_mime (const char *str)
 
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)
 
static int create_vmaccount (char *name, struct ast_variable *var, int realtime)
 Append new mailbox to mailbox list from configuration file. More...
 
static struct minivm_accountfind_account (const char *domain, const char *username, int createtemp)
 
static struct minivm_accountfind_user_realtime (const char *domain, const char *username)
 
static void free_user (struct minivm_account *vmu)
 
static void free_zone (struct minivm_zone *z)
 Free Mini Voicemail timezone. More...
 
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. More...
 
static char * handle_minivm_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload cofiguration. More...
 
static char * handle_minivm_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Show settings. More...
 
static char * handle_minivm_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show stats. More...
 
static char * handle_minivm_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list voicemail accounts. More...
 
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. More...
 
static int invent_message (struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
 
static int leave_voicemail (struct ast_channel *chan, char *username, struct leave_vm_options *options)
 
static int load_config (int reload)
 Load minivoicemail configuration. More...
 
static int load_module (void)
 Load mini voicemail module. More...
 
static int make_dir (char *dest, int len, const char *domain, const char *username, const char *folder)
 
static void message_destroy_list (void)
 
static int message_template_build (const char *name, struct ast_variable *var)
 
static struct minivm_templatemessage_template_create (const char *name)
 
static struct minivm_templatemessage_template_find (const char *name)
 
static void message_template_free (struct minivm_template *template)
 
static char * message_template_parse_emailbody (const char *configuration)
 Parse emailbody template from configuration file. More...
 
static char * message_template_parse_filebody (const char *filename)
 Read message template from file. More...
 
static int minivm_accmess_exec (struct ast_channel *chan, const char *data)
 Record specific messages for voicemail account. More...
 
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 More...
 
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 More...
 
static int minivm_counter_func_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 ${MINIVMCOUNTER()} Dialplan function - changes counter data More...
 
static int minivm_delete_exec (struct ast_channel *chan, const char *data)
 
static int minivm_greet_exec (struct ast_channel *chan, const char *data)
 
static int minivm_mwi_exec (struct ast_channel *chan, const char *data)
 
static int minivm_notify_exec (struct ast_channel *chan, const char *data)
 
static int minivm_record_exec (struct ast_channel *chan, const char *data)
 
static struct minivm_accountmvm_user_alloc (void)
 
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 int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct minivm_account *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain)
 
static void populate_defaults (struct minivm_account *vmu)
 
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 void queue_mwi_event (const char *channel_id, const char *mbx, const char *ctx, int urgent, int new, int old)
 
static int reload (void)
 Reload mini voicemail module. More...
 
static void run_externnotify (struct ast_channel *chan, struct minivm_account *vmu)
 Run external notification for voicemail message. More...
 
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 int timezone_add (const char *zonename, const char *config)
 Add time zone to memory list. More...
 
static void timezone_destroy_list (void)
 Clear list of timezones. More...
 
static int unload_module (void)
 Unload mini voicemail module. More...
 
static int vm_delete (char *file)
 
static int vm_lock_path (const char *path)
 lock directory More...
 
static void vmaccounts_destroy_list (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .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 const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_minivm []
 CLI commands for Mini-voicemail. More...
 
static char default_vmformat [80]
 
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. More...
 
static int global_vmmaxmessage
 
static int global_vmminmessage
 
static double global_volgain
 
static struct ast_flags globalflags = {0}
 
static struct message_templates message_templates = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static const 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 = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static const 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
 
static struct minivm_zones minivm_zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static ast_mutex_t minivmlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static FILE * minivmlogfile
 
static ast_mutex_t minivmloglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char MVM_SPOOL_DIR [PATH_MAX]
 

Detailed Description

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).

See also

Definition in file app_minivm.c.

Macro Definition Documentation

◆ ASTERISK_USERNAME

#define ASTERISK_USERNAME   "asterisk"

Default username for sending mail is asterisk@localhost

Definition at line 553 of file app_minivm.c.

◆ DEFAULT_CHARSET

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 707 of file app_minivm.c.

◆ DEFAULT_DATEFORMAT

#define DEFAULT_DATEFORMAT   "%A, %B %d, %Y at %r"

Definition at line 706 of file app_minivm.c.

◆ EOL

#define EOL   "\r\n"

Definition at line 544 of file app_minivm.c.

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

Definition at line 549 of file app_minivm.c.

◆ FALSE

#define FALSE   0

Definition at line 527 of file app_minivm.c.

◆ HMSU_OUTPUT_FORMAT

#define HMSU_OUTPUT_FORMAT   "%-23s %-15s %-15s %-10s %-10s %-50s\n"

◆ HMSZ_OUTPUT_FORMAT

#define HMSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"

◆ HVLT_OUTPUT_FORMAT

#define HVLT_OUTPUT_FORMAT   "%-15s %-10s %-10s %-15.15s %-50s\n"

◆ MAX_DATETIME_FORMAT

#define MAX_DATETIME_FORMAT   512

Definition at line 546 of file app_minivm.c.

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 547 of file app_minivm.c.

◆ MVM_ALLOCED

#define MVM_ALLOCED   (1 << 13)

Definition at line 537 of file app_minivm.c.

◆ MVM_ENVELOPE

#define MVM_ENVELOPE   (1 << 4)

Definition at line 535 of file app_minivm.c.

◆ MVM_OPERATOR

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

Definition at line 532 of file app_minivm.c.

◆ MVM_PBXSKIP

#define MVM_PBXSKIP   (1 << 9)

Definition at line 536 of file app_minivm.c.

◆ MVM_REALTIME

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 533 of file app_minivm.c.

◆ MVM_REVIEW

#define MVM_REVIEW   (1 << 0)

Review message

Definition at line 531 of file app_minivm.c.

◆ MVM_SVMAIL

#define MVM_SVMAIL   (1 << 3)

Definition at line 534 of file app_minivm.c.

◆ SENDMAIL

#define SENDMAIL   "/usr/sbin/sendmail -t"

Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail.conf.

Definition at line 541 of file app_minivm.c.

◆ SOUND_INTRO

#define SOUND_INTRO   "vm-intro"

Definition at line 543 of file app_minivm.c.

◆ TRUE

#define TRUE   1

Definition at line 524 of file app_minivm.c.

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 552 of file app_minivm.c.

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0700

Definition at line 550 of file app_minivm.c.

Enumeration Type Documentation

◆ minivm_option_args

Enumerator
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 583 of file app_minivm.c.

583 {
586};
@ OPT_ARG_RECORDGAIN
Definition: app_minivm.c:584
@ OPT_ARG_ARRAY_SIZE
Definition: app_minivm.c:585

◆ minivm_option_flags

Enumerator
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 574 of file app_minivm.c.

574 {
575 OPT_SILENT = (1 << 0),
576 OPT_BUSY_GREETING = (1 << 1),
577 OPT_UNAVAIL_GREETING = (1 << 2),
578 OPT_TEMP_GREETING = (1 << 3),
579 OPT_NAME_GREETING = (1 << 4),
580 OPT_RECORDGAIN = (1 << 5),
581};
@ OPT_NAME_GREETING
Definition: app_minivm.c:579
@ OPT_TEMP_GREETING
Definition: app_minivm.c:578
@ OPT_BUSY_GREETING
Definition: app_minivm.c:576
@ OPT_RECORDGAIN
Definition: app_minivm.c:580
@ OPT_UNAVAIL_GREETING
Definition: app_minivm.c:577
@ OPT_SILENT
Definition: app_minivm.c:575

◆ mvm_messagetype

Message types for notification.

Enumerator
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 556 of file app_minivm.c.

556 {
559 /* For trunk: MVM_MESSAGE_JABBER, */
560};
@ MVM_MESSAGE_EMAIL
Definition: app_minivm.c:557
@ MVM_MESSAGE_PAGE
Definition: app_minivm.c:558

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3450 of file app_minivm.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3450 of file app_minivm.c.

◆ access_counter_file()

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.

Parameters
directoryDirectory to crate file in
counternamefilename
valueIf set to zero, we only read the variable
operand0 to read, 1 to set new value, 2 to change
Returns
-1 on error, otherwise counter value

Definition at line 3170 of file app_minivm.c.

3171{
3172 char filename[BUFSIZ];
3173 char readbuf[BUFSIZ];
3174 FILE *counterfile;
3175 int old = 0, counter = 0;
3176
3177 /* Lock directory */
3178 if (vm_lock_path(directory)) {
3179 return -1; /* Could not lock directory */
3180 }
3181 snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
3182 if (operand != 1) {
3183 counterfile = fopen(filename, "r");
3184 if (counterfile) {
3185 if(fgets(readbuf, sizeof(readbuf), counterfile)) {
3186 ast_debug(3, "Read this string from counter file: %s\n", readbuf);
3187 old = counter = atoi(readbuf);
3188 }
3189 fclose(counterfile);
3190 }
3191 }
3192 switch (operand) {
3193 case 0: /* Read only */
3194 ast_unlock_path(directory);
3195 ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
3196 return counter;
3197 break;
3198 case 1: /* Set new value */
3199 counter = value;
3200 break;
3201 case 2: /* Change value */
3202 counter += value;
3203 if (counter < 0) /* Don't allow counters to fall below zero */
3204 counter = 0;
3205 break;
3206 }
3207
3208 /* Now, write the new value to the file */
3209 counterfile = fopen(filename, "w");
3210 if (!counterfile) {
3211 ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
3212 ast_unlock_path(directory);
3213 return -1; /* Could not open file for writing */
3214 }
3215 fprintf(counterfile, "%d\n\n", counter);
3216 fclose(counterfile);
3217 ast_unlock_path(directory);
3218 ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
3219 return counter;
3220}
static int vm_lock_path(const char *path)
lock directory
Definition: app_minivm.c:3153
#define ast_log
Definition: astobj2.c:42
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2620
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
int errno
int value
Definition: syslog.c:37

References ast_debug, ast_log, ast_unlock_path(), errno, LOG_ERROR, value, and vm_lock_path().

Referenced by minivm_counter_func_read(), and minivm_counter_func_write().

◆ apply_general_options()

static int apply_general_options ( struct ast_variable var)
static

Apply general configuration options.

Definition at line 2655 of file app_minivm.c.

2656{
2657 int error = 0;
2658
2659 while (var) {
2660 /* Mail command */
2661 if (!strcmp(var->name, "mailcmd")) {
2662 ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
2663 } else if (!strcmp(var->name, "maxgreet")) {
2664 global_maxgreet = atoi(var->value);
2665 } else if (!strcmp(var->name, "maxsilence")) {
2666 global_maxsilence = atoi(var->value);
2667 if (global_maxsilence > 0)
2668 global_maxsilence *= 1000;
2669 } else if (!strcmp(var->name, "logfile")) {
2670 if (!ast_strlen_zero(var->value) ) {
2671 if(*(var->value) == '/')
2673 else
2674 snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
2675 }
2676 } else if (!strcmp(var->name, "externnotify")) {
2677 /* External voicemail notify application */
2679 } else if (!strcmp(var->name, "silencethreshold") || !strcmp(var->name, "silencetreshold")) {
2680 /* Silence treshold */
2681 global_silencethreshold = atoi(var->value);
2682 } else if (!strcmp(var->name, "maxmessage")) {
2683 int x;
2684 if (sscanf(var->value, "%30d", &x) == 1) {
2686 } else {
2687 error ++;
2688 ast_log(LOG_WARNING, "Invalid max message time length\n");
2689 }
2690 } else if (!strcmp(var->name, "minmessage")) {
2691 int x;
2692 if (sscanf(var->value, "%30d", &x) == 1) {
2695 ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
2696 } else {
2697 error ++;
2698 ast_log(LOG_WARNING, "Invalid min message time length\n");
2699 }
2700 } else if (!strcmp(var->name, "format")) {
2702 } else if (!strcmp(var->name, "review")) {
2704 } else if (!strcmp(var->name, "operator")) {
2706 }
2707 var = var->next;
2708 }
2709 return error;
2710}
static int global_maxsilence
Definition: app_minivm.c:691
static char default_vmformat[80]
Definition: app_minivm.c:697
#define MVM_REVIEW
Definition: app_minivm.c:531
static struct ast_flags globalflags
Definition: app_minivm.c:699
static int global_maxgreet
Definition: app_minivm.c:692
static int global_vmmaxmessage
Definition: app_minivm.c:690
static char global_mailcmd[160]
Definition: app_minivm.c:694
static int global_silencethreshold
Definition: app_minivm.c:693
#define MVM_OPERATOR
Definition: app_minivm.c:532
static char global_externnotify[160]
Definition: app_minivm.c:695
static int global_vmminmessage
Definition: app_minivm.c:689
static char global_logfile[PATH_MAX]
Definition: app_minivm.c:696
#define var
Definition: ast_expr2f.c:605
#define LOG_WARNING
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94

References ast_config_AST_LOG_DIR, ast_copy_string(), ast_log, ast_set2_flag, ast_strlen_zero(), ast_true(), default_vmformat, error(), global_externnotify, global_logfile, global_mailcmd, global_maxgreet, global_maxsilence, global_silencethreshold, global_vmmaxmessage, global_vmminmessage, globalflags, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, and var.

Referenced by load_config().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 3450 of file app_minivm.c.

◆ ast_str_encode_mime()

static const char * ast_str_encode_mime ( struct ast_str **  end,
ssize_t  maxlen,
const char *  charset,
const char *  start,
size_t  preamble,
size_t  postamble 
)
static

Definition at line 1040 of file app_minivm.c.

1041{
1042 struct ast_str *tmp = ast_str_alloca(80);
1043 int first_section = 1;
1044
1046 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
1047 for (; *start; start++) {
1048 int need_encoding = 0;
1049 if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
1050 need_encoding = 1;
1051 }
1052 if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
1053 (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
1054 (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
1055 (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
1056 /* Start new line */
1057 ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
1058 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
1059 first_section = 0;
1060 }
1061 if (need_encoding && *start == ' ') {
1062 ast_str_append(&tmp, -1, "_");
1063 } else if (need_encoding) {
1064 ast_str_append(&tmp, -1, "=%hhX", *start);
1065 } else {
1066 ast_str_append(&tmp, -1, "%c", *start);
1067 }
1068 }
1069 ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
1070 return ast_str_buffer(*end);
1071}
static int tmp()
Definition: bt_open.c:389
charset
Definition: chan_unistim.c:336
char * end
Definition: eagi_proxy.c:73
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_alloca(init_len)
Definition: strings.h:848
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
Support for dynamic strings.
Definition: strings.h:623

References ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set(), ast_str_strlen(), end, and tmp().

Referenced by sendmail().

◆ ast_str_quote()

static const char * ast_str_quote ( struct ast_str **  buf,
ssize_t  maxlen,
const char *  from 
)
static

Definition at line 1081 of file app_minivm.c.

1082{
1083 const char *ptr;
1084
1085 /* We're only ever passing 0 to maxlen, so short output isn't possible */
1086 ast_str_set(buf, maxlen, "\"");
1087 for (ptr = from; *ptr; ptr++) {
1088 if (*ptr == '"' || *ptr == '\\') {
1089 ast_str_append(buf, maxlen, "\\%c", *ptr);
1090 } else {
1091 ast_str_append(buf, maxlen, "%c", *ptr);
1092 }
1093 }
1094 ast_str_append(buf, maxlen, "\"");
1095
1096 return ast_str_buffer(*buf);
1097}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66

References ast_str_append(), ast_str_buffer(), ast_str_set(), and buf.

Referenced by sendmail().

◆ check_dirpath()

static int check_dirpath ( char *  dest,
int  len,
char *  domain,
char *  username,
char *  folder 
)
static

Definition at line 1405 of file app_minivm.c.

1406{
1407 struct stat filestat;
1408 make_dir(dest, len, domain, username, folder ? folder : "");
1409 if (stat(dest, &filestat)== -1)
1410 return FALSE;
1411 else
1412 return TRUE;
1413}
static int make_dir(char *dest, int len, const char *domain, const char *username, const char *folder)
Definition: app_minivm.c:1391
#define TRUE
Definition: app_minivm.c:524
#define FALSE
Definition: app_minivm.c:527
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References FALSE, len(), make_dir(), and TRUE.

Referenced by leave_voicemail(), minivm_account_func_read(), and minivm_greet_exec().

◆ check_mime()

static int check_mime ( const char *  str)
static

Definition at line 1011 of file app_minivm.c.

1012{
1013 for (; *str; str++) {
1014 if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
1015 return 1;
1016 }
1017 }
1018 return 0;
1019}
const char * str
Definition: app_jack.c:147

References str.

Referenced by sendmail().

◆ complete_minivm_show_users()

static char * complete_minivm_show_users ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 2896 of file app_minivm.c.

2897{
2898 int which = 0;
2899 int wordlen;
2900 struct minivm_account *vmu;
2901 const char *domain = "";
2902
2903 /* 0 - minivm; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
2904 if (pos > 4)
2905 return NULL;
2906 wordlen = strlen(word);
2908 if (!strncasecmp(word, vmu->domain, wordlen)) {
2909 if (domain && strcmp(domain, vmu->domain) && ++which > state)
2910 return ast_strdup(vmu->domain);
2911 /* ignore repeated domains ? */
2912 domain = vmu->domain;
2913 }
2914 }
2915 return NULL;
2916}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
short word
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define NULL
Definition: resample.c:96
struct minivm_account::@38 list
char domain[AST_MAX_CONTEXT]
Definition: app_minivm.c:606

References AST_LIST_TRAVERSE, ast_strdup, minivm_account::domain, minivm_template::list, and NULL.

Referenced by handle_minivm_show_users().

◆ create_dirpath()

static int create_dirpath ( char *  dest,
int  len,
char *  domain,
char *  username,
char *  folder 
)
static

Definition at line 1424 of file app_minivm.c.

1425{
1426 int res;
1427 make_dir(dest, len, domain, username, folder);
1428 if ((res = ast_mkdir(dest, 0777))) {
1429 ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
1430 return -1;
1431 }
1432 ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
1433 return 0;
1434}
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2479

References ast_debug, ast_log, ast_mkdir(), len(), LOG_WARNING, and make_dir().

Referenced by leave_voicemail(), minivm_counter_func_read(), and minivm_counter_func_write().

◆ create_vmaccount()

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 2443 of file app_minivm.c.

2444{
2445 struct minivm_account *vmu;
2446 char *domain;
2447 char *username;
2448 char accbuf[BUFSIZ];
2449
2450 ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
2451
2452 ast_copy_string(accbuf, name, sizeof(accbuf));
2453 username = accbuf;
2454 domain = strchr(accbuf, '@');
2455 if (domain) {
2456 *domain = '\0';
2457 domain++;
2458 }
2459 if (ast_strlen_zero(domain)) {
2460 ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
2461 return 0;
2462 }
2463
2464 ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
2465
2466 /* Allocate user account */
2467 vmu = ast_calloc(1, sizeof(*vmu));
2468 if (!vmu)
2469 return 0;
2470
2471 ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
2472 ast_copy_string(vmu->username, username, sizeof(vmu->username));
2473
2474 populate_defaults(vmu);
2475
2476 ast_debug(3, "...Configuring account %s\n", name);
2477
2478 while (var) {
2479 ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
2480 if (!strcasecmp(var->name, "serveremail")) {
2481 ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
2482 } else if (!strcasecmp(var->name, "email")) {
2483 ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
2484 } else if (!strcasecmp(var->name, "accountcode")) {
2485 ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
2486 } else if (!strcasecmp(var->name, "pincode")) {
2487 ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
2488 } else if (!strcasecmp(var->name, "domain")) {
2489 ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
2490 } else if (!strcasecmp(var->name, "language")) {
2491 ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
2492 } else if (!strcasecmp(var->name, "timezone")) {
2493 ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
2494 } else if (!strcasecmp(var->name, "externnotify")) {
2495 ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
2496 } else if (!strcasecmp(var->name, "etemplate")) {
2497 ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
2498 } else if (!strcasecmp(var->name, "ptemplate")) {
2499 ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
2500 } else if (!strcasecmp(var->name, "fullname")) {
2501 ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
2502 } else if (!strcasecmp(var->name, "setvar")) {
2503 char *varval;
2504 char varname[strlen(var->value) + 1];
2505 struct ast_variable *tmpvar;
2506
2507 strcpy(varname, var->value); /* safe */
2508 if ((varval = strchr(varname, '='))) {
2509 *varval = '\0';
2510 varval++;
2511 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
2512 tmpvar->next = vmu->chanvars;
2513 vmu->chanvars = tmpvar;
2514 }
2515 }
2516 } else if (!strcasecmp(var->name, "pager")) {
2517 ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
2518 } else if (!strcasecmp(var->name, "volgain")) {
2519 sscanf(var->value, "%30lf", &vmu->volgain);
2520 } else {
2521 ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
2522 }
2523 var = var->next;
2524 }
2525 ast_debug(3, "...Linking account %s\n", name);
2526
2530
2532
2533 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)" : "");
2534 return 0;
2535}
static void populate_defaults(struct minivm_account *vmu)
Definition: app_minivm.c:898
static struct minivm_stats global_stats
Statistics for voicemail.
Definition: app_minivm.c:682
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static const char name[]
Definition: format_mp3.c:68
#define ast_variable_new(name, value, filename)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
struct ast_variable * chanvars
Definition: app_minivm.c:623
char serveremail[80]
Definition: app_minivm.c:613
char pager[80]
Definition: app_minivm.c:611
char zonetag[80]
Definition: app_minivm.c:616
char username[AST_MAX_CONTEXT]
Definition: app_minivm.c:605
char ptemplate[80]
Definition: app_minivm.c:621
double volgain
Definition: app_minivm.c:624
char externnotify[160]
Definition: app_minivm.c:614
char email[80]
Definition: app_minivm.c:610
char fullname[120]
Definition: app_minivm.c:609
char etemplate[80]
Definition: app_minivm.c:620
char language[MAX_LANGUAGE]
Definition: app_minivm.c:615
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: app_minivm.c:612
char pincode[10]
Definition: app_minivm.c:608
int voicemailaccounts
Definition: app_minivm.c:672

References minivm_account::accountcode, ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, 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, minivm_template::list, LOG_ERROR, name, ast_variable::next, minivm_account::pager, minivm_account::pincode, populate_defaults(), minivm_account::ptemplate, minivm_account::serveremail, minivm_account::username, var, minivm_stats::voicemailaccounts, minivm_account::volgain, and minivm_account::zonetag.

Referenced by find_user_realtime(), and load_config().

◆ find_account()

static struct minivm_account * find_account ( const char *  domain,
const char *  username,
int  createtemp 
)
static

Definition at line 934 of file app_minivm.c.

935{
936 struct minivm_account *vmu = NULL, *cur;
937
938
940 ast_log(LOG_NOTICE, "No username or domain? \n");
941 return NULL;
942 }
943 ast_debug(3, "Looking for voicemail user %s in domain %s\n", username, domain);
944
947 /* Is this the voicemail account we're looking for? */
948 if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
949 break;
950 }
952
953 if (cur) {
954 ast_debug(3, "Found account for %s@%s\n", username, domain);
955 vmu = cur;
956
957 } else
959
960 if (createtemp && !vmu) {
961 /* Create a temporary user, send e-mail and be gone */
962 vmu = mvm_user_alloc();
964 if (vmu) {
965 ast_copy_string(vmu->username, username, sizeof(vmu->username));
966 ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
967 ast_debug(1, "Created temporary account\n");
968 }
969
970 }
971 return vmu;
972}
static struct minivm_account * mvm_user_alloc(void)
Definition: app_minivm.c:907
#define MVM_ALLOCED
Definition: app_minivm.c:537
static struct minivm_account * find_user_realtime(const char *domain, const char *username)
Definition: app_minivm.c:978
#define LOG_NOTICE

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(), minivm_template::list, LOG_NOTICE, MVM_ALLOCED, mvm_user_alloc(), NULL, 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().

◆ find_user_realtime()

static struct minivm_account * find_user_realtime ( const char *  domain,
const char *  username 
)
static

Definition at line 978 of file app_minivm.c.

979{
980 struct ast_variable *var;
981 struct minivm_account *retval;
982 char name[MAXHOSTNAMELEN];
983
985 if (!retval)
986 return NULL;
987
988 if (username)
989 ast_copy_string(retval->username, username, sizeof(retval->username));
990
992 var = ast_load_realtime("minivm", "username", username, "domain", domain, SENTINEL);
993
994 if (!var) {
996 return NULL;
997 }
998
999 snprintf(name, sizeof(name), "%s@%s", username, domain);
1001
1003 return retval;
1004}
static int create_vmaccount(char *name, struct ast_variable *var, int realtime)
Append new mailbox to mailbox list from configuration file.
Definition: app_minivm.c:2443
#define ast_free(a)
Definition: astmm.h:180
#define SENTINEL
Definition: compiler.h:87
static ENTRY retval
Definition: hsearch.c:50
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3506
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define MAXHOSTNAMELEN
Definition: network.h:69

References ast_copy_string(), ast_free, ast_load_realtime(), ast_variables_destroy(), create_vmaccount(), MAXHOSTNAMELEN, mvm_user_alloc(), name, NULL, populate_defaults(), retval, SENTINEL, TRUE, and var.

Referenced by find_account().

◆ free_user()

static void free_user ( struct minivm_account vmu)
static

◆ free_zone()

static void free_zone ( struct minivm_zone z)
static

Free Mini Voicemail timezone.

Definition at line 2538 of file app_minivm.c.

2539{
2540 ast_free(z);
2541}

References ast_free.

Referenced by timezone_destroy_list().

◆ get_date()

static int get_date ( char *  s,
int  len 
)
static

Definition at line 844 of file app_minivm.c.

845{
846 struct ast_tm tm;
847 struct timeval now = ast_tvnow();
848
849 ast_localtime(&now, &tm, NULL);
850 return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
851}
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_localtime(), ast_strftime(), ast_tvnow(), len(), and NULL.

Referenced by leave_voicemail().

◆ handle_minivm_list_templates()

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 2855 of file app_minivm.c.

2856{
2857 struct minivm_template *this;
2858#define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
2859 int count = 0;
2860
2861 switch (cmd) {
2862 case CLI_INIT:
2863 e->command = "minivm list templates";
2864 e->usage =
2865 "Usage: minivm list templates\n"
2866 " Lists message templates for e-mail, paging and IM\n";
2867 return NULL;
2868 case CLI_GENERATE:
2869 return NULL;
2870 }
2871
2872 if (a->argc > 3)
2873 return CLI_SHOWUSAGE;
2874
2877 ast_cli(a->fd, "There are no message templates defined\n");
2879 return CLI_FAILURE;
2880 }
2881 ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
2882 ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
2884 ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name,
2885 S_OR(this->charset, "-"),
2886 S_OR(this->locale, "-"),
2887 this->attachment ? "Yes" : "No",
2888 S_OR(this->subject, "-"));
2889 count++;
2890 }
2892 ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
2893 return CLI_SUCCESS;
2894}
#define HVLT_OUTPUT_FORMAT
static char locale[20]
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
The list of e-mail templates.
Definition: app_minivm.c:651
char subject[100]
Definition: app_minivm.c:642
struct minivm_template::@39 list
static struct test_val a

References a, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, minivm_template::attachment, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, HVLT_OUTPUT_FORMAT, minivm_template::list, locale, NULL, S_OR, minivm_template::subject, and ast_cli_entry::usage.

◆ handle_minivm_reload()

static char * handle_minivm_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Reload cofiguration.

Definition at line 3402 of file app_minivm.c.

3403{
3404
3405 switch (cmd) {
3406 case CLI_INIT:
3407 e->command = "minivm reload";
3408 e->usage =
3409 "Usage: minivm reload\n"
3410 " Reload mini-voicemail configuration and reset statistics\n";
3411 return NULL;
3412 case CLI_GENERATE:
3413 return NULL;
3414 }
3415
3416 reload();
3417 ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
3418 return CLI_SUCCESS;
3419}
static int reload(void)
Reload mini voicemail module.
Definition: app_minivm.c:3396

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, NULL, reload(), and ast_cli_entry::usage.

◆ handle_minivm_show_settings()

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 3004 of file app_minivm.c.

3005{
3006 switch (cmd) {
3007 case CLI_INIT:
3008 e->command = "minivm show settings";
3009 e->usage =
3010 "Usage: minivm show settings\n"
3011 " Display Mini-Voicemail general settings\n";
3012 return NULL;
3013 case CLI_GENERATE:
3014 return NULL;
3015 }
3016
3017 ast_cli(a->fd, "* Mini-Voicemail general settings\n");
3018 ast_cli(a->fd, " -------------------------------\n");
3019 ast_cli(a->fd, "\n");
3020 ast_cli(a->fd, " Mail command (shell): %s\n", global_mailcmd);
3021 ast_cli(a->fd, " Max silence: %d\n", global_maxsilence);
3022 ast_cli(a->fd, " Silence threshold: %d\n", global_silencethreshold);
3023 ast_cli(a->fd, " Max message length (secs): %d\n", global_vmmaxmessage);
3024 ast_cli(a->fd, " Min message length (secs): %d\n", global_vmminmessage);
3025 ast_cli(a->fd, " Default format: %s\n", default_vmformat);
3026 ast_cli(a->fd, " Extern notify (shell): %s\n", global_externnotify);
3027 ast_cli(a->fd, " Logfile: %s\n", global_logfile[0] ? global_logfile : "<disabled>");
3028 ast_cli(a->fd, " Operator exit: %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
3029 ast_cli(a->fd, " Message review: %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
3030
3031 ast_cli(a->fd, "\n");
3032 return CLI_SUCCESS;
3033}
#define ast_test_flag(p, flag)
Definition: utils.h:63

References a, ast_cli(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, default_vmformat, global_externnotify, global_logfile, global_mailcmd, global_maxsilence, global_silencethreshold, global_vmmaxmessage, global_vmminmessage, globalflags, MVM_OPERATOR, MVM_REVIEW, NULL, and ast_cli_entry::usage.

◆ handle_minivm_show_stats()

static char * handle_minivm_show_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Show stats.

Definition at line 3036 of file app_minivm.c.

3037{
3038 struct ast_tm timebuf;
3039 char buf[BUFSIZ];
3040
3041 switch (cmd) {
3042
3043 case CLI_INIT:
3044 e->command = "minivm show stats";
3045 e->usage =
3046 "Usage: minivm show stats\n"
3047 " Display Mini-Voicemail counters\n";
3048 return NULL;
3049 case CLI_GENERATE:
3050 return NULL;
3051 }
3052
3053 ast_cli(a->fd, "* Mini-Voicemail statistics\n");
3054 ast_cli(a->fd, " -------------------------\n");
3055 ast_cli(a->fd, "\n");
3056 ast_cli(a->fd, " Voicemail accounts: %5d\n", global_stats.voicemailaccounts);
3057 ast_cli(a->fd, " Templates: %5d\n", global_stats.templates);
3058 ast_cli(a->fd, " Timezones: %5d\n", global_stats.timezones);
3059 if (global_stats.receivedmessages == 0) {
3060 ast_cli(a->fd, " Received messages since last reset: <none>\n");
3061 } else {
3062 ast_cli(a->fd, " Received messages since last reset: %d\n", global_stats.receivedmessages);
3064 ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
3065 ast_cli(a->fd, " Last received voicemail: %s\n", buf);
3066 }
3067 ast_localtime(&global_stats.reset, &timebuf, NULL);
3068 ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
3069 ast_cli(a->fd, " Last reset: %s\n", buf);
3070
3071 ast_cli(a->fd, "\n");
3072 return CLI_SUCCESS;
3073}
struct timeval lastreceived
Definition: app_minivm.c:678
int receivedmessages
Definition: app_minivm.c:677
struct timeval reset
Definition: app_minivm.c:676

References a, ast_cli(), ast_localtime(), ast_strftime(), buf, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, global_stats, minivm_stats::lastreceived, NULL, minivm_stats::receivedmessages, minivm_stats::reset, minivm_stats::templates, minivm_stats::timezones, ast_cli_entry::usage, and minivm_stats::voicemailaccounts.

◆ handle_minivm_show_users()

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 2919 of file app_minivm.c.

2920{
2921 struct minivm_account *vmu;
2922#define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
2923 int count = 0;
2924
2925 switch (cmd) {
2926 case CLI_INIT:
2927 e->command = "minivm list accounts [for]";
2928 e->usage =
2929 "Usage: minivm list accounts [for <domain>]\n"
2930 " Lists all mailboxes currently set up\n";
2931 return NULL;
2932 case CLI_GENERATE:
2933 return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
2934 }
2935
2936 if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
2937 return CLI_SHOWUSAGE;
2938 if ((a->argc == 5) && strcmp(a->argv[3],"for"))
2939 return CLI_SHOWUSAGE;
2940
2943 ast_cli(a->fd, "There are no voicemail users currently defined\n");
2945 return CLI_FAILURE;
2946 }
2947 ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
2948 ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
2950 char tmp[256] = "";
2951 if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
2952 count++;
2953 snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
2954 ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, S_OR(vmu->etemplate, "-"),
2955 S_OR(vmu->ptemplate, "-"),
2956 S_OR(vmu->zonetag, "-"),
2957 S_OR(vmu->attachfmt, "-"),
2958 vmu->fullname);
2959 }
2960 }
2962 ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
2963 return CLI_SUCCESS;
2964}
#define HMSU_OUTPUT_FORMAT
static char * complete_minivm_show_users(const char *line, const char *word, int pos, int state)
Definition: app_minivm.c:2896
char attachfmt[80]
Definition: app_minivm.c:619

References a, 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, minivm_account::fullname, HMSU_OUTPUT_FORMAT, minivm_template::list, NULL, minivm_account::ptemplate, S_OR, tmp(), ast_cli_entry::usage, minivm_account::username, and minivm_account::zonetag.

◆ handle_minivm_show_zones()

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 2967 of file app_minivm.c.

2968{
2969 struct minivm_zone *zone;
2970#define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
2971 char *res = CLI_SUCCESS;
2972
2973 switch (cmd) {
2974 case CLI_INIT:
2975 e->command = "minivm list zones";
2976 e->usage =
2977 "Usage: minivm list zones\n"
2978 " Lists zone message formats\n";
2979 return NULL;
2980 case CLI_GENERATE:
2981 return NULL;
2982 }
2983
2984 if (a->argc != e->args)
2985 return CLI_SHOWUSAGE;
2986
2989 ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
2990 ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
2992 ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
2993 }
2994 } else {
2995 ast_cli(a->fd, "There are no voicemail zones currently defined\n");
2996 res = CLI_FAILURE;
2997 }
2999
3000 return res;
3001}
#define HMSZ_OUTPUT_FORMAT
int args
This gets set in ast_cli_register()
Definition: cli.h:185
Voicemail time zones.
Definition: app_minivm.c:660
char msg_format[BUFSIZ]
Definition: app_minivm.c:663
char name[80]
Definition: app_minivm.c:661
char timezone[80]
Definition: app_minivm.c:662
struct minivm_zone::@40 list
The list of e-mail time zones.
Definition: app_minivm.c:668

References a, 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, HMSZ_OUTPUT_FORMAT, minivm_template::list, minivm_zone::msg_format, minivm_zone::name, NULL, minivm_zone::timezone, and ast_cli_entry::usage.

◆ invent_message()

static int invent_message ( struct ast_channel chan,
char *  domain,
char *  username,
int  busy,
char *  ecodes 
)
static

Definition at line 1440 of file app_minivm.c.

1441{
1442 int res;
1443 char fn[PATH_MAX];
1444
1445 ast_debug(2, "Still preparing to play message ...\n");
1446
1447 snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
1448
1449 if (ast_fileexists(fn, NULL, NULL) > 0) {
1450 res = ast_streamfile(chan, fn, ast_channel_language(chan));
1451 if (res)
1452 return -1;
1453 res = ast_waitstream(chan, ecodes);
1454 if (res)
1455 return res;
1456 } else {
1457 int numericusername = 1;
1458 char *i = username;
1459
1460 ast_debug(2, "No personal prompts. Using default prompt set for language\n");
1461
1462 while (*i) {
1463 ast_debug(2, "Numeric? Checking %c\n", *i);
1464 if (!isdigit(*i)) {
1465 numericusername = FALSE;
1466 break;
1467 }
1468 i++;
1469 }
1470
1471 if (numericusername) {
1472 if (ast_streamfile(chan, "vm-theperson", ast_channel_language(chan)))
1473 return -1;
1474 if ((res = ast_waitstream(chan, ecodes)))
1475 return res;
1476
1477 res = ast_say_digit_str(chan, username, ecodes, ast_channel_language(chan));
1478 if (res)
1479 return res;
1480 } else {
1481 if (ast_streamfile(chan, "vm-theextensionis", ast_channel_language(chan)))
1482 return -1;
1483 if ((res = ast_waitstream(chan, ecodes)))
1484 return res;
1485 }
1486 }
1487
1488 res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", ast_channel_language(chan));
1489 if (res)
1490 return -1;
1491 res = ast_waitstream(chan, ecodes);
1492 return res;
1493}
static char MVM_SPOOL_DIR[PATH_MAX]
Definition: app_minivm.c:562
#define PATH_MAX
Definition: asterisk.h:40
const char * ast_channel_language(const struct ast_channel *chan)
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1129
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1840
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8259

References ast_channel_language(), ast_debug, ast_fileexists(), ast_say_digit_str(), ast_streamfile(), ast_waitstream(), FALSE, MVM_SPOOL_DIR, NULL, and PATH_MAX.

Referenced by minivm_greet_exec().

◆ leave_voicemail()

static int leave_voicemail ( struct ast_channel chan,
char *  username,
struct leave_vm_options options 
)
static

Definition at line 1779 of file app_minivm.c.

1780{
1781 char tmptxtfile[PATH_MAX];
1782 char callerid[256];
1783 FILE *txt;
1784 int res = 0, txtdes;
1785 int duration = 0;
1786 int sound_duration = 0;
1787 char date[256];
1788 char tmpdir[PATH_MAX];
1789 char ext_context[256] = "";
1790 char fmt[80];
1791 char *domain;
1792 char tmp[256] = "";
1793 struct minivm_account *vmu;
1794 int userdir;
1795
1796 ast_copy_string(tmp, username, sizeof(tmp));
1797 username = tmp;
1798 domain = strchr(tmp, '@');
1799 if (domain) {
1800 *domain = '\0';
1801 domain++;
1802 }
1803
1804 if (!(vmu = find_account(domain, username, TRUE))) {
1805 /* We could not find user, let's exit */
1806 ast_log(LOG_ERROR, "Can't allocate temporary account for '%s@%s'\n", username, domain);
1807 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1808 return 0;
1809 }
1810
1811 /* Setup pre-file if appropriate */
1812 if (strcmp(vmu->domain, "localhost"))
1813 snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
1814 else
1815 ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
1816
1817 /* The meat of recording the message... All the announcements and beeps have been played*/
1818 if (ast_strlen_zero(vmu->attachfmt))
1819 ast_copy_string(fmt, default_vmformat, sizeof(fmt));
1820 else
1821 ast_copy_string(fmt, vmu->attachfmt, sizeof(fmt));
1822
1823 if (ast_strlen_zero(fmt)) {
1824 ast_log(LOG_WARNING, "No format for saving voicemail? Default %s\n", default_vmformat);
1825 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1826 return res;
1827 }
1828
1829 userdir = check_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
1830
1831 /* If we have no user directory, use generic temporary directory */
1832 if (!userdir) {
1833 create_dirpath(tmpdir, sizeof(tmpdir), "0000_minivm_temp", "mediafiles", "");
1834 ast_debug(3, "Creating temporary directory %s\n", tmpdir);
1835 }
1836
1837
1838 snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
1839
1840 /* XXX This file needs to be in temp directory */
1841 txtdes = mkstemp(tmptxtfile);
1842 if (txtdes < 0) {
1843 ast_log(LOG_ERROR, "Unable to create message file %s: %s\n", tmptxtfile, strerror(errno));
1844 res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
1845 if (!res)
1846 res = ast_waitstream(chan, "");
1847 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1848 return res;
1849 }
1850
1851 if (res >= 0) {
1852 /* Unless we're *really* silent, try to send the beep */
1853 res = ast_streamfile(chan, "beep", ast_channel_language(chan));
1854 if (!res)
1855 res = ast_waitstream(chan, "");
1856 }
1857
1858 /* OEJ XXX Maybe this can be turned into a log file? Hmm. */
1859 /* Store information */
1860 ast_debug(2, "Open file for metadata: %s\n", tmptxtfile);
1861
1862 res = play_record_review(chan, NULL, tmptxtfile, global_vmmaxmessage, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain);
1863
1864 txt = fdopen(txtdes, "w+");
1865 if (!txt) {
1866 ast_log(LOG_WARNING, "Error opening text file for output\n");
1867 } else {
1868 struct ast_tm tm;
1869 struct timeval now = ast_tvnow();
1870 char timebuf[30];
1871 char logbuf[BUFSIZ];
1872 get_date(date, sizeof(date));
1873 ast_localtime(&now, &tm, NULL);
1874 ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
1875
1876 ast_callerid_merge(callerid, sizeof(callerid),
1877 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
1878 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
1879 "Unknown");
1880 snprintf(logbuf, sizeof(logbuf),
1881 /* "Mailbox:domain:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
1882 "%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
1883 username,
1884 ast_channel_context(chan),
1885 ast_channel_exten(chan),
1887 ast_channel_name(chan),
1888 callerid,
1889 date,
1890 timebuf,
1891 duration,
1892 duration < global_vmminmessage ? "IGNORED" : "OK",
1893 vmu->accountcode
1894 );
1895 fprintf(txt, "%s", logbuf);
1896 if (minivmlogfile) {
1898 fprintf(minivmlogfile, "%s", logbuf);
1900 }
1901
1902 if (sound_duration < global_vmminmessage) {
1903 ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, global_vmminmessage);
1904 fclose(txt);
1905 ast_filedelete(tmptxtfile, NULL);
1906 unlink(tmptxtfile);
1907 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1908 return 0;
1909 }
1910 fclose(txt); /* Close log file */
1911 if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
1912 ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
1913 unlink(tmptxtfile);
1914 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1915 if(ast_test_flag(vmu, MVM_ALLOCED))
1916 free_user(vmu);
1917 return 0;
1918 }
1919
1920 /* Set channel variables for the notify application */
1921 pbx_builtin_setvar_helper(chan, "MVM_FILENAME", tmptxtfile);
1922 snprintf(timebuf, sizeof(timebuf), "%d", duration);
1923 pbx_builtin_setvar_helper(chan, "MVM_DURATION", timebuf);
1924 pbx_builtin_setvar_helper(chan, "MVM_FORMAT", fmt);
1925
1926 }
1929#if 0
1930 /* Go ahead and delete audio files from system, they're not needed any more */
1931 if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
1932 ast_filedelete(tmptxtfile, NULL);
1933 /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
1934 ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
1935 }
1936#endif
1937
1938 if (res > 0)
1939 res = 0;
1940
1941 if(ast_test_flag(vmu, MVM_ALLOCED))
1942 free_user(vmu);
1943
1944 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
1945 return res;
1946}
static FILE * minivmlogfile
Definition: app_minivm.c:687
static void free_user(struct minivm_account *vmu)
Definition: app_minivm.c:856
static ast_mutex_t minivmloglock
Definition: app_minivm.c:685
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, int *sound_duration, const char *unlockdir, signed char record_gain)
Definition: app_minivm.c:1511
static int check_dirpath(char *dest, int len, char *domain, char *username, char *folder)
Definition: app_minivm.c:1405
static int create_dirpath(char *dest, int len, char *domain, char *username, char *folder)
Definition: app_minivm.c:1424
static struct minivm_account * find_account(const char *domain, const char *username, int createtemp)
Definition: app_minivm.c:934
static int get_date(char *s, int len)
Definition: app_minivm.c:844
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1174
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1141
#define ast_verb(level,...)
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
Number structure.
Definition: app_followme.c:154
static struct test_options options

References minivm_account::accountcode, ast_callerid_merge(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_language(), ast_channel_name(), ast_channel_priority(), 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(), create_dirpath(), default_vmformat, minivm_account::domain, errno, find_account(), free_user(), get_date(), global_stats, global_vmmaxmessage, global_vmminmessage, minivm_stats::lastreceived, LOG_ERROR, LOG_WARNING, minivmlogfile, minivmloglock, MVM_ALLOCED, name, NULL, options, PATH_MAX, pbx_builtin_setvar_helper(), play_record_review(), minivm_stats::receivedmessages, S_COR, tmp(), and TRUE.

Referenced by minivm_record_exec().

◆ load_config()

static int load_config ( int  reload)
static

Load minivoicemail configuration.

Definition at line 2713 of file app_minivm.c.

2714{
2715 struct ast_config *cfg;
2716 struct ast_variable *var;
2717 char *cat;
2718 const char *chanvar;
2719 int error = 0;
2720 struct minivm_template *template;
2721 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2722
2723 cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
2724 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2725 return 0;
2726 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2727 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
2728 return 0;
2729 }
2730
2732
2733 /* Destroy lists to reconfigure */
2734 message_destroy_list(); /* Destroy list of voicemail message templates */
2735 timezone_destroy_list(); /* Destroy list of timezones */
2736 vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
2737 ast_debug(2, "Destroyed memory objects...\n");
2738
2739 /* First, set some default settings */
2740 global_externnotify[0] = '\0';
2741 global_logfile[0] = '\0';
2742 global_vmmaxmessage = 2000;
2743 global_maxgreet = 2000;
2745 strcpy(global_mailcmd, SENDMAIL);
2751 /* Reset statistics */
2752 memset(&global_stats, 0, sizeof(global_stats));
2754
2756
2757 /* Make sure we could load configuration file */
2758 if (!cfg) {
2759 ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
2761 return 0;
2762 }
2763
2764 ast_debug(2, "Loaded configuration file, now parsing\n");
2765
2766 /* General settings */
2767
2768 cat = ast_category_browse(cfg, NULL);
2769 while (cat) {
2770 ast_debug(3, "Found configuration section [%s]\n", cat);
2771 if (!strcasecmp(cat, "general")) {
2772 /* Nothing right now */
2774 } else if (!strncasecmp(cat, "template-", 9)) {
2775 /* Template */
2776 char *name = cat + 9;
2777
2778 /* Now build and link template to list */
2780 } else {
2781 var = ast_variable_browse(cfg, cat);
2782 if (!strcasecmp(cat, "zonemessages")) {
2783 /* Timezones in this context */
2784 while (var) {
2785 timezone_add(var->name, var->value);
2786 var = var->next;
2787 }
2788 } else {
2789 /* Create mailbox from this */
2790 error += create_vmaccount(cat, var, FALSE);
2791 }
2792 }
2793 /* Find next section in configuration file */
2794 cat = ast_category_browse(cfg, cat);
2795 }
2796
2797 /* Configure the default email template */
2798 message_template_build("email-default", NULL);
2799 template = message_template_find("email-default");
2800
2801 /* Load date format config for voicemail mail */
2802 if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat")))
2803 ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
2804 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
2805 ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
2806 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
2807 ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2808 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaddress")))
2809 ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2810 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
2811 ast_copy_string(template->charset, chanvar, sizeof(template->charset));
2812 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject")))
2813 ast_copy_string(template->subject, chanvar, sizeof(template->subject));
2814 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody")))
2815 template->body = message_template_parse_emailbody(chanvar);
2816 template->attachment = TRUE;
2817
2818 message_template_build("pager-default", NULL);
2819 template = message_template_find("pager-default");
2820 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
2821 ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
2822 if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
2823 ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2824 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
2825 ast_copy_string(template->charset, chanvar, sizeof(template->charset));
2826 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
2827 ast_copy_string(template->subject, chanvar,sizeof(template->subject));
2828 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody")))
2829 template->body = message_template_parse_emailbody(chanvar);
2830 template->attachment = FALSE;
2831
2832 if (error)
2833 ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
2834
2836 ast_config_destroy(cfg);
2837
2838 /* Close log file if it's open and disabled */
2839 if(minivmlogfile)
2840 fclose(minivmlogfile);
2841
2842 /* Open log file if it's enabled */
2844 minivmlogfile = fopen(global_logfile, "a");
2845 if(!minivmlogfile)
2846 ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
2847 if (minivmlogfile)
2848 ast_debug(3, "Opened log file %s \n", global_logfile);
2849 }
2850
2851 return 0;
2852}
static void message_destroy_list(void)
Definition: app_minivm.c:833
static int apply_general_options(struct ast_variable *var)
Apply general configuration options.
Definition: app_minivm.c:2655
static void timezone_destroy_list(void)
Clear list of timezones.
Definition: app_minivm.c:2544
static int timezone_add(const char *zonename, const char *config)
Add time zone to memory list.
Definition: app_minivm.c:2556
#define VOICEMAIL_CONFIG
Definition: app_minivm.c:552
static char * message_template_parse_emailbody(const char *body)
Parse emailbody template from configuration file.
Definition: app_minivm.c:2628
static int message_template_build(const char *name, struct ast_variable *var)
Definition: app_minivm.c:748
#define SENDMAIL
Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail....
Definition: app_minivm.c:541
static void vmaccounts_destroy_list(void)
Definition: app_minivm.c:922
static int global_saydurationminfo
Definition: app_minivm.c:700
static struct minivm_template * message_template_find(const char *name)
Definition: app_minivm.c:811
static ast_mutex_t minivmlock
Definition: app_minivm.c:684
static char * chanvar
Definition: app_system.c:113
@ THRESHOLD_SILENCE
Definition: dsp.h:73
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:2009
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
Structure used to handle boolean flags.
Definition: utils.h:199
structure for queuing ARI channel variable setting
Definition: control.c:705

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_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, create_vmaccount(), default_vmformat, errno, error(), FALSE, 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, name, NULL, reload(), minivm_stats::reset, SENDMAIL, THRESHOLD_SILENCE, timezone_add(), timezone_destroy_list(), TRUE, var, vmaccounts_destroy_list(), and VOICEMAIL_CONFIG.

Referenced by load_module(), and reload().

◆ load_module()

static int load_module ( void  )
static

Load mini voicemail module.

Definition at line 3368 of file app_minivm.c.

3369{
3370 int res;
3371
3378
3381 if (res)
3382 return(res);
3383
3384 if ((res = load_config(0)))
3385 return(res);
3386
3388
3389 /* compute the location of the voicemail spool directory */
3390 snprintf(MVM_SPOOL_DIR, sizeof(MVM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
3391
3392 return res;
3393}
static int minivm_record_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2081
static int minivm_notify_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2003
static char * app_minivm_delete
Definition: app_minivm.c:568
static char * app_minivm_greet
Definition: app_minivm.c:566
static struct ast_custom_function minivm_account_function
Definition: app_minivm.c:3362
static int minivm_delete_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2307
static int minivm_mwi_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:1965
static int minivm_accmess_exec(struct ast_channel *chan, const char *data)
Record specific messages for voicemail account.
Definition: app_minivm.c:2345
static char * app_minivm_notify
Definition: app_minivm.c:567
static struct ast_cli_entry cli_minivm[]
CLI commands for Mini-voicemail.
Definition: app_minivm.c:3347
static char * app_minivm_record
Definition: app_minivm.c:565
static char * app_minivm_accmess
Definition: app_minivm.c:569
static int minivm_greet_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2134
static int load_config(int reload)
Load minivoicemail configuration.
Definition: app_minivm.c:2713
static struct ast_custom_function minivm_counter_function
Definition: app_minivm.c:3356
static char * app_minivm_mwi
Definition: app_minivm.c:570
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
#define ARRAY_LEN(a)
Definition: utils.h:666

References app_minivm_accmess, app_minivm_delete, app_minivm_greet, app_minivm_mwi, app_minivm_notify, app_minivm_record, 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(), minivm_record_exec(), and MVM_SPOOL_DIR.

◆ make_dir()

static int make_dir ( char *  dest,
int  len,
const char *  domain,
const char *  username,
const char *  folder 
)
static

Definition at line 1391 of file app_minivm.c.

1392{
1393 return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
1394}

References ast_strlen_zero(), len(), and MVM_SPOOL_DIR.

Referenced by check_dirpath(), and create_dirpath().

◆ message_destroy_list()

static void message_destroy_list ( void  )
static

Definition at line 833 of file app_minivm.c.

834{
835 struct minivm_template *this;
837 while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) {
839 }
840
842}
static void message_template_free(struct minivm_template *template)
Definition: app_minivm.c:738
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, minivm_template::list, and message_template_free().

Referenced by load_config(), and unload_module().

◆ message_template_build()

static int message_template_build ( const char *  name,
struct ast_variable var 
)
static

Definition at line 748 of file app_minivm.c.

749{
750 struct minivm_template *template;
751 int error = 0;
752
753 template = message_template_create(name);
754 if (!template) {
755 ast_log(LOG_ERROR, "Out of memory, can't allocate message template object %s.\n", name);
756 return -1;
757 }
758
759 while (var) {
760 ast_debug(3, "Configuring template option %s = \"%s\" for template %s\n", var->name, var->value, name);
761 if (!strcasecmp(var->name, "fromaddress")) {
762 ast_copy_string(template->fromaddress, var->value, sizeof(template->fromaddress));
763 } else if (!strcasecmp(var->name, "fromemail")) {
764 ast_copy_string(template->serveremail, var->value, sizeof(template->serveremail));
765 } else if (!strcasecmp(var->name, "subject")) {
766 ast_copy_string(template->subject, var->value, sizeof(template->subject));
767 } else if (!strcasecmp(var->name, "locale")) {
768 ast_copy_string(template->locale, var->value, sizeof(template->locale));
769 } else if (!strcasecmp(var->name, "attachmedia")) {
770 template->attachment = ast_true(var->value);
771 } else if (!strcasecmp(var->name, "dateformat")) {
772 ast_copy_string(template->dateformat, var->value, sizeof(template->dateformat));
773 } else if (!strcasecmp(var->name, "charset")) {
774 ast_copy_string(template->charset, var->value, sizeof(template->charset));
775 } else if (!strcasecmp(var->name, "templatefile")) {
776 if (template->body)
777 ast_free(template->body);
778 template->body = message_template_parse_filebody(var->value);
779 if (!template->body) {
780 ast_log(LOG_ERROR, "Error reading message body definition file %s\n", var->value);
781 error++;
782 }
783 } else if (!strcasecmp(var->name, "messagebody")) {
784 if (template->body)
785 ast_free(template->body);
786 template->body = message_template_parse_emailbody(var->value);
787 if (!template->body) {
788 ast_log(LOG_ERROR, "Error parsing message body definition:\n %s\n", var->value);
789 error++;
790 }
791 } else {
792 ast_log(LOG_ERROR, "Unknown message template configuration option \"%s=%s\"\n", var->name, var->value);
793 error++;
794 }
795 var = var->next;
796 }
797 if (error)
798 ast_log(LOG_ERROR, "-- %d errors found parsing message template definition %s\n", error, name);
799
803
805
806 return error;
807}
static char * message_template_parse_filebody(const char *filename)
Read message template from file.
Definition: app_minivm.c:2588
static struct minivm_template * message_template_create(const char *name)
Definition: app_minivm.c:718

References ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_true(), error(), global_stats, minivm_template::list, LOG_ERROR, message_template_create(), message_template_parse_emailbody(), message_template_parse_filebody(), name, minivm_stats::templates, and var.

Referenced by load_config().

◆ message_template_create()

static struct minivm_template * message_template_create ( const char *  name)
static

Definition at line 718 of file app_minivm.c.

719{
720 struct minivm_template *template;
721
722 template = ast_calloc(1, sizeof(*template));
723 if (!template)
724 return NULL;
725
726 /* Set some defaults for templates */
727 ast_copy_string(template->name, name, sizeof(template->name));
728 ast_copy_string(template->dateformat, DEFAULT_DATEFORMAT, sizeof(template->dateformat));
729 ast_copy_string(template->charset, DEFAULT_CHARSET, sizeof(template->charset));
730 ast_copy_string(template->subject, "New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}", sizeof(template->subject));
731 template->attachment = TRUE;
732
733 return template;
734}
#define DEFAULT_DATEFORMAT
Definition: app_minivm.c:706
#define DEFAULT_CHARSET
Definition: app_minivm.c:707

References ast_calloc, ast_copy_string(), DEFAULT_CHARSET, DEFAULT_DATEFORMAT, name, NULL, and TRUE.

Referenced by message_template_build().

◆ message_template_find()

static struct minivm_template * message_template_find ( const char *  name)
static

Definition at line 811 of file app_minivm.c.

812{
813 struct minivm_template *this, *res = NULL;
814
816 return NULL;
817
820 if (!strcasecmp(this->name, name)) {
821 res = this;
822 break;
823 }
824 }
826
827 return res;
828}

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), minivm_template::list, name, and NULL.

Referenced by load_config(), and notify_new_message().

◆ message_template_free()

static void message_template_free ( struct minivm_template template)
static

Definition at line 738 of file app_minivm.c.

739{
740 if (template->body)
741 ast_free(template->body);
742
743 ast_free (template);
744}

References ast_free.

Referenced by message_destroy_list().

◆ message_template_parse_emailbody()

static char * message_template_parse_emailbody ( const char *  body)
static

Parse emailbody template from configuration file.

Definition at line 2628 of file app_minivm.c.

2629{
2630 char *tmpread, *tmpwrite;
2631 char *emailbody = ast_strdup(configuration);
2632
2633 /* substitute strings \t and \n into the apropriate characters */
2634 tmpread = tmpwrite = emailbody;
2635 while ((tmpwrite = strchr(tmpread,'\\'))) {
2636 int len = strlen("\n");
2637 switch (tmpwrite[1]) {
2638 case 'n':
2639 memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2640 tmpwrite[0] = '\n';
2641 break;
2642 case 't':
2643 memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2644 tmpwrite[0] = '\t';
2645 break;
2646 default:
2647 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
2648 }
2649 tmpread = tmpwrite + len;
2650 }
2651 return emailbody;
2652}
static char * emailbody

References ast_log, ast_strdup, emailbody, len(), and LOG_NOTICE.

Referenced by load_config(), and message_template_build().

◆ message_template_parse_filebody()

static char * message_template_parse_filebody ( const char *  filename)
static

Read message template from file.

Definition at line 2588 of file app_minivm.c.

2588 {
2589 char buf[BUFSIZ * 6];
2590 char readbuf[BUFSIZ];
2591 char filenamebuf[BUFSIZ];
2592 char *writepos;
2593 char *messagebody;
2594 FILE *fi;
2595 int lines = 0;
2596
2597 if (ast_strlen_zero(filename))
2598 return NULL;
2599 if (*filename == '/')
2600 ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
2601 else
2602 snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
2603
2604 if (!(fi = fopen(filenamebuf, "r"))) {
2605 ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
2606 return NULL;
2607 }
2608 writepos = buf;
2609 while (fgets(readbuf, sizeof(readbuf), fi)) {
2610 lines ++;
2611 if (writepos != buf) {
2612 *writepos = '\n'; /* Replace EOL with new line */
2613 writepos++;
2614 }
2615 ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
2616 writepos += strlen(readbuf) - 1;
2617 }
2618 fclose(fi);
2619 messagebody = ast_calloc(1, strlen(buf + 1));
2620 ast_copy_string(messagebody, buf, strlen(buf) + 1);
2621 ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
2622 ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
2623
2624 return messagebody;
2625}
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151

References ast_calloc, ast_config_AST_CONFIG_DIR, ast_copy_string(), ast_debug, ast_log, ast_strlen_zero(), buf, LOG_ERROR, and NULL.

Referenced by message_template_build().

◆ minivm_accmess_exec()

static int minivm_accmess_exec ( struct ast_channel chan,
const char *  data 
)
static

Record specific messages for voicemail account.

Definition at line 2345 of file app_minivm.c.

2346{
2347 int argc = 0;
2348 char *argv[2];
2349 char filename[PATH_MAX];
2350 char tmp[PATH_MAX];
2351 char *domain;
2352 char *tmpptr = NULL;
2353 struct minivm_account *vmu;
2354 char *username;
2355 struct ast_flags flags = { 0 };
2356 char *opts[OPT_ARG_ARRAY_SIZE];
2357 int error = FALSE;
2358 char *message = NULL;
2359 char *prompt = NULL;
2360 int duration;
2361
2362 if (ast_strlen_zero(data)) {
2363 ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
2364 error = TRUE;
2365 } else {
2366 tmpptr = ast_strdupa((char *)data);
2367 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2368 }
2369
2370 if (argc <=1) {
2371 ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
2372 error = TRUE;
2373 }
2374 if (!error && strlen(argv[1]) > 1) {
2375 ast_log(LOG_ERROR, "MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
2376 error = TRUE;
2377 }
2378
2379 if (!error && ast_app_parse_options(minivm_accmess_options, &flags, opts, argv[1])) {
2380 ast_log(LOG_ERROR, "Can't parse option %s\n", argv[1]);
2381 error = TRUE;
2382 }
2383
2384 if (error) {
2385 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
2386 return -1;
2387 }
2388
2389 ast_copy_string(tmp, argv[0], sizeof(tmp));
2390 username = tmp;
2391 domain = strchr(tmp, '@');
2392 if (domain) {
2393 *domain = '\0';
2394 domain++;
2395 }
2396 if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
2397 ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2398 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
2399 return -1;
2400 }
2401
2402 if(!(vmu = find_account(domain, username, TRUE))) {
2403 /* We could not find user, let's exit */
2404 ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
2405 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
2406 return -1;
2407 }
2408
2409 /* Answer channel if it's not already answered */
2410 if (ast_channel_state(chan) != AST_STATE_UP)
2411 ast_answer(chan);
2412
2413 /* Here's where the action is */
2415 message = "busy";
2416 prompt = "vm-rec-busy";
2418 message = "unavailable";
2419 prompt = "vm-rec-unv";
2420 } else if (ast_test_flag(&flags, OPT_TEMP_GREETING)) {
2421 message = "temp";
2422 prompt = "vm-rec-temp";
2423 } else if (ast_test_flag(&flags, OPT_NAME_GREETING)) {
2424 message = "greet";
2425 prompt = "vm-rec-name";
2426 }
2427 snprintf(filename,sizeof(filename), "%s%s/%s/%s", MVM_SPOOL_DIR, vmu->domain, vmu->username, message);
2428 /* Maybe we should check the result of play_record_review ? */
2429 play_record_review(chan, prompt, filename, global_maxgreet, default_vmformat, 0, vmu, &duration, NULL, NULL, FALSE);
2430
2431 ast_debug(1, "Recorded new %s message in %s (duration %d)\n", message, filename, duration);
2432
2433 if(ast_test_flag(vmu, MVM_ALLOCED))
2434 free_user(vmu);
2435
2436 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "SUCCESS");
2437
2438 /* Ok, we're ready to rock and roll. Return to dialplan */
2439 return 0;
2440}
static const struct ast_app_option minivm_accmess_options[128]
Definition: app_minivm.c:600
static struct ast_str * prompt
Definition: asterisk.c:2763
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2805
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#define ast_app_separate_args(a, b, c, d)
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3056
unsigned int flags
Definition: utils.h:200

References 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, error(), FALSE, find_account(), free_user(), global_maxgreet, LOG_ERROR, LOG_WARNING, minivm_accmess_options, MVM_ALLOCED, MVM_SPOOL_DIR, NULL, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_NAME_GREETING, OPT_TEMP_GREETING, OPT_UNAVAIL_GREETING, PATH_MAX, pbx_builtin_setvar_helper(), play_record_review(), prompt, tmp(), TRUE, and minivm_account::username.

Referenced by load_module().

◆ minivm_account_func_read()

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 3076 of file app_minivm.c.

3077{
3078 struct minivm_account *vmu;
3079 char *username, *domain, *colname;
3080
3081 username = ast_strdupa(data);
3082
3083 if ((colname = strchr(username, ':'))) {
3084 *colname = '\0';
3085 colname++;
3086 } else {
3087 colname = "path";
3088 }
3089 if ((domain = strchr(username, '@'))) {
3090 *domain = '\0';
3091 domain++;
3092 }
3094 ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
3095 return 0;
3096 }
3097
3098 if (!(vmu = find_account(domain, username, TRUE)))
3099 return 0;
3100
3101 if (!strcasecmp(colname, "hasaccount")) {
3102 ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
3103 } else if (!strcasecmp(colname, "fullname")) {
3105 } else if (!strcasecmp(colname, "email")) {
3106 if (!ast_strlen_zero(vmu->email))
3107 ast_copy_string(buf, vmu->email, len);
3108 else
3109 snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
3110 } else if (!strcasecmp(colname, "pager")) {
3111 ast_copy_string(buf, vmu->pager, len);
3112 } else if (!strcasecmp(colname, "etemplate")) {
3113 if (!ast_strlen_zero(vmu->etemplate))
3115 else
3116 ast_copy_string(buf, "email-default", len);
3117 } else if (!strcasecmp(colname, "language")) {
3119 } else if (!strcasecmp(colname, "timezone")) {
3121 } else if (!strcasecmp(colname, "ptemplate")) {
3122 if (!ast_strlen_zero(vmu->ptemplate))
3124 else
3125 ast_copy_string(buf, "email-default", len);
3126 } else if (!strcasecmp(colname, "accountcode")) {
3128 } else if (!strcasecmp(colname, "pincode")) {
3130 } else if (!strcasecmp(colname, "path")) {
3131 check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
3132 } else { /* Look in channel variables */
3133 struct ast_variable *var;
3134
3135 for (var = vmu->chanvars ; var ; var = var->next)
3136 if (!strcmp(var->name, colname)) {
3137 ast_copy_string(buf, var->value, len);
3138 break;
3139 }
3140 }
3141
3142 if(ast_test_flag(vmu, MVM_ALLOCED))
3143 free_user(vmu);
3144
3145 return 0;
3146}

References minivm_account::accountcode, ast_copy_string(), ast_log, ast_strdupa, ast_strlen_zero(), ast_test_flag, buf, minivm_account::chanvars, check_dirpath(), minivm_account::domain, minivm_account::email, minivm_account::etemplate, find_account(), free_user(), minivm_account::fullname, minivm_account::language, len(), LOG_ERROR, MVM_ALLOCED, NULL, minivm_account::pager, minivm_account::pincode, minivm_account::ptemplate, TRUE, minivm_account::username, var, and minivm_account::zonetag.

◆ minivm_counter_func_read()

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 3223 of file app_minivm.c.

3224{
3225 char *username, *domain, *countername;
3226 char userpath[BUFSIZ];
3227 int res;
3228
3229 *buf = '\0';
3230
3231 username = ast_strdupa(data);
3232
3233 if ((countername = strchr(username, ':'))) {
3234 *countername = '\0';
3235 countername++;
3236 }
3237
3238 if ((domain = strchr(username, '@'))) {
3239 *domain = '\0';
3240 domain++;
3241 }
3242
3243 /* If we have neither username nor domain now, let's give up */
3244 if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3245 ast_log(LOG_ERROR, "No account given\n");
3246 return -1;
3247 }
3248
3249 if (ast_strlen_zero(countername)) {
3250 ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
3251 return -1;
3252 }
3253
3254 /* We only have a domain, no username */
3255 if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3256 domain = username;
3257 username = NULL;
3258 }
3259
3260 /* If we can't find account or if the account is temporary, return. */
3261 if (!ast_strlen_zero(username) && !find_account(domain, username, FALSE)) {
3262 ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
3263 return 0;
3264 }
3265
3266 create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
3267
3268 /* We have the path, now read the counter file */
3269 res = access_counter_file(userpath, countername, 0, 0);
3270 if (res >= 0)
3271 snprintf(buf, len, "%d", res);
3272 return 0;
3273}
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.
Definition: app_minivm.c:3170

References access_counter_file(), ast_log, ast_strdupa, ast_strlen_zero(), buf, create_dirpath(), FALSE, find_account(), len(), LOG_ERROR, and NULL.

◆ minivm_counter_func_write()

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 3276 of file app_minivm.c.

3277{
3278 char *username, *domain, *countername, *operand;
3279 char userpath[BUFSIZ];
3280 int change = 0;
3281 int operation = 0;
3282
3283 if(!value)
3284 return -1;
3285 change = atoi(value);
3286
3287 username = ast_strdupa(data);
3288
3289 if ((countername = strchr(username, ':'))) {
3290 *countername = '\0';
3291 countername++;
3292 }
3293 if ((operand = strchr(countername, ':'))) {
3294 *operand = '\0';
3295 operand++;
3296 }
3297
3298 if ((domain = strchr(username, '@'))) {
3299 *domain = '\0';
3300 domain++;
3301 }
3302
3303 /* If we have neither username nor domain now, let's give up */
3304 if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3305 ast_log(LOG_ERROR, "No account given\n");
3306 return -1;
3307 }
3308
3309 /* We only have a domain, no username */
3310 if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3311 domain = username;
3312 username = NULL;
3313 }
3314
3315 if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
3316 ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
3317 return -1;
3318 }
3319
3320 /* If we can't find account or if the account is temporary, return. */
3321 if (!ast_strlen_zero(username) && !find_account(domain, username, FALSE)) {
3322 ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
3323 return 0;
3324 }
3325
3326 create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
3327 /* Now, find out our operator */
3328 if (*operand == 'i') /* Increment */
3329 operation = 2;
3330 else if (*operand == 'd') {
3331 change = change * -1;
3332 operation = 2;
3333 } else if (*operand == 's')
3334 operation = 1;
3335 else {
3336 ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
3337 return -1;
3338 }
3339
3340 /* We have the path, now read the counter file */
3341 access_counter_file(userpath, countername, change, operation);
3342 return 0;
3343}

References access_counter_file(), ast_log, ast_strdupa, ast_strlen_zero(), create_dirpath(), FALSE, find_account(), LOG_ERROR, NULL, and value.

◆ minivm_delete_exec()

static int minivm_delete_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 2307 of file app_minivm.c.

2308{
2309 int res = 0;
2310 char filename[BUFSIZ];
2311
2312 if (!ast_strlen_zero(data)) {
2313 ast_copy_string(filename, (char *) data, sizeof(filename));
2314 } else {
2315 ast_channel_lock(chan);
2316 ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
2317 ast_channel_unlock(chan);
2318 }
2319
2320 if (ast_strlen_zero(filename)) {
2321 ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
2322 return res;
2323 }
2324
2325 /* Go ahead and delete audio files from system, they're not needed any more */
2326 /* We should look for both audio and text files here */
2327 if (ast_fileexists(filename, NULL, NULL) > 0) {
2328 res = vm_delete(filename);
2329 if (res) {
2330 ast_debug(2, "Can't delete file: %s\n", filename);
2331 pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
2332 } else {
2333 ast_debug(2, "Deleted voicemail file :: %s \n", filename);
2334 pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
2335 }
2336 } else {
2337 ast_debug(2, "Filename does not exist: %s\n", filename);
2338 pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
2339 }
2340
2341 return res;
2342}
static int vm_delete(char *file)
Definition: app_minivm.c:1497
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_fileexists(), ast_log, ast_strlen_zero(), LOG_ERROR, NULL, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and vm_delete().

Referenced by load_module().

◆ minivm_greet_exec()

static int minivm_greet_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 2134 of file app_minivm.c.

2135{
2136 struct leave_vm_options leave_options = { 0, '\0'};
2137 int argc;
2138 char *argv[2];
2139 struct ast_flags flags = { 0 };
2140 char *opts[OPT_ARG_ARRAY_SIZE];
2141 int res = 0;
2142 int ouseexten = 0;
2143 char tmp[PATH_MAX];
2144 char dest[PATH_MAX];
2145 char prefile[PATH_MAX] = "";
2146 char tempfile[PATH_MAX] = "";
2147 char ext_context[256] = "";
2148 char *domain;
2149 char ecodes[16] = "#";
2150 char *tmpptr;
2151 struct minivm_account *vmu;
2152 char *username;
2153
2154 if (ast_strlen_zero(data)) {
2155 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2156 return -1;
2157 }
2158 tmpptr = ast_strdupa((char *)data);
2159 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2160
2161 if (argc == 2) {
2162 if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1]))
2163 return -1;
2165 }
2166
2167 ast_copy_string(tmp, argv[0], sizeof(tmp));
2168 username = tmp;
2169 domain = strchr(tmp, '@');
2170 if (domain) {
2171 *domain = '\0';
2172 domain++;
2173 }
2175 ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument: %s\n", argv[0]);
2176 return -1;
2177 }
2178 ast_debug(1, "Trying to find configuration for user %s in domain %s\n", username, domain);
2179
2180 if (!(vmu = find_account(domain, username, TRUE))) {
2181 ast_log(LOG_ERROR, "Could not allocate memory. \n");
2182 return -1;
2183 }
2184
2185 /* Answer channel if it's not already answered */
2186 if (ast_channel_state(chan) != AST_STATE_UP)
2187 ast_answer(chan);
2188
2189 /* Setup pre-file if appropriate */
2190 if (strcmp(vmu->domain, "localhost"))
2191 snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
2192 else
2193 ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
2194
2195 if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
2196 res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
2197 if (res)
2198 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
2199 } else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
2200 res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
2201 if (res)
2202 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
2203 }
2204 /* Check for temporary greeting - it overrides busy and unavail */
2205 snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
2206 if (!(res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
2207 ast_debug(2, "Temporary message directory does not exist, using default (%s)\n", tempfile);
2208 ast_copy_string(prefile, tempfile, sizeof(prefile));
2209 }
2210 ast_debug(2, "Preparing to play message ...\n");
2211
2212 /* Check current context for special extensions */
2213 if (ast_test_flag(vmu, MVM_OPERATOR)) {
2214 if (!ast_strlen_zero(vmu->exit)) {
2215 if (ast_exists_extension(chan, vmu->exit, "o", 1,
2216 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2217 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
2218 ouseexten = 1;
2219 }
2220 } else if (ast_exists_extension(chan, ast_channel_context(chan), "o", 1,
2221 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2222 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
2223 ouseexten = 1;
2224 }
2225 }
2226
2227 if (!ast_strlen_zero(vmu->exit)) {
2228 if (ast_exists_extension(chan, vmu->exit, "a", 1,
2229 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2230 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
2231 }
2232 } else if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
2233 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2234 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
2235 }
2236
2237 res = 0; /* Reset */
2238 /* Play the beginning intro if desired */
2239 if (!ast_strlen_zero(prefile)) {
2240 if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1)
2241 res = ast_waitstream(chan, ecodes);
2242 } else {
2243 ast_debug(2, "%s doesn't exist, doing what we can\n", prefile);
2244 res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
2245 }
2246 if (res < 0) {
2247 ast_debug(2, "Hang up during prefile playback\n");
2248 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
2249 if(ast_test_flag(vmu, MVM_ALLOCED))
2250 free_user(vmu);
2251 return -1;
2252 }
2253 if (res == '#') {
2254 /* On a '#' we skip the instructions */
2255 ast_set_flag(&leave_options, OPT_SILENT);
2256 res = 0;
2257 }
2258 if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
2260 if (!res)
2261 res = ast_waitstream(chan, ecodes);
2262 if (res == '#') {
2263 ast_set_flag(&leave_options, OPT_SILENT);
2264 res = 0;
2265 }
2266 }
2267 if (res > 0)
2268 ast_stopstream(chan);
2269 /* Check for a '*' here in case the caller wants to escape from voicemail to something
2270 other than the operator -- an automated attendant or mailbox login for example */
2271 if (res == '*') {
2272 ast_channel_exten_set(chan, "a");
2273 if (!ast_strlen_zero(vmu->exit)) {
2274 ast_channel_context_set(chan, vmu->exit);
2275 }
2276 ast_channel_priority_set(chan, 0);
2277 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
2278 res = 0;
2279 } else if (res == '0') { /* Check for a '0' here */
2280 if(ouseexten) {
2281 ast_channel_exten_set(chan, "o");
2282 if (!ast_strlen_zero(vmu->exit)) {
2283 ast_channel_context_set(chan, vmu->exit);
2284 }
2285 ast_play_and_wait(chan, "transfer");
2286 ast_channel_priority_set(chan, 0);
2287 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
2288 }
2289 res = 0;
2290 } else if (res < 0) {
2291 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
2292 res = -1;
2293 } else
2294 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "SUCCESS");
2295
2296 if(ast_test_flag(vmu, MVM_ALLOCED))
2297 free_user(vmu);
2298
2299
2300 /* Ok, we're ready to rock and roll. Return to dialplan */
2301 return res;
2302
2303}
#define SOUND_INTRO
Definition: app_minivm.c:543
static int invent_message(struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
Definition: app_minivm.c:1440
static const struct ast_app_option minivm_app_options[128]
Definition: app_minivm.c:593
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: main/app.c:1616
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:654
char exit[80]
Definition: app_minivm.c:618
unsigned int flags
Definition: app_minivm.c:622
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84

References ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args, ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_language(), ast_channel_priority_set(), 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(), minivm_account::domain, minivm_account::exit, find_account(), free_user(), invent_message(), LOG_ERROR, minivm_app_options, MVM_ALLOCED, MVM_OPERATOR, MVM_SPOOL_DIR, NULL, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, PATH_MAX, pbx_builtin_setvar_helper(), S_COR, SOUND_INTRO, tmp(), and TRUE.

Referenced by load_module().

◆ minivm_mwi_exec()

static int minivm_mwi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1965 of file app_minivm.c.

1966{
1967 int argc;
1968 char *argv[4];
1969 int res = 0;
1970 char *tmpptr;
1971 char tmp[PATH_MAX];
1972 char *mailbox;
1973 char *domain;
1974 if (ast_strlen_zero(data)) {
1975 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
1976 return -1;
1977 }
1978 tmpptr = ast_strdupa((char *)data);
1979 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
1980 if (argc < 4) {
1981 ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
1982 return -1;
1983 }
1984 ast_copy_string(tmp, argv[0], sizeof(tmp));
1985 mailbox = tmp;
1986 domain = strchr(tmp, '@');
1987 if (domain) {
1988 *domain = '\0';
1989 domain++;
1990 }
1991 if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
1992 ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
1993 return -1;
1994 }
1995 queue_mwi_event(ast_channel_uniqueid(chan), mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
1996
1997 return res;
1998}
static void queue_mwi_event(const char *channel_id, const char *mbx, const char *ctx, int urgent, int new, int old)
Definition: app_minivm.c:1950
const char * ast_channel_uniqueid(const struct ast_channel *chan)

References ARRAY_LEN, ast_app_separate_args, ast_channel_uniqueid(), ast_copy_string(), ast_log, ast_strdupa, ast_strlen_zero(), LOG_ERROR, voicemailpwcheck::mailbox, PATH_MAX, queue_mwi_event(), and tmp().

Referenced by load_module().

◆ minivm_notify_exec()

static int minivm_notify_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 2003 of file app_minivm.c.

2004{
2005 int argc;
2006 char *argv[2];
2007 int res = 0;
2008 char tmp[PATH_MAX];
2009 char *domain;
2010 char *tmpptr;
2011 struct minivm_account *vmu;
2012 char *username;
2013 const char *template = "";
2014 const char *filename;
2015 const char *format;
2016 const char *duration_string;
2017 if (ast_strlen_zero(data)) {
2018 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2019 return -1;
2020 }
2021 tmpptr = ast_strdupa((char *)data);
2022 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2023
2024 if (argc == 2 && !ast_strlen_zero(argv[1]))
2025 template = argv[1];
2026
2027 ast_copy_string(tmp, argv[0], sizeof(tmp));
2028 username = tmp;
2029 domain = strchr(tmp, '@');
2030 if (domain) {
2031 *domain = '\0';
2032 domain++;
2033 }
2035 ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2036 return -1;
2037 }
2038
2039 if(!(vmu = find_account(domain, username, TRUE))) {
2040 /* We could not find user, let's exit */
2041 ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
2042 pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
2043 return -1;
2044 }
2045
2046 ast_channel_lock(chan);
2047 if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
2048 filename = ast_strdupa(filename);
2049 }
2050 ast_channel_unlock(chan);
2051 /* Notify of new message to e-mail and pager */
2052 if (!ast_strlen_zero(filename)) {
2053 ast_channel_lock(chan);
2054 if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
2055 format = ast_strdupa(format);
2056 }
2057 if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
2058 duration_string = ast_strdupa(duration_string);
2059 }
2060 ast_channel_unlock(chan);
2061 res = notify_new_message(chan, template, vmu, filename, atoi(duration_string),
2062 format,
2063 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
2064 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL));
2065 }
2066
2067 pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
2068
2069
2070 if(ast_test_flag(vmu, MVM_ALLOCED))
2071 free_user(vmu);
2072
2073 /* Ok, we're ready to rock and roll. Return to dialplan */
2074
2075 return res;
2076
2077}
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)
Definition: app_minivm.c:1678

References ARRAY_LEN, ast_app_separate_args, ast_channel_caller(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log, ast_strdupa, ast_strlen_zero(), ast_test_flag, find_account(), free_user(), LOG_ERROR, LOG_WARNING, MVM_ALLOCED, name, notify_new_message(), NULL, PATH_MAX, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), S_COR, tmp(), and TRUE.

Referenced by load_module().

◆ minivm_record_exec()

static int minivm_record_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 2081 of file app_minivm.c.

2082{
2083 int res = 0;
2084 char *tmp;
2085 struct leave_vm_options leave_options;
2086 int argc;
2087 char *argv[2];
2088 struct ast_flags flags = { 0 };
2089 char *opts[OPT_ARG_ARRAY_SIZE];
2090
2091 memset(&leave_options, 0, sizeof(leave_options));
2092
2093 /* Answer channel if it's not already answered */
2094 if (ast_channel_state(chan) != AST_STATE_UP)
2095 ast_answer(chan);
2096
2097 if (ast_strlen_zero(data)) {
2098 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2099 return -1;
2100 }
2101 tmp = ast_strdupa((char *)data);
2102 argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
2103 if (argc == 2) {
2104 if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
2105 return -1;
2106 }
2109 int gain;
2110
2111 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
2112 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
2113 return -1;
2114 } else
2115 leave_options.record_gain = (signed char) gain;
2116 }
2117 }
2118
2119 /* Now run the appliation and good luck to you! */
2120 res = leave_voicemail(chan, argv[0], &leave_options);
2121
2122 if (res == ERROR_LOCK_PATH) {
2123 ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
2124 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
2125 res = 0;
2126 }
2127 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
2128
2129 return res;
2130}
#define ERROR_LOCK_PATH
Definition: app_minivm.c:549
static int leave_voicemail(struct ast_channel *chan, char *username, struct leave_vm_options *options)
Definition: app_minivm.c:1779

References 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, 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(), leave_vm_options::record_gain, and tmp().

Referenced by load_module().

◆ mvm_user_alloc()

static struct minivm_account * mvm_user_alloc ( void  )
static

Definition at line 907 of file app_minivm.c.

908{
909 struct minivm_account *new;
910
911 new = ast_calloc(1, sizeof(*new));
912 if (!new)
913 return NULL;
915
916 return new;
917}

References ast_calloc, NULL, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

◆ notify_new_message()

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

Definition at line 1678 of file app_minivm.c.

1679{
1680 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1682 RAII_VAR(struct ast_mwi_state *, mwi_state, NULL, ao2_cleanup);
1683 char *stringp;
1684 struct minivm_template *etemplate;
1685 char *messageformat;
1686 int res = 0;
1687 char oldlocale[100];
1688 const char *counter;
1689
1690 if (!ast_strlen_zero(vmu->attachfmt)) {
1691 if (strstr(format, vmu->attachfmt)) {
1692 format = vmu->attachfmt;
1693 } else {
1694 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);
1695 }
1696 }
1697
1698 etemplate = message_template_find(vmu->etemplate);
1699 if (!etemplate)
1700 etemplate = message_template_find(templatename);
1701 if (!etemplate)
1702 etemplate = message_template_find("email-default");
1703
1704 /* Attach only the first format */
1705 stringp = messageformat = ast_strdupa(format);
1706 strsep(&stringp, "|");
1707
1708 if (!ast_strlen_zero(etemplate->locale)) {
1709 char *new_locale;
1710 ast_copy_string(oldlocale, setlocale(LC_TIME, NULL), sizeof(oldlocale));
1711 ast_debug(2, "Changing locale from %s to %s\n", oldlocale, etemplate->locale);
1712 new_locale = setlocale(LC_TIME, etemplate->locale);
1713 if (new_locale == NULL) {
1714 ast_log(LOG_WARNING, "-_-_- Changing to new locale did not work. Locale: %s\n", etemplate->locale);
1715 }
1716 }
1717
1718
1719
1720 /* Read counter if available */
1721 ast_channel_lock(chan);
1722 if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
1723 counter = ast_strdupa(counter);
1724 }
1725 ast_channel_unlock(chan);
1726
1727 if (ast_strlen_zero(counter)) {
1728 ast_debug(2, "MVM_COUNTER not found\n");
1729 } else {
1730 ast_debug(2, "MVM_COUNTER found - will use it with value %s\n", counter);
1731 }
1732
1733 res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_EMAIL, counter);
1734
1735 if (res == 0 && !ast_strlen_zero(vmu->pager)) {
1736 /* Find template for paging */
1737 etemplate = message_template_find(vmu->ptemplate);
1738 if (!etemplate)
1739 etemplate = message_template_find("pager-default");
1740
1741 if (!ast_strlen_zero(etemplate->locale)) {
1742 ast_copy_string(oldlocale, setlocale(LC_TIME, ""), sizeof(oldlocale));
1743 setlocale(LC_TIME, etemplate->locale);
1744 }
1745
1746 res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_PAGE, counter);
1747 }
1748
1749 mwi_state = ast_mwi_create(vmu->username, vmu->domain);
1750 if (!mwi_state) {
1751 goto notify_cleanup;
1752 }
1753 mwi_state->snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
1754
1755 json_object = ast_json_pack("{s: s, s: s, s: s}",
1756 "Event", "MiniVoiceMail",
1757 "Action", "SentNotification",
1758 "Counter", counter ?: "");
1759 if (!json_object) {
1760 goto notify_cleanup;
1761 }
1762 message = ast_mwi_blob_create(mwi_state, ast_mwi_vm_app_type(), json_object);
1763 if (!message) {
1764 goto notify_cleanup;
1765 }
1766 stasis_publish(ast_mwi_topic(mwi_state->uniqueid), message);
1767
1768notify_cleanup:
1769 run_externnotify(chan, vmu); /* Run external notification */
1770 if (!ast_strlen_zero(etemplate->locale)) {
1771 setlocale(LC_TIME, oldlocale); /* Reset to old locale */
1772 }
1773 return res;
1774}
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)
Definition: app_minivm.c:1101
static void run_externnotify(struct ast_channel *chan, struct minivm_account *vmu)
Run external notification for voicemail message.
Definition: app_minivm.c:1643
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
char * strsep(char **str, const char *delims)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct stasis_message_type * ast_mwi_vm_app_type(void)
Get the Stasis Message Bus API message type for voicemail application specific messages.
struct stasis_message * ast_mwi_blob_create(struct ast_mwi_state *mwi_state, struct stasis_message_type *message_type, struct ast_json *blob)
Creates a ast_mwi_blob message.
Definition: mwi.c:467
struct stasis_topic * ast_mwi_topic(const char *uniqueid)
Get the Stasis Message Bus API topic for MWI messages on a unique ID.
Definition: mwi.c:104
struct ast_mwi_state * ast_mwi_create(const char *mailbox, const char *context)
Create a ast_mwi_state object.
Definition: mwi.c:152
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
Abstract JSON element (object, array, string, int, ...).
The structure that contains MWI state.
Definition: mwi.h:455
char locale[20]
Definition: app_minivm.c:644
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ast_channel_lock, ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_channel_unlock, ast_copy_string(), ast_debug, ast_json_pack(), ast_json_unref(), ast_log, ast_mwi_blob_create(), ast_mwi_create(), ast_mwi_topic(), ast_mwi_vm_app_type(), ast_strdupa, ast_strlen_zero(), minivm_account::attachfmt, minivm_template::attachment, minivm_account::domain, minivm_account::etemplate, minivm_template::locale, LOG_WARNING, message_template_find(), MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, NULL, minivm_account::pager, pbx_builtin_getvar_helper(), minivm_account::ptemplate, RAII_VAR, run_externnotify(), sendmail(), stasis_publish(), strsep(), and minivm_account::username.

Referenced by minivm_notify_exec().

◆ play_record_review()

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,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain 
)
static

Definition at line 1511 of file app_minivm.c.

1514{
1515 int cmd = 0;
1516 int max_attempts = 3;
1517 int attempts = 0;
1518 int recorded = 0;
1519 int message_exists = 0;
1520 signed char zero_gain = 0;
1521 char *acceptdtmf = "#";
1522 char *canceldtmf = "";
1523
1524 /* Note that urgent and private are for flagging messages as such in the future */
1525
1526 /* barf if no pointer passed to store duration in */
1527 if (duration == NULL) {
1528 ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
1529 return -1;
1530 }
1531
1532 cmd = '3'; /* Want to start by recording */
1533
1534 while ((cmd >= 0) && (cmd != 't')) {
1535 switch (cmd) {
1536 case '1':
1537 ast_verb(3, "Saving message as is\n");
1538 ast_stream_and_wait(chan, "vm-msgsaved", "");
1539 cmd = 't';
1540 break;
1541 case '2':
1542 /* Review */
1543 ast_verb(3, "Reviewing the message\n");
1544 ast_streamfile(chan, recordfile, ast_channel_language(chan));
1545 cmd = ast_waitstream(chan, AST_DIGIT_ANY);
1546 break;
1547 case '3':
1548 message_exists = 0;
1549 /* Record */
1550 if (recorded == 1)
1551 ast_verb(3, "Re-recording the message\n");
1552 else
1553 ast_verb(3, "Recording the message\n");
1554 if (recorded && outsidecaller)
1555 cmd = ast_play_and_wait(chan, "beep");
1556 recorded = 1;
1557 /* 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 */
1558 if (record_gain)
1559 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
1560 if (ast_test_flag(vmu, MVM_OPERATOR))
1561 canceldtmf = "0";
1562 cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf, 0, AST_RECORD_IF_EXISTS_OVERWRITE);
1563 if (record_gain)
1564 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
1565 if (cmd == -1) /* User has hung up, no options to give */
1566 return cmd;
1567 if (cmd == '0')
1568 break;
1569 else if (cmd == '*')
1570 break;
1571 else {
1572 /* If all is well, a message exists */
1573 message_exists = 1;
1574 cmd = 0;
1575 }
1576 break;
1577 case '4':
1578 case '5':
1579 case '6':
1580 case '7':
1581 case '8':
1582 case '9':
1583 case '*':
1584 case '#':
1585 cmd = ast_play_and_wait(chan, "vm-sorry");
1586 break;
1587 case '0':
1588 if(!ast_test_flag(vmu, MVM_OPERATOR)) {
1589 cmd = ast_play_and_wait(chan, "vm-sorry");
1590 break;
1591 }
1592 if (message_exists || recorded) {
1593 cmd = ast_play_and_wait(chan, "vm-saveoper");
1594 if (!cmd)
1595 cmd = ast_waitfordigit(chan, 3000);
1596 if (cmd == '1') {
1597 ast_play_and_wait(chan, "vm-msgsaved");
1598 cmd = '0';
1599 } else {
1600 ast_play_and_wait(chan, "vm-deleted");
1601 vm_delete(recordfile);
1602 cmd = '0';
1603 }
1604 }
1605 return cmd;
1606 default:
1607 /* If the caller is an outside caller, and the review option is enabled,
1608 allow them to review the message, but let the owner of the box review
1609 their OGM's */
1610 if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
1611 return cmd;
1612 if (message_exists) {
1613 cmd = ast_play_and_wait(chan, "vm-review");
1614 } else {
1615 cmd = ast_play_and_wait(chan, "vm-torerecord");
1616 if (!cmd)
1617 cmd = ast_waitfordigit(chan, 600);
1618 }
1619
1620 if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
1621 cmd = ast_play_and_wait(chan, "vm-reachoper");
1622 if (!cmd)
1623 cmd = ast_waitfordigit(chan, 600);
1624 }
1625 if (!cmd)
1626 cmd = ast_waitfordigit(chan, 6000);
1627 if (!cmd) {
1628 attempts++;
1629 }
1630 if (attempts > max_attempts) {
1631 cmd = 't';
1632 }
1633 }
1634 }
1635 if (outsidecaller)
1636 ast_play_and_wait(chan, "vm-goodbye");
1637 if (cmd == 't')
1638 cmd = 0;
1639 return cmd;
1640}
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7422
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1878
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence_ms, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
Record a file based on input from a channel This function will play "auth-thankyou" upon successful r...
Definition: main/app.c:2139
@ AST_RECORD_IF_EXISTS_OVERWRITE
#define AST_OPTION_RXGAIN

References ast_channel_language(), ast_channel_setoption(), AST_DIGIT_ANY, ast_log, AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), AST_RECORD_IF_EXISTS_OVERWRITE, ast_stream_and_wait(), ast_streamfile(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_waitstream(), global_maxsilence, global_silencethreshold, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, NULL, and vm_delete().

Referenced by leave_voicemail(), and minivm_accmess_exec().

◆ populate_defaults()

static void populate_defaults ( struct minivm_account vmu)
static

◆ prep_email_sub_vars()

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

Definition at line 869 of file app_minivm.c.

870{
871 char callerid[256];
872 struct ast_variable *var;
873
874 if (!channel) {
875 ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
876 return;
877 }
878
879 for (var = vmu->chanvars ; var ; var = var->next) {
880 pbx_builtin_setvar_helper(channel, var->name, var->value);
881 }
882
883 /* Prepare variables for substition in email body and subject */
884 pbx_builtin_setvar_helper(channel, "MVM_NAME", vmu->fullname);
885 pbx_builtin_setvar_helper(channel, "MVM_DUR", dur);
886 pbx_builtin_setvar_helper(channel, "MVM_DOMAIN", vmu->domain);
887 pbx_builtin_setvar_helper(channel, "MVM_USERNAME", vmu->username);
888 pbx_builtin_setvar_helper(channel, "MVM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
889 pbx_builtin_setvar_helper(channel, "MVM_CIDNAME", (cidname ? cidname : "an unknown caller"));
890 pbx_builtin_setvar_helper(channel, "MVM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
891 pbx_builtin_setvar_helper(channel, "MVM_DATE", date);
892 if (!ast_strlen_zero(counter))
893 pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
894}

References ast_callerid_merge(), ast_log, ast_strlen_zero(), minivm_account::chanvars, minivm_account::domain, minivm_account::fullname, LOG_ERROR, pbx_builtin_setvar_helper(), minivm_account::username, and var.

Referenced by sendmail().

◆ queue_mwi_event()

static void queue_mwi_event ( const char *  channel_id,
const char *  mbx,
const char *  ctx,
int  urgent,
int  new,
int  old 
)
static

Definition at line 1950 of file app_minivm.c.

1951{
1952 char *mailbox, *context;
1953
1954 mailbox = ast_strdupa(mbx);
1955 context = ast_strdupa(ctx);
1956 if (ast_strlen_zero(context)) {
1957 context = "default";
1958 }
1959
1960 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
1961}
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id)
Publish a MWI state update associated with some channel.
Definition: mwi.h:395

References ast_publish_mwi_state_channel, ast_strdupa, ast_strlen_zero(), voicemailpwcheck::context, and voicemailpwcheck::mailbox.

Referenced by minivm_mwi_exec().

◆ reload()

static int reload ( void  )
static

Reload mini voicemail module.

Definition at line 3396 of file app_minivm.c.

3397{
3398 return(load_config(1));
3399}

References load_config().

Referenced by handle_minivm_reload(), and load_config().

◆ run_externnotify()

static void run_externnotify ( struct ast_channel chan,
struct minivm_account vmu 
)
static

Run external notification for voicemail message.

Definition at line 1643 of file app_minivm.c.

1644{
1645 char fquser[AST_MAX_CONTEXT * 2];
1646 char *argv[5] = { NULL };
1647 struct ast_party_caller *caller;
1648 char *cid;
1649 int idx;
1650
1652 return;
1653 }
1654
1655 snprintf(fquser, sizeof(fquser), "%s@%s", vmu->username, vmu->domain);
1656
1657 caller = ast_channel_caller(chan);
1658 idx = 0;
1659 argv[idx++] = ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify;
1660 argv[idx++] = fquser;
1661 cid = S_COR(caller->id.name.valid, caller->id.name.str, NULL);
1662 if (cid) {
1663 argv[idx++] = cid;
1664 }
1665 cid = S_COR(caller->id.number.valid, caller->id.number.str, NULL);
1666 if (cid) {
1667 argv[idx++] = cid;
1668 }
1669 argv[idx] = NULL;
1670
1671 ast_debug(1, "Executing: %s %s %s %s\n",
1672 argv[0], argv[1], argv[2] ?: "", argv[3] ?: "");
1673 ast_safe_execvp(1, argv[0], argv);
1674}
#define AST_MAX_CONTEXT
Definition: channel.h:135
int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1218
Caller Party information.
Definition: channel.h:418
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
char * str
Subscriber name (Malloced)
Definition: channel.h:264
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291

References ast_channel_caller(), ast_debug, AST_MAX_CONTEXT, ast_safe_execvp(), ast_strlen_zero(), minivm_account::domain, minivm_account::externnotify, global_externnotify, ast_party_caller::id, ast_party_id::name, NULL, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, minivm_account::username, ast_party_name::valid, and ast_party_number::valid.

Referenced by notify_new_message().

◆ sendmail()

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

Definition at line 1101 of file app_minivm.c.

1102{
1103 RAII_VAR(struct ast_str *, str1, ast_str_create(16), ast_free);
1104 RAII_VAR(struct ast_str *, str2, ast_str_create(16), ast_free);
1105 FILE *p = NULL;
1106 int pfd;
1107 char email[256] = "";
1108 char who[256] = "";
1109 char date[256];
1110 char bound[256];
1111 char fname[PATH_MAX];
1112 char dur[PATH_MAX];
1113 char tmp[80] = "/tmp/astmail-XXXXXX";
1114 char mail_cmd_buffer[PATH_MAX];
1115 char sox_gain_tmpdir[PATH_MAX] = ""; /* Only used with volgain */
1116 char *file_to_delete = NULL, *dir_to_delete = NULL;
1117 struct timeval now;
1118 struct ast_tm tm;
1119 struct minivm_zone *the_zone = NULL;
1120 struct ast_channel *chan = NULL;
1121 char *fromaddress;
1122 char *fromemail;
1123 int res = -1;
1124
1125 if (!str1 || !str2) {
1126 return -1;
1127 }
1128
1129 if (type == MVM_MESSAGE_EMAIL) {
1130 if (vmu && !ast_strlen_zero(vmu->email)) {
1131 ast_copy_string(email, vmu->email, sizeof(email));
1132 } else if (!ast_strlen_zero(vmu->username) && !ast_strlen_zero(vmu->domain))
1133 snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
1134 } else if (type == MVM_MESSAGE_PAGE) {
1135 ast_copy_string(email, vmu->pager, sizeof(email));
1136 }
1137
1138 if (ast_strlen_zero(email)) {
1139 ast_log(LOG_WARNING, "No address to send message to.\n");
1140 return -1;
1141 }
1142
1143 ast_debug(3, "Sending mail to %s@%s - Using template %s\n", vmu->username, vmu->domain, template->name);
1144
1145 if (!strcmp(format, "wav49"))
1146 format = "WAV";
1147
1148 /* If we have a gain option, process it now with sox */
1149 if (type == MVM_MESSAGE_EMAIL && (vmu->volgain < -.001 || vmu->volgain > .001) ) {
1150 char sox_gain_cmd[PATH_MAX];
1151
1152 ast_copy_string(sox_gain_tmpdir, "/tmp/minivm-gain-XXXXXX", sizeof(sox_gain_tmpdir));
1153 ast_debug(3, "sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
1154 if (!mkdtemp(sox_gain_tmpdir)) {
1155 ast_log(LOG_WARNING, "Failed to create temporary directory for volgain: %d\n", errno);
1156 return -1;
1157 }
1158 snprintf(fname, sizeof(fname), "%s/output.%s", sox_gain_tmpdir, format);
1159 snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s", vmu->volgain, filename, format, fname);
1160 ast_safe_system(sox_gain_cmd);
1161 ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->volgain, vmu->username);
1162
1163 /* Mark some things for deletion */
1164 file_to_delete = fname;
1165 dir_to_delete = sox_gain_tmpdir;
1166 } else {
1167 snprintf(fname, sizeof(fname), "%s.%s", filename, format);
1168 }
1169
1170 if (template->attachment)
1171 ast_debug(1, "Attaching file '%s', format '%s', uservm is '%d'\n", fname, format, attach_user_voicemail);
1172
1173 /* Make a temporary file instead of piping directly to sendmail, in case the mail
1174 command hangs */
1175 pfd = mkstemp(tmp);
1176 if (pfd > -1) {
1177 p = fdopen(pfd, "w");
1178 if (!p) {
1179 close(pfd);
1180 pfd = -1;
1181 }
1182 ast_debug(1, "Opening temp file for e-mail: %s\n", tmp);
1183 }
1184 if (!p) {
1185 ast_log(LOG_WARNING, "Unable to open temporary file '%s'\n", tmp);
1186 goto out;
1187 }
1188 /* Allocate channel used for chanvar substitution */
1189 chan = ast_dummy_channel_alloc();
1190 if (!chan) {
1191 goto out;
1192 }
1193
1194 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
1195
1196 /* Does this user have a timezone specified? */
1197 if (!ast_strlen_zero(vmu->zonetag)) {
1198 /* Find the zone in the list */
1199 struct minivm_zone *z;
1202 if (strcmp(z->name, vmu->zonetag))
1203 continue;
1204 the_zone = z;
1205 }
1207 }
1208
1209 now = ast_tvnow();
1210 ast_localtime(&now, &tm, the_zone ? the_zone->timezone : NULL);
1211 ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
1212
1213 /* Start printing the email to the temporary file */
1214 fprintf(p, "Date: %s\n", date);
1215
1216 /* Set date format for voicemail mail */
1217 ast_strftime(date, sizeof(date), template->dateformat, &tm);
1218
1219 /* Populate channel with channel variables for substitution */
1220 prep_email_sub_vars(chan, vmu, cidnum, cidname, dur, date, counter);
1221
1222 /* Find email address to use */
1223 /* If there's a server e-mail address in the account, use that, otherwise template */
1224 fromemail = ast_strlen_zero(vmu->serveremail) ? template->serveremail : vmu->serveremail;
1225
1226 /* Find name to user for server e-mail */
1227 fromaddress = ast_strlen_zero(template->fromaddress) ? "" : template->fromaddress;
1228
1229 /* If needed, add hostname as domain */
1230 if (ast_strlen_zero(fromemail))
1231 fromemail = "asterisk";
1232
1233 if (strchr(fromemail, '@'))
1234 ast_copy_string(who, fromemail, sizeof(who));
1235 else {
1236 char host[MAXHOSTNAMELEN];
1237 gethostname(host, sizeof(host)-1);
1238 snprintf(who, sizeof(who), "%s@%s", fromemail, host);
1239 }
1240
1241 if (ast_strlen_zero(fromaddress)) {
1242 fprintf(p, "From: Asterisk PBX <%s>\n", who);
1243 } else {
1244 ast_debug(4, "Fromaddress template: %s\n", fromaddress);
1245 ast_str_substitute_variables(&str1, 0, chan, fromaddress);
1246 if (check_mime(ast_str_buffer(str1))) {
1247 int first_line = 1;
1248 char *ptr;
1249 ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
1250 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
1251 *ptr = '\0';
1252 fprintf(p, "%s %s\n", first_line ? "From:" : "", ast_str_buffer(str2));
1253 first_line = 0;
1254 /* Substring is smaller, so this will never grow */
1255 ast_str_set(&str2, 0, "%s", ptr + 1);
1256 }
1257 fprintf(p, "%s %s <%s>\n", first_line ? "From:" : "", ast_str_buffer(str2), who);
1258 } else {
1259 fprintf(p, "From: %s <%s>\n", ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
1260 }
1261 }
1262
1263 fprintf(p, "Message-ID: <Asterisk-%u-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
1264
1265 if (ast_strlen_zero(vmu->email)) {
1266 snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
1267 } else {
1268 ast_copy_string(email, vmu->email, sizeof(email));
1269 }
1270
1271 if (check_mime(vmu->fullname)) {
1272 int first_line = 1;
1273 char *ptr;
1274 ast_str_encode_mime(&str2, 0, template->charset, vmu->fullname, strlen("To: "), strlen(email) + 3);
1275 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
1276 *ptr = '\0';
1277 fprintf(p, "%s %s\n", first_line ? "To:" : "", ast_str_buffer(str2));
1278 first_line = 0;
1279 /* Substring is smaller, so this will never grow */
1280 ast_str_set(&str2, 0, "%s", ptr + 1);
1281 }
1282 fprintf(p, "%s %s <%s>\n", first_line ? "To:" : "", ast_str_buffer(str2), email);
1283 } else {
1284 fprintf(p, "To: %s <%s>\n", ast_str_quote(&str2, 0, vmu->fullname), email);
1285 }
1286
1287 if (!ast_strlen_zero(template->subject)) {
1288 ast_str_substitute_variables(&str1, 0, chan, template->subject);
1289 if (check_mime(ast_str_buffer(str1))) {
1290 int first_line = 1;
1291 char *ptr;
1292 ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("Subject: "), 0);
1293 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
1294 *ptr = '\0';
1295 fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
1296 first_line = 0;
1297 /* Substring is smaller, so this will never grow */
1298 ast_str_set(&str2, 0, "%s", ptr + 1);
1299 }
1300 fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
1301 } else {
1302 fprintf(p, "Subject: %s\n", ast_str_buffer(str1));
1303 }
1304 } else {
1305 fprintf(p, "Subject: New message in mailbox %s@%s\n", vmu->username, vmu->domain);
1306 ast_debug(1, "Using default subject for this email \n");
1307 }
1308
1309 if (DEBUG_ATLEAST(3))
1310 fprintf(p, "X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->username, vmu->domain);
1311 fprintf(p, "MIME-Version: 1.0\n");
1312
1313 /* Something unique. */
1314 snprintf(bound, sizeof(bound), "voicemail_%s%d%u", vmu->username, (int)getpid(), (unsigned int)ast_random());
1315
1316 fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
1317
1318 fprintf(p, "--%s\n", bound);
1319 fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", template->charset);
1320 if (!ast_strlen_zero(template->body)) {
1321 ast_str_substitute_variables(&str1, 0, chan, template->body);
1322 ast_debug(3, "Message now: %s\n-----\n", ast_str_buffer(str1));
1323 fprintf(p, "%s\n", ast_str_buffer(str1));
1324 } else {
1325 fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
1326 "in mailbox %s from %s, on %s so you might\n"
1327 "want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname,
1328 dur, vmu->username, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
1329 ast_debug(3, "Using default message body (no template)\n-----\n");
1330 }
1331 /* Eww. We want formats to tell us their own MIME type */
1332 if (template->attachment) {
1333 char *ctype = "audio/x-";
1334 ast_debug(3, "Attaching file to message: %s\n", fname);
1335 if (!strcasecmp(format, "ogg"))
1336 ctype = "application/";
1337
1338 fprintf(p, "--%s\n", bound);
1339 fprintf(p, "Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
1340 fprintf(p, "Content-Transfer-Encoding: base64\n");
1341 fprintf(p, "Content-Description: Voicemail sound attachment.\n");
1342 fprintf(p, "Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter : "", format);
1343
1345 fprintf(p, "\n\n--%s--\n.\n", bound);
1346 }
1347 fclose(p);
1348
1349 chan = ast_channel_unref(chan);
1350
1351 if (file_to_delete && dir_to_delete) {
1352 /* We can't delete these files ourselves because the mail command will execute in
1353 the background and we'll end up deleting them out from under it. */
1354 res = snprintf(mail_cmd_buffer, sizeof(mail_cmd_buffer),
1355 "( %s < %s ; rm -f %s %s ; rmdir %s ) &",
1356 global_mailcmd, tmp, tmp, file_to_delete, dir_to_delete);
1357 } else {
1358 res = snprintf(mail_cmd_buffer, sizeof(mail_cmd_buffer),
1359 "( %s < %s ; rm -f %s ) &",
1361 }
1362
1363 if (res < sizeof(mail_cmd_buffer)) {
1364 file_to_delete = dir_to_delete = NULL;
1365 } else {
1366 ast_log(LOG_ERROR, "Could not send message, command line too long\n");
1367 res = -1;
1368 goto out;
1369 }
1370
1371 ast_safe_system(mail_cmd_buffer);
1372 ast_debug(1, "Sent message to %s with command '%s'%s\n", vmu->email, global_mailcmd, template->attachment ? " - (media attachment)" : "");
1373 ast_debug(3, "Actual command used: %s\n", mail_cmd_buffer);
1374
1375 res = 0;
1376
1377out:
1378 if (file_to_delete) {
1379 unlink(file_to_delete);
1380 }
1381
1382 if (dir_to_delete) {
1383 rmdir(dir_to_delete);
1384 }
1385
1386 return res;
1387}
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)
Definition: app_minivm.c:869
static const char * ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
Definition: app_minivm.c:1081
static int check_mime(const char *str)
Definition: app_minivm.c:1011
#define EOL
Definition: app_minivm.c:544
static const char * ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
Definition: app_minivm.c:1040
static const char type[]
Definition: chan_ooh323.c:109
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
char * mkdtemp(char *template_s)
#define DEBUG_ATLEAST(level)
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
static char email[80]
Definition: pbx_dundi.c:206
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
Main Channel structure associated with a channel.
char name[80]
Definition: app_minivm.c:638
char fromaddress[100]
Definition: app_minivm.c:640
char dateformat[80]
Definition: app_minivm.c:645
char charset[32]
Definition: app_minivm.c:643
FILE * out
Definition: utils/frame.c:33
long int ast_random(void)
Definition: utils.c:2312
int ast_base64_encode_file_path(const char *filename, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.
Definition: utils.c:702

References ast_base64_encode_file_path(), ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log, ast_random(), ast_safe_system(), ast_str_buffer(), ast_str_create, ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strftime(), ast_strlen_zero(), ast_tvnow(), check_mime(), DEBUG_ATLEAST, minivm_account::domain, minivm_account::email, email, EOL, errno, minivm_template::fromaddress, minivm_account::fullname, global_mailcmd, minivm_template::list, LOG_ERROR, LOG_WARNING, MAXHOSTNAMELEN, mkdtemp(), MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_zone::name, NULL, out, minivm_account::pager, PATH_MAX, prep_email_sub_vars(), RAII_VAR, minivm_account::serveremail, minivm_zone::timezone, tmp(), type, minivm_account::username, minivm_account::volgain, and minivm_account::zonetag.

Referenced by notify_new_message().

◆ timezone_add()

static int timezone_add ( const char *  zonename,
const char *  config 
)
static

Add time zone to memory list.

Definition at line 2556 of file app_minivm.c.

2557{
2558 struct minivm_zone *newzone;
2559 char *msg_format, *timezone_str;
2560
2561 newzone = ast_calloc(1, sizeof(*newzone));
2562 if (newzone == NULL)
2563 return 0;
2564
2566
2567 timezone_str = strsep(&msg_format, "|");
2568 if (!msg_format) {
2569 ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
2570 ast_free(newzone);
2571 return 0;
2572 }
2573
2574 ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
2575 ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
2576 ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
2577
2581
2583
2584 return 0;
2585}
static const char config[]
Definition: chan_ooh323.c:111

References ast_calloc, ast_copy_string(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_strdupa, config, global_stats, minivm_template::list, LOG_WARNING, minivm_zone::msg_format, minivm_zone::name, NULL, strsep(), minivm_zone::timezone, and minivm_stats::timezones.

Referenced by load_config().

◆ timezone_destroy_list()

static void timezone_destroy_list ( void  )
static

Clear list of timezones.

Definition at line 2544 of file app_minivm.c.

2545{
2546 struct minivm_zone *this;
2547
2549 while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list)))
2550 free_zone(this);
2551
2553}
static void free_zone(struct minivm_zone *z)
Free Mini Voicemail timezone.
Definition: app_minivm.c:2538

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, free_zone(), and minivm_template::list.

Referenced by load_config(), and unload_module().

◆ unload_module()

static int unload_module ( void  )
static

Unload mini voicemail module.

Definition at line 3422 of file app_minivm.c.

3423{
3424 int res;
3425
3432
3436
3437 message_destroy_list(); /* Destroy list of voicemail message templates */
3438 timezone_destroy_list(); /* Destroy list of timezones */
3439 vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
3440
3441 return res;
3442}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

References app_minivm_accmess, app_minivm_delete, app_minivm_greet, app_minivm_mwi, app_minivm_notify, app_minivm_record, 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().

◆ vm_delete()

static int vm_delete ( char *  file)
static

Definition at line 1497 of file app_minivm.c.

1498{
1499 int res;
1500
1501 ast_debug(1, "Deleting voicemail file %s\n", file);
1502
1503 res = unlink(file); /* Remove the meta data file */
1504 res |= ast_filedelete(file, NULL); /* remove the media file */
1505 return res;
1506}

References ast_debug, ast_filedelete(), make_ari_stubs::file, and NULL.

Referenced by minivm_delete_exec(), and play_record_review().

◆ vm_lock_path()

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 3153 of file app_minivm.c.

3154{
3155 switch (ast_lock_path(path)) {
3156 case AST_LOCK_TIMEOUT:
3157 return -1;
3158 default:
3159 return 0;
3160 }
3161}
@ AST_LOCK_TIMEOUT
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2604

References ast_lock_path(), and AST_LOCK_TIMEOUT.

Referenced by access_counter_file().

◆ vmaccounts_destroy_list()

static void vmaccounts_destroy_list ( void  )
static

Definition at line 922 of file app_minivm.c.

923{
924 struct minivm_account *this;
926 while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list)))
927 ast_free(this);
929}

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and minivm_template::list.

Referenced by load_config(), and unload_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
static

Definition at line 3450 of file app_minivm.c.

◆ app_minivm_accmess

char* app_minivm_accmess = "MinivmAccMess"
static

Definition at line 569 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_delete

char* app_minivm_delete = "MinivmDelete"
static

Definition at line 568 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_greet

char* app_minivm_greet = "MinivmGreet"
static

Definition at line 566 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_mwi

char* app_minivm_mwi = "MinivmMWI"
static

Definition at line 570 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_notify

char* app_minivm_notify = "MinivmNotify"
static

Definition at line 567 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_record

char* app_minivm_record = "MinivmRecord"
static

Definition at line 565 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 3450 of file app_minivm.c.

◆ cli_minivm

struct ast_cli_entry cli_minivm[]
static

CLI commands for Mini-voicemail.

Definition at line 3347 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ default_vmformat

char default_vmformat[80]
static

◆ global_externnotify

char global_externnotify[160]
static

External notification application

Definition at line 695 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and run_externnotify().

◆ global_logfile

char global_logfile[PATH_MAX]
static

Global log file for messages

Definition at line 696 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), and load_config().

◆ global_mailcmd

char global_mailcmd[160]
static

Configurable mail cmd

Definition at line 694 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and sendmail().

◆ global_maxgreet

int global_maxgreet
static

Maximum length of prompts

Definition at line 692 of file app_minivm.c.

Referenced by apply_general_options(), load_config(), and minivm_accmess_exec().

◆ global_maxsilence

int global_maxsilence
static

Maximum silence during recording

Definition at line 691 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and play_record_review().

◆ global_saydurationminfo

int global_saydurationminfo
static

Definition at line 700 of file app_minivm.c.

Referenced by load_config().

◆ global_silencethreshold

int global_silencethreshold = 128
static

◆ global_stats

struct minivm_stats global_stats
static

Statistics for voicemail.

Definition at line 682 of file app_minivm.c.

Referenced by create_vmaccount(), handle_minivm_show_stats(), leave_voicemail(), load_config(), message_template_build(), and timezone_add().

◆ global_vmmaxmessage

int global_vmmaxmessage
static

Maximum duration of message

Definition at line 690 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), leave_voicemail(), and load_config().

◆ global_vmminmessage

int global_vmminmessage
static

Minimum duration of messages

Definition at line 689 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), leave_voicemail(), and load_config().

◆ global_volgain

double global_volgain
static

Volume gain for voicmemail via e-mail

Definition at line 702 of file app_minivm.c.

Referenced by populate_defaults().

◆ globalflags

struct ast_flags globalflags = {0}
static

Global voicemail flags

Definition at line 699 of file app_minivm.c.

Referenced by apply_general_options(), handle_minivm_show_settings(), load_config(), and populate_defaults().

◆ message_templates

struct message_templates message_templates = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ minivm_accmess_options

const 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 600 of file app_minivm.c.

Referenced by minivm_accmess_exec().

◆ minivm_account_function

struct ast_custom_function minivm_account_function
static
Initial value:
= {
.name = "MINIVMACCOUNT",
}
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
Definition: app_minivm.c:3076

Definition at line 3362 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ minivm_accounts

struct minivm_accounts minivm_accounts = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ minivm_app_options

const 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 593 of file app_minivm.c.

Referenced by minivm_greet_exec(), and minivm_record_exec().

◆ minivm_counter_function

struct ast_custom_function minivm_counter_function
static
Initial value:
= {
.name = "MINIVMCOUNTER",
}
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
Definition: app_minivm.c:3223
static int minivm_counter_func_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
${MINIVMCOUNTER()} Dialplan function - changes counter data
Definition: app_minivm.c:3276

Definition at line 3356 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ minivm_zones

struct minivm_zones minivm_zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ minivmlock

ast_mutex_t minivmlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Lock to protect voicemail system

Definition at line 684 of file app_minivm.c.

Referenced by load_config().

◆ minivmlogfile

FILE* minivmlogfile
static

The minivm log file

Definition at line 687 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

◆ minivmloglock

ast_mutex_t minivmloglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Lock to protect voicemail system log file

Definition at line 685 of file app_minivm.c.

Referenced by leave_voicemail().

◆ MVM_SPOOL_DIR

char MVM_SPOOL_DIR[PATH_MAX]
static