Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 configuration. 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 580 of file app_minivm.c.

◆ DEFAULT_CHARSET

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 734 of file app_minivm.c.

◆ DEFAULT_DATEFORMAT

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

Definition at line 733 of file app_minivm.c.

◆ EOL

#define EOL   "\r\n"

Definition at line 571 of file app_minivm.c.

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

Definition at line 576 of file app_minivm.c.

◆ FALSE

#define FALSE   0

Definition at line 554 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 573 of file app_minivm.c.

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 574 of file app_minivm.c.

◆ MVM_ALLOCED

#define MVM_ALLOCED   (1 << 13)

Definition at line 564 of file app_minivm.c.

◆ MVM_ENVELOPE

#define MVM_ENVELOPE   (1 << 4)

Definition at line 562 of file app_minivm.c.

◆ MVM_OPERATOR

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

Definition at line 559 of file app_minivm.c.

◆ MVM_PBXSKIP

#define MVM_PBXSKIP   (1 << 9)

Definition at line 563 of file app_minivm.c.

◆ MVM_REALTIME

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 560 of file app_minivm.c.

◆ MVM_REVIEW

#define MVM_REVIEW   (1 << 0)

Review message

Definition at line 558 of file app_minivm.c.

◆ MVM_SVMAIL

#define MVM_SVMAIL   (1 << 3)

Definition at line 561 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 568 of file app_minivm.c.

◆ SOUND_INTRO

#define SOUND_INTRO   "vm-intro"

Definition at line 570 of file app_minivm.c.

◆ TRUE

#define TRUE   1

Definition at line 551 of file app_minivm.c.

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 579 of file app_minivm.c.

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0700

Definition at line 577 of file app_minivm.c.

Enumeration Type Documentation

◆ minivm_option_args

Enumerator
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 610 of file app_minivm.c.

610 {
613};
@ OPT_ARG_RECORDGAIN
Definition: app_minivm.c:611
@ OPT_ARG_ARRAY_SIZE
Definition: app_minivm.c:612

◆ minivm_option_flags

Enumerator
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 601 of file app_minivm.c.

601 {
602 OPT_SILENT = (1 << 0),
603 OPT_BUSY_GREETING = (1 << 1),
604 OPT_UNAVAIL_GREETING = (1 << 2),
605 OPT_TEMP_GREETING = (1 << 3),
606 OPT_NAME_GREETING = (1 << 4),
607 OPT_RECORDGAIN = (1 << 5),
608};
@ OPT_NAME_GREETING
Definition: app_minivm.c:606
@ OPT_TEMP_GREETING
Definition: app_minivm.c:605
@ OPT_BUSY_GREETING
Definition: app_minivm.c:603
@ OPT_RECORDGAIN
Definition: app_minivm.c:607
@ OPT_UNAVAIL_GREETING
Definition: app_minivm.c:604
@ OPT_SILENT
Definition: app_minivm.c:602

◆ mvm_messagetype

Message types for notification.

Enumerator
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 583 of file app_minivm.c.

583 {
586 /* For trunk: MVM_MESSAGE_JABBER, */
587};
@ MVM_MESSAGE_EMAIL
Definition: app_minivm.c:584
@ MVM_MESSAGE_PAGE
Definition: app_minivm.c:585

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3477 of file app_minivm.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3477 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 3197 of file app_minivm.c.

3198{
3199 char filename[BUFSIZ];
3200 char readbuf[BUFSIZ];
3201 FILE *counterfile;
3202 int old = 0, counter = 0;
3203
3204 /* Lock directory */
3205 if (vm_lock_path(directory)) {
3206 return -1; /* Could not lock directory */
3207 }
3208 snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
3209 if (operand != 1) {
3210 counterfile = fopen(filename, "r");
3211 if (counterfile) {
3212 if(fgets(readbuf, sizeof(readbuf), counterfile)) {
3213 ast_debug(3, "Read this string from counter file: %s\n", readbuf);
3214 old = counter = atoi(readbuf);
3215 }
3216 fclose(counterfile);
3217 }
3218 }
3219 switch (operand) {
3220 case 0: /* Read only */
3221 ast_unlock_path(directory);
3222 ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
3223 return counter;
3224 break;
3225 case 1: /* Set new value */
3226 counter = value;
3227 break;
3228 case 2: /* Change value */
3229 counter += value;
3230 if (counter < 0) /* Don't allow counters to fall below zero */
3231 counter = 0;
3232 break;
3233 }
3234
3235 /* Now, write the new value to the file */
3236 counterfile = fopen(filename, "w");
3237 if (!counterfile) {
3238 ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
3239 ast_unlock_path(directory);
3240 return -1; /* Could not open file for writing */
3241 }
3242 fprintf(counterfile, "%d\n\n", counter);
3243 fclose(counterfile);
3244 ast_unlock_path(directory);
3245 ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
3246 return counter;
3247}
static int vm_lock_path(const char *path)
lock directory
Definition: app_minivm.c:3180
#define ast_log
Definition: astobj2.c:42
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2630
#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 2682 of file app_minivm.c.

2683{
2684 int error = 0;
2685
2686 while (var) {
2687 /* Mail command */
2688 if (!strcmp(var->name, "mailcmd")) {
2689 ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
2690 } else if (!strcmp(var->name, "maxgreet")) {
2691 global_maxgreet = atoi(var->value);
2692 } else if (!strcmp(var->name, "maxsilence")) {
2693 global_maxsilence = atoi(var->value);
2694 if (global_maxsilence > 0)
2695 global_maxsilence *= 1000;
2696 } else if (!strcmp(var->name, "logfile")) {
2697 if (!ast_strlen_zero(var->value) ) {
2698 if(*(var->value) == '/')
2700 else
2701 snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
2702 }
2703 } else if (!strcmp(var->name, "externnotify")) {
2704 /* External voicemail notify application */
2706 } else if (!strcmp(var->name, "silencethreshold") || !strcmp(var->name, "silencetreshold")) {
2707 /* Silence treshold */
2708 global_silencethreshold = atoi(var->value);
2709 } else if (!strcmp(var->name, "maxmessage")) {
2710 int x;
2711 if (sscanf(var->value, "%30d", &x) == 1) {
2713 } else {
2714 error ++;
2715 ast_log(LOG_WARNING, "Invalid max message time length\n");
2716 }
2717 } else if (!strcmp(var->name, "minmessage")) {
2718 int x;
2719 if (sscanf(var->value, "%30d", &x) == 1) {
2722 ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
2723 } else {
2724 error ++;
2725 ast_log(LOG_WARNING, "Invalid min message time length\n");
2726 }
2727 } else if (!strcmp(var->name, "format")) {
2729 } else if (!strcmp(var->name, "review")) {
2731 } else if (!strcmp(var->name, "operator")) {
2733 }
2734 var = var->next;
2735 }
2736 return error;
2737}
static int global_maxsilence
Definition: app_minivm.c:718
static char default_vmformat[80]
Definition: app_minivm.c:724
#define MVM_REVIEW
Definition: app_minivm.c:558
static struct ast_flags globalflags
Definition: app_minivm.c:726
static int global_maxgreet
Definition: app_minivm.c:719
static int global_vmmaxmessage
Definition: app_minivm.c:717
static char global_mailcmd[160]
Definition: app_minivm.c:721
static int global_silencethreshold
Definition: app_minivm.c:720
#define MVM_OPERATOR
Definition: app_minivm.c:559
static char global_externnotify[160]
Definition: app_minivm.c:722
static int global_vmminmessage
Definition: app_minivm.c:716
static char global_logfile[PATH_MAX]
Definition: app_minivm.c:723
#define var
Definition: ast_expr2f.c:605
#define LOG_WARNING
const char * ast_config_AST_LOG_DIR
Definition: options.c:160
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 3477 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 1067 of file app_minivm.c.

1068{
1069 struct ast_str *tmp = ast_str_alloca(80);
1070 int first_section = 1;
1071
1073 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
1074 for (; *start; start++) {
1075 int need_encoding = 0;
1076 if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
1077 need_encoding = 1;
1078 }
1079 if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
1080 (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
1081 (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
1082 (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
1083 /* Start new line */
1084 ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
1085 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
1086 first_section = 0;
1087 }
1088 if (need_encoding && *start == ' ') {
1089 ast_str_append(&tmp, -1, "_");
1090 } else if (need_encoding) {
1091 ast_str_append(&tmp, -1, "=%hhX", *start);
1092 } else {
1093 ast_str_append(&tmp, -1, "%c", *start);
1094 }
1095 }
1096 ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
1097 return ast_str_buffer(*end);
1098}
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(), and end.

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

1109{
1110 const char *ptr;
1111
1112 /* We're only ever passing 0 to maxlen, so short output isn't possible */
1113 ast_str_set(buf, maxlen, "\"");
1114 for (ptr = from; *ptr; ptr++) {
1115 if (*ptr == '"' || *ptr == '\\') {
1116 ast_str_append(buf, maxlen, "\\%c", *ptr);
1117 } else {
1118 ast_str_append(buf, maxlen, "%c", *ptr);
1119 }
1120 }
1121 ast_str_append(buf, maxlen, "\"");
1122
1123 return ast_str_buffer(*buf);
1124}
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 1432 of file app_minivm.c.

1433{
1434 struct stat filestat;
1435 make_dir(dest, len, domain, username, folder ? folder : "");
1436 if (stat(dest, &filestat)== -1)
1437 return FALSE;
1438 else
1439 return TRUE;
1440}
static int make_dir(char *dest, int len, const char *domain, const char *username, const char *folder)
Definition: app_minivm.c:1418
#define TRUE
Definition: app_minivm.c:551
#define FALSE
Definition: app_minivm.c:554
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 1038 of file app_minivm.c.

1039{
1040 for (; *str; str++) {
1041 if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
1042 return 1;
1043 }
1044 }
1045 return 0;
1046}
const char * str
Definition: app_jack.c:150

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

