Wed Oct 28 11:51:24 2009

Asterisk developer's documentation


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/manager.h"
#include "asterisk/dsp.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/callerid.h"

Include dependency graph for app_minivm.c:

Go to the source code of this file.

Data Structures

struct  b64_baseio
 Structure for base64 encoding. More...
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  message_templates
 The list of e-mail templates. More...
struct  minivm_account
 Structure for linked list of Mini-Voicemail users: minivm_accounts. More...
struct  minivm_accounts
 The list of e-mail accounts. More...
struct  minivm_stats
 Structure for gathering statistics. More...
struct  minivm_template
 Linked list of e-mail templates in various languages These are used as templates for e-mails, pager messages and jabber messages message_templates. More...
struct  minivm_zone
 Voicemail time zones. More...
struct  minivm_zones
 The list of e-mail time zones. More...

Defines

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

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int access_counter_file (char *directory, char *countername, int value, int operand)
 Access counter file, lock directory, read and possibly write it again changed.
static int apply_general_options (struct ast_variable *var)
 Apply general configuration options.
static int b64_inbuf (struct b64_baseio *bio, FILE *fi)
 read buffer from file (base64 conversion)
static int b64_inchar (struct b64_baseio *bio, FILE *fi)
 read character from file to buffer (base64 conversion)
static int b64_ochar (struct b64_baseio *bio, int c, FILE *so)
 write buffer to file (base64 conversion)
static int base_encode (char *filename, FILE *so)
 Encode file to base64 encoding for email attachment (base64 conversion).
static int check_dirpath (char *dest, int len, char *domain, char *username, char *folder)
 Checks if directory exists. Does not create directory, but builds string in dest.
static char * complete_minivm_show_users (const char *line, const char *word, int pos, int state)
static int create_dirpath (char *dest, int len, char *domain, char *username, char *folder)
 basically mkdir -p $dest/$domain/$username/$folder
static int create_vmaccount (char *name, struct ast_variable *var, int realtime)
 Append new mailbox to mailbox list from configuration file.
static struct minivm_accountfind_account (const char *domain, const char *username, int createtemp)
 Find user from static memory object list.
static struct minivm_accountfind_user_realtime (const char *domain, const char *username)
 Find user in realtime storage Returns pointer to minivm_account structure.
static void free_user (struct minivm_account *vmu)
 Free user structure - if it's allocated.
static void free_zone (struct minivm_zone *z)
 Free Mini Voicemail timezone.
static int get_date (char *s, int len)
static char * handle_minivm_list_templates (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI routine for listing templates.
static char * handle_minivm_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload cofiguration.
static char * handle_minivm_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Show settings.
static char * handle_minivm_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show stats.
static char * handle_minivm_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list voicemail accounts.
static char * handle_minivm_show_zones (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail zones in the CLI.
static int invent_message (struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
 Play intro message before recording voicemail.
static int leave_voicemail (struct ast_channel *chan, char *username, struct leave_vm_options *options)
 Record voicemail message, store into file prepared for sending e-mail.
static int load_config (int reload)
 Load minivoicemail configuration.
static int load_module (void)
 Load mini voicemail module.
static char * mailheader_quote (const char *from, char *to, size_t len)
 Fix quote of mail headers for non-ascii characters.
static int make_dir (char *dest, int len, const char *domain, const char *username, const char *folder)
 Create directory based on components.
static void message_destroy_list (void)
 Clear list of templates.
static int message_template_build (const char *name, struct ast_variable *var)
 Build message template from configuration.
static struct minivm_templatemessage_template_create (const char *name)
 Create message template.
static struct minivm_templatemessage_template_find (const char *name)
 Find named template.
static void message_template_free (struct minivm_template *template)
 Release memory allocated by message template.
static char * message_template_parse_emailbody (const char *configuration)
 Parse emailbody template from configuration file.
static char * message_template_parse_filebody (const char *filename)
 Read message template from file.
static int minivm_accmess_exec (struct ast_channel *chan, void *data)
 Record specific messages for voicemail account.
static int minivm_account_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${MINIVMACCOUNT()} Dialplan function - reads account data
static int minivm_counter_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${MINIVMCOUNTER()} Dialplan function - read counters
static int minivm_counter_func_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 ${MINIVMCOUNTER()} Dialplan function - changes counter data
static int minivm_delete_exec (struct ast_channel *chan, void *data)
 Dialplan application to delete voicemail.
static int minivm_greet_exec (struct ast_channel *chan, void *data)
 Play voicemail prompts - either generic or user specific.
static int minivm_notify_exec (struct ast_channel *chan, void *data)
 Notify voicemail account owners - either generic template or user specific.
static int minivm_record_exec (struct ast_channel *chan, void *data)
 Dialplan function to record voicemail.
static struct minivm_accountmvm_user_alloc (void)
 Allocate new vm user and set default values.
static int notify_new_message (struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
 Send message to voicemail account owner.
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct minivm_account *vmu, int *duration, const char *unlockdir, signed char record_gain)
 Record voicemail message & let caller review or re-record it, or set options if applicable.
static void populate_defaults (struct minivm_account *vmu)
 Set default values for Mini-Voicemail users.
static void prep_email_sub_vars (struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
 Prepare for voicemail template by adding channel variables to the channel.
static int reload (void)
 Reload mini voicemail module.
static void run_externnotify (struct ast_channel *chan, struct minivm_account *vmu)
 Run external notification for voicemail message.
static int sendmail (struct minivm_template *template, struct minivm_account *vmu, char *cidnum, char *cidname, const char *filename, char *format, int duration, int attach_user_voicemail, enum mvm_messagetype type, const char *counter)
 Send voicemail with audio file as an attachment.
static int timezone_add (const char *zonename, const char *config)
 Add time zone to memory list.
static void timezone_destroy_list (void)
 Clear list of timezones.
static int unload_module (void)
 Unload mini voicemail module.
static int vm_delete (char *file)
 Delete media files and attribute file.
static int vm_lock_path (const char *path)
 lock directory
static void vmaccounts_destroy_list (void)
 Clear list of users.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static char * app_minivm_accmess = "MinivmAccMess"
static char * app_minivm_delete = "MinivmDelete"
static char * app_minivm_greet = "MinivmGreet"
static char * app_minivm_notify = "MinivmNotify"
static char * app_minivm_record = "MinivmRecord"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_minivm []
 CLI commands for Mini-voicemail.
static char default_vmformat [80]
static char * descrip_minivm_accmess
static char * descrip_minivm_delete
static char * descrip_minivm_greet
static char * descrip_minivm_notify
static char * descrip_minivm_record
static char global_charset [32]
static char global_externnotify [160]
static char global_logfile [PATH_MAX]
static char global_mailcmd [160]
static int global_maxgreet
static int global_maxsilence
static int global_saydurationminfo
static int global_silencethreshold = 128
static struct minivm_stats global_stats
 Statistics for voicemail.
static int global_vmmaxmessage
static int global_vmminmessage
static double global_volgain
static struct ast_flags globalflags = {0}
static struct 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 ast_app_option minivm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 },}
static struct ast_custom_function minivm_counter_function
enum { ... }  minivm_option_args
enum { ... }  minivm_option_flags
static ast_mutex_t minivmlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
FILE * minivmlogfile
static ast_mutex_t minivmloglock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char MVM_SPOOL_DIR [PATH_MAX]
static char * synopsis_minivm_accmess = "Record account specific messages"
static char * synopsis_minivm_delete = "Delete Mini-Voicemail voicemail messages"
static char * synopsis_minivm_greet = "Play Mini-Voicemail prompts"
static char * synopsis_minivm_notify = "Notify voicemail owner about new messages."
static char * synopsis_minivm_record = "Receive Mini-Voicemail and forward via e-mail"


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.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Default username for sending mail is asterisk@localhost

Definition at line 206 of file app_minivm.c.

Referenced by load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 196 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 195 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 451 of file app_minivm.c.

Referenced by message_template_create().

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

Default dateformat, can be overridden in configuration file.

Definition at line 450 of file app_minivm.c.

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 197 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100

#define FALSE   0

Definition at line 178 of file app_minivm.c.

#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

Definition at line 199 of file app_minivm.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 200 of file app_minivm.c.

Referenced by load_config(), and play_message_callerid().

#define MVM_ALLOCED   (1 << 13)

#define MVM_ENVELOPE   (1 << 4)

Definition at line 186 of file app_minivm.c.

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

Definition at line 183 of file app_minivm.c.

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

#define MVM_PBXSKIP   (1 << 9)

Definition at line 187 of file app_minivm.c.

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 184 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)

#define MVM_SVMAIL   (1 << 3)

Definition at line 185 of file app_minivm.c.

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

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

Definition at line 192 of file app_minivm.c.

Referenced by load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 194 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 175 of file app_minivm.c.

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 205 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

Definition at line 203 of file app_minivm.c.

Referenced by create_dirpath().


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 312 of file app_minivm.c.

00312      {
00313    OPT_SILENT =      (1 << 0),
00314    OPT_BUSY_GREETING =    (1 << 1),
00315    OPT_UNAVAIL_GREETING = (1 << 2),
00316    OPT_TEMP_GREETING = (1 << 3),
00317    OPT_NAME_GREETING = (1 << 4),
00318    OPT_RECORDGAIN =  (1 << 5),
00319 } minivm_option_flags;

anonymous enum

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 321 of file app_minivm.c.

00321      {
00322    OPT_ARG_RECORDGAIN = 0,
00323    OPT_ARG_ARRAY_SIZE = 1,
00324 } minivm_option_args;

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 209 of file app_minivm.c.

00209                      {
00210    MVM_MESSAGE_EMAIL,
00211    MVM_MESSAGE_PAGE
00212    /* For trunk: MVM_MESSAGE_JABBER, */
00213 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3132 of file app_minivm.c.

static void __unreg_module ( void   )  [static]

Definition at line 3132 of file app_minivm.c.

static int access_counter_file ( char *  directory,
char *  countername,
int  value,
int  operand 
) [static]

Access counter file, lock directory, read and possibly write it again changed.

Parameters:
directory Directory to crate file in
countername filename
value If set to zero, we only read the variable
operand 0 to read, 1 to set new value, 2 to change
Returns:
-1 on error, otherwise counter value

Definition at line 2821 of file app_minivm.c.

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

Referenced by minivm_counter_func_read(), and minivm_counter_func_write().

02822 {
02823    char filename[BUFSIZ];
02824    char readbuf[BUFSIZ];
02825    FILE *counterfile;
02826    int old = 0, counter = 0;
02827 
02828    /* Lock directory */
02829    if (vm_lock_path(directory)) {
02830       return -1;  /* Could not lock directory */
02831    }
02832    snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
02833    if (operand != 1) {
02834       counterfile = fopen(filename, "r");
02835       if (counterfile) {
02836          if(fgets(readbuf, sizeof(readbuf), counterfile)) {
02837             ast_debug(3, "Read this string from counter file: %s\n", readbuf);
02838             old = counter = atoi(readbuf);
02839          }
02840          fclose(counterfile);
02841       }
02842    }
02843    switch (operand) {
02844    case 0:  /* Read only */
02845       ast_unlock_path(directory);
02846       ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
02847       return counter;
02848       break;
02849    case 1: /* Set new value */
02850       counter = value;
02851       break;
02852    case 2: /* Change value */
02853       counter += value;
02854       if (counter < 0)  /* Don't allow counters to fall below zero */
02855          counter = 0;
02856       break;
02857    }
02858    
02859    /* Now, write the new value to the file */
02860    counterfile = fopen(filename, "w");
02861    if (!counterfile) {
02862       ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
02863       ast_unlock_path(directory);
02864       return -1;  /* Could not open file for writing */
02865    }
02866    fprintf(counterfile, "%d\n\n", counter);
02867    fclose(counterfile);
02868    ast_unlock_path(directory);
02869    ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
02870    return counter;
02871 }

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

Definition at line 2304 of file app_minivm.c.

References ast_config_AST_LOG_DIR, ast_copy_string(), ast_log(), ast_set2_flag, ast_strlen_zero(), ast_true(), default_vmformat, global_externnotify, global_logfile, global_mailcmd, global_maxgreet, global_maxsilence, global_silencethreshold, global_vmmaxmessage, global_vmminmessage, globalflags, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by load_config().

02305 {
02306    int error = 0;
02307 
02308    while (var) {
02309       /* Mail command */
02310       if (!strcmp(var->name, "mailcmd")) {
02311          ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
02312       } else if (!strcmp(var->name, "maxgreet")) {
02313          global_maxgreet = atoi(var->value);
02314       } else if (!strcmp(var->name, "maxsilence")) {
02315          global_maxsilence = atoi(var->value);
02316          if (global_maxsilence > 0)
02317             global_maxsilence *= 1000;
02318       } else if (!strcmp(var->name, "logfile")) {
02319          if (!ast_strlen_zero(var->value) ) {
02320             if(*(var->value) == '/')
02321                ast_copy_string(global_logfile, var->value, sizeof(global_logfile));
02322             else
02323                snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
02324          }
02325       } else if (!strcmp(var->name, "externnotify")) {
02326          /* External voicemail notify application */
02327          ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
02328       } else if (!strcmp(var->name, "silencetreshold")) {
02329          /* Silence treshold */
02330          global_silencethreshold = atoi(var->value);
02331       } else if (!strcmp(var->name, "maxmessage")) {
02332          int x;
02333          if (sscanf(var->value, "%30d", &x) == 1) {
02334             global_vmmaxmessage = x;
02335          } else {
02336             error ++;
02337             ast_log(LOG_WARNING, "Invalid max message time length\n");
02338          }
02339       } else if (!strcmp(var->name, "minmessage")) {
02340          int x;
02341          if (sscanf(var->value, "%30d", &x) == 1) {
02342             global_vmminmessage = x;
02343             if (global_maxsilence <= global_vmminmessage)
02344                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
02345          } else {
02346             error ++;
02347             ast_log(LOG_WARNING, "Invalid min message time length\n");
02348          }
02349       } else if (!strcmp(var->name, "format")) {
02350          ast_copy_string(default_vmformat, var->value, sizeof(default_vmformat));
02351       } else if (!strcmp(var->name, "review")) {
02352          ast_set2_flag((&globalflags), ast_true(var->value), MVM_REVIEW);  
02353       } else if (!strcmp(var->name, "operator")) {
02354          ast_set2_flag((&globalflags), ast_true(var->value), MVM_OPERATOR);   
02355       }
02356       var = var->next;
02357    }
02358    return error;
02359 }

static int b64_inbuf ( struct b64_baseio bio,
FILE *  fi 
) [static]

read buffer from file (base64 conversion)

Definition at line 583 of file app_minivm.c.

References b64_baseio::ateof, B64_BASEMAXINLINE, b64_baseio::iobuf, b64_baseio::iocp, and b64_baseio::iolen.

Referenced by b64_inchar().

00584 {
00585    int l;
00586 
00587    if (bio->ateof)
00588       return 0;
00589 
00590    if ((l = fread(bio->iobuf, 1, B64_BASEMAXINLINE,fi)) <= 0) {
00591       if (ferror(fi))
00592          return -1;
00593 
00594       bio->ateof = 1;
00595       return 0;
00596    }
00597 
00598    bio->iolen= l;
00599    bio->iocp= 0;
00600 
00601    return 1;
00602 }

static int b64_inchar ( struct b64_baseio bio,
FILE *  fi 
) [static]

read character from file to buffer (base64 conversion)

Definition at line 605 of file app_minivm.c.

References b64_inbuf(), b64_baseio::iobuf, b64_baseio::iocp, and b64_baseio::iolen.

Referenced by base_encode().

00606 {
00607    if (bio->iocp >= bio->iolen) {
00608       if (!b64_inbuf(bio, fi))
00609          return EOF;
00610    }
00611 
00612    return bio->iobuf[bio->iocp++];
00613 }

static int b64_ochar ( struct b64_baseio bio,
int  c,
FILE *  so 
) [static]

write buffer to file (base64 conversion)

Definition at line 616 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

00617 {
00618    if (bio->linelength >= B64_BASELINELEN) {
00619       if (fputs(EOL,so) == EOF)
00620          return -1;
00621 
00622       bio->linelength= 0;
00623    }
00624 
00625    if (putc(((unsigned char) c), so) == EOF)
00626       return -1;
00627 
00628    bio->linelength++;
00629 
00630    return 1;
00631 }

static int base_encode ( char *  filename,
FILE *  so 
) [static]

Encode file to base64 encoding for email attachment (base64 conversion).

Definition at line 634 of file app_minivm.c.

References ast_log(), B64_BASEMAXINLINE, b64_inchar(), b64_ochar(), EOL, errno, b64_baseio::iocp, and LOG_WARNING.

Referenced by add_email_attachment(), and sendmail().

00635 {
00636    unsigned char dtable[B64_BASEMAXINLINE];
00637    int i,hiteof= 0;
00638    FILE *fi;
00639    struct b64_baseio bio;
00640 
00641    memset(&bio, 0, sizeof(bio));
00642    bio.iocp = B64_BASEMAXINLINE;
00643 
00644    if (!(fi = fopen(filename, "rb"))) {
00645       ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
00646       return -1;
00647    }
00648 
00649    for (i= 0; i<9; i++) {
00650       dtable[i]= 'A'+i;
00651       dtable[i+9]= 'J'+i;
00652       dtable[26+i]= 'a'+i;
00653       dtable[26+i+9]= 'j'+i;
00654    }
00655    for (i= 0; i < 8; i++) {
00656       dtable[i+18]= 'S'+i;
00657       dtable[26+i+18]= 's'+i;
00658    }
00659    for (i= 0; i < 10; i++) {
00660       dtable[52+i]= '0'+i;
00661    }
00662    dtable[62]= '+';
00663    dtable[63]= '/';
00664 
00665    while (!hiteof){
00666       unsigned char igroup[3], ogroup[4];
00667       int c,n;
00668 
00669       igroup[0]= igroup[1]= igroup[2]= 0;
00670 
00671       for (n= 0; n < 3; n++) {
00672          if ((c = b64_inchar(&bio, fi)) == EOF) {
00673             hiteof= 1;
00674             break;
00675          }
00676          igroup[n]= (unsigned char)c;
00677       }
00678 
00679       if (n> 0) {
00680          ogroup[0]= dtable[igroup[0]>>2];
00681          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
00682          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
00683          ogroup[3]= dtable[igroup[2]&0x3F];
00684 
00685          if (n<3) {
00686             ogroup[3]= '=';
00687 
00688             if (n<2)
00689                ogroup[2]= '=';
00690          }
00691 
00692          for (i= 0;i<4;i++)
00693             b64_ochar(&bio, ogroup[i], so);
00694       }
00695    }
00696 
00697    /* Put end of line - line feed */
00698    if (fputs(EOL, so) == EOF)
00699       return 0;
00700 
00701    fclose(fi);
00702 
00703    return 1;
00704 }

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

Checks if directory exists. Does not create directory, but builds string in dest.

Parameters:
dest String. base directory.
len Int. Length base directory string.
domain String. Ignored if is null or empty string.
username String. Ignored if is null or empty string.
folder String. Ignored if is null or empty string.
Returns:
0 on failure, 1 on success.

Definition at line 1130 of file app_minivm.c.

References FALSE, make_dir(), and TRUE.

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

01131 {
01132    struct stat filestat;
01133    make_dir(dest, len, domain, username, folder ? folder : "");
01134    if (stat(dest, &filestat)== -1)
01135       return FALSE;
01136    else
01137       return TRUE;
01138 }

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

Definition at line 2540 of file app_minivm.c.

References AST_LIST_TRAVERSE, ast_strdup, and minivm_account::domain.

Referenced by handle_minivm_show_users().

02541 {
02542    int which = 0;
02543    int wordlen;
02544    struct minivm_account *vmu;
02545    const char *domain = "";
02546 
02547    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
02548    if (pos > 4)
02549       return NULL;
02550    if (pos == 3)
02551       return (state == 0) ? ast_strdup("for") : NULL;
02552    wordlen = strlen(word);
02553    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02554       if (!strncasecmp(word, vmu->domain, wordlen)) {
02555          if (domain && strcmp(domain, vmu->domain) && ++which > state)
02556             return ast_strdup(vmu->domain);
02557          /* ignore repeated domains ? */
02558          domain = vmu->domain;
02559       }
02560    }
02561    return NULL;
02562 }

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

basically mkdir -p $dest/$domain/$username/$folder

Parameters:
dest String. base directory.
len Length of directory string
domain String. Ignored if is null or empty string.
folder String. Ignored if is null or empty string.
username String. Ignored if is null or empty string.
Returns:
-1 on failure, 0 on success.

Definition at line 1148 of file app_minivm.c.

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

Referenced by add_email_attachment(), copy_message(), invent_message(), leave_voicemail(), minivm_counter_func_read(), minivm_counter_func_write(), open_mailbox(), and save_to_folder().

01149 {
01150    int res;
01151    make_dir(dest, len, domain, username, folder);
01152    if ((res = ast_mkdir(dest, 0777))) {
01153       ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01154       return -1;
01155    }
01156    ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
01157    return 0;
01158 }

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

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

Referenced by find_user_realtime(), and load_config().

02089 {
02090    struct minivm_account *vmu;
02091    char *domain;
02092    char *username;
02093    char accbuf[BUFSIZ];
02094 
02095    ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
02096 
02097    ast_copy_string(accbuf, name, sizeof(accbuf));
02098    username = accbuf;
02099    domain = strchr(accbuf, '@');
02100    if (domain) {
02101       *domain = '\0';
02102       domain++;
02103    }
02104    if (ast_strlen_zero(domain)) {
02105       ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
02106       return 0;
02107    }
02108 
02109    ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
02110 
02111    /* Allocate user account */
02112    vmu = ast_calloc(1, sizeof(*vmu));
02113    if (!vmu)
02114       return 0;
02115    
02116    ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
02117    ast_copy_string(vmu->username, username, sizeof(vmu->username));
02118 
02119    populate_defaults(vmu);
02120 
02121    ast_debug(3, "...Configuring account %s\n", name);
02122 
02123    while (var) {
02124       ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
02125       if (!strcasecmp(var->name, "serveremail")) {
02126          ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
02127       } else if (!strcasecmp(var->name, "email")) {
02128          ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
02129       } else if (!strcasecmp(var->name, "accountcode")) {
02130          ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
02131       } else if (!strcasecmp(var->name, "pincode")) {
02132          ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
02133       } else if (!strcasecmp(var->name, "domain")) {
02134          ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
02135       } else if (!strcasecmp(var->name, "language")) {
02136          ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
02137       } else if (!strcasecmp(var->name, "timezone")) {
02138          ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
02139       } else if (!strcasecmp(var->name, "externnotify")) {
02140          ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
02141       } else if (!strcasecmp(var->name, "etemplate")) {
02142          ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
02143       } else if (!strcasecmp(var->name, "ptemplate")) {
02144          ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
02145       } else if (!strcasecmp(var->name, "fullname")) {
02146          ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
02147       } else if (!strcasecmp(var->name, "setvar")) {
02148          char *varval;
02149          char *varname = ast_strdupa(var->value);
02150          struct ast_variable *tmpvar;
02151 
02152          if (varname && (varval = strchr(varname, '='))) {
02153             *varval = '\0';
02154             varval++;
02155             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
02156                tmpvar->next = vmu->chanvars;
02157                vmu->chanvars = tmpvar;
02158             }
02159          }
02160       } else if (!strcasecmp(var->name, "pager")) {
02161          ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
02162       } else if (!strcasecmp(var->name, "volgain")) {
02163          sscanf(var->value, "%30lf", &vmu->volgain);
02164       } else {
02165          ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
02166       }
02167       var = var->next;
02168    }
02169    ast_debug(3, "...Linking account %s\n", name);
02170    
02171    AST_LIST_LOCK(&minivm_accounts);
02172    AST_LIST_INSERT_TAIL(&minivm_accounts, vmu, list);
02173    AST_LIST_UNLOCK(&minivm_accounts);
02174 
02175    global_stats.voicemailaccounts++;
02176 
02177    ast_debug(2, "MINIVM :: 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)" : "");
02178    return 0;
02179 }

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

