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

MiniVoiceMail - A Minimal Voicemail System for Asterisk. More...

#include "asterisk.h"
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <time.h>
#include <dirent.h>
#include <locale.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/mwi.h"
#include "asterisk/dsp.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/callerid.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
Include dependency graph for app_minivm.c:

Go to the source code of this file.

Data Structures

struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
 
struct  message_templates
 The list of e-mail templates. More...
 
struct  minivm_account
 
struct  minivm_accounts
 
struct  minivm_stats
 Structure for gathering statistics. More...
 
struct  minivm_template
 
struct  minivm_zone
 Voicemail time zones. More...
 
struct  minivm_zones
 The list of e-mail time zones. More...
 

Macros

#define ASTERISK_USERNAME   "asterisk"
 
#define DEFAULT_CHARSET   "ISO-8859-1"
 
#define DEFAULT_DATEFORMAT   "%A, %B %d, %Y at %r"
 
#define EOL   "\r\n"
 
#define ERROR_LOCK_PATH   -100
 
#define FALSE   0
 
#define HMSU_OUTPUT_FORMAT   "%-23s %-15s %-15s %-10s %-10s %-50s\n"
 
#define HMSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
 
#define HVLT_OUTPUT_FORMAT   "%-15s %-10s %-10s %-15.15s %-50s\n"
 
#define MAX_DATETIME_FORMAT   512
 
#define MAX_NUM_CID_CONTEXTS   10
 
#define MVM_ALLOCED   (1 << 13)
 
#define MVM_ENVELOPE   (1 << 4)
 
#define MVM_OPERATOR   (1 << 1)
 
#define MVM_PBXSKIP   (1 << 9)
 
#define MVM_REALTIME   (1 << 2)
 
#define MVM_REVIEW   (1 << 0)
 
#define MVM_SVMAIL   (1 << 3)
 
#define SENDMAIL   "/usr/sbin/sendmail -t"
 Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail.conf. More...
 
#define SOUND_INTRO   "vm-intro"
 
#define TRUE   1
 
#define VOICEMAIL_CONFIG   "minivm.conf"
 
#define VOICEMAIL_DIR_MODE   0700
 

Enumerations

enum  minivm_option_args { OPT_ARG_RECORDGAIN = 0 , OPT_ARG_ARRAY_SIZE = 1 }
 
enum  minivm_option_flags {
  OPT_SILENT = (1 << 0) , OPT_BUSY_GREETING = (1 << 1) , OPT_UNAVAIL_GREETING = (1 << 2) , OPT_TEMP_GREETING = (1 << 3) ,
  OPT_NAME_GREETING = (1 << 4) , OPT_RECORDGAIN = (1 << 5)
}
 
enum  mvm_messagetype { MVM_MESSAGE_EMAIL , MVM_MESSAGE_PAGE }
 Message types for notification. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int access_counter_file (char *directory, char *countername, int value, int operand)
 Access counter file, lock directory, read and possibly write it again changed. More...
 