2924{
2925 int which = 0;
2926 int wordlen;
2927 struct minivm_account *vmu;
2928 const char *domain = "";
2929
2930 /* 0 - minivm; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
2931 if (pos > 4)
2932 return NULL;
2933 wordlen = strlen(word);
2935 if (!strncasecmp(word, vmu->domain, wordlen)) {
2936 if (domain && strcmp(domain, vmu->domain) && ++which > state)
2937 return ast_strdup(vmu->domain);
2938 /* ignore repeated domains ? */
2939 domain = vmu->domain;
2940 }
2941 }
2942 return NULL;
2943}
#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:633

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

1452{
1453 int res;
1454 make_dir(dest, len, domain, username, folder);
1455 if ((res = ast_mkdir(dest, 0777))) {
1456 ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
1457 return -1;
1458 }
1459 ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
1460 return 0;
1461}
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 2470 of file app_minivm.c.

2471{
2472 struct minivm_account *vmu;
2473 char *domain;
2474 char *username;
2475 char accbuf[BUFSIZ];
2476
2477 ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
2478
2479 ast_copy_string(accbuf, name, sizeof(accbuf));
2480 username = accbuf;
2481 domain = strchr(accbuf, '@');
2482 if (domain) {
2483 *domain = '\0';
2484 domain++;
2485 }
2486 if (ast_strlen_zero(domain)) {
2487 ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
2488 return 0;
2489 }
2490
2491 ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
2492
2493 /* Allocate user account */
2494 vmu = ast_calloc(1, sizeof(*vmu));
2495 if (!vmu)
2496 return 0;
2497
2498 ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
2499 ast_copy_string(vmu->username, username, sizeof(vmu->username));
2500
2501 populate_defaults(vmu);
2502
2503 ast_debug(3, "...Configuring account %s\n", name);
2504
2505 while (var) {
2506 ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
2507 if (!strcasecmp(var->name, "serveremail")) {
2508 ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
2509 } else if (!strcasecmp(var->name, "email")) {
2510 ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
2511 } else if (!strcasecmp(var->name, "accountcode")) {
2512 ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
2513 } else if (!strcasecmp(var->name, "pincode")) {
2514 ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
2515 } else if (!strcasecmp(var->name, "domain")) {
2516 ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
2517 } else if (!strcasecmp(var->name, "language")) {
2518 ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
2519 } else if (!strcasecmp(var->name, "timezone")) {
2520 ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
2521 } else if (!strcasecmp(var->name, "externnotify")) {
2522 ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
2523 } else if (!strcasecmp(var->name, "etemplate")) {
2524 ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
2525 } else if (!strcasecmp(var->name, "ptemplate")) {
2526 ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
2527 } else if (!strcasecmp(var->name, "fullname")) {
2528 ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
2529 } else if (!strcasecmp(var->name, "setvar")) {
2530 char *varval;
2531 char varname[strlen(var->value) + 1];
2532 struct ast_variable *tmpvar;
2533
2534 strcpy(varname, var->value); /* safe */
2535 if ((varval = strchr(varname, '='))) {
2536 *varval = '\0';
2537 varval++;
2538 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
2539 tmpvar->next = vmu->chanvars;
2540 vmu->chanvars = tmpvar;
2541 }
2542 }
2543 } else if (!strcasecmp(var->name, "pager")) {
2544 ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
2545 } else if (!strcasecmp(var->name, "volgain")) {
2546 sscanf(var->value, "%30lf", &vmu->volgain);
2547 } else {
2548 ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
2549 }
2550 var = var->next;
2551 }
2552 ast_debug(3, "...Linking account %s\n", name);
2553
2557
2559
2560 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)" : "");
2561 return 0;
2562}
static void populate_defaults(struct minivm_account *vmu)
Definition: app_minivm.c:925
static struct minivm_stats global_stats
Statistics for voicemail.
Definition: app_minivm.c:709
#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:650
char serveremail[80]
Definition: app_minivm.c:640
char pager[80]
Definition: app_minivm.c:638
char zonetag[80]
Definition: app_minivm.c:643
char username[AST_MAX_CONTEXT]
Definition: app_minivm.c:632
char ptemplate[80]
Definition: app_minivm.c:648
double volgain
Definition: app_minivm.c:651
char externnotify[160]
Definition: app_minivm.c:641
char email[80]
Definition: app_minivm.c:637
char fullname[120]
Definition: app_minivm.c:636
char etemplate[80]
Definition: app_minivm.c:647
char language[MAX_LANGUAGE]
Definition: app_minivm.c:642
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: app_minivm.c:639
char pincode[10]
Definition: app_minivm.c:635
int voicemailaccounts
Definition: app_minivm.c:699

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

962{
963 struct minivm_account *vmu = NULL, *cur;
964
965
967 ast_log(LOG_NOTICE, "No username or domain? \n");
968 return NULL;
969 }
970 ast_debug(3, "Looking for voicemail user %s in domain %s\n", username, domain);
971
974 /* Is this the voicemail account we're looking for? */
975 if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
976 break;
977 }
979
980 if (cur) {
981 ast_debug(3, "Found account for %s@%s\n", username, domain);
982 vmu = cur;
983
984 } else
986
987 if (createtemp && !vmu) {
988 /* Create a temporary user, send e-mail and be gone */
989 vmu = mvm_user_alloc();
991 if (vmu) {
992 ast_copy_string(vmu->username, username, sizeof(vmu->username));
993 ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
994 ast_debug(1, "Created temporary account\n");
995 }
996
997 }
998 return vmu;
999}
static struct minivm_account * mvm_user_alloc(void)
Definition: app_minivm.c:934
#define MVM_ALLOCED
Definition: app_minivm.c:564
static struct minivm_account * find_user_realtime(const char *domain, const char *username)
Definition: app_minivm.c:1005
#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 1005 of file app_minivm.c.

1006{
1007 struct ast_variable *var;
1008 struct minivm_account *retval;
1009 char name[MAXHOSTNAMELEN];
1010
1011 retval = mvm_user_alloc();
1012 if (!retval)
1013 return NULL;
1014
1015 if (username)
1016 ast_copy_string(retval->username, username, sizeof(retval->username));
1017
1018 populate_defaults(retval);
1019 var = ast_load_realtime("minivm", "username", username, "domain", domain, SENTINEL);
1020
1021 if (!var) {
1022 ast_free(retval);
1023 return NULL;
1024 }
1025
1026 snprintf(name, sizeof(name), "%s@%s", username, domain);
1028
1030 return retval;
1031}
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:2470
#define ast_free(a)
Definition: astmm.h:180
#define SENTINEL
Definition: compiler.h:87
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3726
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(), SENTINEL, TRUE, minivm_account::username, 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 2565 of file app_minivm.c.

2566{
2567 ast_free(z);
2568}

References ast_free.

Referenced by timezone_destroy_list().

◆ get_date()

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

Definition at line 871 of file app_minivm.c.

872{
873 struct ast_tm tm;
874 struct timeval now = ast_tvnow();
875
876 ast_localtime(&now, &tm, NULL);
877 return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
878}
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 2882 of file app_minivm.c.

2883{
2884 struct minivm_template *this;
2885#define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
2886 int count = 0;
2887
2888 switch (cmd) {
2889 case CLI_INIT:
2890 e->command = "minivm list templates";
2891 e->usage =
2892 "Usage: minivm list templates\n"
2893 " Lists message templates for e-mail, paging and IM\n";
2894 return NULL;
2895 case CLI_GENERATE:
2896 return NULL;
2897 }
2898
2899 if (a->argc > 3)
2900 return CLI_SHOWUSAGE;
2901
2904 ast_cli(a->fd, "There are no message templates defined\n");
2906 return CLI_FAILURE;
2907 }
2908 ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
2909 ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
2911 ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name,
2912 S_OR(this->charset, "-"),
2913 S_OR(this->locale, "-"),
2914 this->attachment ? "Yes" : "No",
2915 S_OR(this->subject, "-"));
2916 count++;
2917 }
2919 ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
2920 return CLI_SUCCESS;
2921}
#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:678
char subject[100]
Definition: app_minivm.c:669
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 configuration.

Definition at line 3429 of file app_minivm.c.

3430{
3431
3432 switch (cmd) {
3433 case CLI_INIT:
3434 e->command = "minivm reload";
3435 e->usage =
3436 "Usage: minivm reload\n"
3437 " Reload mini-voicemail configuration and reset statistics\n";
3438 return NULL;
3439 case CLI_GENERATE:
3440 return NULL;
3441 }
3442
3443 reload();
3444 ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
3445 return CLI_SUCCESS;
3446}
static int reload(void)
Reload mini voicemail module.
Definition: app_minivm.c:3423

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