Find user from static memory object list.

Definition at line 809 of file app_minivm.c.

References ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set2_flag, ast_strlen_zero(), minivm_account::domain, find_user_realtime(), LOG_NOTICE, MVM_ALLOCED, mvm_user_alloc(), TRUE, and minivm_account::username.

Referenced by leave_voicemail(), minivm_accmess_exec(), minivm_account_func_read(), minivm_counter_func_read(), minivm_counter_func_write(), minivm_greet_exec(), and minivm_notify_exec().

00810 {
00811    struct minivm_account *vmu = NULL, *cur;
00812 
00813 
00814    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
00815       ast_log(LOG_NOTICE, "No username or domain? \n");
00816       return NULL;
00817    }
00818    ast_debug(3, "Looking for voicemail user %s in domain %s\n", username, domain);
00819 
00820    AST_LIST_LOCK(&minivm_accounts);
00821    AST_LIST_TRAVERSE(&minivm_accounts, cur, list) {
00822       /* Is this the voicemail account we're looking for? */
00823       if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
00824          break;
00825    }
00826    AST_LIST_UNLOCK(&minivm_accounts);
00827 
00828    if (cur) {
00829       ast_debug(3, "Found account for %s@%s\n", username, domain);
00830       vmu = cur;
00831 
00832    } else
00833       vmu = find_user_realtime(domain, username);
00834 
00835    if (createtemp && !vmu) {
00836       /* Create a temporary user, send e-mail and be gone */
00837       vmu = mvm_user_alloc();
00838       ast_set2_flag(vmu, TRUE, MVM_ALLOCED); 
00839       if (vmu) {
00840          ast_copy_string(vmu->username, username, sizeof(vmu->username));
00841          ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
00842          ast_debug(1, "Created temporary account\n");
00843       }
00844 
00845    }
00846    return vmu;
00847 }

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

Find user in realtime storage Returns pointer to minivm_account structure.

Definition at line 852 of file app_minivm.c.

References ast_copy_string(), ast_free, ast_load_realtime(), ast_variables_destroy(), create_vmaccount(), MAXHOSTNAMELEN, mvm_user_alloc(), populate_defaults(), SENTINEL, TRUE, minivm_account::username, and var.

Referenced by find_account(), and find_user().

00853 {
00854    struct ast_variable *var;
00855    struct minivm_account *retval;
00856    char name[MAXHOSTNAMELEN];
00857 
00858    retval = mvm_user_alloc();
00859    if (!retval)
00860       return NULL;
00861 
00862    if (username) 
00863       ast_copy_string(retval->username, username, sizeof(retval->username));
00864 
00865    populate_defaults(retval);
00866    var = ast_load_realtime("minivm", "username", username, "domain", domain, SENTINEL);
00867 
00868    if (!var) {
00869       ast_free(retval);
00870       return NULL;
00871    }
00872 
00873    snprintf(name, sizeof(name), "%s@%s", username, domain);
00874    create_vmaccount(name, var, TRUE);
00875 
00876    ast_variables_destroy(var);
00877    return retval;
00878 }

static void free_user ( struct minivm_account vmu  )  [static]