static int apply_general_options (struct ast_variable *var)
 Apply general configuration options. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static const char * ast_str_encode_mime (struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
 
static const char * ast_str_quote (struct ast_str **buf, ssize_t maxlen, const char *from)
 
static int check_dirpath (char *dest, int len, char *domain, char *username, char *folder)
 
static int check_mime (const char *str)
 
static char * complete_minivm_show_users (const char *line, const char *word, int pos, int state)
 
static int create_dirpath (char *dest, int len, char *domain, char *username, char *folder)
 
static int create_vmaccount (char *name, struct ast_variable *var, int realtime)
 Append new mailbox to mailbox list from configuration file. More...
 
static struct minivm_accountfind_account (const char *domain, const char *username, int createtemp)
 
static struct minivm_accountfind_user_realtime (const char *domain, const char *username)
 
static void free_user (struct minivm_account *vmu)
 
static void free_zone (struct minivm_zone *z)
 Free Mini Voicemail timezone. More...
 
static int get_date (char *s, int len)
 
static char * handle_minivm_list_templates (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI routine for listing templates. More...
 
static char * handle_minivm_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload cofiguration. More...
 
static char * handle_minivm_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Show settings. More...
 
static char * handle_minivm_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show stats. More...
 
static char * handle_minivm_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list voicemail accounts. More...
 
static char * handle_minivm_show_zones (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail zones in the CLI. More...
 
static int invent_message (struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
 
static int leave_voicemail (struct ast_channel *chan, char *username, struct leave_vm_options *options)
 
static int load_config (int reload)
 Load minivoicemail configuration. More...
 
static int load_module (void)
 Load mini voicemail module. More...
 
static int make_dir (char *dest, int len, const char *domain, const char *username, const char *folder)
 
static void message_destroy_list (void)
 
static int message_template_build (const char *name, struct ast_variable *var)
 
static struct minivm_templatemessage_template_create (const char *name)
 
static struct minivm_templatemessage_template_find (const char *name)
 
static void message_template_free (struct minivm_template *template)
 
static char * message_template_parse_emailbody (const char *configuration)
 Parse emailbody template from configuration file. More...
 
static char * message_template_parse_filebody (const char *filename)
 Read message template from file. More...
 
static int minivm_accmess_exec (struct ast_channel *chan, const char *data)
 Record specific messages for voicemail account. More...
 
static int minivm_account_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${MINIVMACCOUNT()} Dialplan function - reads account data More...
 
static int minivm_counter_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${MINIVMCOUNTER()} Dialplan function - read counters More...
 
static int minivm_counter_func_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 ${MINIVMCOUNTER()} Dialplan function - changes counter data More...
 
static int minivm_delete_exec (struct ast_channel *chan, const char *data)
 
static int minivm_greet_exec (struct ast_channel *chan, const char *data)
 
static int minivm_mwi_exec (struct ast_channel *chan, const char *data)
 
static int minivm_notify_exec (struct ast_channel *chan, const char *data)
 
static int minivm_record_exec (struct ast_channel *chan, const char *data)
 
static struct minivm_accountmvm_user_alloc (void)
 
static int notify_new_message (struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
 
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct minivm_account *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain)
 
static void populate_defaults (struct minivm_account *vmu)
 
static void prep_email_sub_vars (struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
 
static void queue_mwi_event (const char *channel_id, const char *mbx, const char *ctx, int urgent, int new, int old)
 
static int reload (void)
 Reload mini voicemail module. More...
 
static void run_externnotify (struct ast_channel *chan, struct minivm_account *vmu)
 Run external notification for voicemail message. More...
 
static int sendmail (struct minivm_template *template, struct minivm_account *vmu, char *cidnum, char *cidname, const char *filename, char *format, int duration, int attach_user_voicemail, enum mvm_messagetype type, const char *counter)
 
static int timezone_add (const char *zonename, const char *config)
 Add time zone to memory list. More...
 
static void timezone_destroy_list (void)
 Clear list of timezones. More...
 
static int unload_module (void)
 Unload mini voicemail module. More...
 
static int vm_delete (char *file)
 
static int vm_lock_path (const char *path)
 lock directory More...
 
static void vmaccounts_destroy_list (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
 
static char * app_minivm_accmess = "MinivmAccMess"
 
static char * app_minivm_delete = "MinivmDelete"
 
static char * app_minivm_greet = "MinivmGreet"
 
static char * app_minivm_mwi = "MinivmMWI"
 
static char * app_minivm_notify = "MinivmNotify"
 
static char * app_minivm_record = "MinivmRecord"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_minivm []
 CLI commands for Mini-voicemail. More...
 
static char default_vmformat [80]
 
static char global_externnotify [160]
 
static char global_logfile [PATH_MAX]
 
static char global_mailcmd [160]
 
static int global_maxgreet
 
static int global_maxsilence
 
static int global_saydurationminfo
 
static int global_silencethreshold = 128
 
static struct minivm_stats global_stats
 Statistics for voicemail. More...
 
static int global_vmmaxmessage
 
static int global_vmminmessage
 
static double global_volgain
 
static struct ast_flags globalflags = {0}
 
static struct message_templates message_templates = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static const struct ast_app_option minivm_accmess_options [128] = { [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 't' ] = { .flag = OPT_TEMP_GREETING }, [ 'n' ] = { .flag = OPT_NAME_GREETING }, }
 
static struct ast_custom_function minivm_account_function
 
static struct minivm_accounts minivm_accounts = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static const struct ast_app_option minivm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, }
 
static struct ast_custom_function minivm_counter_function
 
static struct minivm_zones minivm_zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static ast_mutex_t minivmlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static FILE * minivmlogfile
 
static ast_mutex_t minivmloglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char MVM_SPOOL_DIR [PATH_MAX]
 

Detailed Description

MiniVoiceMail - A Minimal Voicemail System for Asterisk.

A voicemail system in small building blocks, working together based on the Comedian Mail voicemail system (app_voicemail.c).

See also

Definition in file app_minivm.c.

Macro Definition Documentation

◆ ASTERISK_USERNAME

#define ASTERISK_USERNAME   "asterisk"

Default username for sending mail is asterisk@localhost

Definition at line 553 of file app_minivm.c.

◆ DEFAULT_CHARSET

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 707 of file app_minivm.c.

◆ DEFAULT_DATEFORMAT

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

Definition at line 706 of file app_minivm.c.

◆ EOL

#define EOL   "\r\n"

Definition at line 544 of file app_minivm.c.

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

Definition at line 549 of file app_minivm.c.

◆ FALSE

#define FALSE   0

Definition at line 527 of file app_minivm.c.

◆ HMSU_OUTPUT_FORMAT

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

◆ HMSZ_OUTPUT_FORMAT

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

◆ HVLT_OUTPUT_FORMAT

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

◆ MAX_DATETIME_FORMAT

#define MAX_DATETIME_FORMAT   512

Definition at line 546 of file app_minivm.c.

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 547 of file app_minivm.c.

◆ MVM_ALLOCED

#define MVM_ALLOCED   (1 << 13)

Definition at line 537 of file app_minivm.c.

◆ MVM_ENVELOPE

#define MVM_ENVELOPE   (1 << 4)

Definition at line 535 of file app_minivm.c.

◆ MVM_OPERATOR

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

Definition at line 532 of file app_minivm.c.

◆ MVM_PBXSKIP

#define MVM_PBXSKIP   (1 << 9)

Definition at line 536 of file app_minivm.c.

◆ MVM_REALTIME

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 533 of file app_minivm.c.

◆ MVM_REVIEW

#define MVM_REVIEW   (1 << 0)

Review message

Definition at line 531 of file app_minivm.c.

◆ MVM_SVMAIL

#define MVM_SVMAIL   (1 << 3)

Definition at line 534 of file app_minivm.c.

◆ SENDMAIL

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

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

Definition at line 541 of file app_minivm.c.

◆ SOUND_INTRO

#define SOUND_INTRO   "vm-intro"

Definition at line 543 of file app_minivm.c.

◆ TRUE

#define TRUE   1

Definition at line 524 of file app_minivm.c.

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 552 of file app_minivm.c.

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0700

Definition at line 550 of file app_minivm.c.

Enumeration Type Documentation

◆ minivm_option_args

Enumerator
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 583 of file app_minivm.c.

583  {
584  OPT_ARG_RECORDGAIN = 0,
585  OPT_ARG_ARRAY_SIZE = 1,
586 };
@ OPT_ARG_RECORDGAIN
Definition: app_minivm.c:584
@ OPT_ARG_ARRAY_SIZE
Definition: app_minivm.c:585

◆ minivm_option_flags

Enumerator
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 574 of file app_minivm.c.

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

◆ mvm_messagetype

Message types for notification.

Enumerator
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 556 of file app_minivm.c.

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

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3468 of file app_minivm.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

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

◆ apply_general_options()

static int apply_general_options ( struct ast_variable var)
static

Apply general configuration options.

Definition at line 2673 of file app_minivm.c.

2674 {
2675  int error = 0;
2676 
2677  while (var) {
2678  /* Mail command */
2679  if (!strcmp(var->name, "mailcmd")) {
2680  ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
2681  } else if (!strcmp(var->name, "maxgreet")) {
2682  global_maxgreet = atoi(var->value);
2683  } else if (!strcmp(var->name, "maxsilence")) {
2684  global_maxsilence = atoi(var->value);
2685  if (global_maxsilence > 0)
2686  global_maxsilence *= 1000;
2687  } else if (!strcmp(var->name, "logfile")) {
2688  if (!ast_strlen_zero(var->value) ) {
2689  if(*(var->value) == '/')
2691  else
2692  snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
2693  }
2694  } else if (!strcmp(var->name, "externnotify")) {
2695  /* External voicemail notify application */
2697  } else if (!strcmp(var->name, "silencethreshold") || !strcmp(var->name, "silencetreshold")) {
2698  /* Silence treshold */
2699  global_silencethreshold = atoi(var->value);
2700  } else if (!strcmp(var->name, "maxmessage")) {
2701  int x;
2702  if (sscanf(var->value, "%30d", &x) == 1) {
2703  global_vmmaxmessage = x;
2704  } else {
2705  error ++;
2706  ast_log(LOG_WARNING, "Invalid max message time length\n");
2707  }
2708  } else if (!strcmp(var->name, "minmessage")) {
2709  int x;
2710  if (sscanf(var->value, "%30d", &x) == 1) {
2711  global_vmminmessage = x;
2713  ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
2714  } else {
2715  error ++;
2716  ast_log(LOG_WARNING, "Invalid min message time length\n");
2717  }
2718  } else if (!strcmp(var->name, "format")) {
2720  } else if (!strcmp(var->name, "review")) {
2722  } else if (!strcmp(var->name, "operator")) {
2724  }
2725  var = var->next;
2726  }
2727  return error;
2728 }
static int global_maxsilence
Definition: app_minivm.c:691
static char default_vmformat[80]
Definition: app_minivm.c:697
#define MVM_REVIEW
Definition: app_minivm.c:531
static struct ast_flags globalflags
Definition: app_minivm.c:699
static int global_maxgreet
Definition: app_minivm.c:692
static int global_vmmaxmessage
Definition: app_minivm.c:690
static char global_mailcmd[160]
Definition: app_minivm.c:694
static int global_silencethreshold
Definition: app_minivm.c:693
#define MVM_OPERATOR
Definition: app_minivm.c:532
static char global_externnotify[160]
Definition: app_minivm.c:695
static int global_vmminmessage
Definition: app_minivm.c:689
static char global_logfile[PATH_MAX]
Definition: app_minivm.c:696
#define var
Definition: ast_expr2f.c:614
#define LOG_WARNING
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
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:406
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 3468 of file app_minivm.c.

◆ ast_str_encode_mime()

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

Definition at line 1040 of file app_minivm.c.

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

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

Referenced by sendmail().

◆ ast_str_quote()

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

Definition at line 1081 of file app_minivm.c.

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

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

Referenced by sendmail().

◆ check_dirpath()

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

Definition at line 1405 of file app_minivm.c.

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

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

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

◆ check_mime()

static int check_mime ( const char *  str)
static

Definition at line 1011 of file app_minivm.c.

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

References str.

Referenced by sendmail().

◆ complete_minivm_show_users()

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

Definition at line 2914 of file app_minivm.c.

2915 {
2916  int which = 0;
2917  int wordlen;
2918  struct minivm_account *vmu;
2919  const char *domain = "";
2920 
2921  /* 0 - minivm; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
2922  if (pos > 4)
2923  return NULL;
2924  wordlen = strlen(word);
2926  if (!strncasecmp(word, vmu->domain, wordlen)) {
2927  if (domain && strcmp(domain, vmu->domain) && ++which > state)
2928  return ast_strdup(vmu->domain);
2929  /* ignore repeated domains ? */
2930  domain = vmu->domain;
2931  }
2932  }
2933  return NULL;
2934 }
#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::@51 list
char domain[AST_MAX_CONTEXT]
Definition: app_minivm.c:606

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

Referenced by handle_minivm_show_users().

◆ create_dirpath()

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

Definition at line 1424 of file app_minivm.c.

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

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

Referenced by leave_voicemail(), and minivm_counter_func_read().

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

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

References minivm_account::accountcode, ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_strlen_zero(), ast_variable_new, minivm_account::chanvars, minivm_account::domain, minivm_account::email, minivm_account::etemplate, minivm_account::externnotify, minivm_account::fullname, global_stats, minivm_account::language, minivm_template::list, LOG_ERROR, name, ast_variable::next, minivm_account::pager, minivm_account::pincode, populate_defaults(), minivm_account::ptemplate, minivm_account::serveremail, minivm_account::username, var, minivm_stats::voicemailaccounts, minivm_account::volgain, and minivm_account::zonetag.

Referenced by find_user_realtime(), and load_config().

◆ find_account()

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

Definition at line 934 of file app_minivm.c.

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

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, domain::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_greet_exec(), and minivm_notify_exec().

◆ find_user_realtime()

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

Definition at line 978 of file app_minivm.c.

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

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

Referenced by find_account().

◆ free_user()

static void free_user ( struct minivm_account vmu)
static

◆ free_zone()

static void free_zone ( struct minivm_zone z)
static

Free Mini Voicemail timezone.

Definition at line 2556 of file app_minivm.c.

2557 {
2558  ast_free(z);
2559 }

References ast_free.

Referenced by timezone_destroy_list().

◆ get_date()

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

Definition at line 844 of file app_minivm.c.

845 {
846  struct ast_tm tm;
847  struct timeval now = ast_tvnow();
848 
849  ast_localtime(&now, &tm, NULL);
850  return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
851 }
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 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
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:157

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

2874 {
2875  struct minivm_template *this;
2876 #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
2877  int count = 0;
2878 
2879  switch (cmd) {
2880  case CLI_INIT:
2881  e->command = "minivm list templates";
2882  e->usage =
2883  "Usage: minivm list templates\n"
2884  " Lists message templates for e-mail, paging and IM\n";
2885  return NULL;
2886  case CLI_GENERATE:
2887  return NULL;
2888  }
2889 
2890  if (a->argc > 3)
2891  return CLI_SHOWUSAGE;
2892 
2895  ast_cli(a->fd, "There are no message templates defined\n");
2897  return CLI_FAILURE;
2898  }
2899  ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
2900  ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
2902  ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name,
2903  S_OR(this->charset, "-"),
2904  S_OR(this->locale, "-"),
2905  this->attachment ? "Yes" : "No",
2906  S_OR(this->subject, "-"));
2907  count++;
2908  }
2910  ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
2911  return CLI_SUCCESS;
2912 }
#define HVLT_OUTPUT_FORMAT
static char locale[20]
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
The list of e-mail templates.
Definition: app_minivm.c:651
struct minivm_template::@52 list
char subject[100]
Definition: app_minivm.c:642
static struct test_val a

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