3032{
3033 switch (cmd) {
3034 case CLI_INIT:
3035 e->command = "minivm show settings";
3036 e->usage =
3037 "Usage: minivm show settings\n"
3038 " Display Mini-Voicemail general settings\n";
3039 return NULL;
3040 case CLI_GENERATE:
3041 return NULL;
3042 }
3043
3044 ast_cli(a->fd, "* Mini-Voicemail general settings\n");
3045 ast_cli(a->fd, " -------------------------------\n");
3046 ast_cli(a->fd, "\n");
3047 ast_cli(a->fd, " Mail command (shell): %s\n", global_mailcmd);
3048 ast_cli(a->fd, " Max silence: %d\n", global_maxsilence);
3049 ast_cli(a->fd, " Silence threshold: %d\n", global_silencethreshold);
3050 ast_cli(a->fd, " Max message length (secs): %d\n", global_vmmaxmessage);
3051 ast_cli(a->fd, " Min message length (secs): %d\n", global_vmminmessage);
3052 ast_cli(a->fd, " Default format: %s\n", default_vmformat);
3053 ast_cli(a->fd, " Extern notify (shell): %s\n", global_externnotify);
3054 ast_cli(a->fd, " Logfile: %s\n", global_logfile[0] ? global_logfile : "<disabled>");
3055 ast_cli(a->fd, " Operator exit: %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
3056 ast_cli(a->fd, " Message review: %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
3057
3058 ast_cli(a->fd, "\n");
3059 return CLI_SUCCESS;
3060}
#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 3063 of file app_minivm.c.

3064{
3065 struct ast_tm timebuf;
3066 char buf[BUFSIZ];
3067
3068 switch (cmd) {
3069
3070 case CLI_INIT:
3071 e->command = "minivm show stats";
3072 e->usage =
3073 "Usage: minivm show stats\n"
3074 " Display Mini-Voicemail counters\n";
3075 return NULL;
3076 case CLI_GENERATE:
3077 return NULL;
3078 }
3079
3080 ast_cli(a->fd, "* Mini-Voicemail statistics\n");
3081 ast_cli(a->fd, " -------------------------\n");
3082 ast_cli(a->fd, "\n");
3083 ast_cli(a->fd, " Voicemail accounts: %5d\n", global_stats.voicemailaccounts);
3084 ast_cli(a->fd, " Templates: %5d\n", global_stats.templates);
3085 ast_cli(a->fd, " Timezones: %5d\n", global_stats.timezones);
3086 if (global_stats.receivedmessages == 0) {
3087 ast_cli(a->fd, " Received messages since last reset: <none>\n");
3088 } else {
3089 ast_cli(a->fd, " Received messages since last reset: %d\n", global_stats.receivedmessages);
3091 ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
3092 ast_cli(a->fd, " Last received voicemail: %s\n", buf);
3093 }
3094 ast_localtime(&global_stats.reset, &timebuf, NULL);
3095 ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
3096 ast_cli(a->fd, " Last reset: %s\n", buf);
3097
3098 ast_cli(a->fd, "\n");
3099 return CLI_SUCCESS;
3100}
struct timeval lastreceived
Definition: app_minivm.c:705
int receivedmessages
Definition: app_minivm.c:704
struct timeval reset
Definition: app_minivm.c:703

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

2947{
2948 struct minivm_account *vmu;
2949#define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
2950 int count = 0;
2951
2952 switch (cmd) {
2953 case CLI_INIT:
2954 e->command = "minivm list accounts [for]";
2955 e->usage =
2956 "Usage: minivm list accounts [for <domain>]\n"
2957 " Lists all mailboxes currently set up\n";
2958 return NULL;
2959 case CLI_GENERATE:
2960 return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
2961 }
2962
2963 if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
2964 return CLI_SHOWUSAGE;
2965 if ((a->argc == 5) && strcmp(a->argv[3],"for"))
2966 return CLI_SHOWUSAGE;
2967
2970 ast_cli(a->fd, "There are no voicemail users currently defined\n");
2972 return CLI_FAILURE;
2973 }
2974 ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
2975 ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
2977 char tmp[256] = "";
2978 if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
2979 count++;
2980 snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
2981 ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, S_OR(vmu->etemplate, "-"),
2982 S_OR(vmu->ptemplate, "-"),
2983 S_OR(vmu->zonetag, "-"),
2984 S_OR(vmu->attachfmt, "-"),
2985 vmu->fullname);
2986 }
2987 }
2989 ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
2990 return CLI_SUCCESS;
2991}
#define HMSU_OUTPUT_FORMAT
static char * complete_minivm_show_users(const char *line, const char *word, int pos, int state)
Definition: app_minivm.c:2923
char attachfmt[80]
Definition: app_minivm.c:646

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

2995{
2996 struct minivm_zone *zone;
2997#define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
2998 char *res = CLI_SUCCESS;
2999
3000 switch (cmd) {
3001 case CLI_INIT:
3002 e->command = "minivm list zones";
3003 e->usage =
3004 "Usage: minivm list zones\n"
3005 " Lists zone message formats\n";
3006 return NULL;
3007 case CLI_GENERATE:
3008 return NULL;
3009 }
3010
3011 if (a->argc != e->args)
3012 return CLI_SHOWUSAGE;
3013
3016 ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
3017 ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
3019 ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
3020 }
3021 } else {
3022 ast_cli(a->fd, "There are no voicemail zones currently defined\n");
3023 res = CLI_FAILURE;
3024 }
3026
3027 return res;
3028}
#define HMSZ_OUTPUT_FORMAT
int args
This gets set in ast_cli_register()
Definition: cli.h:185
Voicemail time zones.
Definition: app_minivm.c:687
char msg_format[BUFSIZ]
Definition: app_minivm.c:690
char name[80]
Definition: app_minivm.c:688
char timezone[80]
Definition: app_minivm.c:689
struct minivm_zone::@40 list
The list of e-mail time zones.
Definition: app_minivm.c:695

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

1468{
1469 int res;
1470 char fn[PATH_MAX];
1471
1472 ast_debug(2, "Still preparing to play message ...\n");
1473
1474 snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
1475
1476 if (ast_fileexists(fn, NULL, NULL) > 0) {
1477 res = ast_streamfile(chan, fn, ast_channel_language(chan));
1478 if (res)
1479 return -1;
1480 res = ast_waitstream(chan, ecodes);
1481 if (res)
1482 return res;
1483 } else {
1484 int numericusername = 1;
1485 char *i = username;
1486
1487 ast_debug(2, "No personal prompts. Using default prompt set for language\n");
1488
1489 while (*i) {
1490 ast_debug(2, "Numeric? Checking %c\n", *i);
1491 if (!isdigit(*i)) {
1492 numericusername = FALSE;
1493 break;
1494 }
1495 i++;
1496 }
1497
1498 if (numericusername) {
1499 if (ast_streamfile(chan, "vm-theperson", ast_channel_language(chan)))
1500 return -1;
1501 if ((res = ast_waitstream(chan, ecodes)))
1502 return res;
1503
1504 res = ast_say_digit_str(chan, username, ecodes, ast_channel_language(chan));
1505 if (res)
1506 return res;
1507 } else {
1508 if (ast_streamfile(chan, "vm-theextensionis", ast_channel_language(chan)))
1509 return -1;
1510 if ((res = ast_waitstream(chan, ecodes)))
1511 return res;
1512 }
1513 }
1514
1515 res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", ast_channel_language(chan));
1516 if (res)
1517 return -1;
1518 res = ast_waitstream(chan, ecodes);
1519 return res;
1520}
static char MVM_SPOOL_DIR[PATH_MAX]
Definition: app_minivm.c:589
#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:1301
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1137
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1848
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:8264

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

1807{
1808 char tmptxtfile[PATH_MAX];
1809 char callerid[256];
1810 FILE *txt;
1811 int res = 0, txtdes;
1812 int duration = 0;
1813 int sound_duration = 0;
1814 char date[256];
1815 char tmpdir[PATH_MAX];
1816 char ext_context[256] = "";
1817 char fmt[80];
1818 char *domain;
1819 char tmp[256] = "";
1820 struct minivm_account *vmu;
1821 int userdir;
1822
1823 ast_copy_string(tmp, username, sizeof(tmp));
1824 username = tmp;
1825 domain = strchr(tmp, '@');
1826 if (domain) {
1827 *domain = '\0';
1828 domain++;
1829 }
1830
1831 if (!(vmu = find_account(domain, username, TRUE))) {
1832 /* We could not find user, let's exit */
1833 ast_log(LOG_ERROR, "Can't allocate temporary account for '%s@%s'\n", username, domain);
1834 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1835 return 0;
1836 }
1837
1838 /* Setup pre-file if appropriate */
1839 if (strcmp(vmu->domain, "localhost"))
1840 snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
1841 else
1842 ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
1843
1844 /* The meat of recording the message... All the announcements and beeps have been played*/
1845 if (ast_strlen_zero(vmu->attachfmt))
1846 ast_copy_string(fmt, default_vmformat, sizeof(fmt));
1847 else
1848 ast_copy_string(fmt, vmu->attachfmt, sizeof(fmt));
1849
1850 if (ast_strlen_zero(fmt)) {
1851 ast_log(LOG_WARNING, "No format for saving voicemail? Default %s\n", default_vmformat);
1852 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1853 return res;
1854 }
1855
1856 userdir = check_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
1857
1858 /* If we have no user directory, use generic temporary directory */
1859 if (!userdir) {
1860 create_dirpath(tmpdir, sizeof(tmpdir), "0000_minivm_temp", "mediafiles", "");
1861 ast_debug(3, "Creating temporary directory %s\n", tmpdir);
1862 }
1863
1864
1865 snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
1866
1867 /* XXX This file needs to be in temp directory */
1868 txtdes = mkstemp(tmptxtfile);
1869 if (txtdes < 0) {
1870 ast_log(LOG_ERROR, "Unable to create message file %s: %s\n", tmptxtfile, strerror(errno));
1871 res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
1872 if (!res)
1873 res = ast_waitstream(chan, "");
1874 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1875 return res;
1876 }
1877
1878 if (res >= 0) {
1879 /* Unless we're *really* silent, try to send the beep */
1880 res = ast_streamfile(chan, "beep", ast_channel_language(chan));
1881 if (!res)
1882 res = ast_waitstream(chan, "");
1883 }
1884
1885 /* OEJ XXX Maybe this can be turned into a log file? Hmm. */
1886 /* Store information */
1887 ast_debug(2, "Open file for metadata: %s\n", tmptxtfile);
1888
1889 res = play_record_review(chan, NULL, tmptxtfile, global_vmmaxmessage, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain);
1890
1891 txt = fdopen(txtdes, "w+");
1892 if (!txt) {
1893 ast_log(LOG_WARNING, "Error opening text file for output\n");
1894 } else {
1895 struct ast_tm tm;
1896 struct timeval now = ast_tvnow();
1897 char timebuf[30];
1898 char logbuf[BUFSIZ];
1899 get_date(date, sizeof(date));
1900 ast_localtime(&now, &tm, NULL);
1901 ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
1902
1903 ast_callerid_merge(callerid, sizeof(callerid),
1904 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
1905 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
1906 "Unknown");
1907 snprintf(logbuf, sizeof(logbuf),
1908 /* "Mailbox:domain:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
1909 "%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
1910 username,
1911 ast_channel_context(chan),
1912 ast_channel_exten(chan),
1914 ast_channel_name(chan),
1915 callerid,
1916 date,
1917 timebuf,
1918 duration,
1919 duration < global_vmminmessage ? "IGNORED" : "OK",
1920 vmu->accountcode
1921 );
1922 fprintf(txt, "%s", logbuf);
1923 if (minivmlogfile) {
1925 fprintf(minivmlogfile, "%s", logbuf);
1927 }
1928
1929 if (sound_duration < global_vmminmessage) {
1930 ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, global_vmminmessage);
1931 fclose(txt);
1932 ast_filedelete(tmptxtfile, NULL);
1933 unlink(tmptxtfile);
1934 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1935 return 0;
1936 }
1937 fclose(txt); /* Close log file */
1938 if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
1939 ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
1940 unlink(tmptxtfile);
1941 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
1942 if(ast_test_flag(vmu, MVM_ALLOCED))
1943 free_user(vmu);
1944 return 0;
1945 }
1946
1947 /* Set channel variables for the notify application */
1948 pbx_builtin_setvar_helper(chan, "MVM_FILENAME", tmptxtfile);
1949 snprintf(timebuf, sizeof(timebuf), "%d", duration);
1950 pbx_builtin_setvar_helper(chan, "MVM_DURATION", timebuf);
1951 pbx_builtin_setvar_helper(chan, "MVM_FORMAT", fmt);
1952
1953 }
1956#if 0
1957 /* Go ahead and delete audio files from system, they're not needed any more */
1958 if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
1959 ast_filedelete(tmptxtfile, NULL);
1960 /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
1961 ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
1962 }
1963#endif
1964
1965 if (res > 0)
1966 res = 0;
1967
1968 if(ast_test_flag(vmu, MVM_ALLOCED))
1969 free_user(vmu);
1970
1971 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
1972 return res;
1973}
static FILE * minivmlogfile
Definition: app_minivm.c:714
static void free_user(struct minivm_account *vmu)
Definition: app_minivm.c:883
static ast_mutex_t minivmloglock
Definition: app_minivm.c:712
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:1538
static int check_dirpath(char *dest, int len, char *domain, char *username, char *folder)
Definition: app_minivm.c:1432
static int create_dirpath(char *dest, int len, char *domain, char *username, char *folder)
Definition: app_minivm.c:1451
static struct minivm_account * find_account(const char *domain, const char *username, int createtemp)
Definition: app_minivm.c:961
static int get_date(char *s, int len)
Definition: app_minivm.c:871
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1273
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:1149
#define ast_verb(level,...)
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_lock(a)
Definition: lock.h:196
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:157
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, and TRUE.