Free user structure - if it's allocated.

Definition at line 717 of file app_minivm.c.

References ast_free, ast_variables_destroy(), and minivm_account::chanvars.

Referenced by forward_message(), free_vm_users(), leave_voicemail(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), minivm_notify_exec(), and vm_execmain().

00718 {
00719    if (vmu->chanvars)
00720       ast_variables_destroy(vmu->chanvars);
00721    ast_free(vmu);
00722 }

static void free_zone ( struct minivm_zone z  )  [static]

Free Mini Voicemail timezone.

Definition at line 2182 of file app_minivm.c.

References ast_free.

02183 {
02184    ast_free(z);
02185 }

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

Definition at line 706 of file app_minivm.c.

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

Referenced by leave_voicemail(), and tds_log().

00707 {
00708    struct ast_tm tm;
00709    struct timeval now = ast_tvnow();
00710 
00711    ast_localtime(&now, &tm, NULL);
00712    return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
00713 }

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

References ast_cli_args::argc, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HVLT_OUTPUT_FORMAT, and ast_cli_entry::usage.

02500 {
02501    struct minivm_template *this;
02502 #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
02503    int count = 0;
02504 
02505    switch (cmd) {
02506    case CLI_INIT:
02507       e->command = "minivm list templates";
02508       e->usage =
02509          "Usage: minivm list templates\n"
02510          "       Lists message templates for e-mail, paging and IM\n";
02511       return NULL;
02512    case CLI_GENERATE:
02513       return NULL;
02514    }
02515 
02516    if (a->argc > 3)
02517       return CLI_SHOWUSAGE;
02518 
02519    AST_LIST_LOCK(&message_templates);
02520    if (AST_LIST_EMPTY(&message_templates)) {
02521       ast_cli(a->fd, "There are no message templates defined\n");
02522       AST_LIST_UNLOCK(&message_templates);
02523       return CLI_FAILURE;
02524    }
02525    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
02526    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
02527    AST_LIST_TRAVERSE(&message_templates, this, list) {
02528       ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name, 
02529          this->charset ? this->charset : "-", 
02530          this->locale ? this->locale : "-",
02531          this->attachment ? "Yes" : "No",
02532          this->subject ? this->subject : "-");
02533       count++;
02534    }
02535    AST_LIST_UNLOCK(&message_templates);
02536    ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
02537    return CLI_SUCCESS;
02538 }

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

Reload cofiguration.

Definition at line 3087 of file app_minivm.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, reload, and ast_cli_entry::usage.

03088 {
03089    
03090    switch (cmd) {
03091    case CLI_INIT:
03092       e->command = "minivm reload";
03093       e->usage =
03094          "Usage: minivm reload\n"
03095          "       Reload mini-voicemail configuration and reset statistics\n";
03096       return NULL;
03097    case CLI_GENERATE:
03098       return NULL;
03099    }
03100    
03101    reload();
03102    ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
03103    return CLI_SUCCESS;
03104 }

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

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

02651 {
02652    switch (cmd) {
02653    case CLI_INIT:
02654       e->command = "minivm show settings";
02655       e->usage =
02656          "Usage: minivm show settings\n"
02657          "       Display Mini-Voicemail general settings\n";
02658       return NULL;
02659    case CLI_GENERATE:
02660       return NULL;
02661    }
02662 
02663    ast_cli(a->fd, "* Mini-Voicemail general settings\n");
02664    ast_cli(a->fd, "  -------------------------------\n");
02665    ast_cli(a->fd, "\n");
02666    ast_cli(a->fd, "  Mail command (shell):               %s\n", global_mailcmd);
02667    ast_cli(a->fd, "  Max silence:                        %d\n", global_maxsilence);
02668    ast_cli(a->fd, "  Silence threshold:                  %d\n", global_silencethreshold);
02669    ast_cli(a->fd, "  Max message length (secs):          %d\n", global_vmmaxmessage);
02670    ast_cli(a->fd, "  Min message length (secs):          %d\n", global_vmminmessage);
02671    ast_cli(a->fd, "  Default format:                     %s\n", default_vmformat);
02672    ast_cli(a->fd, "  Extern notify (shell):              %s\n", global_externnotify);
02673    ast_cli(a->fd, "  Logfile:                            %s\n", global_logfile[0] ? global_logfile : "<disabled>");
02674    ast_cli(a->fd, "  Operator exit:                      %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
02675    ast_cli(a->fd, "  Message review:                     %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
02676 
02677    ast_cli(a->fd, "\n");
02678    return CLI_SUCCESS;
02679 }

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

Show stats.

Definition at line 2682 of file app_minivm.c.

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

02683 {
02684    struct ast_tm timebuf;
02685    char buf[BUFSIZ];
02686 
02687    switch (cmd) {
02688    
02689    case CLI_INIT:
02690       e->command = "minivm show stats";
02691       e->usage =
02692          "Usage: minivm show stats\n"
02693          "       Display Mini-Voicemail counters\n";
02694       return NULL;
02695    case CLI_GENERATE:
02696       return NULL;
02697    }
02698 
02699    ast_cli(a->fd, "* Mini-Voicemail statistics\n");
02700    ast_cli(a->fd, "  -------------------------\n");
02701    ast_cli(a->fd, "\n");
02702    ast_cli(a->fd, "  Voicemail accounts:                  %5d\n", global_stats.voicemailaccounts);
02703    ast_cli(a->fd, "  Templates:                           %5d\n", global_stats.templates);
02704    ast_cli(a->fd, "  Timezones:                           %5d\n", global_stats.timezones);
02705    if (global_stats.receivedmessages == 0) {
02706       ast_cli(a->fd, "  Received messages since last reset:  <none>\n");
02707    } else {
02708       ast_cli(a->fd, "  Received messages since last reset:  %d\n", global_stats.receivedmessages);
02709       ast_localtime(&global_stats.lastreceived, &timebuf, NULL);
02710       ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
02711       ast_cli(a->fd, "  Last received voicemail:             %s\n", buf);
02712    }
02713    ast_localtime(&global_stats.reset, &timebuf, NULL);
02714    ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
02715    ast_cli(a->fd, "  Last reset:                          %s\n", buf);
02716 
02717    ast_cli(a->fd, "\n");
02718    return CLI_SUCCESS;
02719 }

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

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, minivm_account::attachfmt, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_minivm_show_users(), minivm_account::domain, minivm_account::etemplate, ast_cli_args::fd, minivm_account::fullname, HMSU_OUTPUT_FORMAT, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, minivm_account::ptemplate, ast_cli_entry::usage, minivm_account::username, ast_cli_args::word, and minivm_account::zonetag.

02566 {
02567    struct minivm_account *vmu;
02568 #define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
02569    int count = 0;
02570 
02571    switch (cmd) {
02572    case CLI_INIT:
02573       e->command = "minivm list accounts";
02574       e->usage =
02575          "Usage: minivm list accounts\n"
02576          "       Lists all mailboxes currently set up\n";
02577       return NULL;
02578    case CLI_GENERATE:
02579       return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
02580    }
02581 
02582    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
02583       return CLI_SHOWUSAGE;
02584    if ((a->argc == 5) && strcmp(a->argv[3],"for"))
02585       return CLI_SHOWUSAGE;
02586 
02587    AST_LIST_LOCK(&minivm_accounts);
02588    if (AST_LIST_EMPTY(&minivm_accounts)) {
02589       ast_cli(a->fd, "There are no voicemail users currently defined\n");
02590       AST_LIST_UNLOCK(&minivm_accounts);
02591       return CLI_FAILURE;
02592    }
02593    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
02594    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
02595    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02596       char tmp[256] = "";
02597       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
02598          count++;
02599          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
02600          ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, vmu->etemplate ? vmu->etemplate : "-", 
02601             vmu->ptemplate ? vmu->ptemplate : "-",
02602             vmu->zonetag ? vmu->zonetag : "-", 
02603             vmu->attachfmt ? vmu->attachfmt : "-",
02604             vmu->fullname);
02605       }
02606    }
02607    AST_LIST_UNLOCK(&minivm_accounts);
02608    ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
02609    return CLI_SUCCESS;
02610 }

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

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HMSZ_OUTPUT_FORMAT, minivm_zone::msg_format, minivm_zone::name, minivm_zone::timezone, and ast_cli_entry::usage.

02614 {
02615    struct minivm_zone *zone;
02616 #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
02617    char *res = CLI_SUCCESS;
02618 
02619    switch (cmd) {
02620    case CLI_INIT:
02621       e->command = "minivm list zones";
02622       e->usage =
02623          "Usage: minivm list zones\n"
02624          "       Lists zone message formats\n";
02625       return NULL;
02626    case CLI_GENERATE:
02627       return NULL;
02628    }
02629 
02630    if (a->argc != e->args)
02631       return CLI_SHOWUSAGE;
02632 
02633    AST_LIST_LOCK(&minivm_zones);
02634    if (!AST_LIST_EMPTY(&minivm_zones)) {
02635       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
02636       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
02637       AST_LIST_TRAVERSE(&minivm_zones, zone, list) {
02638          ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
02639       }
02640    } else {
02641       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
02642       res = CLI_FAILURE;
02643    }
02644    AST_LIST_UNLOCK(&minivm_zones);
02645 
02646    return res;
02647 }

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

Play intro message before recording voicemail.

Definition at line 1163 of file app_minivm.c.

References ast_debug, ast_fileexists(), ast_say_digit_str(), ast_streamfile(), ast_waitstream(), FALSE, and ast_channel::language.

Referenced by leave_voicemail(), and minivm_greet_exec().

01164 {
01165    int res;
01166    char fn[PATH_MAX];
01167 
01168    ast_debug(2, "Still preparing to play message ...\n");
01169 
01170    snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
01171 
01172    if (ast_fileexists(fn, NULL, NULL) > 0) {
01173       res = ast_streamfile(chan, fn, chan->language);
01174       if (res) 
01175          return -1;
01176       res = ast_waitstream(chan, ecodes);
01177       if (res) 
01178          return res;
01179    } else {
01180       int numericusername = 1;
01181       char *i = username;
01182 
01183       ast_debug(2, "No personal prompts. Using default prompt set for language\n");
01184       
01185       while (*i)  {
01186          ast_debug(2, "Numeric? Checking %c\n", *i);
01187          if (!isdigit(*i)) {
01188             numericusername = FALSE;
01189             break;
01190          }
01191          i++;
01192       }
01193 
01194       if (numericusername) {
01195          if(ast_streamfile(chan, "vm-theperson", chan->language))
01196             return -1;
01197          if ((res = ast_waitstream(chan, ecodes)))
01198             return res;
01199    
01200          res = ast_say_digit_str(chan, username, ecodes, chan->language);
01201          if (res)
01202             return res;
01203       } else {
01204          if(ast_streamfile(chan, "vm-theextensionis", chan->language))
01205             return -1;
01206          if ((res = ast_waitstream(chan, ecodes)))
01207             return res;
01208       }
01209    }
01210 
01211    res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", chan->language);
01212    if (res)
01213       return -1;
01214    res = ast_waitstream(chan, ecodes);
01215    return res;
01216 }

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

Record voicemail message, store into file prepared for sending e-mail.

Definition at line 1458 of file app_minivm.c.