◆ handle_minivm_reload()

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

Reload cofiguration.

Definition at line 3420 of file app_minivm.c.

3421 {
3422 
3423  switch (cmd) {
3424  case CLI_INIT:
3425  e->command = "minivm reload";
3426  e->usage =
3427  "Usage: minivm reload\n"
3428  " Reload mini-voicemail configuration and reset statistics\n";
3429  return NULL;
3430  case CLI_GENERATE:
3431  return NULL;
3432  }
3433 
3434  reload();
3435  ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
3436  return CLI_SUCCESS;
3437 }
static int reload(void)
Reload mini voicemail module.
Definition: app_minivm.c:3414

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

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

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

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

◆ handle_minivm_show_users()

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

CLI command to list voicemail accounts.

Definition at line 2937 of file app_minivm.c.

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

References a, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, minivm_account::attachfmt, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_minivm_show_users(), minivm_account::domain, minivm_account::etemplate, minivm_account::fullname, HMSU_OUTPUT_FORMAT, minivm_template::list, NULL, minivm_account::ptemplate, S_OR, tmp(), ast_cli_entry::usage, minivm_account::username, and minivm_account::zonetag.

◆ handle_minivm_show_zones()

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

Show a list of voicemail zones in the CLI.

Definition at line 2985 of file app_minivm.c.