Referenced by minivm_record_exec().

◆ load_config()

static int load_config ( int  reload)
static

Load minivoicemail configuration.

Definition at line 2740 of file app_minivm.c.

2741{
2742 struct ast_config *cfg;
2743 struct ast_variable *var;
2744 char *cat;
2745 const char *chanvar;
2746 int error = 0;
2747 struct minivm_template *template;
2748 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2749
2750 cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
2751 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2752 return 0;
2753 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2754 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
2755 return 0;
2756 }
2757
2759
2760 /* Destroy lists to reconfigure */
2761 message_destroy_list(); /* Destroy list of voicemail message templates */
2762 timezone_destroy_list(); /* Destroy list of timezones */
2763 vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
2764 ast_debug(2, "Destroyed memory objects...\n");
2765
2766 /* First, set some default settings */
2767 global_externnotify[0] = '\0';
2768 global_logfile[0] = '\0';
2769 global_vmmaxmessage = 2000;
2770 global_maxgreet = 2000;
2772 strcpy(global_mailcmd, SENDMAIL);
2778 /* Reset statistics */
2779 memset(&global_stats, 0, sizeof(global_stats));
2781
2783
2784 /* Make sure we could load configuration file */
2785 if (!cfg) {
2786 ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
2788 return 0;
2789 }
2790
2791 ast_debug(2, "Loaded configuration file, now parsing\n");
2792
2793 /* General settings */
2794
2795 cat = ast_category_browse(cfg, NULL);
2796 while (cat) {
2797 ast_debug(3, "Found configuration section [%s]\n", cat);
2798 if (!strcasecmp(cat, "general")) {
2799 /* Nothing right now */
2801 } else if (!strncasecmp(cat, "template-", 9)) {
2802 /* Template */
2803 char *name = cat + 9;
2804
2805 /* Now build and link template to list */
2807 } else {
2808 var = ast_variable_browse(cfg, cat);
2809 if (!strcasecmp(cat, "zonemessages")) {
2810 /* Timezones in this context */
2811 while (var) {
2812 timezone_add(var->name, var->value);
2813 var = var->next;
2814 }
2815 } else {
2816 /* Create mailbox from this */
2817 error += create_vmaccount(cat, var, FALSE);
2818 }
2819 }
2820 /* Find next section in configuration file */
2821 cat = ast_category_browse(cfg, cat);
2822 }
2823
2824 /* Configure the default email template */
2825 message_template_build("email-default", NULL);
2826 template = message_template_find("email-default");
2827
2828 /* Load date format config for voicemail mail */
2829 if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat")))
2830 ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
2831 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
2832 ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
2833 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
2834 ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2835 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaddress")))
2836 ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2837 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
2838 ast_copy_string(template->charset, chanvar, sizeof(template->charset));
2839 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject")))
2840 ast_copy_string(template->subject, chanvar, sizeof(template->subject));
2841 if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody")))
2842 template->body = message_template_parse_emailbody(chanvar);
2843 template->attachment = TRUE;
2844
2845 message_template_build("pager-default", NULL);
2846 template = message_template_find("pager-default");
2847 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
2848 ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
2849 if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
2850 ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2851 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
2852 ast_copy_string(template->charset, chanvar, sizeof(template->charset));
2853 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
2854 ast_copy_string(template->subject, chanvar,sizeof(template->subject));
2855 if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody")))
2856 template->body = message_template_parse_emailbody(chanvar);
2857 template->attachment = FALSE;
2858
2859 if (error)
2860 ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
2861
2863 ast_config_destroy(cfg);
2864
2865 /* Close log file if it's open and disabled */
2866 if(minivmlogfile)
2867 fclose(minivmlogfile);
2868
2869 /* Open log file if it's enabled */
2871 minivmlogfile = fopen(global_logfile, "a");
2872 if(!minivmlogfile)
2873 ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
2874 if (minivmlogfile)
2875 ast_debug(3, "Opened log file %s \n", global_logfile);
2876 }
2877
2878 return 0;
2879}
static void message_destroy_list(void)
Definition: app_minivm.c:860
static int apply_general_options(struct ast_variable *var)
Apply general configuration options.
Definition: app_minivm.c:2682
static void timezone_destroy_list(void)
Clear list of timezones.
Definition: app_minivm.c:2571
static int timezone_add(const char *zonename, const char *config)
Add time zone to memory list.
Definition: app_minivm.c:2583
#define VOICEMAIL_CONFIG
Definition: app_minivm.c:579
static char * message_template_parse_emailbody(const char *body)
Parse emailbody template from configuration file.
Definition: app_minivm.c:2655
static int message_template_build(const char *name, struct ast_variable *var)
Definition: app_minivm.c:775
#define SENDMAIL
Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail....
Definition: app_minivm.c:568
static void vmaccounts_destroy_list(void)
Definition: app_minivm.c:949
static int global_saydurationminfo
Definition: app_minivm.c:727
static struct minivm_template * message_template_find(const char *name)
Definition: app_minivm.c:838
static ast_mutex_t minivmlock
Definition: app_minivm.c:711
static char * chanvar
Definition: app_system.c:119
@ 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
@ CONFIG_FLAG_FILEUNCHANGED
#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:869
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
Structure used to handle boolean flags.
Definition: utils.h:199
structure for queuing ARI channel variable setting
Definition: control.c:711

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