References minivm_account::accountcode, ast_callerid_merge(), ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_localtime(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_streamfile(), ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_tvnow(), ast_verb, ast_waitstream(), minivm_account::attachfmt, check_dirpath(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, create_dirpath(), default_vmformat, minivm_account::domain, errno, ast_channel::exten, find_account(), free_user(), get_date(), global_stats, global_vmmaxmessage, global_vmminmessage, ast_channel::language, minivm_stats::lastreceived, LOG_ERROR, LOG_WARNING, ast_channel::macrocontext, minivmlogfile, minivmloglock, MVM_ALLOCED, ast_channel::name, pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, minivm_stats::receivedmessages, leave_vm_options::record_gain, and TRUE.

Referenced by advanced_options(), forward_message(), minivm_record_exec(), and vm_exec().

01459 {
01460    char tmptxtfile[PATH_MAX];
01461    char callerid[256];
01462    FILE *txt;
01463    int res = 0, txtdes;
01464    int msgnum;
01465    int duration = 0;
01466    char date[256];
01467    char tmpdir[PATH_MAX];
01468    char ext_context[256] = "";
01469    char fmt[80];
01470    char *domain;
01471    char tmp[256] = "";
01472    struct minivm_account *vmu;
01473    int userdir;
01474 
01475    ast_copy_string(tmp, username, sizeof(tmp));
01476    username = tmp;
01477    domain = strchr(tmp, '@');
01478    if (domain) {
01479       *domain = '\0';
01480       domain++;
01481    }
01482 
01483    if (!(vmu = find_account(domain, username, TRUE))) {
01484       /* We could not find user, let's exit */
01485       ast_log(LOG_ERROR, "Can't allocate temporary account for '%s@%s'\n", username, domain);
01486       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01487       return 0;
01488    }
01489 
01490    /* Setup pre-file if appropriate */
01491    if (strcmp(vmu->domain, "localhost"))
01492       snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
01493    else
01494       ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
01495 
01496    /* The meat of recording the message...  All the announcements and beeps have been played*/
01497    if (ast_strlen_zero(vmu->attachfmt))
01498       ast_copy_string(fmt, default_vmformat, sizeof(fmt));
01499    else
01500       ast_copy_string(fmt, vmu->attachfmt, sizeof(fmt));
01501 
01502    if (ast_strlen_zero(fmt)) {
01503       ast_log(LOG_WARNING, "No format for saving voicemail? Default %s\n", default_vmformat);
01504       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01505       return res;
01506    }
01507    msgnum = 0;
01508 
01509    userdir = check_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
01510 
01511    /* If we have no user directory, use generic temporary directory */
01512    if (!userdir) {
01513       create_dirpath(tmpdir, sizeof(tmpdir), "0000_minivm_temp", "mediafiles", "");
01514       ast_debug(3, "Creating temporary directory %s\n", tmpdir);
01515    }
01516 
01517 
01518    snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
01519    
01520 
01521    /* XXX This file needs to be in temp directory */
01522    txtdes = mkstemp(tmptxtfile);
01523    if (txtdes < 0) {
01524       ast_log(LOG_ERROR, "Unable to create message file %s: %s\n", tmptxtfile, strerror(errno));
01525       res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
01526       if (!res)
01527          res = ast_waitstream(chan, "");
01528       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01529       return res;
01530    }
01531 
01532    if (res >= 0) {
01533       /* Unless we're *really* silent, try to send the beep */
01534       res = ast_streamfile(chan, "beep", chan->language);
01535       if (!res)
01536          res = ast_waitstream(chan, "");
01537    }
01538 
01539    /* OEJ XXX Maybe this can be turned into a log file? Hmm. */
01540    /* Store information */
01541    ast_debug(2, "Open file for metadata: %s\n", tmptxtfile);
01542 
01543    res = play_record_review(chan, NULL, tmptxtfile, global_vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
01544 
01545    txt = fdopen(txtdes, "w+");
01546    if (!txt) {
01547       ast_log(LOG_WARNING, "Error opening text file for output\n");
01548    } else {
01549       struct ast_tm tm;
01550       struct timeval now = ast_tvnow();
01551       char timebuf[30];
01552       char logbuf[BUFSIZ];
01553       get_date(date, sizeof(date));
01554       ast_localtime(&now, &tm, NULL);
01555       ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
01556       
01557       snprintf(logbuf, sizeof(logbuf),
01558          /* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
01559          "%s:%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
01560          username,
01561          chan->context,
01562          chan->macrocontext, 
01563          chan->exten,
01564          chan->priority,
01565          chan->name,
01566          ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
01567          date, 
01568          timebuf,
01569          duration,
01570          duration < global_vmminmessage ? "IGNORED" : "OK",
01571          vmu->accountcode
01572       ); 
01573       fprintf(txt, "%s", logbuf);
01574       if (minivmlogfile) {
01575          ast_mutex_lock(&minivmloglock);
01576          fprintf(minivmlogfile, "%s", logbuf);
01577          ast_mutex_unlock(&minivmloglock);
01578       }
01579 
01580       if (duration < global_vmminmessage) {
01581          ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, global_vmminmessage);
01582          fclose(txt);
01583          ast_filedelete(tmptxtfile, NULL);
01584          unlink(tmptxtfile);
01585          pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01586          return 0;
01587       } 
01588       fclose(txt); /* Close log file */
01589       if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
01590          ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
01591          unlink(tmptxtfile);
01592          pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01593          if(ast_test_flag(vmu, MVM_ALLOCED))
01594             free_user(vmu);
01595          return 0;
01596       }
01597 
01598       /* Set channel variables for the notify application */
01599       pbx_builtin_setvar_helper(chan, "MVM_FILENAME", tmptxtfile);
01600       snprintf(timebuf, sizeof(timebuf), "%d", duration);
01601       pbx_builtin_setvar_helper(chan, "MVM_DURATION", timebuf);
01602       pbx_builtin_setvar_helper(chan, "MVM_FORMAT", fmt);
01603 
01604    }
01605    global_stats.lastreceived = ast_tvnow();
01606    global_stats.receivedmessages++;
01607 // /* Go ahead and delete audio files from system, they're not needed any more */
01608 // if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
01609 //    ast_filedelete(tmptxtfile, NULL);
01610 //     /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
01611 //    ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
01612 // }
01613 
01614    if (res > 0)
01615       res = 0;
01616 
01617    if(ast_test_flag(vmu, MVM_ALLOCED))
01618       free_user(vmu);
01619 
01620    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
01621    return res;
01622 }

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2362 of file app_minivm.c.

References apply_general_options(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set2_flag, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), ast_variable_retrieve(), chanvar, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, create_vmaccount(), default_vmformat, errno, FALSE, global_charset, global_externnotify, global_logfile, global_mailcmd, global_maxgreet, global_maxsilence, global_saydurationminfo, global_silencethreshold, global_stats, global_vmmaxmessage, global_vmminmessage, globalflags, LOG_ERROR, LOG_WARNING, message_destroy_list(), message_template_build(), message_template_find(), message_template_parse_emailbody(), minivmlock, minivmlogfile, MVM_OPERATOR, MVM_REVIEW, ast_variable::name, ast_variable::next, minivm_stats::reset, SENDMAIL, THRESHOLD_SILENCE, timezone_add(), timezone_destroy_list(), TRUE, ast_variable::value, var, vmaccounts_destroy_list(), and VOICEMAIL_CONFIG.

02363 {
02364    struct ast_config *cfg;
02365    struct ast_variable *var;
02366    char *cat;
02367    const char *chanvar;
02368    int error = 0;
02369    struct minivm_template *template;
02370    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02371 
02372    cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
02373    if (cfg == CONFIG_STATUS_FILEUNCHANGED)
02374       return 0;
02375 
02376    ast_mutex_lock(&minivmlock);
02377 
02378    /* Destroy lists to reconfigure */
02379    message_destroy_list();    /* Destroy list of voicemail message templates */
02380    timezone_destroy_list();   /* Destroy list of timezones */
02381    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
02382    ast_debug(2, "Destroyed memory objects...\n");
02383 
02384    /* First, set some default settings */
02385    global_externnotify[0] = '\0';
02386    global_logfile[0] = '\0';
02387    global_vmmaxmessage = 2000;
02388    global_maxgreet = 2000;
02389    global_vmminmessage = 0;
02390    strcpy(global_mailcmd, SENDMAIL);
02391    global_maxsilence = 0;
02392    global_saydurationminfo = 2;
02393    ast_copy_string(default_vmformat, "wav", sizeof(default_vmformat));
02394    ast_set2_flag((&globalflags), FALSE, MVM_REVIEW);  
02395    ast_set2_flag((&globalflags), FALSE, MVM_OPERATOR);   
02396    strcpy(global_charset, "ISO-8859-1");
02397    /* Reset statistics */
02398    memset(&global_stats, 0, sizeof(global_stats));
02399    global_stats.reset = ast_tvnow();
02400 
02401    global_silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
02402 
02403    /* Make sure we could load configuration file */
02404    if (!cfg) {
02405       ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
02406       ast_mutex_unlock(&minivmlock);
02407       return 0;
02408    }
02409 
02410    ast_debug(2, "Loaded configuration file, now parsing\n");
02411 
02412    /* General settings */
02413 
02414    cat = ast_category_browse(cfg, NULL);
02415    while (cat) {
02416       ast_debug(3, "Found configuration section [%s]\n", cat);
02417       if (!strcasecmp(cat, "general")) {
02418          /* Nothing right now */
02419          error += apply_general_options(ast_variable_browse(cfg, cat));
02420       } else if (!strncasecmp(cat, "template-", 9))  {
02421          /* Template */
02422          char *name = cat + 9;
02423 
02424          /* Now build and link template to list */
02425          error += message_template_build(name, ast_variable_browse(cfg, cat));
02426       } else {
02427          var = ast_variable_browse(cfg, cat);
02428          if (!strcasecmp(cat, "zonemessages")) {
02429             /* Timezones in this context */
02430             while (var) {
02431                timezone_add(var->name, var->value);
02432                var = var->next;
02433             }
02434          } else {
02435             /* Create mailbox from this */
02436             error += create_vmaccount(cat, var, FALSE);
02437          }
02438       }
02439       /* Find next section in configuration file */
02440       cat = ast_category_browse(cfg, cat);
02441    }
02442 
02443    /* Configure the default email template */
02444    message_template_build("email-default", NULL);
02445    template = message_template_find("email-default");
02446 
02447    /* Load date format config for voicemail mail */
02448    if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat"))) 
02449       ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
02450    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
02451       ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
02452    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
02453       ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
02454    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
02455       ast_copy_string(template->charset, chanvar, sizeof(template->charset));
02456    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject"))) 
02457       ast_copy_string(template->subject, chanvar, sizeof(template->subject));
02458    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody"))) 
02459       template->body = message_template_parse_emailbody(chanvar);
02460    template->attachment = TRUE;
02461 
02462    message_template_build("pager-default", NULL);
02463    template = message_template_find("pager-default");
02464    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
02465       ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
02466    if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
02467       ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
02468    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
02469       ast_copy_string(template->charset, chanvar, sizeof(template->charset));
02470    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
02471       ast_copy_string(template->subject, chanvar,sizeof(template->subject));
02472    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody"))) 
02473       template->body = message_template_parse_emailbody(chanvar);
02474    template->attachment = FALSE;
02475 
02476    if (error)
02477       ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
02478 
02479    ast_mutex_unlock(&minivmlock);
02480    ast_config_destroy(cfg);
02481 
02482    /* Close log file if it's open and disabled */
02483    if(minivmlogfile)
02484       fclose(minivmlogfile);
02485 
02486    /* Open log file if it's enabled */
02487    if(!ast_strlen_zero(global_logfile)) {
02488       minivmlogfile = fopen(global_logfile, "a");
02489       if(!minivmlogfile)
02490          ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
02491       if (minivmlogfile)
02492          ast_debug(3, "Opened log file %s \n", global_logfile);
02493    }
02494 
02495    return 0;
02496 }

static int load_module ( void   )  [static]

Load mini voicemail module.

Definition at line 3054 of file app_minivm.c.

References ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_register_application, cli_minivm, load_config(), minivm_accmess_exec(), minivm_account_function, minivm_counter_function, minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), and minivm_record_exec().

static char* mailheader_quote ( const char *  from,
char *  to,
size_t  len 
) [static]

Fix quote of mail headers for non-ascii characters.

Definition at line 765 of file app_minivm.c.

Referenced by sendmail().

00766 {
00767    char *ptr = to;
00768    *ptr++ = '"';
00769    for (; ptr < to + len - 1; from++) {
00770       if (*from == '"')
00771          *ptr++ = '\\';
00772       else if (*from == '\0')
00773          break;
00774       *ptr++ = *from;
00775    }
00776    if (ptr < to + len - 1)
00777       *ptr++ = '"';
00778    *ptr = '\0';
00779    return to;
00780 }

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

Create directory based on components.

Definition at line 1117 of file app_minivm.c.

References ast_strlen_zero().

Referenced by check_dirpath(), copy_message(), create_dirpath(), make_email_file(), manager_list_voicemail_users(), notify_new_message(), and prep_email_sub_vars().

01118 {
01119    return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
01120 }

static void message_destroy_list ( void   )  [static]

Clear list of templates.

Definition at line 572 of file app_minivm.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and message_template_free().

Referenced by load_config(), and unload_module().

00573 {
00574    struct minivm_template *this;
00575    AST_LIST_LOCK(&message_templates);
00576    while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) 
00577       message_template_free(this);
00578       
00579    AST_LIST_UNLOCK(&message_templates);
00580 }

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

Build message template from configuration.

Definition at line 489 of file app_minivm.c.

References ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_true(), global_stats, LOG_ERROR, message_template_create(), message_template_parse_emailbody(), message_template_parse_filebody(), ast_variable::name, ast_variable::next, minivm_stats::templates, and ast_variable::value.

Referenced by load_config().

00490 {
00491    struct minivm_template *template;
00492    int error = 0;
00493 
00494    template = message_template_create(name);
00495    if (!template) {
00496       ast_log(LOG_ERROR, "Out of memory, can't allocate message template object %s.\n", name);
00497       return -1;
00498    }
00499 
00500    while (var) {
00501       ast_debug(3, "Configuring template option %s = \"%s\" for template %s\n", var->name, var->value, name);
00502       if (!strcasecmp(var->name, "fromaddress")) {
00503          ast_copy_string(template->fromaddress, var->value, sizeof(template->fromaddress));
00504       } else if (!strcasecmp(var->name, "fromemail")) {
00505          ast_copy_string(template->serveremail, var->value, sizeof(template->serveremail));
00506       } else if (!strcasecmp(var->name, "subject")) {
00507          ast_copy_string(template->subject, var->value, sizeof(template->subject));
00508       } else if (!strcasecmp(var->name, "locale")) {
00509          ast_copy_string(template->locale, var->value, sizeof(template->locale));
00510       } else if (!strcasecmp(var->name, "attachmedia")) {
00511          template->attachment = ast_true(var->value);
00512       } else if (!strcasecmp(var->name, "dateformat")) {
00513          ast_copy_string(template->dateformat, var->value, sizeof(template->dateformat));
00514       } else if (!strcasecmp(var->name, "charset")) {
00515          ast_copy_string(template->charset, var->value, sizeof(template->charset));
00516       } else if (!strcasecmp(var->name, "templatefile")) {
00517          if (template->body) 
00518             ast_free(template->body);
00519          template->body = message_template_parse_filebody(var->value);
00520          if (!template->body) {
00521             ast_log(LOG_ERROR, "Error reading message body definition file %s\n", var->value);
00522             error++;
00523          }
00524       } else if (!strcasecmp(var->name, "messagebody")) {
00525          if (template->body) 
00526             ast_free(template->body);
00527          template->body = message_template_parse_emailbody(var->value);
00528          if (!template->body) {
00529             ast_log(LOG_ERROR, "Error parsing message body definition:\n          %s\n", var->value);
00530             error++;
00531          }
00532       } else {
00533          ast_log(LOG_ERROR, "Unknown message template configuration option \"%s=%s\"\n", var->name, var->value);
00534          error++;
00535       }
00536       var = var->next;
00537    }
00538    if (error)
00539       ast_log(LOG_ERROR, "-- %d errors found parsing message template definition %s\n", error, name);
00540 
00541    AST_LIST_LOCK(&message_templates);
00542    AST_LIST_INSERT_TAIL(&message_templates, template, list);
00543    AST_LIST_UNLOCK(&message_templates);
00544 
00545    global_stats.templates++;
00546 
00547    return error;
00548 }

static struct minivm_template* message_template_create ( const char *  name  )  [static, read]

Create message template.

Definition at line 461 of file app_minivm.c.

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

Referenced by message_template_build().

00462 {
00463    struct minivm_template *template;
00464 
00465    template = ast_calloc(1, sizeof(*template));
00466    if (!template)
00467       return NULL;
00468 
00469    /* Set some defaults for templates */
00470    ast_copy_string(template->name, name, sizeof(template->name));
00471    ast_copy_string(template->dateformat, DEFAULT_DATEFORMAT, sizeof(template->dateformat));
00472    ast_copy_string(template->charset, DEFAULT_CHARSET, sizeof(template->charset));
00473    ast_copy_string(template->subject, "New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}", sizeof(template->subject));
00474    template->attachment = TRUE;
00475 
00476    return template;
00477 }

static struct minivm_template* message_template_find ( const char *  name  )  [static, read]

Find named template.

Definition at line 551 of file app_minivm.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_strlen_zero().

Referenced by load_config(), and notify_new_message().

00552 {
00553    struct minivm_template *this, *res = NULL;
00554 
00555    if (ast_strlen_zero(name))
00556       return NULL;
00557 
00558    AST_LIST_LOCK(&message_templates);
00559    AST_LIST_TRAVERSE(&message_templates, this, list) {
00560       if (!strcasecmp(this->name, name)) {
00561          res = this;
00562          break;
00563       }
00564    }
00565    AST_LIST_UNLOCK(&message_templates);
00566 
00567    return res;
00568 }

static void message_template_free ( struct minivm_template template  )  [static]

Release memory allocated by message template.

Definition at line 480 of file app_minivm.c.

References ast_free.

Referenced by message_destroy_list().

00481 {
00482    if (template->body)
00483       ast_free(template->body);
00484 
00485    ast_free (template);
00486 }

static char * message_template_parse_emailbody ( const char *  body  )  [static]

Parse emailbody template from configuration file.

Definition at line 2277 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02278 {
02279    char *tmpread, *tmpwrite;
02280    char *emailbody = ast_strdup(configuration);
02281 
02282    /* substitute strings \t and \n into the apropriate characters */
02283    tmpread = tmpwrite = emailbody;
02284    while ((tmpwrite = strchr(tmpread,'\\'))) {
02285           int len = strlen("\n");
02286           switch (tmpwrite[1]) {
02287           case 'n':
02288             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02289             strncpy(tmpwrite, "\n", len);
02290             break;
02291           case 't':
02292             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02293             strncpy(tmpwrite, "\t", len);
02294             break;
02295           default:
02296             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02297           }
02298           tmpread = tmpwrite + len;
02299    }
02300    return emailbody; 
02301 }

static char * message_template_parse_filebody ( const char *  filename  )  [static]

Read message template from file.

Definition at line 2237 of file app_minivm.c.

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

Referenced by message_template_build().

02237                                                                    {
02238    char buf[BUFSIZ * 6];
02239    char readbuf[BUFSIZ];
02240    char filenamebuf[BUFSIZ];
02241    char *writepos;
02242    char *messagebody;
02243    FILE *fi;
02244    int lines = 0;
02245 
02246    if (ast_strlen_zero(filename))
02247       return NULL;
02248    if (*filename == '/') 
02249       ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
02250    else 
02251       snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
02252 
02253    if (!(fi = fopen(filenamebuf, "r"))) {
02254       ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
02255       return NULL;
02256    }
02257    writepos = buf;
02258    while (fgets(readbuf, sizeof(readbuf), fi)) {
02259       lines ++;
02260       if (writepos != buf) {
02261          *writepos = '\n';    /* Replace EOL with new line */
02262          writepos++;
02263       }
02264       ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
02265       writepos += strlen(readbuf) - 1;
02266    }
02267    fclose(fi);
02268    messagebody = ast_calloc(1, strlen(buf + 1));
02269    ast_copy_string(messagebody, buf, strlen(buf) + 1);
02270    ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
02271    ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
02272 
02273    return messagebody;
02274 }

static int minivm_accmess_exec ( struct ast_channel chan,
void *  data 
) [static]

Record specific messages for voicemail account.

Definition at line 1984 of file app_minivm.c.

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

Referenced by load_module().

01985 {
01986    int argc = 0;
01987    char *argv[2];
01988    char filename[PATH_MAX];
01989    char tmp[PATH_MAX];
01990    char *domain;
01991    char *tmpptr = NULL;
01992    struct minivm_account *vmu;
01993    char *username = argv[0];
01994    struct ast_flags flags = { 0 };
01995    char *opts[OPT_ARG_ARRAY_SIZE];
01996    int error = FALSE;
01997    char *message = NULL;
01998    char *prompt = NULL;
01999    int duration;
02000    int cmd;
02001 
02002    if (ast_strlen_zero(data))  {
02003       ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
02004       error = TRUE;
02005    } else 
02006       tmpptr = ast_strdupa((char *)data);
02007    if (!error) {
02008       if (!tmpptr) {
02009          ast_log(LOG_ERROR, "Out of memory\n");
02010          error = TRUE;
02011       } else
02012          argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02013    }
02014 
02015    if (argc <=1) {
02016       ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
02017       error = TRUE;
02018    }
02019    if (!error && strlen(argv[1]) > 1) {
02020       ast_log(LOG_ERROR, "MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
02021       error = TRUE;
02022    }
02023 
02024    if (!error && ast_app_parse_options(minivm_accmess_options, &flags, opts, argv[1])) {
02025       ast_log(LOG_ERROR, "Can't parse option %s\n", argv[1]);
02026       error = TRUE;
02027    }
02028 
02029    if (error) {
02030       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02031       return -1;
02032    }
02033 
02034    ast_copy_string(tmp, argv[0], sizeof(tmp));
02035    username = tmp;
02036    domain = strchr(tmp, '@');
02037    if (domain) {
02038       *domain = '\0';
02039       domain++;
02040    } 
02041    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
02042       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
02043       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02044       return -1;
02045    }
02046 
02047    if(!(vmu = find_account(domain, username, TRUE))) {
02048       /* We could not find user, let's exit */
02049       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
02050       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02051       return -1;
02052    }
02053 
02054    /* Answer channel if it's not already answered */
02055    if (chan->_state != AST_STATE_UP)
02056       ast_answer(chan);
02057    
02058    /* Here's where the action is */
02059    if (ast_test_flag(&flags, OPT_BUSY_GREETING)) {
02060       message = "busy";
02061       prompt = "vm-rec-busy";
02062    } else if (ast_test_flag(&flags, OPT_UNAVAIL_GREETING)) {
02063       message = "unavailable";
02064       prompt = "vm-rec-unv";
02065    } else if (ast_test_flag(&flags, OPT_TEMP_GREETING)) {
02066       message = "temp";
02067       prompt = "vm-rec-temp";
02068    } else if (ast_test_flag(&flags, OPT_NAME_GREETING)) {
02069       message = "greet";
02070       prompt = "vm-rec-name";
02071    }
02072    snprintf(filename,sizeof(filename), "%s%s/%s/%s", MVM_SPOOL_DIR, vmu->domain, vmu->username, message);
02073    /* Maybe we should check the result of play_record_review ? */
02074    cmd = play_record_review(chan, prompt, filename, global_maxgreet, default_vmformat, 0, vmu, &duration, NULL, FALSE);
02075 
02076    ast_debug(1, "Recorded new %s message in %s (duration %d)\n", message, filename, duration);
02077 
02078    if(ast_test_flag(vmu, MVM_ALLOCED))
02079       free_user(vmu);
02080 
02081    pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "SUCCESS");
02082 
02083    /* Ok, we're ready to rock and roll. Return to dialplan */
02084    return 0;
02085 }

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

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