2986 {
2987  struct minivm_zone *zone;
2988 #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
2989  char *res = CLI_SUCCESS;
2990 
2991  switch (cmd) {
2992  case CLI_INIT:
2993  e->command = "minivm list zones";
2994  e->usage =
2995  "Usage: minivm list zones\n"
2996  " Lists zone message formats\n";
2997  return NULL;
2998  case CLI_GENERATE:
2999  return NULL;
3000  }
3001 
3002  if (a->argc != e->args)
3003  return CLI_SHOWUSAGE;
3004 
3006  if (!AST_LIST_EMPTY(&minivm_zones)) {
3007  ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
3008  ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
3010  ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
3011  }
3012  } else {
3013  ast_cli(a->fd, "There are no voicemail zones currently defined\n");
3014  res = CLI_FAILURE;
3015  }
3017 
3018  return res;
3019 }
#define HMSZ_OUTPUT_FORMAT
int args
This gets set in ast_cli_register()
Definition: cli.h:185
Voicemail time zones.
Definition: app_minivm.c:660
char msg_format[BUFSIZ]
Definition: app_minivm.c:663
char name[80]
Definition: app_minivm.c:661
struct minivm_zone::@53 list
char timezone[80]
Definition: app_minivm.c:662
The list of e-mail time zones.
Definition: app_minivm.c:668

References a, ast_cli_entry::args, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, HMSZ_OUTPUT_FORMAT, minivm_template::list, minivm_zone::msg_format, minivm_zone::name, NULL, minivm_zone::timezone, and ast_cli_entry::usage.

◆ invent_message()

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

Definition at line 1440 of file app_minivm.c.

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

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