3396{
3397 int res;
3398
3405
3408 if (res)
3409 return(res);
3410
3411 if ((res = load_config(0)))
3412 return(res);
3413
3415
3416 /* compute the location of the voicemail spool directory */
3417 snprintf(MVM_SPOOL_DIR, sizeof(MVM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
3418
3419 return res;
3420}
static int minivm_record_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2108
static int minivm_notify_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2030
static char * app_minivm_delete
Definition: app_minivm.c:595
static char * app_minivm_greet
Definition: app_minivm.c:593
static struct ast_custom_function minivm_account_function
Definition: app_minivm.c:3389
static int minivm_delete_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2334
static int minivm_mwi_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:1992
static int minivm_accmess_exec(struct ast_channel *chan, const char *data)
Record specific messages for voicemail account.
Definition: app_minivm.c:2372
static char * app_minivm_notify
Definition: app_minivm.c:594
static struct ast_cli_entry cli_minivm[]
CLI commands for Mini-voicemail.
Definition: app_minivm.c:3374
static char * app_minivm_record
Definition: app_minivm.c:592
static char * app_minivm_accmess
Definition: app_minivm.c:596
static int minivm_greet_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2161
static int load_config(int reload)
Load minivoicemail configuration.
Definition: app_minivm.c:2740
static struct ast_custom_function minivm_counter_function
Definition: app_minivm.c:3383
static char * app_minivm_mwi
Definition: app_minivm.c:597
#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:640
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:155
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
#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 1418 of file app_minivm.c.

1419{
1420 return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
1421}

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

861{
862 struct minivm_template *this;
864 while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) {
866 }
867
869}
static void message_template_free(struct minivm_template *template)
Definition: app_minivm.c:765
#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 775 of file app_minivm.c.

776{
777 struct minivm_template *template;
778 int error = 0;
779
780 template = message_template_create(name);
781 if (!template) {
782 ast_log(LOG_ERROR, "Out of memory, can't allocate message template object %s.\n", name);
783 return -1;
784 }
785
786 while (var) {
787 ast_debug(3, "Configuring template option %s = \"%s\" for template %s\n", var->name, var->value, name);
788 if (!strcasecmp(var->name, "fromaddress")) {
789 ast_copy_string(template->fromaddress, var->value, sizeof(template->fromaddress));
790 } else if (!strcasecmp(var->name, "fromemail")) {
791 ast_copy_string(template->serveremail, var->value, sizeof(template->serveremail));
792 } else if (!strcasecmp(var->name, "subject")) {
793 ast_copy_string(template->subject, var->value, sizeof(template->subject));
794 } else if (!strcasecmp(var->name, "locale")) {
795 ast_copy_string(template->locale, var->value, sizeof(template->locale));
796 } else if (!strcasecmp(var->name, "attachmedia")) {
797 template->attachment = ast_true(var->value);
798 } else if (!strcasecmp(var->name, "dateformat")) {
799 ast_copy_string(template->dateformat, var->value, sizeof(template->dateformat));
800 } else if (!strcasecmp(var->name, "charset")) {
801 ast_copy_string(template->charset, var->value, sizeof(template->charset));
802 } else if (!strcasecmp(var->name, "templatefile")) {
803 if (template->body)
804 ast_free(template->body);
805 template->body = message_template_parse_filebody(var->value);
806 if (!template->body) {
807 ast_log(LOG_ERROR, "Error reading message body definition file %s\n", var->value);
808 error++;
809 }
810 } else if (!strcasecmp(var->name, "messagebody")) {
811 if (template->body)
812 ast_free(template->body);
813 template->body = message_template_parse_emailbody(var->value);
814 if (!template->body) {
815 ast_log(LOG_ERROR, "Error parsing message body definition:\n %s\n", var->value);
816 error++;
817 }
818 } else {
819 ast_log(LOG_ERROR, "Unknown message template configuration option \"%s=%s\"\n", var->name, var->value);
820 error++;
821 }
822 var = var->next;
823 }
824 if (error)
825 ast_log(LOG_ERROR, "-- %d errors found parsing message template definition %s\n", error, name);
826
830
832
833 return error;
834}
static char * message_template_parse_filebody(const char *filename)
Read message template from file.
Definition: app_minivm.c:2615
static struct minivm_template * message_template_create(const char *name)
Definition: app_minivm.c:745

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

746{
747 struct minivm_template *template;
748
749 template = ast_calloc(1, sizeof(*template));
750 if (!template)
751 return NULL;
752
753 /* Set some defaults for templates */
754 ast_copy_string(template->name, name, sizeof(template->name));
755 ast_copy_string(template->dateformat, DEFAULT_DATEFORMAT, sizeof(template->dateformat));
756 ast_copy_string(template->charset, DEFAULT_CHARSET, sizeof(template->charset));
757 ast_copy_string(template->subject, "New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}", sizeof(template->subject));
758 template->attachment = TRUE;
759
760 return template;
761}
#define DEFAULT_DATEFORMAT
Definition: app_minivm.c:733
#define DEFAULT_CHARSET
Definition: app_minivm.c:734

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

839{
840 struct minivm_template *this, *res = NULL;
841
843 return NULL;
844
847 if (!strcasecmp(this->name, name)) {
848 res = this;
849 break;
850 }
851 }
853
854 return res;
855}

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

766{
767 if (template->body)
768 ast_free(template->body);
769
770 ast_free (template);
771}

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

2656{
2657 char *tmpread, *tmpwrite;
2658 char *emailbody = ast_strdup(configuration);
2659
2660 /* substitute strings \t and \n into the apropriate characters */
2661 tmpread = tmpwrite = emailbody;
2662 while ((tmpwrite = strchr(tmpread,'\\'))) {
2663 int len = strlen("\n");
2664 switch (tmpwrite[1]) {
2665 case 'n':
2666 memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2667 tmpwrite[0] = '\n';
2668 break;
2669 case 't':
2670 memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2671 tmpwrite[0] = '\t';
2672 break;
2673 default:
2674 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
2675 }
2676 tmpread = tmpwrite + len;
2677 }
2678 return emailbody;
2679}
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 2615 of file app_minivm.c.

2615 {
2616 char buf[BUFSIZ * 6];
2617 char readbuf[BUFSIZ];
2618 char filenamebuf[BUFSIZ];
2619 char *writepos;
2620 char *messagebody;
2621 FILE *fi;
2622 int lines = 0;
2623
2624 if (ast_strlen_zero(filename))
2625 return NULL;
2626 if (*filename == '/')
2627 ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
2628 else
2629 snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
2630
2631 if (!(fi = fopen(filenamebuf, "r"))) {
2632 ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
2633 return NULL;
2634 }
2635 writepos = buf;
2636 while (fgets(readbuf, sizeof(readbuf), fi)) {
2637 lines ++;
2638 if (writepos != buf) {
2639 *writepos = '\n'; /* Replace EOL with new line */
2640 writepos++;
2641 }
2642 ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
2643 writepos += strlen(readbuf) - 1;
2644 }
2645 fclose(fi);
2646 messagebody = ast_calloc(1, strlen(buf + 1));
2647 ast_copy_string(messagebody, buf, strlen(buf) + 1);
2648 ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
2649 ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
2650
2651 return messagebody;
2652}
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:152

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

2373{
2374 int argc = 0;
2375 char *argv[2];
2376 char filename[PATH_MAX];
2377 char tmp[PATH_MAX];
2378 char *domain;
2379 char *tmpptr = NULL;
2380 struct minivm_account *vmu;
2381 char *username;
2382 struct ast_flags flags = { 0 };
2383 char *opts[OPT_ARG_ARRAY_SIZE];
2384 int error = FALSE;
2385 char *message = NULL;
2386 char *prompt = NULL;
2387 int duration;
2388
2389 if (ast_strlen_zero(data)) {
2390 ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
2391 error = TRUE;
2392 } else {
2393 tmpptr = ast_strdupa((char *)data);
2394 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2395 }
2396
2397 if (argc <=1) {
2398 ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
2399 error = TRUE;
2400 }
2401 if (!error && strlen(argv[1]) > 1) {
2402 ast_log(LOG_ERROR, "MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
2403 error = TRUE;
2404 }
2405
2406 if (!error && ast_app_parse_options(minivm_accmess_options, &flags, opts, argv[1])) {
2407 ast_log(LOG_ERROR, "Can't parse option %s\n", argv[1]);
2408 error = TRUE;
2409 }
2410
2411 if (error) {
2412 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
2413 return -1;
2414 }
2415
2416 ast_copy_string(tmp, argv[0], sizeof(tmp));
2417 username = tmp;
2418 domain = strchr(tmp, '@');
2419 if (domain) {
2420 *domain = '\0';
2421 domain++;
2422 }
2423 if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
2424 ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2425 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
2426 return -1;
2427 }
2428
2429 if(!(vmu = find_account(domain, username, TRUE))) {
2430 /* We could not find user, let's exit */
2431 ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
2432 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
2433 return -1;
2434 }
2435
2436 /* Answer channel if it's not already answered */
2437 if (ast_channel_state(chan) != AST_STATE_UP)
2438 ast_answer(chan);
2439
2440 /* Here's where the action is */
2442 message = "busy";
2443 prompt = "vm-rec-busy";
2445 message = "unavailable";
2446 prompt = "vm-rec-unv";
2447 } else if (ast_test_flag(&flags, OPT_TEMP_GREETING)) {
2448 message = "temp";
2449 prompt = "vm-rec-temp";
2450 } else if (ast_test_flag(&flags, OPT_NAME_GREETING)) {
2451 message = "greet";
2452 prompt = "vm-rec-name";
2453 }
2454 snprintf(filename,sizeof(filename), "%s%s/%s/%s", MVM_SPOOL_DIR, vmu->domain, vmu->username, message);
2455 /* Maybe we should check the result of play_record_review ? */
2456 play_record_review(chan, prompt, filename, global_maxgreet, default_vmformat, 0, vmu, &duration, NULL, NULL, FALSE);
2457
2458 ast_debug(1, "Recorded new %s message in %s (duration %d)\n", message, filename, duration);
2459
2460 if(ast_test_flag(vmu, MVM_ALLOCED))
2461 free_user(vmu);
2462
2463 pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "SUCCESS");
2464
2465 /* Ok, we're ready to rock and roll. Return to dialplan */
2466 return 0;
2467}
static const struct ast_app_option minivm_accmess_options[128]
Definition: app_minivm.c:627
static struct ast_str * prompt
Definition: asterisk.c:2789
#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:2774
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:3066
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, 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 3103 of file app_minivm.c.

3104{
3105 struct minivm_account *vmu;
3106 char *username, *domain, *colname;
3107
3108 username = ast_strdupa(data);
3109
3110 if ((colname = strchr(username, ':'))) {
3111 *colname = '\0';
3112 colname++;
3113 } else {
3114 colname = "path";
3115 }
3116 if ((domain = strchr(username, '@'))) {
3117 *domain = '\0';
3118 domain++;
3119 }
3121 ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
3122 return 0;
3123 }
3124
3125 if (!(vmu = find_account(domain, username, TRUE)))
3126 return 0;
3127
3128 if (!strcasecmp(colname, "hasaccount")) {
3129 ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
3130 } else if (!strcasecmp(colname, "fullname")) {
3132 } else if (!strcasecmp(colname, "email")) {
3133 if (!ast_strlen_zero(vmu->email))
3134 ast_copy_string(buf, vmu->email, len);
3135 else
3136 snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
3137 } else if (!strcasecmp(colname, "pager")) {
3138 ast_copy_string(buf, vmu->pager, len);
3139 } else if (!strcasecmp(colname, "etemplate")) {
3140 if (!ast_strlen_zero(vmu->etemplate))
3142 else
3143 ast_copy_string(buf, "email-default", len);
3144 } else if (!strcasecmp(colname, "language")) {
3146 } else if (!strcasecmp(colname, "timezone")) {
3148 } else if (!strcasecmp(colname, "ptemplate")) {
3149 if (!ast_strlen_zero(vmu->ptemplate))
3151 else
3152 ast_copy_string(buf, "email-default", len);
3153 } else if (!strcasecmp(colname, "accountcode")) {
3155 } else if (!strcasecmp(colname, "pincode")) {
3157 } else if (!strcasecmp(colname, "path")) {
3158 check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
3159 } else { /* Look in channel variables */
3160 struct ast_variable *var;
3161
3162 for (var = vmu->chanvars ; var ; var = var->next)
3163 if (!strcmp(var->name, colname)) {
3164 ast_copy_string(buf, var->value, len);
3165 break;
3166 }
3167 }
3168
3169 if(ast_test_flag(vmu, MVM_ALLOCED))
3170 free_user(vmu);
3171
3172 return 0;
3173}

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