02723 {
02724    struct minivm_account *vmu;
02725    char *username, *domain, *colname;
02726 
02727    if (!(username = ast_strdupa(data))) {
02728       ast_log(LOG_ERROR, "Memory Error!\n");
02729       return -1;
02730    }
02731 
02732    if ((colname = strchr(username, ':'))) {
02733       *colname = '\0';
02734       colname++;
02735    } else {
02736       colname = "path";
02737    }
02738    if ((domain = strchr(username, '@'))) {
02739       *domain = '\0';
02740       domain++;
02741    }
02742    if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
02743       ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
02744       return 0;
02745    }
02746 
02747    if (!(vmu = find_account(domain, username, TRUE)))
02748       return 0;
02749 
02750    if (!strcasecmp(colname, "hasaccount")) {
02751       ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
02752    } else  if (!strcasecmp(colname, "fullname")) { 
02753       ast_copy_string(buf, vmu->fullname, len);
02754    } else  if (!strcasecmp(colname, "email")) { 
02755       if (!ast_strlen_zero(vmu->email))
02756          ast_copy_string(buf, vmu->email, len);
02757       else
02758          snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
02759    } else  if (!strcasecmp(colname, "pager")) { 
02760       ast_copy_string(buf, vmu->pager, len);
02761    } else  if (!strcasecmp(colname, "etemplate")) { 
02762       if (!ast_strlen_zero(vmu->etemplate))
02763          ast_copy_string(buf, vmu->etemplate, len);
02764       else
02765          ast_copy_string(buf, "email-default", len);
02766    } else  if (!strcasecmp(colname, "language")) { 
02767       ast_copy_string(buf, vmu->language, len);
02768    } else  if (!strcasecmp(colname, "timezone")) { 
02769       ast_copy_string(buf, vmu->zonetag, len);
02770    } else  if (!strcasecmp(colname, "ptemplate")) { 
02771       if (!ast_strlen_zero(vmu->ptemplate))
02772          ast_copy_string(buf, vmu->ptemplate, len);
02773       else
02774          ast_copy_string(buf, "email-default", len);
02775    } else  if (!strcasecmp(colname, "accountcode")) {
02776       ast_copy_string(buf, vmu->accountcode, len);
02777    } else  if (!strcasecmp(colname, "pincode")) {
02778       ast_copy_string(buf, vmu->pincode, len);
02779    } else  if (!strcasecmp(colname, "path")) {
02780       check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
02781    } else { /* Look in channel variables */
02782       struct ast_variable *var;
02783       int found = 0;
02784 
02785       for (var = vmu->chanvars ; var ; var = var->next)
02786          if (!strcmp(var->name, colname)) {
02787             ast_copy_string(buf, var->value, len);
02788             found = 1;
02789             break;
02790          }
02791    }
02792 
02793    if(ast_test_flag(vmu, MVM_ALLOCED))
02794       free_user(vmu);
02795 
02796    return 0;
02797 }

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

References access_counter_file(), ast_log(), ast_strdupa, ast_strlen_zero(), create_dirpath(), FALSE, find_account(), LOG_ERROR, LOG_WARNING, and minivm_account::username.

02875 {
02876    char *username, *domain, *countername;
02877    struct minivm_account *vmu = NULL;
02878    char userpath[BUFSIZ];
02879    int res;
02880 
02881    *buf = '\0';
02882 
02883    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
02884       ast_log(LOG_WARNING, "Memory error!\n");
02885       return -1;
02886    }
02887    if ((countername = strchr(username, ':'))) {
02888       *countername = '\0';
02889       countername++;
02890    } 
02891 
02892    if ((domain = strchr(username, '@'))) {
02893       *domain = '\0';
02894       domain++;
02895    }
02896 
02897    /* If we have neither username nor domain now, let's give up */
02898    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02899       ast_log(LOG_ERROR, "No account given\n");
02900       return -1;
02901    }
02902 
02903    if (ast_strlen_zero(countername)) {
02904       ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
02905       return -1;
02906    }
02907 
02908    /* We only have a domain, no username */
02909    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02910       domain = username;
02911       username = NULL;
02912    }
02913 
02914    /* If we can't find account or if the account is temporary, return. */
02915    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
02916       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
02917       return 0;
02918    }
02919 
02920    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
02921 
02922    /* We have the path, now read the counter file */
02923    res = access_counter_file(userpath, countername, 0, 0);
02924    if (res >= 0)
02925       snprintf(buf, len, "%d", res);
02926    return 0;
02927 }

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

References access_counter_file(), ast_log(), ast_strdupa, ast_strlen_zero(), create_dirpath(), FALSE, find_account(), LOG_ERROR, LOG_WARNING, and minivm_account::username.

02931 {
02932    char *username, *domain, *countername, *operand;
02933    char userpath[BUFSIZ];
02934    struct minivm_account *vmu;
02935    int change = 0;
02936    int operation = 0;
02937 
02938    if(!value)
02939       return -1;
02940    change = atoi(value);
02941 
02942    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
02943       ast_log(LOG_WARNING, "Memory error!\n");
02944       return -1;
02945    }
02946 
02947    if ((countername = strchr(username, ':'))) {
02948       *countername = '\0';
02949       countername++;
02950    } 
02951    if ((operand = strchr(countername, ':'))) {
02952       *operand = '\0';
02953       operand++;
02954    } 
02955 
02956    if ((domain = strchr(username, '@'))) {
02957       *domain = '\0';
02958       domain++;
02959    }
02960 
02961    /* If we have neither username nor domain now, let's give up */
02962    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02963       ast_log(LOG_ERROR, "No account given\n");
02964       return -1;
02965    }
02966 
02967    /* We only have a domain, no username */
02968    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02969       domain = username;
02970       username = NULL;
02971    }
02972 
02973    if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
02974       ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
02975       return -1;
02976    }
02977 
02978    /* If we can't find account or if the account is temporary, return. */
02979    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
02980       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
02981       return 0;
02982    }
02983 
02984    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
02985    /* Now, find out our operator */
02986    if (*operand == 'i') /* Increment */
02987       operation = 2;
02988    else if (*operand == 'd') {
02989       change = change * -1;
02990       operation = 2;
02991    } else if (*operand == 's')
02992       operation = 1;
02993    else {
02994       ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
02995       return -1;
02996    }
02997 
02998    /* We have the path, now read the counter file */
02999    access_counter_file(userpath, countername, change, operation);
03000    return 0;
03001 }