Referenced by minivm_greet_exec().

◆ leave_voicemail()

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

Definition at line 1779 of file app_minivm.c.

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

References minivm_account::accountcode, ast_callerid_merge(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_language(), ast_channel_macrocontext(), ast_channel_name(), ast_channel_priority(), ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_localtime(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_streamfile(), ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_tvnow(), ast_verb, ast_waitstream(), minivm_account::attachfmt, check_dirpath(), create_dirpath(), default_vmformat, minivm_account::domain, errno, find_account(), free_user(), get_date(), global_stats, global_vmmaxmessage, global_vmminmessage, minivm_stats::lastreceived, LOG_ERROR, LOG_WARNING, minivmlogfile, minivmloglock, MVM_ALLOCED, name, NULL, options, PATH_MAX, pbx_builtin_setvar_helper(), play_record_review(), minivm_stats::receivedmessages, S_COR, tmp(), and TRUE.

Referenced by minivm_record_exec().

◆ load_config()

static int load_config ( int  reload)
static

Load minivoicemail configuration.

Definition at line 2731 of file app_minivm.c.

2732 {
2733  struct ast_config *cfg;
2734  struct ast_variable *var;
2735  char *cat;
2736  const char *chanvar;
2737  int error = 0;
2738  struct minivm_template *template;
2739  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2740 
2741  cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
2742  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2743  return 0;
2744  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2745  ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
2746  return 0;
2747  }
2748 
2750 
2751  /* Destroy lists to reconfigure */
2752  message_destroy_list(); /* Destroy list of voicemail message templates */
2753  timezone_destroy_list(); /* Destroy list of timezones */
2754  vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
2755  ast_debug(2, "Destroyed memory objects...\n");
2756 
2757  /* First, set some default settings */
2758  global_externnotify[0] = '\0';
2759  global_logfile[0] = '\0';
2760  global_vmmaxmessage = 2000;
2761  global_maxgreet = 2000;
2762  global_vmminmessage = 0;
2763  strcpy(global_mailcmd, SENDMAIL);
2764  global_maxsilence = 0;
2769  /* Reset statistics */
2770  memset(&global_stats, 0, sizeof(global_stats));
2772 
2774 
2775  /* Make sure we could load configuration file */
2776  if (!cfg) {
2777  ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
2779  return 0;
2780  }
2781 
2782  ast_debug(2, "Loaded configuration file, now parsing\n");
2783 
2784  /* General settings */
2785 
2786  cat = ast_category_browse(cfg, NULL);
2787  while (cat) {
2788  ast_debug(3, "Found configuration section [%s]\n", cat);
2789  if (!strcasecmp(cat, "general")) {
2790  /* Nothing right now */
2792  } else if (!strncasecmp(cat, "template-", 9)) {
2793  /* Template */
2794  char *name = cat + 9;
2795 
2796  /* Now build and link template to list */
2798  } else {
2799  var = ast_variable_browse(cfg, cat);
2800  if (!strcasecmp(cat, "zonemessages")) {
2801  /* Timezones in this context */
2802  while (var) {
2803  timezone_add(var->name, var->value);
2804  var = var->next;
2805  }
2806  } else {
2807  /* Create mailbox from this */
2808  error += create_vmaccount(cat, var, FALSE);
2809  }
2810  }
2811  /* Find next section in configuration file */
2812  cat = ast_category_browse(cfg, cat);
2813  }
2814 
2815  /* Configure the default email template */
2816  message_template_build("email-default", NULL);
2817  template = message_template_find("email-default");
2818 
2819  /* Load date format config for voicemail mail */
2820  if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat")))
2821  ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
2822  if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
2823  ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
2824  if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
2825  ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2826  if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaddress")))
2827  ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2828  if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
2829  ast_copy_string(template->charset, chanvar, sizeof(template->charset));
2830  if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject")))
2831  ast_copy_string(template->subject, chanvar, sizeof(template->subject));
2832  if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody")))
2833  template->body = message_template_parse_emailbody(chanvar);
2834  template->attachment = TRUE;
2835 
2836  message_template_build("pager-default", NULL);
2837  template = message_template_find("pager-default");
2838  if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
2839  ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
2840  if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
2841  ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
2842  if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
2843  ast_copy_string(template->charset, chanvar, sizeof(template->charset));
2844  if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
2845  ast_copy_string(template->subject, chanvar,sizeof(template->subject));
2846  if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody")))
2847  template->body = message_template_parse_emailbody(chanvar);
2848  template->attachment = FALSE;
2849 
2850  if (error)
2851  ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
2852 
2854  ast_config_destroy(cfg);
2855 
2856  /* Close log file if it's open and disabled */
2857  if(minivmlogfile)
2858  fclose(minivmlogfile);
2859 
2860  /* Open log file if it's enabled */
2862  minivmlogfile = fopen(global_logfile, "a");
2863  if(!minivmlogfile)
2864  ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
2865  if (minivmlogfile)
2866  ast_debug(3, "Opened log file %s \n", global_logfile);
2867  }
2868 
2869  return 0;
2870 }
static void message_destroy_list(void)
Definition: app_minivm.c:833
static struct minivm_template * message_template_find(const char *name)
Definition: app_minivm.c:811
static int apply_general_options(struct ast_variable *var)
Apply general configuration options.
Definition: app_minivm.c:2673
static void timezone_destroy_list(void)
Clear list of timezones.
Definition: app_minivm.c:2562
static int timezone_add(const char *zonename, const char *config)
Add time zone to memory list.
Definition: app_minivm.c:2574
#define VOICEMAIL_CONFIG
Definition: app_minivm.c:552
static char * message_template_parse_emailbody(const char *body)
Parse emailbody template from configuration file.
Definition: app_minivm.c:2646
static int message_template_build(const char *name, struct ast_variable *var)
Definition: app_minivm.c:748
#define SENDMAIL
Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail....
Definition: app_minivm.c:541
static void vmaccounts_destroy_list(void)
Definition: app_minivm.c:922
static int global_saydurationminfo
Definition: app_minivm.c:700
static ast_mutex_t minivmlock
Definition: app_minivm.c:684
static char * chanvar
Definition: app_system.c:113
@ THRESHOLD_SILENCE
Definition: dsp.h:73
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1999
#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:3327
@ 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:768
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:685

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