3251{
3252 char *username, *domain, *countername;
3253 char userpath[BUFSIZ];
3254 int res;
3255
3256 *buf = '\0';
3257
3258 username = ast_strdupa(data);
3259
3260 if ((countername = strchr(username, ':'))) {
3261 *countername = '\0';
3262 countername++;
3263 }
3264
3265 if ((domain = strchr(username, '@'))) {
3266 *domain = '\0';
3267 domain++;
3268 }
3269
3270 /* If we have neither username nor domain now, let's give up */
3271 if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3272 ast_log(LOG_ERROR, "No account given\n");
3273 return -1;
3274 }
3275
3276 if (ast_strlen_zero(countername)) {
3277 ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
3278 return -1;
3279 }
3280
3281 /* We only have a domain, no username */
3282 if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3283 domain = username;
3284 username = NULL;
3285 }
3286
3287 /* If we can't find account or if the account is temporary, return. */
3288 if (!ast_strlen_zero(username) && !find_account(domain, username, FALSE)) {
3289 ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
3290 return 0;
3291 }
3292
3293 create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
3294
3295 /* We have the path, now read the counter file */
3296 res = access_counter_file(userpath, countername, 0, 0);
3297 if (res >= 0)
3298 snprintf(buf, len, "%d", res);
3299 return 0;
3300}
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:3197

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

3304{
3305 char *username, *domain, *countername, *operand;
3306 char userpath[BUFSIZ];
3307 int change = 0;
3308 int operation = 0;
3309
3310 if(!value)
3311 return -1;
3312 change = atoi(value);
3313
3314 username = ast_strdupa(data);
3315
3316 if ((countername = strchr(username, ':'))) {
3317 *countername = '\0';
3318 countername++;
3319 }
3320 if ((operand = strchr(countername, ':'))) {
3321 *operand = '\0';
3322 operand++;
3323 }
3324
3325 if ((domain = strchr(username, '@'))) {
3326 *domain = '\0';
3327 domain++;
3328 }
3329
3330 /* If we have neither username nor domain now, let's give up */
3331 if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3332 ast_log(LOG_ERROR, "No account given\n");
3333 return -1;
3334 }
3335
3336 /* We only have a domain, no username */
3337 if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
3338 domain = username;
3339 username = NULL;
3340 }
3341
3342 if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
3343 ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
3344 return -1;
3345 }
3346
3347 /* If we can't find account or if the account is temporary, return. */
3348 if (!ast_strlen_zero(username) && !find_account(domain, username, FALSE)) {
3349 ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
3350 return 0;
3351 }
3352
3353 create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
3354 /* Now, find out our operator */
3355 if (*operand == 'i') /* Increment */
3356 operation = 2;
3357 else if (*operand == 'd') {
3358 change = change * -1;
3359 operation = 2;
3360 } else if (*operand == 's')
3361 operation = 1;
3362 else {
3363 ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
3364 return -1;
3365 }
3366
3367 /* We have the path, now read the counter file */
3368 access_counter_file(userpath, countername, change, operation);
3369 return 0;
3370}

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

2335{
2336 int res = 0;
2337 char filename[BUFSIZ];
2338
2339 if (!ast_strlen_zero(data)) {
2340 ast_copy_string(filename, (char *) data, sizeof(filename));
2341 } else {
2342 ast_channel_lock(chan);
2343 ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
2344 ast_channel_unlock(chan);
2345 }
2346
2347 if (ast_strlen_zero(filename)) {
2348 ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
2349 return res;
2350 }
2351
2352 /* Go ahead and delete audio files from system, they're not needed any more */
2353 /* We should look for both audio and text files here */
2354 if (ast_fileexists(filename, NULL, NULL) > 0) {
2355 res = vm_delete(filename);
2356 if (res) {
2357 ast_debug(2, "Can't delete file: %s\n", filename);
2358 pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
2359 } else {
2360 ast_debug(2, "Deleted voicemail file :: %s \n", filename);
2361 pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
2362 }
2363 } else {
2364 ast_debug(2, "Filename does not exist: %s\n", filename);
2365 pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
2366 }
2367
2368 return res;
2369}
static int vm_delete(char *file)
Definition: app_minivm.c:1524
#define ast_channel_lock(chan)
Definition: channel.h:2972
#define ast_channel_unlock(chan)
Definition: channel.h:2973
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 2161 of file app_minivm.c.

2162{
2163 struct leave_vm_options leave_options = { 0, '\0'};
2164 int argc;
2165 char *argv[2];
2166 struct ast_flags flags = { 0 };
2167 char *opts[OPT_ARG_ARRAY_SIZE];
2168 int res = 0;
2169 int ouseexten = 0;
2170 char tmp[PATH_MAX];
2171 char dest[PATH_MAX];
2172 char prefile[PATH_MAX] = "";
2173 char tempfile[PATH_MAX] = "";
2174 char ext_context[256] = "";
2175 char *domain;
2176 char ecodes[16] = "#";
2177 char *tmpptr;
2178 struct minivm_account *vmu;
2179 char *username;
2180
2181 if (ast_strlen_zero(data)) {
2182 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2183 return -1;
2184 }
2185 tmpptr = ast_strdupa((char *)data);
2186 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2187
2188 if (argc == 2) {
2189 if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1]))
2190 return -1;
2192 }
2193
2194 ast_copy_string(tmp, argv[0], sizeof(tmp));
2195 username = tmp;
2196 domain = strchr(tmp, '@');
2197 if (domain) {
2198 *domain = '\0';
2199 domain++;
2200 }
2202 ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument: %s\n", argv[0]);
2203 return -1;
2204 }
2205 ast_debug(1, "Trying to find configuration for user %s in domain %s\n", username, domain);
2206
2207 if (!(vmu = find_account(domain, username, TRUE))) {
2208 ast_log(LOG_ERROR, "Could not allocate memory. \n");
2209 return -1;
2210 }
2211
2212 /* Answer channel if it's not already answered */
2213 if (ast_channel_state(chan) != AST_STATE_UP)
2214 ast_answer(chan);
2215
2216 /* Setup pre-file if appropriate */
2217 if (strcmp(vmu->domain, "localhost"))
2218 snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
2219 else
2220 ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
2221
2222 if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
2223 res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
2224 if (res)
2225 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
2226 } else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
2227 res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
2228 if (res)
2229 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
2230 }
2231 /* Check for temporary greeting - it overrides busy and unavail */
2232 snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
2233 if (!(res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
2234 ast_debug(2, "Temporary message directory does not exist, using default (%s)\n", tempfile);
2235 ast_copy_string(prefile, tempfile, sizeof(prefile));
2236 }
2237 ast_debug(2, "Preparing to play message ...\n");
2238
2239 /* Check current context for special extensions */
2240 if (ast_test_flag(vmu, MVM_OPERATOR)) {
2241 if (!ast_strlen_zero(vmu->exit)) {
2242 if (ast_exists_extension(chan, vmu->exit, "o", 1,
2243 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2244 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
2245 ouseexten = 1;
2246 }
2247 } else if (ast_exists_extension(chan, ast_channel_context(chan), "o", 1,
2248 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2249 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
2250 ouseexten = 1;
2251 }
2252 }
2253
2254 if (!ast_strlen_zero(vmu->exit)) {
2255 if (ast_exists_extension(chan, vmu->exit, "a", 1,
2256 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2257 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
2258 }
2259 } else if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
2260 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
2261 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
2262 }
2263
2264 res = 0; /* Reset */
2265 /* Play the beginning intro if desired */
2266 if (!ast_strlen_zero(prefile)) {
2267 if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1)
2268 res = ast_waitstream(chan, ecodes);
2269 } else {
2270 ast_debug(2, "%s doesn't exist, doing what we can\n", prefile);
2271 res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
2272 }
2273 if (res < 0) {
2274 ast_debug(2, "Hang up during prefile playback\n");
2275 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
2276 if(ast_test_flag(vmu, MVM_ALLOCED))
2277 free_user(vmu);
2278 return -1;
2279 }
2280 if (res == '#') {
2281 /* On a '#' we skip the instructions */
2282 ast_set_flag(&leave_options, OPT_SILENT);
2283 res = 0;
2284 }
2285 if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
2287 if (!res)
2288 res = ast_waitstream(chan, ecodes);
2289 if (res == '#') {
2290 ast_set_flag(&leave_options, OPT_SILENT);
2291 res = 0;
2292 }
2293 }
2294 if (res > 0)
2295 ast_stopstream(chan);
2296 /* Check for a '*' here in case the caller wants to escape from voicemail to something
2297 other than the operator -- an automated attendant or mailbox login for example */
2298 if (res == '*') {
2299 ast_channel_exten_set(chan, "a");
2300 if (!ast_strlen_zero(vmu->exit)) {
2301 ast_channel_context_set(chan, vmu->exit);
2302 }
2303 ast_channel_priority_set(chan, 0);
2304 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
2305 res = 0;
2306 } else if (res == '0') { /* Check for a '0' here */
2307 if(ouseexten) {
2308 ast_channel_exten_set(chan, "o");
2309 if (!ast_strlen_zero(vmu->exit)) {
2310 ast_channel_context_set(chan, vmu->exit);
2311 }
2312 ast_play_and_wait(chan, "transfer");
2313 ast_channel_priority_set(chan, 0);
2314 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
2315 }
2316 res = 0;
2317 } else if (res < 0) {
2318 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
2319 res = -1;
2320 } else
2321 pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "SUCCESS");
2322
2323 if(ast_test_flag(vmu, MVM_ALLOCED))
2324 free_user(vmu);
2325
2326
2327 /* Ok, we're ready to rock and roll. Return to dialplan */
2328 return res;
2329
2330}
#define SOUND_INTRO
Definition: app_minivm.c:570
static int invent_message(struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
Definition: app_minivm.c:1467
static const struct ast_app_option minivm_app_options[128]
Definition: app_minivm.c:620
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:4190
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:681
char exit[80]
Definition: app_minivm.c:645
unsigned int flags
Definition: app_minivm.c:649
#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, 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 1992 of file app_minivm.c.

1993{
1994 int argc;
1995 char *argv[4];
1996 int res = 0;
1997 char *tmpptr;
1998 char tmp[PATH_MAX];
1999 char *mailbox;
2000 char *domain;
2001 if (ast_strlen_zero(data)) {
2002 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2003 return -1;
2004 }
2005 tmpptr = ast_strdupa((char *)data);
2006 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2007 if (argc < 4) {
2008 ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
2009 return -1;
2010 }
2011 ast_copy_string(tmp, argv[0], sizeof(tmp));
2012 mailbox = tmp;
2013 domain = strchr(tmp, '@');
2014 if (domain) {
2015 *domain = '\0';
2016 domain++;
2017 }
2018 if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
2019 ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
2020 return -1;
2021 }
2022 queue_mwi_event(ast_channel_uniqueid(chan), mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
2023
2024 return res;
2025}
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:1977
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, and queue_mwi_event().

Referenced by load_module().

◆ minivm_notify_exec()

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

Definition at line 2030 of file app_minivm.c.

2031{
2032 int argc;
2033 char *argv[2];
2034 int res = 0;
2035 char tmp[PATH_MAX];
2036 char *domain;
2037 char *tmpptr;
2038 struct minivm_account *vmu;
2039 char *username;
2040 const char *template = "";
2041 const char *filename;
2042 const char *format;
2043 const char *duration_string;
2044 if (ast_strlen_zero(data)) {
2045 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2046 return -1;
2047 }
2048 tmpptr = ast_strdupa((char *)data);
2049 argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
2050
2051 if (argc == 2 && !ast_strlen_zero(argv[1]))
2052 template = argv[1];
2053
2054 ast_copy_string(tmp, argv[0], sizeof(tmp));
2055 username = tmp;
2056 domain = strchr(tmp, '@');
2057 if (domain) {
2058 *domain = '\0';
2059 domain++;
2060 }
2062 ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2063 return -1;
2064 }
2065
2066 if(!(vmu = find_account(domain, username, TRUE))) {
2067 /* We could not find user, let's exit */
2068 ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
2069 pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
2070 return -1;
2071 }
2072
2073 ast_channel_lock(chan);
2074 if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
2075 filename = ast_strdupa(filename);
2076 }
2077 ast_channel_unlock(chan);
2078 /* Notify of new message to e-mail and pager */
2079 if (!ast_strlen_zero(filename)) {
2080 ast_channel_lock(chan);
2081 if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
2082 format = ast_strdupa(format);
2083 }
2084 if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
2085 duration_string = ast_strdupa(duration_string);
2086 }
2087 ast_channel_unlock(chan);
2088 res = notify_new_message(chan, template, vmu, filename, atoi(duration_string),
2089 format,
2090 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
2091 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL));
2092 }
2093
2094 pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
2095
2096
2097 if(ast_test_flag(vmu, MVM_ALLOCED))
2098 free_user(vmu);
2099
2100 /* Ok, we're ready to rock and roll. Return to dialplan */
2101
2102 return res;
2103
2104}
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:1705

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