static int minivm_delete_exec ( struct ast_channel chan,
void *  data 
) [static]

Dialplan application to delete voicemail.

Definition at line 1946 of file app_minivm.c.

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

Referenced by load_module().

01947 {
01948    int res = 0;
01949    char filename[BUFSIZ];
01950       
01951    if (!ast_strlen_zero(data)) {
01952       ast_copy_string(filename, (char *) data, sizeof(filename));
01953    } else {
01954       ast_channel_lock(chan);
01955       ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
01956       ast_channel_unlock(chan);
01957    }
01958 
01959    if (ast_strlen_zero(filename)) {
01960       ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
01961       return res;
01962    } 
01963 
01964    /* Go ahead and delete audio files from system, they're not needed any more */
01965    /* We should look for both audio and text files here */
01966    if (ast_fileexists(filename, NULL, NULL) > 0) {
01967       res = vm_delete(filename);
01968       if (res) {
01969          ast_debug(2, "Can't delete file: %s\n", filename);
01970          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
01971       } else {
01972          ast_debug(2, "Deleted voicemail file :: %s \n", filename);
01973          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
01974       }
01975    } else {
01976       ast_debug(2, "Filename does not exist: %s\n", filename);
01977       pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
01978    }
01979 
01980    return res;
01981 }

static int minivm_greet_exec ( struct ast_channel chan,
void *  data 
) [static]

Play voicemail prompts - either generic or user specific.

Definition at line 1760 of file app_minivm.c.

References ast_channel::_state, ARRAY_LEN, ast_answer(), ast_app_parse_options(), ast_app_separate_args, ast_copy_flags, ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), ast_play_and_wait(), ast_set_flag, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), check_dirpath(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, minivm_account::domain, minivm_account::exit, ast_channel::exten, find_account(), minivm_account::flags, free_user(), invent_message(), ast_channel::language, LOG_ERROR, ast_channel::macrocontext, minivm_app_options, MVM_ALLOCED, MVM_OPERATOR, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), ast_channel::priority, SOUND_INTRO, TRUE, and minivm_account::username.

Referenced by load_module().

01761 {
01762    struct leave_vm_options leave_options = { 0, '\0'};
01763    int argc;
01764    char *argv[2];
01765    struct ast_flags flags = { 0 };
01766    char *opts[OPT_ARG_ARRAY_SIZE];
01767    int res = 0;
01768    int ausemacro = 0;
01769    int ousemacro = 0;
01770    int ouseexten = 0;
01771    char tmp[PATH_MAX];
01772    char dest[PATH_MAX];
01773    char prefile[PATH_MAX] = "";
01774    char tempfile[PATH_MAX] = "";
01775    char ext_context[256] = "";
01776    char *domain;
01777    char ecodes[16] = "#";
01778    char *tmpptr;
01779    struct minivm_account *vmu;
01780    char *username = argv[0];
01781 
01782    if (ast_strlen_zero(data))  {
01783       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01784       return -1;
01785    }
01786    tmpptr = ast_strdupa((char *)data);
01787    if (!tmpptr) {
01788       ast_log(LOG_ERROR, "Out of memory\n");
01789       return -1;
01790    }
01791    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
01792 
01793    if (argc == 2) {
01794       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1]))
01795          return -1;
01796       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
01797    }
01798 
01799    ast_copy_string(tmp, argv[0], sizeof(tmp));
01800    username = tmp;
01801    domain = strchr(tmp, '@');
01802    if (domain) {
01803       *domain = '\0';
01804       domain++;
01805    } 
01806    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
01807       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument:  %s\n", argv[0]);
01808       return -1;
01809    }
01810    ast_debug(1, "Trying to find configuration for user %s in domain %s\n", username, domain);
01811 
01812    if (!(vmu = find_account(domain, username, TRUE))) {
01813       ast_log(LOG_ERROR, "Could not allocate memory. \n");
01814       return -1;
01815    }
01816 
01817    /* Answer channel if it's not already answered */
01818    if (chan->_state != AST_STATE_UP)
01819       ast_answer(chan);
01820 
01821    /* Setup pre-file if appropriate */
01822    if (strcmp(vmu->domain, "localhost"))
01823       snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
01824    else
01825       ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
01826 
01827    if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
01828       res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
01829       if (res)
01830          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
01831    } else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
01832       res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
01833       if (res)
01834          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
01835    }
01836    /* Check for temporary greeting - it overrides busy and unavail */
01837    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
01838    if (!(res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
01839       ast_debug(2, "Temporary message directory does not exist, using default (%s)\n", tempfile);
01840       ast_copy_string(prefile, tempfile, sizeof(prefile));
01841    }
01842    ast_debug(2, "Preparing to play message ...\n");
01843 
01844    /* Check current or macro-calling context for special extensions */
01845    if (ast_test_flag(vmu, MVM_OPERATOR)) {
01846       if (!ast_strlen_zero(vmu->exit)) {
01847          if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
01848             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
01849             ouseexten = 1;
01850          }
01851       } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
01852          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
01853          ouseexten = 1;
01854       }
01855       else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
01856          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
01857          ousemacro = 1;
01858       }
01859    }
01860 
01861    if (!ast_strlen_zero(vmu->exit)) {
01862       if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
01863          strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
01864    } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
01865       strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
01866    else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
01867       strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
01868       ausemacro = 1;
01869    }
01870 
01871    res = 0; /* Reset */
01872    /* Play the beginning intro if desired */
01873    if (!ast_strlen_zero(prefile)) {
01874       if (ast_streamfile(chan, prefile, chan->language) > -1) 
01875          res = ast_waitstream(chan, ecodes);
01876    } else {
01877       ast_debug(2, "%s doesn't exist, doing what we can\n", prefile);
01878       res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
01879    }
01880    if (res < 0) {
01881       ast_debug(2, "Hang up during prefile playback\n");
01882       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
01883       if(ast_test_flag(vmu, MVM_ALLOCED))
01884          free_user(vmu);
01885       return -1;
01886    }
01887    if (res == '#') {
01888       /* On a '#' we skip the instructions */
01889       ast_set_flag(&leave_options, OPT_SILENT);
01890       res = 0;
01891    }
01892    if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
01893       res = ast_streamfile(chan, SOUND_INTRO, chan->language);
01894       if (!res)
01895          res = ast_waitstream(chan, ecodes);
01896       if (res == '#') {
01897          ast_set_flag(&leave_options, OPT_SILENT);
01898          res = 0;
01899       }
01900    }
01901    if (res > 0)
01902       ast_stopstream(chan);
01903    /* Check for a '*' here in case the caller wants to escape from voicemail to something
01904       other than the operator -- an automated attendant or mailbox login for example */
01905    if (res == '*') {
01906       chan->exten[0] = 'a';
01907       chan->exten[1] = '\0';
01908       if (!ast_strlen_zero(vmu->exit)) {
01909          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
01910       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
01911          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
01912       }
01913       chan->priority = 0;
01914       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
01915       res = 0;
01916    } else if (res == '0') { /* Check for a '0' here */
01917       if(ouseexten || ousemacro) {
01918          chan->exten[0] = 'o';
01919          chan->exten[1] = '\0';
01920          if (!ast_strlen_zero(vmu->exit)) {
01921             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
01922          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
01923             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
01924          }
01925          ast_play_and_wait(chan, "transfer");
01926          chan->priority = 0;
01927          pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
01928       }
01929       res =  0;
01930    } else if (res < 0) {
01931       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
01932       res = -1;
01933    } else
01934       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "SUCCESS");
01935 
01936    if(ast_test_flag(vmu, MVM_ALLOCED))
01937       free_user(vmu);
01938 
01939 
01940    /* Ok, we're ready to rock and roll. Return to dialplan */
01941    return res;
01942 
01943 }

static int minivm_notify_exec ( struct ast_channel chan,
void *  data 
) [static]

Notify voicemail account owners - either generic template or user specific.

Definition at line 1625 of file app_minivm.c.

References ARRAY_LEN, ast_app_separate_args, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, find_account(), format, free_user(), LOG_ERROR, LOG_WARNING, MVM_ALLOCED, notify_new_message(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), TRUE, and minivm_account::username.

Referenced by load_module().

01626 {
01627    int argc;
01628    char *argv[2];
01629    int res = 0;
01630    char tmp[PATH_MAX];
01631    char *domain;
01632    char *tmpptr;
01633    struct minivm_account *vmu;
01634    char *username = argv[0];
01635    const char *template = "";
01636    const char *filename;
01637    const char *format;
01638    const char *duration_string;
01639    
01640    if (ast_strlen_zero(data))  {
01641       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01642       return -1;
01643    }
01644    tmpptr = ast_strdupa((char *)data);
01645    if (!tmpptr) {
01646       ast_log(LOG_ERROR, "Out of memory\n");
01647       return -1;
01648    }
01649    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
01650 
01651    if (argc == 2 && !ast_strlen_zero(argv[1]))
01652       template = argv[1];
01653 
01654    ast_copy_string(tmp, argv[0], sizeof(tmp));
01655    username = tmp;
01656    domain = strchr(tmp, '@');
01657    if (domain) {
01658       *domain = '\0';
01659       domain++;
01660    } 
01661    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
01662       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
01663       return -1;
01664    }
01665 
01666    if(!(vmu = find_account(domain, username, TRUE))) {
01667       /* We could not find user, let's exit */
01668       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
01669       pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
01670       return -1;
01671    }
01672 
01673    ast_channel_lock(chan);
01674    if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
01675       filename = ast_strdupa(filename);
01676    }
01677    ast_channel_unlock(chan);
01678    /* Notify of new message to e-mail and pager */
01679    if (!ast_strlen_zero(filename)) {
01680       ast_channel_lock(chan); 
01681       if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
01682          format = ast_strdupa(format);
01683       }
01684       if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
01685          duration_string = ast_strdupa(duration_string);
01686       }
01687       ast_channel_unlock(chan);
01688       res = notify_new_message(chan, template, vmu, filename, atoi(duration_string), format, chan->cid.cid_num, chan->cid.cid_name);
01689    }
01690 
01691    pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
01692 
01693 
01694    if(ast_test_flag(vmu, MVM_ALLOCED))
01695       free_user(vmu);
01696 
01697    /* Ok, we're ready to rock and roll. Return to dialplan */
01698 
01699    return res;
01700 
01701 }

static int minivm_record_exec ( struct ast_channel chan,
void *  data 
) [static]

Dialplan function to record voicemail.

Definition at line 1704 of file app_minivm.c.

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

Referenced by load_module().

01705 {
01706    int res = 0;
01707    char *tmp;
01708    struct leave_vm_options leave_options;
01709    int argc;
01710    char *argv[2];
01711    struct ast_flags flags = { 0 };
01712    char *opts[OPT_ARG_ARRAY_SIZE];
01713       
01714    memset(&leave_options, 0, sizeof(leave_options));
01715 
01716    /* Answer channel if it's not already answered */
01717    if (chan->_state != AST_STATE_UP)
01718       ast_answer(chan);
01719 
01720    if (ast_strlen_zero(data))  {
01721       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01722       return -1;
01723    }
01724    tmp = ast_strdupa((char *)data);
01725    if (!tmp) {
01726       ast_log(LOG_ERROR, "Out of memory\n");
01727       return -1;
01728    }
01729    argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
01730    if (argc == 2) {
01731       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
01732          return -1;
01733       }
01734       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
01735       if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
01736          int gain;
01737 
01738          if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
01739             ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
01740             return -1;
01741          } else 
01742             leave_options.record_gain = (signed char) gain;
01743       }
01744    } 
01745 
01746    /* Now run the appliation and good luck to you! */
01747    res = leave_voicemail(chan, argv[0], &leave_options);
01748 
01749    if (res == ERROR_LOCK_PATH) {
01750       ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
01751       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01752       res = 0;
01753    }
01754    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
01755 
01756    return res;
01757 }

static struct minivm_account* mvm_user_alloc ( void   )  [static, read]

Allocate new vm user and set default values.

Definition at line 784 of file app_minivm.c.

References ast_calloc, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

00785 {
00786    struct minivm_account *new;
00787 
00788    new = ast_calloc(1, sizeof(*new));
00789    if (!new)
00790       return NULL;
00791    populate_defaults(new);
00792 
00793    return new;
00794 }

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

Send message to voicemail account owner.

Definition at line 1381 of file app_minivm.c.

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), minivm_account::attachfmt, minivm_template::attachment, minivm_account::domain, minivm_account::etemplate, EVENT_FLAG_CALL, minivm_template::locale, LOG_WARNING, manager_event, message_template_find(), MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_account::pager, pbx_builtin_getvar_helper(), minivm_account::ptemplate, run_externnotify(), sendmail(), strsep(), and minivm_account::username.

Referenced by copy_message(), leave_voicemail(), and minivm_notify_exec().