3387 {
3388  int res;
3389 
3396 
3399  if (res)
3400  return(res);
3401 
3402  if ((res = load_config(0)))
3403  return(res);
3404 
3406 
3407  /* compute the location of the voicemail spool directory */
3408  snprintf(MVM_SPOOL_DIR, sizeof(MVM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
3409 
3410  return res;
3411 }
static int minivm_record_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2082
static int minivm_notify_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2004
static char * app_minivm_delete
Definition: app_minivm.c:568
static char * app_minivm_greet
Definition: app_minivm.c:566
static struct ast_custom_function minivm_account_function
Definition: app_minivm.c:3380
static int minivm_delete_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2325
static int minivm_mwi_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:1966
static int minivm_accmess_exec(struct ast_channel *chan, const char *data)
Record specific messages for voicemail account.
Definition: app_minivm.c:2363
static char * app_minivm_notify
Definition: app_minivm.c:567
static struct ast_cli_entry cli_minivm[]
CLI commands for Mini-voicemail.
Definition: app_minivm.c:3365
static char * app_minivm_record
Definition: app_minivm.c:565
static char * app_minivm_accmess
Definition: app_minivm.c:569
static int minivm_greet_exec(struct ast_channel *chan, const char *data)
Definition: app_minivm.c:2135
static int load_config(int reload)
Load minivoicemail configuration.
Definition: app_minivm.c:2731
static struct ast_custom_function minivm_counter_function
Definition: app_minivm.c:3374
static char * app_minivm_mwi
Definition: app_minivm.c:570
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1543
#define ARRAY_LEN(a)
Definition: utils.h:661

References app_minivm_accmess, app_minivm_delete, app_minivm_greet, app_minivm_mwi, app_minivm_notify, app_minivm_record, ARRAY_LEN, ast_cli_register_multiple, ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_register_application_xml, cli_minivm, load_config(), minivm_accmess_exec(), minivm_account_function, minivm_counter_function, minivm_delete_exec(), minivm_greet_exec(), minivm_mwi_exec(), minivm_notify_exec(), minivm_record_exec(), and MVM_SPOOL_DIR.

◆ make_dir()

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

Definition at line 1391 of file app_minivm.c.

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

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

Referenced by check_dirpath(), and create_dirpath().

◆ message_destroy_list()

static void message_destroy_list ( void  )
static

Definition at line 833 of file app_minivm.c.

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

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

Referenced by load_config().

◆ message_template_build()

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

Definition at line 748 of file app_minivm.c.

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

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

Referenced by load_config().

◆ message_template_create()

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

Definition at line 718 of file app_minivm.c.

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

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

Referenced by message_template_build().

◆ message_template_find()

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

Definition at line 811 of file app_minivm.c.

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

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

Referenced by load_config(), and notify_new_message().

◆ message_template_free()

static void message_template_free ( struct minivm_template template)
static

Definition at line 738 of file app_minivm.c.

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

References ast_free.

Referenced by message_destroy_list().

◆ message_template_parse_emailbody()

static char * message_template_parse_emailbody ( const char *  body)
static

Parse emailbody template from configuration file.

Definition at line 2646 of file app_minivm.c.

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

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

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

Referenced by message_template_build().

◆ minivm_accmess_exec()

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

Record specific messages for voicemail account.

Definition at line 2363 of file app_minivm.c.

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

References ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args, ast_copy_string(), ast_debug, ast_log, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, default_vmformat, minivm_account::domain, error(), FALSE, find_account(), free_user(), global_maxgreet, LOG_ERROR, LOG_WARNING, minivm_accmess_options, MVM_ALLOCED, MVM_SPOOL_DIR, NULL, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_NAME_GREETING, OPT_TEMP_GREETING, OPT_UNAVAIL_GREETING, PATH_MAX, pbx_builtin_setvar_helper(), play_record_review(), prompt, tmp(), TRUE, and minivm_account::username.

Referenced by load_module().

◆ minivm_account_func_read()

static int minivm_account_func_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

${MINIVMACCOUNT()} Dialplan function - reads account data

Definition at line 3094 of file app_minivm.c.

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

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

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

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

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

◆ minivm_delete_exec()

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

Definition at line 2325 of file app_minivm.c.

2326 {
2327  int res = 0;
2328  char filename[BUFSIZ];
2329 
2330  if (!ast_strlen_zero(data)) {
2331  ast_copy_string(filename, (char *) data, sizeof(filename));
2332  } else {
2333  ast_channel_lock(chan);
2334  ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
2335  ast_channel_unlock(chan);
2336  }
2337 
2338  if (ast_strlen_zero(filename)) {
2339  ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
2340  return res;
2341  }
2342 
2343  /* Go ahead and delete audio files from system, they're not needed any more */
2344  /* We should look for both audio and text files here */
2345  if (ast_fileexists(filename, NULL, NULL) > 0) {
2346  res = vm_delete(filename);
2347  if (res) {
2348  ast_debug(2, "Can't delete file: %s\n", filename);
2349  pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
2350  } else {
2351  ast_debug(2, "Deleted voicemail file :: %s \n", filename);
2352  pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
2353  }
2354  } else {
2355  ast_debug(2, "Filename does not exist: %s\n", filename);
2356  pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
2357  }
2358 
2359  return res;
2360 }
static int vm_delete(char *file)
Definition: app_minivm.c:1497
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.

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

Referenced by load_module().

◆ minivm_greet_exec()

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

Definition at line 2135 of file app_minivm.c.

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

References ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args, ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_language(), ast_channel_macrocontext(), ast_channel_priority_set(), ast_copy_flags, ast_copy_string(), ast_debug, ast_exists_extension(), ast_log, ast_play_and_wait(), ast_set_flag, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), check_dirpath(), minivm_account::domain, minivm_account::exit, find_account(), free_user(), invent_message(), LOG_ERROR, minivm_app_options, MVM_ALLOCED, MVM_OPERATOR, MVM_SPOOL_DIR, NULL, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, PATH_MAX, pbx_builtin_setvar_helper(), S_COR, SOUND_INTRO, tmp(), and TRUE.

Referenced by load_module().

◆ minivm_mwi_exec()

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

Definition at line 1966 of file app_minivm.c.

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

Referenced by load_module().

◆ minivm_notify_exec()

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

Definition at line 2004 of file app_minivm.c.

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

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(), format, free_user(), LOG_ERROR, LOG_WARNING, MVM_ALLOCED, name, notify_new_message(), NULL, PATH_MAX, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), S_COR, tmp(), and TRUE.