2109{
2110 int res = 0;
2111 char *tmp;
2112 struct leave_vm_options leave_options;
2113 int argc;
2114 char *argv[2];
2115 struct ast_flags flags = { 0 };
2116 char *opts[OPT_ARG_ARRAY_SIZE];
2117
2118 memset(&leave_options, 0, sizeof(leave_options));
2119
2120 /* Answer channel if it's not already answered */
2121 if (ast_channel_state(chan) != AST_STATE_UP)
2122 ast_answer(chan);
2123
2124 if (ast_strlen_zero(data)) {
2125 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
2126 return -1;
2127 }
2128 tmp = ast_strdupa((char *)data);
2129 argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
2130 if (argc == 2) {
2131 if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
2132 return -1;
2133 }
2136 int gain;
2137
2138 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
2139 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
2140 return -1;
2141 } else
2142 leave_options.record_gain = (signed char) gain;
2143 }
2144 }
2145
2146 /* Now run the appliation and good luck to you! */
2147 res = leave_voicemail(chan, argv[0], &leave_options);
2148
2149 if (res == ERROR_LOCK_PATH) {
2150 ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
2151 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
2152 res = 0;
2153 }
2154 pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
2155
2156 return res;
2157}
#define ERROR_LOCK_PATH
Definition: app_minivm.c:576
static int leave_voicemail(struct ast_channel *chan, char *username, struct leave_vm_options *options)
Definition: app_minivm.c:1806

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

Referenced by load_module().

◆ mvm_user_alloc()

static struct minivm_account * mvm_user_alloc ( void  )
static

Definition at line 934 of file app_minivm.c.

935{
936 struct minivm_account *new;
937
938 new = ast_calloc(1, sizeof(*new));
939 if (!new)
940 return NULL;
942
943 return new;
944}

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

1706{
1707 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1709 RAII_VAR(struct ast_mwi_state *, mwi_state, NULL, ao2_cleanup);
1710 char *stringp;
1711 struct minivm_template *etemplate;
1712 char *messageformat;
1713 int res = 0;
1714 char oldlocale[100];
1715 const char *counter;
1716
1717 if (!ast_strlen_zero(vmu->attachfmt)) {
1718 if (strstr(format, vmu->attachfmt)) {
1719 format = vmu->attachfmt;
1720 } else {
1721 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);
1722 }
1723 }
1724
1725 etemplate = message_template_find(vmu->etemplate);
1726 if (!etemplate)
1727 etemplate = message_template_find(templatename);
1728 if (!etemplate)
1729 etemplate = message_template_find("email-default");
1730
1731 /* Attach only the first format */
1732 stringp = messageformat = ast_strdupa(format);
1733 strsep(&stringp, "|");
1734
1735 if (!ast_strlen_zero(etemplate->locale)) {
1736 char *new_locale;
1737 ast_copy_string(oldlocale, setlocale(LC_TIME, NULL), sizeof(oldlocale));
1738 ast_debug(2, "Changing locale from %s to %s\n", oldlocale, etemplate->locale);
1739 new_locale = setlocale(LC_TIME, etemplate->locale);
1740 if (new_locale == NULL) {
1741 ast_log(LOG_WARNING, "-_-_- Changing to new locale did not work. Locale: %s\n", etemplate->locale);
1742 }
1743 }
1744
1745
1746
1747 /* Read counter if available */
1748 ast_channel_lock(chan);
1749 if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
1750 counter = ast_strdupa(counter);
1751 }
1752 ast_channel_unlock(chan);
1753
1754 if (ast_strlen_zero(counter)) {
1755 ast_debug(2, "MVM_COUNTER not found\n");
1756 } else {
1757 ast_debug(2, "MVM_COUNTER found - will use it with value %s\n", counter);
1758 }
1759
1760 res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_EMAIL, counter);
1761
1762 if (res == 0 && !ast_strlen_zero(vmu->pager)) {
1763 /* Find template for paging */
1764 etemplate = message_template_find(vmu->ptemplate);
1765 if (!etemplate)
1766 etemplate = message_template_find("pager-default");
1767
1768 if (!ast_strlen_zero(etemplate->locale)) {
1769 ast_copy_string(oldlocale, setlocale(LC_TIME, ""), sizeof(oldlocale));
1770 setlocale(LC_TIME, etemplate->locale);
1771 }
1772
1773 res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_PAGE, counter);
1774 }
1775
1776 mwi_state = ast_mwi_create(vmu->username, vmu->domain);
1777 if (!mwi_state) {
1778 goto notify_cleanup;
1779 }
1780 mwi_state->snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
1781
1782 json_object = ast_json_pack("{s: s, s: s, s: s}",
1783 "Event", "MiniVoiceMail",
1784 "Action", "SentNotification",
1785 "Counter", counter ?: "");
1786 if (!json_object) {
1787 goto notify_cleanup;
1788 }
1789 message = ast_mwi_blob_create(mwi_state, ast_mwi_vm_app_type(), json_object);
1790 if (!message) {
1791 goto notify_cleanup;
1792 }
1793 stasis_publish(ast_mwi_topic(mwi_state->uniqueid), message);
1794
1795notify_cleanup:
1796 run_externnotify(chan, vmu); /* Run external notification */
1797 if (!ast_strlen_zero(etemplate->locale)) {
1798 setlocale(LC_TIME, oldlocale); /* Reset to old locale */
1799 }
1800 return res;
1801}
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:1128
static void run_externnotify(struct ast_channel *chan, struct minivm_account *vmu)
Run external notification for voicemail message.
Definition: app_minivm.c:1670
char * strsep(char **str, const char *delims)
#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,...
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:1538
Abstract JSON element (object, array, string, int, ...).
The structure that contains MWI state.
Definition: mwi.h:455
char locale[20]
Definition: app_minivm.c:671
#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 1538 of file app_minivm.c.