01382 {
01383    char *stringp;
01384    struct minivm_template *etemplate;
01385    char *messageformat;
01386    int res = 0;
01387    char oldlocale[100];
01388    const char *counter;
01389 
01390    if (!ast_strlen_zero(vmu->attachfmt)) {
01391       if (strstr(format, vmu->attachfmt)) {
01392          format = vmu->attachfmt;
01393       } else 
01394          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);
01395    }
01396 
01397    etemplate = message_template_find(vmu->etemplate);
01398    if (!etemplate)
01399       etemplate = message_template_find(templatename);
01400    if (!etemplate)
01401       etemplate = message_template_find("email-default");
01402 
01403    /* Attach only the first format */
01404    stringp = messageformat = ast_strdupa(format);
01405    strsep(&stringp, "|");
01406 
01407    if (!ast_strlen_zero(etemplate->locale)) {
01408       char *new_locale;
01409       ast_copy_string(oldlocale, setlocale(LC_TIME, NULL), sizeof(oldlocale));
01410       ast_debug(2, "Changing locale from %s to %s\n", oldlocale, etemplate->locale);
01411       new_locale = setlocale(LC_TIME, etemplate->locale);
01412       if (new_locale == NULL) {
01413          ast_log(LOG_WARNING, "-_-_- Changing to new locale did not work. Locale: %s\n", etemplate->locale);
01414       }
01415    }
01416 
01417 
01418 
01419    /* Read counter if available */
01420    ast_channel_lock(chan);
01421    if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
01422       counter = ast_strdupa(counter);
01423    }
01424    ast_channel_unlock(chan);
01425 
01426    if (ast_strlen_zero(counter)) {
01427       ast_debug(2, "MVM_COUNTER not found\n");
01428    } else {
01429       ast_debug(2, "MVM_COUNTER found - will use it with value %s\n", counter);
01430    }
01431 
01432    res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_EMAIL, counter);
01433 
01434    if (res == 0 && !ast_strlen_zero(vmu->pager))  {
01435       /* Find template for paging */
01436       etemplate = message_template_find(vmu->ptemplate);
01437       if (!etemplate)
01438          etemplate = message_template_find("pager-default");
01439       if (etemplate->locale) {
01440          ast_copy_string(oldlocale, setlocale(LC_TIME, ""), sizeof(oldlocale));
01441          setlocale(LC_TIME, etemplate->locale);
01442       }
01443 
01444       res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_PAGE, counter);
01445    }
01446 
01447    manager_event(EVENT_FLAG_CALL, "MiniVoiceMail", "Action: SentNotification\rn\nMailbox: %s@%s\r\nCounter: %s\r\n", vmu->username, vmu->domain, counter);
01448 
01449    run_externnotify(chan, vmu);     /* Run external notification */
01450 
01451    if (etemplate->locale) 
01452       setlocale(LC_TIME, oldlocale); /* Rest to old locale */
01453    return res;
01454 }

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

Record voicemail message & let caller review or re-record it, or set options if applicable.

Definition at line 1232 of file app_minivm.c.

References acceptdtmf, ast_channel_setoption(), AST_DIGIT_ANY, ast_log(), AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_stream_and_wait(), ast_streamfile(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_waitstream(), global_maxsilence, global_silencethreshold, ast_channel::language, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, and vm_delete().

Referenced by leave_voicemail(), minivm_accmess_exec(), vm_forwardoptions(), vm_newuser(), vm_options(), and vm_tempgreeting().

01235 {
01236    int cmd = 0;
01237    int max_attempts = 3;
01238    int attempts = 0;
01239    int recorded = 0;
01240    int message_exists = 0;
01241    signed char zero_gain = 0;
01242    char *acceptdtmf = "#";
01243    char *canceldtmf = "";
01244 
01245    /* Note that urgent and private are for flagging messages as such in the future */
01246  
01247    /* barf if no pointer passed to store duration in */
01248    if (duration == NULL) {
01249       ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
01250       return -1;
01251    }
01252 
01253    cmd = '3';   /* Want to start by recording */
01254  
01255    while ((cmd >= 0) && (cmd != 't')) {
01256       switch (cmd) {
01257       case '1':
01258          ast_verb(3, "Saving message as is\n");
01259          ast_stream_and_wait(chan, "vm-msgsaved", "");
01260          cmd = 't';
01261          break;
01262       case '2':
01263          /* Review */
01264          ast_verb(3, "Reviewing the message\n");
01265          ast_streamfile(chan, recordfile, chan->language);
01266          cmd = ast_waitstream(chan, AST_DIGIT_ANY);
01267          break;
01268       case '3':
01269          message_exists = 0;
01270          /* Record */
01271          if (recorded == 1) 
01272             ast_verb(3, "Re-recording the message\n");
01273          else
01274             ast_verb(3, "Recording the message\n");
01275          if (recorded && outsidecaller) 
01276             cmd = ast_play_and_wait(chan, "beep");
01277          recorded = 1;
01278          /* 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 */
01279          if (record_gain)
01280             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
01281          if (ast_test_flag(vmu, MVM_OPERATOR))
01282             canceldtmf = "0";
01283          cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
01284          if (record_gain)
01285             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
01286          if (cmd == -1) /* User has hung up, no options to give */
01287             return cmd;
01288          if (cmd == '0')
01289             break;
01290          else if (cmd == '*')
01291             break;
01292          else {
01293             /* If all is well, a message exists */
01294             message_exists = 1;
01295             cmd = 0;
01296          }
01297          break;
01298       case '4':
01299       case '5':
01300       case '6':
01301       case '7':
01302       case '8':
01303       case '9':
01304       case '*':
01305       case '#':
01306          cmd = ast_play_and_wait(chan, "vm-sorry");
01307          break;
01308       case '0':
01309          if(!ast_test_flag(vmu, MVM_OPERATOR)) {
01310             cmd = ast_play_and_wait(chan, "vm-sorry");
01311             break;
01312          }
01313          if (message_exists || recorded) {
01314             cmd = ast_play_and_wait(chan, "vm-saveoper");
01315             if (!cmd)
01316                cmd = ast_waitfordigit(chan, 3000);
01317             if (cmd == '1') {
01318                ast_play_and_wait(chan, "vm-msgsaved");
01319                cmd = '0';
01320             } else {
01321                ast_play_and_wait(chan, "vm-deleted");
01322                vm_delete(recordfile);
01323                cmd = '0';
01324             }
01325          }
01326          return cmd;
01327       default:
01328          /* If the caller is an ouside caller, and the review option is enabled,
01329             allow them to review the message, but let the owner of the box review
01330             their OGM's */
01331          if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
01332             return cmd;
01333          if (message_exists) {
01334             cmd = ast_play_and_wait(chan, "vm-review");
01335          } else {
01336             cmd = ast_play_and_wait(chan, "vm-torerecord");
01337             if (!cmd)
01338                cmd = ast_waitfordigit(chan, 600);
01339          }
01340          
01341          if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
01342             cmd = ast_play_and_wait(chan, "vm-reachoper");
01343             if (!cmd)
01344                cmd = ast_waitfordigit(chan, 600);
01345          }
01346          if (!cmd)
01347             cmd = ast_waitfordigit(chan, 6000);
01348          if (!cmd) {
01349             attempts++;
01350          }
01351          if (attempts > max_attempts) {
01352             cmd = 't';
01353          }
01354       }
01355    }
01356    if (outsidecaller)  
01357       ast_play_and_wait(chan, "vm-goodbye");
01358    if (cmd == 't')
01359       cmd = 0;
01360    return cmd;
01361 }

static void populate_defaults ( struct minivm_account vmu  )  [static]

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

Prepare for voicemail template by adding channel variables to the channel.

Definition at line 729 of file app_minivm.c.

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

Referenced by make_email_file(), sendmail(), and sendpage().

00730 {
00731    char callerid[256];
00732    struct ast_variable *var;
00733    
00734    if (!channel) {
00735       ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
00736       return;
00737    }
00738 
00739    for (var = vmu->chanvars ; var ; var = var->next) {
00740       pbx_builtin_setvar_helper(channel, var->name, var->value);
00741    }
00742 
00743    /* Prepare variables for substition in email body and subject */
00744    pbx_builtin_setvar_helper(channel, "MVM_NAME", vmu->fullname);
00745    pbx_builtin_setvar_helper(channel, "MVM_DUR", dur);
00746    pbx_builtin_setvar_helper(channel, "MVM_DOMAIN", vmu->domain);
00747    pbx_builtin_setvar_helper(channel, "MVM_USERNAME", vmu->username);
00748    pbx_builtin_setvar_helper(channel, "MVM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
00749    pbx_builtin_setvar_helper(channel, "MVM_CIDNAME", (cidname ? cidname : "an unknown caller"));
00750    pbx_builtin_setvar_helper(channel, "MVM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
00751    pbx_builtin_setvar_helper(channel, "MVM_DATE", date);
00752    if (!ast_strlen_zero(counter))
00753       pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
00754 }

static int reload ( void   )  [static]

Reload mini voicemail module.

Definition at line 3081 of file app_minivm.c.

References load_config().

03082 {
03083    return(load_config(1));
03084 }

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

Run external notification for voicemail message.

Definition at line 1364 of file app_minivm.c.

References ast_debug, ast_safe_system(), ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, minivm_account::domain, minivm_account::externnotify, global_externnotify, and minivm_account::username.

Referenced by forward_message(), notify_new_message(), and vm_execmain().

01365 {
01366    char arguments[BUFSIZ];
01367 
01368    if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify))
01369       return;
01370 
01371    snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&", 
01372       ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify, 
01373       vmu->username, vmu->domain,
01374       chan->cid.cid_name, chan->cid.cid_num);
01375 
01376    ast_debug(1, "Executing: %s\n", arguments);
01377    ast_safe_system(arguments);
01378 }

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

Send voicemail with audio file as an attachment.

Definition at line 881 of file app_minivm.c.