Referenced by load_module().

◆ minivm_record_exec()

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

Definition at line 2082 of file app_minivm.c.

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

References ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args, ast_copy_flags, ast_log, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_voicemail(), LOG_ERROR, LOG_WARNING, minivm_app_options, OPT_ARG_ARRAY_SIZE, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), leave_vm_options::record_gain, and tmp().

Referenced by load_module().

◆ mvm_user_alloc()

static struct minivm_account* mvm_user_alloc ( void  )
static

Definition at line 907 of file app_minivm.c.

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

References ast_calloc, NULL, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

◆ notify_new_message()

static int notify_new_message ( struct ast_channel chan,
const char *  templatename,
struct minivm_account vmu,
const char *  filename,
long  duration,
const char *  format,
char *  cidnum,
char *  cidname 
)
static

Definition at line 1678 of file app_minivm.c.

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

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, format, minivm_template::locale, LOG_WARNING, message_template_find(), MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, NULL, minivm_account::pager, pbx_builtin_getvar_helper(), minivm_account::ptemplate, RAII_VAR, run_externnotify(), sendmail(), stasis_publish(), strsep(), and minivm_account::username.

Referenced by minivm_notify_exec().

◆ play_record_review()

static int play_record_review ( struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime,
char *  fmt,
int  outsidecaller,
struct minivm_account vmu,
int *  duration,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain 
)
static

Definition at line 1511 of file app_minivm.c.

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

Definition at line 898 of file app_minivm.c.

899 {
902  vmu->volgain = global_volgain;
903 }
static double global_volgain
Definition: app_minivm.c:702
#define AST_FLAGS_ALL
Definition: utils.h:196

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, minivm_account::attachfmt, default_vmformat, global_volgain, globalflags, and minivm_account::volgain.

Referenced by create_vmaccount(), find_user_realtime(), and mvm_user_alloc().

◆ prep_email_sub_vars()

static void prep_email_sub_vars ( struct ast_channel channel,
const struct minivm_account vmu,
const char *  cidnum,
const char *  cidname,
const char *  dur,
const char *  date,
const char *  counter 
)
static

Definition at line 869 of file app_minivm.c.

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

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

Referenced by sendmail().

◆ queue_mwi_event()

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

Definition at line 1951 of file app_minivm.c.

1952 {
1953  char *mailbox, *context;
1954 
1955  mailbox = ast_strdupa(mbx);
1956  context = ast_strdupa(ctx);
1957  if (ast_strlen_zero(context)) {
1958  context = "default";
1959  }
1960 
1961  ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
1962 }
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
#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(), context, and mailbox.

Referenced by minivm_mwi_exec().

◆ reload()

static int reload ( void  )
static

Reload mini voicemail module.

Definition at line 3414 of file app_minivm.c.

3415 {
3416  return(load_config(1));
3417 }

References load_config().

Referenced by handle_minivm_reload(), and load_config().

◆ run_externnotify()

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

Run external notification for voicemail message.

Definition at line 1643 of file app_minivm.c.

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

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

Referenced by notify_new_message().

◆ sendmail()

static int sendmail ( struct minivm_template template,
struct minivm_account vmu,
char *  cidnum,
char *  cidname,
const char *  filename,
char *  format,
int  duration,
int  attach_user_voicemail,
enum mvm_messagetype  type,
const char *  counter 
)
static

Definition at line 1101 of file app_minivm.c.

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

Referenced by notify_new_message().

◆ timezone_add()

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

Add time zone to memory list.

Definition at line 2574 of file app_minivm.c.