1541{
1542 int cmd = 0;
1543 int max_attempts = 3;
1544 int attempts = 0;
1545 int recorded = 0;
1546 int message_exists = 0;
1547 signed char zero_gain = 0;
1548 char *acceptdtmf = "#";
1549 char *canceldtmf = "";
1550
1551 /* Note that urgent and private are for flagging messages as such in the future */
1552
1553 /* barf if no pointer passed to store duration in */
1554 if (duration == NULL) {
1555 ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
1556 return -1;
1557 }
1558
1559 cmd = '3'; /* Want to start by recording */
1560
1561 while ((cmd >= 0) && (cmd != 't')) {
1562 switch (cmd) {
1563 case '1':
1564 ast_verb(3, "Saving message as is\n");
1565 ast_stream_and_wait(chan, "vm-msgsaved", "");
1566 cmd = 't';
1567 break;
1568 case '2':
1569 /* Review */
1570 ast_verb(3, "Reviewing the message\n");
1571 ast_streamfile(chan, recordfile, ast_channel_language(chan));
1572 cmd = ast_waitstream(chan, AST_DIGIT_ANY);
1573 break;
1574 case '3':
1575 message_exists = 0;
1576 /* Record */
1577 if (recorded == 1)
1578 ast_verb(3, "Re-recording the message\n");
1579 else
1580 ast_verb(3, "Recording the message\n");
1581 if (recorded && outsidecaller)
1582 cmd = ast_play_and_wait(chan, "beep");
1583 recorded = 1;
1584 /* 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 */
1585 if (record_gain)
1586 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
1587 if (ast_test_flag(vmu, MVM_OPERATOR))
1588 canceldtmf = "0";
1589 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);
1590 if (record_gain)
1591 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
1592 if (cmd == -1) /* User has hung up, no options to give */
1593 return cmd;
1594 if (cmd == '0')
1595 break;
1596 else if (cmd == '*')
1597 break;
1598 else {
1599 /* If all is well, a message exists */
1600 message_exists = 1;
1601 cmd = 0;
1602 }
1603 break;
1604 case '4':
1605 case '5':
1606 case '6':
1607 case '7':
1608 case '8':
1609 case '9':
1610 case '*':
1611 case '#':
1612 cmd = ast_play_and_wait(chan, "vm-sorry");
1613 break;
1614 case '0':
1615 if(!ast_test_flag(vmu, MVM_OPERATOR)) {
1616 cmd = ast_play_and_wait(chan, "vm-sorry");
1617 break;
1618 }
1619 if (message_exists || recorded) {
1620 cmd = ast_play_and_wait(chan, "vm-saveoper");
1621 if (!cmd)
1622 cmd = ast_waitfordigit(chan, 3000);
1623 if (cmd == '1') {
1624 ast_play_and_wait(chan, "vm-msgsaved");
1625 cmd = '0';
1626 } else {
1627 ast_play_and_wait(chan, "vm-deleted");
1628 vm_delete(recordfile);
1629 cmd = '0';
1630 }
1631 }
1632 return cmd;
1633 default:
1634 /* If the caller is an outside caller, and the review option is enabled,
1635 allow them to review the message, but let the owner of the box review
1636 their OGM's */
1637 if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
1638 return cmd;
1639 if (message_exists) {
1640 cmd = ast_play_and_wait(chan, "vm-review");
1641 } else {
1642 cmd = ast_play_and_wait(chan, "vm-torerecord");
1643 if (!cmd)
1644 cmd = ast_waitfordigit(chan, 600);
1645 }
1646
1647 if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
1648 cmd = ast_play_and_wait(chan, "vm-reachoper");
1649 if (!cmd)
1650 cmd = ast_waitfordigit(chan, 600);
1651 }
1652 if (!cmd)
1653 cmd = ast_waitfordigit(chan, 6000);
1654 if (!cmd) {
1655 attempts++;
1656 }
1657 if (attempts > max_attempts) {
1658 cmd = 't';
1659 }
1660 }
1661 }
1662 if (outsidecaller)
1663 ast_play_and_wait(chan, "vm-goodbye");
1664 if (cmd == 't')
1665 cmd = 0;
1666 return cmd;
1667}
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3143
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:7395
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:1886
#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:2149
@ 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 896 of file app_minivm.c.

897{
898 char callerid[256];
899 struct ast_variable *var;
900
901 if (!channel) {
902 ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
903 return;
904 }
905
906 for (var = vmu->chanvars ; var ; var = var->next) {
907 pbx_builtin_setvar_helper(channel, var->name, var->value);
908 }
909
910 /* Prepare variables for substition in email body and subject */
911 pbx_builtin_setvar_helper(channel, "MVM_NAME", vmu->fullname);
912 pbx_builtin_setvar_helper(channel, "MVM_DUR", dur);
913 pbx_builtin_setvar_helper(channel, "MVM_DOMAIN", vmu->domain);
914 pbx_builtin_setvar_helper(channel, "MVM_USERNAME", vmu->username);
915 pbx_builtin_setvar_helper(channel, "MVM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
916 pbx_builtin_setvar_helper(channel, "MVM_CIDNAME", (cidname ? cidname : "an unknown caller"));
917 pbx_builtin_setvar_helper(channel, "MVM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
918 pbx_builtin_setvar_helper(channel, "MVM_DATE", date);
919 if (!ast_strlen_zero(counter))
920 pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
921}

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

1978{
1979 char *mailbox, *context;
1980
1981 mailbox = ast_strdupa(mbx);
1982 context = ast_strdupa(ctx);
1983 if (ast_strlen_zero(context)) {
1984 context = "default";
1985 }
1986
1987 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
1988}
#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 3423 of file app_minivm.c.

3424{
3425 return(load_config(1));
3426}

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

1671{
1672 char fquser[AST_MAX_CONTEXT * 2];
1673 char *argv[5] = { NULL };
1674 struct ast_party_caller *caller;
1675 char *cid;
1676 int idx;
1677
1679 return;
1680 }
1681
1682 snprintf(fquser, sizeof(fquser), "%s@%s", vmu->username, vmu->domain);
1683
1684 caller = ast_channel_caller(chan);
1685 idx = 0;
1686 argv[idx++] = ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify;
1687 argv[idx++] = fquser;
1688 cid = S_COR(caller->id.name.valid, caller->id.name.str, NULL);
1689 if (cid) {
1690 argv[idx++] = cid;
1691 }
1692 cid = S_COR(caller->id.number.valid, caller->id.number.str, NULL);
1693 if (cid) {
1694 argv[idx++] = cid;
1695 }
1696 argv[idx] = NULL;
1697
1698 ast_debug(1, "Executing: %s %s %s %s\n",
1699 argv[0], argv[1], argv[2] ?: "", argv[3] ?: "");
1700 ast_safe_execvp(1, argv[0], argv);
1701}
#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:1232
Caller Party information.
Definition: channel.h:420
struct ast_party_id id
Caller party ID.
Definition: channel.h:422
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:281
char * str
Subscriber name (Malloced)
Definition: channel.h:266
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293

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

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

2584{
2585 struct minivm_zone *newzone;
2586 char *msg_format, *timezone_str;
2587
2588 newzone = ast_calloc(1, sizeof(*newzone));
2589 if (newzone == NULL)
2590 return 0;
2591
2593
2594 timezone_str = strsep(&msg_format, "|");
2595 if (!msg_format) {
2596 ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
2597 ast_free(newzone);
2598 return 0;
2599 }
2600
2601 ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
2602 ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
2603 ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
2604
2608
2610
2611 return 0;
2612}
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 2571 of file app_minivm.c.

2572{
2573 struct minivm_zone *this;
2574
2576 while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list)))
2577 free_zone(this);
2578
2580}
static void free_zone(struct minivm_zone *z)
Free Mini Voicemail timezone.
Definition: app_minivm.c:2565

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

3450{
3451 int res;
3452
3459
3463
3464 message_destroy_list(); /* Destroy list of voicemail message templates */
3465 timezone_destroy_list(); /* Destroy list of timezones */
3466 vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
3467
3468 return res;
3469}
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 1524 of file app_minivm.c.

1525{
1526 int res;
1527
1528 ast_debug(1, "Deleting voicemail file %s\n", file);
1529
1530 res = unlink(file); /* Remove the meta data file */
1531 res |= ast_filedelete(file, NULL); /* remove the media file */
1532 return res;
1533}

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

3181{
3182 switch (ast_lock_path(path)) {
3183 case AST_LOCK_TIMEOUT:
3184 return -1;
3185 default:
3186 return 0;
3187 }
3188}
@ AST_LOCK_TIMEOUT
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2614

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

950{
951 struct minivm_account *this;
953 while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list)))
954 ast_free(this);
956}

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

◆ app_minivm_accmess

char* app_minivm_accmess = "MinivmAccMess"
static

Definition at line 596 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_delete

char* app_minivm_delete = "MinivmDelete"
static

Definition at line 595 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_greet

char* app_minivm_greet = "MinivmGreet"
static

Definition at line 593 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_mwi

char* app_minivm_mwi = "MinivmMWI"
static

Definition at line 597 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_notify

char* app_minivm_notify = "MinivmNotify"
static

Definition at line 594 of file app_minivm.c.

Referenced by load_module(), and unload_module().

◆ app_minivm_record

char* app_minivm_record = "MinivmRecord"
static

Definition at line 592 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 3477 of file app_minivm.c.

◆ cli_minivm

struct ast_cli_entry cli_minivm[]
static

CLI commands for Mini-voicemail.

Definition at line 3374 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 722 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 723 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 721 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 719 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 718 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 727 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 709 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 717 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 716 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 729 of file app_minivm.c.

Referenced by populate_defaults().

◆ globalflags

struct ast_flags globalflags = {0}
static

Global voicemail flags

Definition at line 726 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 627 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:3103

Definition at line 3389 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 620 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:3250
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:3303

Definition at line 3383 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 711 of file app_minivm.c.

Referenced by load_config().

◆ minivmlogfile

FILE* minivmlogfile
static

The minivm log file

Definition at line 714 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 712 of file app_minivm.c.

Referenced by leave_voicemail().

◆ MVM_SPOOL_DIR

char MVM_SPOOL_DIR[PATH_MAX]
static