References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_random(), ast_safe_system(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_tvnow(), base_encode(), minivm_account::domain, minivm_account::email, minivm_account::fullname, global_charset, global_mailcmd, LOG_WARNING, mailheader_quote(), MAXHOSTNAMELEN, MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_zone::name, option_debug, minivm_account::pager, pbx_substitute_variables_helper(), prep_email_sub_vars(), minivm_account::serveremail, minivm_zone::timezone, minivm_account::username, minivm_account::volgain, and minivm_account::zonetag.

Referenced by forward_message(), and notify_new_message().

00882 {
00883    FILE *p = NULL;
00884    int pfd;
00885    char email[256] = "";
00886    char who[256] = "";
00887    char date[256];
00888    char bound[256];
00889    char fname[PATH_MAX];
00890    char dur[PATH_MAX];
00891    char tmp[80] = "/tmp/astmail-XXXXXX";
00892    char tmp2[PATH_MAX];
00893    struct timeval now;
00894    struct ast_tm tm;
00895    struct minivm_zone *the_zone = NULL;
00896    int len_passdata;
00897    struct ast_channel *ast;
00898    char *finalfilename;
00899    char *passdata = NULL;
00900    char *passdata2 = NULL;
00901    char *fromaddress;
00902    char *fromemail;
00903 
00904    if (type == MVM_MESSAGE_EMAIL) {
00905       if (vmu && !ast_strlen_zero(vmu->email)) {
00906          ast_copy_string(email, vmu->email, sizeof(email)); 
00907       } else if (!ast_strlen_zero(vmu->username) && !ast_strlen_zero(vmu->domain))
00908          snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
00909    } else if (type == MVM_MESSAGE_PAGE) {
00910       ast_copy_string(email, vmu->pager, sizeof(email));
00911    }
00912 
00913    if (ast_strlen_zero(email)) {
00914       ast_log(LOG_WARNING, "No address to send message to.\n");
00915       return -1;  
00916    }
00917 
00918    ast_debug(3, "Sending mail to %s@%s - Using template %s\n", vmu->username, vmu->domain, template->name);
00919 
00920    if (!strcmp(format, "wav49"))
00921       format = "WAV";
00922 
00923 
00924    /* If we have a gain option, process it now with sox */
00925    if (type == MVM_MESSAGE_EMAIL && (vmu->volgain < -.001 || vmu->volgain > .001) ) {
00926       char newtmp[PATH_MAX];
00927       char tmpcmd[PATH_MAX];
00928       int tmpfd;
00929 
00930       ast_copy_string(newtmp, "/tmp/XXXXXX", sizeof(newtmp));
00931       ast_debug(3, "newtmp: %s\n", newtmp);
00932       tmpfd = mkstemp(newtmp);
00933       snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, filename, format, newtmp, format);
00934       ast_safe_system(tmpcmd);
00935       finalfilename = newtmp;
00936       ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->volgain, vmu->username);
00937    } else {
00938       finalfilename = ast_strdupa(filename);
00939    }
00940 
00941    /* Create file name */
00942    snprintf(fname, sizeof(fname), "%s.%s", finalfilename, format);
00943 
00944    if (template->attachment)
00945       ast_debug(1, "Attaching file '%s', format '%s', uservm is '%d'\n", finalfilename, format, attach_user_voicemail);
00946 
00947    /* Make a temporary file instead of piping directly to sendmail, in case the mail
00948       command hangs */
00949    pfd = mkstemp(tmp);
00950    if (pfd > -1) {
00951       p = fdopen(pfd, "w");
00952       if (!p) {
00953          close(pfd);
00954          pfd = -1;
00955       }
00956       ast_debug(1, "Opening temp file for e-mail: %s\n", tmp);
00957    }
00958    if (!p) {
00959       ast_log(LOG_WARNING, "Unable to open temporary file '%s'\n", tmp);
00960       return -1;
00961    }
00962    /* Allocate channel used for chanvar substitution */
00963    ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
00964 
00965 
00966    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
00967 
00968    /* Does this user have a timezone specified? */
00969    if (!ast_strlen_zero(vmu->zonetag)) {
00970       /* Find the zone in the list */
00971       struct minivm_zone *z;
00972       AST_LIST_LOCK(&minivm_zones);
00973       AST_LIST_TRAVERSE(&minivm_zones, z, list) {
00974          if (strcmp(z->name, vmu->zonetag)) 
00975             continue;
00976          the_zone = z;
00977       }
00978       AST_LIST_UNLOCK(&minivm_zones);
00979    }
00980 
00981    now = ast_tvnow();
00982    ast_localtime(&now, &tm, the_zone ? the_zone->timezone : NULL);
00983    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
00984 
00985    /* Start printing the email to the temporary file */
00986    fprintf(p, "Date: %s\n", date);
00987 
00988    /* Set date format for voicemail mail */
00989    ast_strftime(date, sizeof(date), template->dateformat, &tm);
00990 
00991 
00992    /* Populate channel with channel variables for substitution */
00993    prep_email_sub_vars(ast, vmu, cidnum, cidname, dur, date, counter);
00994 
00995    /* Find email address to use */
00996    /* If there's a server e-mail adress in the account, user that, othterwise template */
00997    fromemail = ast_strlen_zero(vmu->serveremail) ?  template->serveremail : vmu->serveremail;
00998 
00999    /* Find name to user for server e-mail */
01000    fromaddress = ast_strlen_zero(template->fromaddress) ? "" : template->fromaddress;
01001 
01002    /* If needed, add hostname as domain */
01003    if (ast_strlen_zero(fromemail))
01004       fromemail = "asterisk";
01005 
01006    if (strchr(fromemail, '@'))
01007       ast_copy_string(who, fromemail, sizeof(who));
01008    else  {
01009       char host[MAXHOSTNAMELEN];
01010       gethostname(host, sizeof(host)-1);
01011       snprintf(who, sizeof(who), "%s@%s", fromemail, host);
01012    }
01013 
01014    if (ast_strlen_zero(fromaddress)) {
01015       fprintf(p, "From: Asterisk PBX <%s>\n", who);
01016    } else {
01017       /* Allocate a buffer big enough for variable substitution */
01018       int vmlen = strlen(fromaddress) * 3 + 200;
01019 
01020       ast_debug(4, "Fromaddress template: %s\n", fromaddress);
01021       if ((passdata = alloca(vmlen))) {
01022          pbx_substitute_variables_helper(ast, fromaddress, passdata, vmlen);
01023          len_passdata = strlen(passdata) * 2 + 3;
01024          passdata2 = alloca(len_passdata);
01025          fprintf(p, "From: %s <%s>\n", mailheader_quote(passdata, passdata2, len_passdata), who);
01026       } else  {
01027          ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01028          fclose(p);
01029          return -1;  
01030       }
01031    } 
01032    ast_debug(4, "Fromstring now: %s\n", ast_strlen_zero(passdata) ? "-default-" : passdata);
01033 
01034    fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
01035    len_passdata = strlen(vmu->fullname) * 2 + 3;
01036    passdata2 = alloca(len_passdata);
01037    if (!ast_strlen_zero(vmu->email))
01038       fprintf(p, "To: %s <%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->email);
01039    else
01040       fprintf(p, "To: %s <%s@%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->username, vmu->domain);
01041 
01042    if (!ast_strlen_zero(template->subject)) {
01043       char *pass_data;
01044       int vmlen = strlen(template->subject) * 3 + 200;
01045       if ((pass_data = alloca(vmlen))) {
01046          pbx_substitute_variables_helper(ast, template->subject, pass_data, vmlen);
01047          fprintf(p, "Subject: %s\n", pass_data);
01048       } else {
01049          ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01050          fclose(p);
01051          return -1;  
01052       }
01053 
01054       ast_debug(4, "Subject now: %s\n", pass_data);
01055 
01056    } else  {
01057       fprintf(p, "Subject: New message in mailbox %s@%s\n", vmu->username, vmu->domain);
01058       ast_debug(1, "Using default subject for this email \n");
01059    }
01060 
01061 
01062    if (option_debug > 2)
01063       fprintf(p, "X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->username, vmu->domain);
01064    fprintf(p, "MIME-Version: 1.0\n");
01065 
01066    /* Something unique. */
01067    snprintf(bound, sizeof(bound), "voicemail_%s%d%d", vmu->username, (int)getpid(), (unsigned int)ast_random());
01068 
01069    fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
01070 
01071    fprintf(p, "--%s\n", bound);
01072    fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", global_charset);
01073    if (!ast_strlen_zero(template->body)) {
01074       char *pass_data;
01075       int vmlen = strlen(template->body)*3 + 200;
01076       if ((pass_data = alloca(vmlen))) {
01077          pbx_substitute_variables_helper(ast, template->body, pass_data, vmlen);
01078          ast_debug(3, "Message now: %s\n-----\n", pass_data);
01079          fprintf(p, "%s\n", pass_data);
01080       } else
01081          ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01082    } else {
01083       fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
01084 
01085          "in mailbox %s from %s, on %s so you might\n"
01086          "want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname, 
01087          dur,  vmu->username, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
01088       ast_debug(3, "Using default message body (no template)\n-----\n");
01089    }
01090    /* Eww. We want formats to tell us their own MIME type */
01091    if (template->attachment) {
01092       char *ctype = "audio/x-";
01093       ast_debug(3, "Attaching file to message: %s\n", fname);
01094       if (!strcasecmp(format, "ogg"))
01095          ctype = "application/";
01096    
01097       fprintf(p, "--%s\n", bound);
01098       fprintf(p, "Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
01099       fprintf(p, "Content-Transfer-Encoding: base64\n");
01100       fprintf(p, "Content-Description: Voicemail sound attachment.\n");
01101       fprintf(p, "Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter : "", format);
01102 
01103       base_encode(fname, p);
01104       fprintf(p, "\n\n--%s--\n.\n", bound);
01105    }
01106    fclose(p);
01107    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", global_mailcmd, tmp, tmp);
01108    ast_safe_system(tmp2);
01109    ast_debug(1, "Sent message to %s with command '%s' - %s\n", vmu->email, global_mailcmd, template->attachment ? "(media attachment)" : "");
01110    ast_debug(3, "Actual command used: %s\n", tmp2);
01111    if (ast)
01112       ast_channel_free(ast);
01113    return 0;
01114 }

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

Add time zone to memory list.

Definition at line 2200 of file app_minivm.c.

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

Referenced by load_config().

02201 {
02202    struct minivm_zone *newzone;
02203    char *msg_format, *timezone_str;
02204 
02205    newzone = ast_calloc(1, sizeof(*newzone));
02206    if (newzone == NULL)
02207       return 0;
02208 
02209    msg_format = ast_strdupa(config);
02210    if (msg_format == NULL) {
02211       ast_log(LOG_WARNING, "Out of memory.\n");
02212       ast_free(newzone);
02213       return 0;
02214    }
02215 
02216    timezone_str = strsep(&msg_format, "|");
02217    if (!msg_format) {
02218       ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
02219       ast_free(newzone);
02220       return 0;
02221    }
02222          
02223    ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
02224    ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
02225    ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
02226 
02227    AST_LIST_LOCK(&minivm_zones);
02228    AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
02229    AST_LIST_UNLOCK(&minivm_zones);
02230 
02231    global_stats.timezones++;
02232 
02233    return 0;
02234 }

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

Definition at line 2188 of file app_minivm.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and free_zone().

Referenced by load_config(), and unload_module().

02189 {
02190    struct minivm_zone *this;
02191 
02192    AST_LIST_LOCK(&minivm_zones);
02193    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02194       free_zone(this);
02195       
02196    AST_LIST_UNLOCK(&minivm_zones);
02197 }

static int unload_module ( void   )  [static]

Unload mini voicemail module.

Definition at line 3107 of file app_minivm.c.

References ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_unregister_application(), cli_minivm, message_destroy_list(), minivm_account_function, minivm_counter_function, timezone_destroy_list(), and vmaccounts_destroy_list().

03108 {
03109    int res;
03110    
03111    res = ast_unregister_application(app_minivm_record);
03112    res |= ast_unregister_application(app_minivm_greet);
03113    res |= ast_unregister_application(app_minivm_notify);
03114    res |= ast_unregister_application(app_minivm_delete);
03115    res |= ast_unregister_application(app_minivm_accmess);
03116    ast_cli_unregister_multiple(cli_minivm, sizeof(cli_minivm)/sizeof(cli_minivm[0]));
03117    ast_custom_function_unregister(&minivm_account_function);
03118    ast_custom_function_unregister(&minivm_counter_function);
03119 
03120    message_destroy_list();    /* Destroy list of voicemail message templates */
03121    timezone_destroy_list();   /* Destroy list of timezones */
03122    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
03123 
03124    return res;
03125 }

static int vm_delete ( char *  file  )  [static]

Delete media files and attribute file.

Definition at line 1219 of file app_minivm.c.

References ast_debug, and ast_filedelete().

Referenced by copy_message(), minivm_delete_exec(), notify_new_message(), and play_record_review().

01220 {
01221    int res;
01222 
01223    ast_debug(1, "Deleting voicemail file %s\n", file);
01224 
01225    res = unlink(file);  /* Remove the meta data file */
01226    res |=  ast_filedelete(file, NULL); /* remove the media file */
01227    return res;
01228 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

Referenced by access_counter_file(), close_mailbox(), copy_message(), count_messages(), leave_voicemail(), open_mailbox(), and save_to_folder().

02805 {
02806    switch (ast_lock_path(path)) {
02807    case AST_LOCK_TIMEOUT:
02808       return -1;
02809    default:
02810       return 0;
02811    }
02812 }

static void vmaccounts_destroy_list ( void   )  [static]

Clear list of users.

Definition at line 798 of file app_minivm.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.

Referenced by load_config(), and unload_module().

00799 {
00800    struct minivm_account *this;
00801    AST_LIST_LOCK(&minivm_accounts);
00802    while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list))) 
00803       ast_free(this);
00804    AST_LIST_UNLOCK(&minivm_accounts);
00805 }


Variable Documentation

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

Definition at line 3132 of file app_minivm.c.

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 222 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 221 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 219 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 220 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 218 of file app_minivm.c.

Definition at line 3132 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 3005 of file app_minivm.c.

Referenced by load_module(), and unload_module().

char default_vmformat[80] [static]

char* descrip_minivm_accmess [static]

Definition at line 295 of file app_minivm.c.

char* descrip_minivm_delete [static]

Definition at line 284 of file app_minivm.c.

char* descrip_minivm_greet [static]

Definition at line 248 of file app_minivm.c.

char* descrip_minivm_notify [static]

Definition at line 265 of file app_minivm.c.

char* descrip_minivm_record [static]

Definition at line 225 of file app_minivm.c.

char global_charset[32] [static]

Global charset in messages

Definition at line 445 of file app_minivm.c.

Referenced by load_config(), and sendmail().

char global_externnotify[160] [static]

External notification application

Definition at line 439 of file app_minivm.c.

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

char global_logfile[PATH_MAX] [static]

Global log file for messages

Definition at line 440 of file app_minivm.c.

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

char global_mailcmd[160] [static]

Configurable mail cmd

Definition at line 438 of file app_minivm.c.

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

int global_maxgreet [static]

Maximum length of prompts

Definition at line 436 of file app_minivm.c.

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

int global_maxsilence [static]

Maximum silence during recording

Definition at line 435 of file app_minivm.c.

Definition at line 444 of file app_minivm.c.

Referenced by load_config().

int global_silencethreshold = 128 [static]

struct minivm_stats global_stats [static]

Statistics for voicemail.

Definition at line 426 of file app_minivm.c.

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

int global_vmmaxmessage [static]

Maximum duration of message

Definition at line 434 of file app_minivm.c.

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

int global_vmminmessage [static]

Minimum duration of messages

Definition at line 433 of file app_minivm.c.

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

double global_volgain [static]

Volume gain for voicmemail via e-mail

Definition at line 447 of file app_minivm.c.

Referenced by populate_defaults().

struct ast_flags globalflags = {0} [static]

Global voicemail flags

Definition at line 443 of file app_minivm.c.

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

Referenced by minivm_accmess_exec().

Definition at line 3033 of file app_minivm.c.

Referenced by load_module(), and unload_module().

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

Referenced by minivm_greet_exec(), and minivm_record_exec().

Definition at line 3014 of file app_minivm.c.

Referenced by load_module(), and unload_module().

enum { ... } minivm_option_args

enum { ... } minivm_option_flags

ast_mutex_t minivmlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Lock to protect voicemail system

Definition at line 428 of file app_minivm.c.

Referenced by load_config().

The minivm log file

Definition at line 431 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

ast_mutex_t minivmloglock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Lock to protect voicemail system log file

Definition at line 429 of file app_minivm.c.

Referenced by leave_voicemail().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 215 of file app_minivm.c.

char* synopsis_minivm_accmess = "Record account specific messages" [static]

Definition at line 294 of file app_minivm.c.

char* synopsis_minivm_delete = "Delete Mini-Voicemail voicemail messages" [static]

Definition at line 283 of file app_minivm.c.

char* synopsis_minivm_greet = "Play Mini-Voicemail prompts" [static]

Definition at line 247 of file app_minivm.c.

char* synopsis_minivm_notify = "Notify voicemail owner about new messages." [static]

Definition at line 264 of file app_minivm.c.

char* synopsis_minivm_record = "Receive Mini-Voicemail and forward via e-mail" [static]

Definition at line 224 of file app_minivm.c.


Generated on Wed Oct 28 11:51:25 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6