2575 {
2576  struct minivm_zone *newzone;
2577  char *msg_format, *timezone_str;
2578 
2579  newzone = ast_calloc(1, sizeof(*newzone));
2580  if (newzone == NULL)
2581  return 0;
2582 
2584 
2585  timezone_str = strsep(&msg_format, "|");
2586  if (!msg_format) {
2587  ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
2588  ast_free(newzone);
2589  return 0;
2590  }
2591 
2592  ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
2593  ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
2594  ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
2595 
2599 
2601 
2602  return 0;
2603 }
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 2562 of file app_minivm.c.

2563 {
2564  struct minivm_zone *this;
2565 
2567  while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list)))
2568  free_zone(this);
2569 
2571 }
static void free_zone(struct minivm_zone *z)
Free Mini Voicemail timezone.
Definition: app_minivm.c:2556

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

Referenced by load_config().

◆ unload_module()

static int unload_module ( void  )
static

Unload mini voicemail module.

Definition at line 3440 of file app_minivm.c.

3441 {
3442  int res;
3443 
3450 
3454 
3455  message_destroy_list(); /* Destroy list of voicemail message templates */
3456  timezone_destroy_list(); /* Destroy list of timezones */
3457  vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
3458 
3459  return res;
3460 }
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.

◆ vm_delete()

static int vm_delete ( char *  file)
static

Definition at line 1497 of file app_minivm.c.

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

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

Referenced by minivm_delete_exec(), and play_record_review().

◆ vm_lock_path()

static int vm_lock_path ( const char *  path)
static

lock directory

only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason

Definition at line 3171 of file app_minivm.c.

3172 {
3173  switch (ast_lock_path(path)) {
3174  case AST_LOCK_TIMEOUT:
3175  return -1;
3176  default:
3177  return 0;
3178  }
3179 }
@ AST_LOCK_TIMEOUT
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2674

References ast_lock_path(), and AST_LOCK_TIMEOUT.

Referenced by access_counter_file().

◆ vmaccounts_destroy_list()

static void vmaccounts_destroy_list ( void  )
static

Definition at line 922 of file app_minivm.c.

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

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

Referenced by load_config().

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

◆ app_minivm_accmess

char* app_minivm_accmess = "MinivmAccMess"
static

Definition at line 569 of file app_minivm.c.

Referenced by load_module().

◆ app_minivm_delete

char* app_minivm_delete = "MinivmDelete"
static

Definition at line 568 of file app_minivm.c.

Referenced by load_module().

◆ app_minivm_greet

char* app_minivm_greet = "MinivmGreet"
static

Definition at line 566 of file app_minivm.c.

Referenced by load_module().

◆ app_minivm_mwi

char* app_minivm_mwi = "MinivmMWI"
static

Definition at line 570 of file app_minivm.c.

Referenced by load_module().

◆ app_minivm_notify

char* app_minivm_notify = "MinivmNotify"
static

Definition at line 567 of file app_minivm.c.

Referenced by load_module().

◆ app_minivm_record

char* app_minivm_record = "MinivmRecord"
static

Definition at line 565 of file app_minivm.c.

Referenced by load_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 3468 of file app_minivm.c.

◆ cli_minivm

struct ast_cli_entry cli_minivm[]
static

CLI commands for Mini-voicemail.

Definition at line 3294 of file app_minivm.c.

Referenced by load_module().

◆ default_vmformat

char default_vmformat[80]
static

◆ global_externnotify

char global_externnotify[160]
static

External notification application

Definition at line 695 of file app_minivm.c.

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

◆ global_logfile

char global_logfile[PATH_MAX]
static

Global log file for messages

Definition at line 696 of file app_minivm.c.

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

◆ global_mailcmd

char global_mailcmd[160]
static

Configurable mail cmd

Definition at line 694 of file app_minivm.c.

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

◆ global_maxgreet

int global_maxgreet
static

Maximum length of prompts

Definition at line 692 of file app_minivm.c.

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

◆ global_maxsilence

int global_maxsilence
static

Maximum silence during recording

Definition at line 691 of file app_minivm.c.

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

◆ global_saydurationminfo

int global_saydurationminfo
static

Definition at line 700 of file app_minivm.c.

Referenced by load_config().

◆ global_silencethreshold

int global_silencethreshold = 128
static

◆ global_stats

struct minivm_stats global_stats
static

Statistics for voicemail.

Definition at line 570 of file app_minivm.c.

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

◆ global_vmmaxmessage

int global_vmmaxmessage
static

Maximum duration of message

Definition at line 690 of file app_minivm.c.

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

◆ global_vmminmessage

int global_vmminmessage
static

Minimum duration of messages

Definition at line 689 of file app_minivm.c.

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

◆ global_volgain

double global_volgain
static

Volume gain for voicmemail via e-mail

Definition at line 702 of file app_minivm.c.

Referenced by populate_defaults().

◆ globalflags

struct ast_flags globalflags = {0}
static

Global voicemail flags

Definition at line 697 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 570 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:3094

Definition at line 3294 of file app_minivm.c.

Referenced by load_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 570 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:3241
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:3294

Definition at line 3294 of file app_minivm.c.

Referenced by load_module().

◆ minivm_zones

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

◆ minivmlock

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

Lock to protect voicemail system

Definition at line 684 of file app_minivm.c.

Referenced by load_config().

◆ minivmlogfile

FILE* minivmlogfile
static

The minivm log file

Definition at line 687 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

◆ minivmloglock

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

Lock to protect voicemail system log file

Definition at line 685 of file app_minivm.c.

Referenced by leave_voicemail().

◆ MVM_SPOOL_DIR

char MVM_SPOOL_DIR[PATH_MAX]
static