Thu Jul 9 13:40:46 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/astobj.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"

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 = "068e67f60f50dd9ee86464c05884a49d" , .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 const 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_RECURSIVE_MUTEX_INITIALIZER_NP )
FILE * minivmlogfile
static ast_mutex_t minivmloglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
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 207 of file app_minivm.c.

Referenced by load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 197 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 196 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

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

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 198 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100

Definition at line 203 of file app_minivm.c.

Referenced by close_mailbox(), copy_message(), count_messages(), minivm_record_exec(), resequence_mailbox(), save_to_folder(), vm_exec(), and vm_execmain().

#define FALSE   0

Definition at line 179 of file app_minivm.c.

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

Referenced by handle_minivm_show_users().

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

Referenced by handle_minivm_show_zones().

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

Referenced by handle_minivm_list_templates().

#define MAX_DATETIME_FORMAT   512

Definition at line 200 of file app_minivm.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 201 of file app_minivm.c.

Referenced by load_config(), and play_message_callerid().

#define MVM_ALLOCED   (1 << 13)

Definition at line 189 of file app_minivm.c.

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

#define MVM_ENVELOPE   (1 << 4)

Definition at line 187 of file app_minivm.c.

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

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

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 185 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)

Review message

Definition at line 183 of file app_minivm.c.

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

#define MVM_SVMAIL   (1 << 3)

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

Referenced by load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 195 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 176 of file app_minivm.c.

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 206 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

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

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

anonymous enum

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 322 of file app_minivm.c.

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

enum mvm_messagetype

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 210 of file app_minivm.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3109 of file app_minivm.c.

static void __unreg_module ( void   )  [static]

Definition at line 3109 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 2798 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().

02799 {
02800    char filename[BUFSIZ];
02801    char readbuf[BUFSIZ];
02802    FILE *counterfile;
02803    int old = 0, counter = 0;
02804 
02805    /* Lock directory */
02806    if (vm_lock_path(directory)) {
02807       return -1;  /* Could not lock directory */
02808    }
02809    snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
02810    if (operand != 1) {
02811       counterfile = fopen(filename, "r");
02812       if (counterfile) {
02813          if(fgets(readbuf, sizeof(readbuf), counterfile)) {
02814             ast_debug(3, "Read this string from counter file: %s\n", readbuf);
02815             old = counter = atoi(readbuf);
02816          }
02817          fclose(counterfile);
02818       }
02819    }
02820    switch (operand) {
02821    case 0:  /* Read only */
02822       ast_unlock_path(directory);
02823       ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
02824       return counter;
02825       break;
02826    case 1: /* Set new value */
02827       counter = value;
02828       break;
02829    case 2: /* Change value */
02830       counter += value;
02831       if (counter < 0)  /* Don't allow counters to fall below zero */
02832          counter = 0;
02833       break;
02834    }
02835    
02836    /* Now, write the new value to the file */
02837    counterfile = fopen(filename, "w");
02838    if (!counterfile) {
02839       ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
02840       ast_unlock_path(directory);
02841       return -1;  /* Could not open file for writing */
02842    }
02843    fprintf(counterfile, "%d\n\n", counter);
02844    fclose(counterfile);
02845    ast_unlock_path(directory);
02846    ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
02847    return counter;
02848 }

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

Definition at line 2282 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, and var.

Referenced by load_config().

02283 {
02284    int error = 0;
02285 
02286    while (var) {
02287       /* Mail command */
02288       if (!strcmp(var->name, "mailcmd")) {
02289          ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
02290       } else if (!strcmp(var->name, "maxgreet")) {
02291          global_maxgreet = atoi(var->value);
02292       } else if (!strcmp(var->name, "maxsilence")) {
02293          global_maxsilence = atoi(var->value);
02294          if (global_maxsilence > 0)
02295             global_maxsilence *= 1000;
02296       } else if (!strcmp(var->name, "logfile")) {
02297          if (!ast_strlen_zero(var->value) ) {
02298             if(*(var->value) == '/')
02299                ast_copy_string(global_logfile, var->value, sizeof(global_logfile));
02300             else
02301                snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
02302          }
02303       } else if (!strcmp(var->name, "externnotify")) {
02304          /* External voicemail notify application */
02305          ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
02306       } else if (!strcmp(var->name, "silencetreshold")) {
02307          /* Silence treshold */
02308          global_silencethreshold = atoi(var->value);
02309       } else if (!strcmp(var->name, "maxmessage")) {
02310          int x;
02311          if (sscanf(var->value, "%d", &x) == 1) {
02312             global_vmmaxmessage = x;
02313          } else {
02314             error ++;
02315             ast_log(LOG_WARNING, "Invalid max message time length\n");
02316          }
02317       } else if (!strcmp(var->name, "minmessage")) {
02318          int x;
02319          if (sscanf(var->value, "%d", &x) == 1) {
02320             global_vmminmessage = x;
02321             if (global_maxsilence <= global_vmminmessage)
02322                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
02323          } else {
02324             error ++;
02325             ast_log(LOG_WARNING, "Invalid min message time length\n");
02326          }
02327       } else if (!strcmp(var->name, "format")) {
02328          ast_copy_string(default_vmformat, var->value, sizeof(default_vmformat));
02329       } else if (!strcmp(var->name, "review")) {
02330          ast_set2_flag((&globalflags), ast_true(var->value), MVM_REVIEW);  
02331       } else if (!strcmp(var->name, "operator")) {
02332          ast_set2_flag((&globalflags), ast_true(var->value), MVM_OPERATOR);   
02333       }
02334       var = var->next;
02335    }
02336    return error;
02337 }

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

read buffer from file (base64 conversion)

Definition at line 584 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().

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

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

read character from file to buffer (base64 conversion)

Definition at line 606 of file app_minivm.c.

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

Referenced by base_encode().

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

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

write buffer to file (base64 conversion)

Definition at line 617 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

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

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

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

Definition at line 635 of file app_minivm.c.

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

Referenced by make_email_file(), and sendmail().

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

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

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

Referenced by handle_minivm_show_users().

02518 {
02519    int which = 0;
02520    int wordlen;
02521    struct minivm_account *vmu;
02522    const char *domain = "";
02523 
02524    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
02525    if (pos > 4)
02526       return NULL;
02527    if (pos == 3)
02528       return (state == 0) ? ast_strdup("for") : NULL;
02529    wordlen = strlen(word);
02530    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02531       if (!strncasecmp(word, vmu->domain, wordlen)) {
02532          if (domain && strcmp(domain, vmu->domain) && ++which > state)
02533             return ast_strdup(vmu->domain);
02534          /* ignore repeated domains ? */
02535          domain = vmu->domain;
02536       }
02537    }
02538    return NULL;
02539 }

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 copy_message(), forward_message(), invent_message(), leave_voicemail(), make_email_file(), 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 2065 of file app_minivm.c.

References 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(), global_stats, minivm_account::list, LOG_ERROR, ast_variable::next, populate_defaults(), minivm_account::username, var, and minivm_stats::voicemailaccounts.

Referenced by find_user_realtime(), and load_config().

02066 {
02067    struct minivm_account *vmu;
02068    char *domain;
02069    char *username;
02070    char accbuf[BUFSIZ];
02071 
02072    ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
02073 
02074    ast_copy_string(accbuf, name, sizeof(accbuf));
02075    username = accbuf;
02076    domain = strchr(accbuf, '@');
02077    if (domain) {
02078       *domain = '\0';
02079       domain++;
02080    }
02081    if (ast_strlen_zero(domain)) {
02082       ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
02083       return 0;
02084    }
02085 
02086    ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
02087 
02088    /* Allocate user account */
02089    vmu = ast_calloc(1, sizeof(*vmu));
02090    if (!vmu)
02091       return 0;
02092    
02093    ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
02094    ast_copy_string(vmu->username, username, sizeof(vmu->username));
02095 
02096    populate_defaults(vmu);
02097 
02098    ast_debug(3, "...Configuring account %s\n", name);
02099 
02100    while (var) {
02101       ast_debug(3, "---- Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
02102       if (!strcasecmp(var->name, "serveremail")) {
02103          ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
02104       } else if (!strcasecmp(var->name, "email")) {
02105          ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
02106       } else if (!strcasecmp(var->name, "accountcode")) {
02107          ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
02108       } else if (!strcasecmp(var->name, "pincode")) {
02109          ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
02110       } else if (!strcasecmp(var->name, "domain")) {
02111          ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
02112       } else if (!strcasecmp(var->name, "language")) {
02113          ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
02114       } else if (!strcasecmp(var->name, "timezone")) {
02115          ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
02116       } else if (!strcasecmp(var->name, "externnotify")) {
02117          ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
02118       } else if (!strcasecmp(var->name, "etemplate")) {
02119          ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
02120       } else if (!strcasecmp(var->name, "ptemplate")) {
02121          ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
02122       } else if (!strcasecmp(var->name, "fullname")) {
02123          ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
02124       } else if (!strcasecmp(var->name, "setvar")) {
02125          char *varval;
02126          char *varname = ast_strdupa(var->value);
02127          struct ast_variable *tmpvar;
02128 
02129          if (varname && (varval = strchr(varname, '='))) {
02130             *varval = '\0';
02131             varval++;
02132             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
02133                tmpvar->next = vmu->chanvars;
02134                vmu->chanvars = tmpvar;
02135             }
02136          }
02137       } else if (!strcasecmp(var->name, "pager")) {
02138          ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
02139       } else if (!strcasecmp(var->name, "volgain")) {
02140          sscanf(var->value, "%lf", &vmu->volgain);
02141       } else {
02142          ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
02143       }
02144       var = var->next;
02145    }
02146    ast_debug(3, "...Linking account %s\n", name);
02147    
02148    AST_LIST_LOCK(&minivm_accounts);
02149    AST_LIST_INSERT_TAIL(&minivm_accounts, vmu, list);
02150    AST_LIST_UNLOCK(&minivm_accounts);
02151 
02152    global_stats.voicemailaccounts++;
02153 
02154    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)" : "");
02155    return 0;
02156 }

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

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(), minivm_account::list, 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]

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(), 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, NULL);
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 718 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().

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

static void free_zone ( struct minivm_zone z  )  [static]

Free Mini Voicemail timezone.

Definition at line 2159 of file app_minivm.c.

References ast_free.

02160 {
02161    ast_free(z);
02162 }

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

Definition at line 707 of file app_minivm.c.

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

Referenced by leave_voicemail(), and tds_log().

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

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 2476 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, minivm_account::list, and ast_cli_entry::usage.

02477 {
02478    struct minivm_template *this;
02479 #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
02480    int count = 0;
02481 
02482    switch (cmd) {
02483    case CLI_INIT:
02484       e->command = "minivm list templates";
02485       e->usage =
02486          "Usage: minivm list templates\n"
02487          "       Lists message templates for e-mail, paging and IM\n";
02488       return NULL;
02489    case CLI_GENERATE:
02490       return NULL;
02491    }
02492 
02493    if (a->argc > 3)
02494       return CLI_SHOWUSAGE;
02495 
02496    AST_LIST_LOCK(&message_templates);
02497    if (AST_LIST_EMPTY(&message_templates)) {
02498       ast_cli(a->fd, "There are no message templates defined\n");
02499       AST_LIST_UNLOCK(&message_templates);
02500       return CLI_FAILURE;
02501    }
02502    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
02503    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
02504    AST_LIST_TRAVERSE(&message_templates, this, list) {
02505       ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name, 
02506          this->charset ? this->charset : "-", 
02507          this->locale ? this->locale : "-",
02508          this->attachment ? "Yes" : "No",
02509          this->subject ? this->subject : "-");
02510       count++;
02511    }
02512    AST_LIST_UNLOCK(&message_templates);
02513    ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
02514    return CLI_SUCCESS;
02515 }

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

Reload cofiguration.

Definition at line 3064 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.

03065 {
03066    
03067    switch (cmd) {
03068    case CLI_INIT:
03069       e->command = "minivm reload";
03070       e->usage =
03071          "Usage: minivm reload\n"
03072          "       Reload mini-voicemail configuration and reset statistics\n";
03073       return NULL;
03074    case CLI_GENERATE:
03075       return NULL;
03076    }
03077    
03078    reload();
03079    ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
03080    return CLI_SUCCESS;
03081 }

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

02628 {
02629    switch (cmd) {
02630    case CLI_INIT:
02631       e->command = "minivm show settings";
02632       e->usage =
02633          "Usage: minivm show settings\n"
02634          "       Display Mini-Voicemail general settings\n";
02635       return NULL;
02636    case CLI_GENERATE:
02637       return NULL;
02638    }
02639 
02640    ast_cli(a->fd, "* Mini-Voicemail general settings\n");
02641    ast_cli(a->fd, "  -------------------------------\n");
02642    ast_cli(a->fd, "\n");
02643    ast_cli(a->fd, "  Mail command (shell):               %s\n", global_mailcmd);
02644    ast_cli(a->fd, "  Max silence:                        %d\n", global_maxsilence);
02645    ast_cli(a->fd, "  Silence treshold:                   %d\n", global_silencethreshold);
02646    ast_cli(a->fd, "  Max message length (secs):          %d\n", global_vmmaxmessage);
02647    ast_cli(a->fd, "  Min message length (secs):          %d\n", global_vmminmessage);
02648    ast_cli(a->fd, "  Default format:                     %s\n", default_vmformat);
02649    ast_cli(a->fd, "  Extern notify (shell):              %s\n", global_externnotify);
02650    ast_cli(a->fd, "  Logfile:                            %s\n", global_logfile[0] ? global_logfile : "<disabled>");
02651    ast_cli(a->fd, "  Operator exit:                      %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
02652    ast_cli(a->fd, "  Message review:                     %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
02653 
02654    ast_cli(a->fd, "\n");
02655    return CLI_SUCCESS;
02656 }

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

Show stats.

Definition at line 2659 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.

02660 {
02661    struct ast_tm time;
02662    char buf[BUFSIZ];
02663 
02664    switch (cmd) {
02665    
02666    case CLI_INIT:
02667       e->command = "minivm show stats";
02668       e->usage =
02669          "Usage: minivm show stats\n"
02670          "       Display Mini-Voicemail counters\n";
02671       return NULL;
02672    case CLI_GENERATE:
02673       return NULL;
02674    }
02675 
02676    ast_cli(a->fd, "* Mini-Voicemail statistics\n");
02677    ast_cli(a->fd, "  -------------------------\n");
02678    ast_cli(a->fd, "\n");
02679    ast_cli(a->fd, "  Voicemail accounts:                  %5d\n", global_stats.voicemailaccounts);
02680    ast_cli(a->fd, "  Templates:                           %5d\n", global_stats.templates);
02681    ast_cli(a->fd, "  Timezones:                           %5d\n", global_stats.timezones);
02682    if (global_stats.receivedmessages == 0) {
02683       ast_cli(a->fd, "  Received messages since last reset:  <none>\n");
02684    } else {
02685       ast_cli(a->fd, "  Received messages since last reset:  %d\n", global_stats.receivedmessages);
02686       ast_localtime(&global_stats.lastreceived, &time, NULL);
02687       ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &time);
02688       ast_cli(a->fd, "  Last received voicemail:             %s\n", buf);
02689    }
02690    ast_localtime(&global_stats.reset, &time, NULL);
02691    ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &time);
02692    ast_cli(a->fd, "  Last reset:                          %s\n", buf);
02693 
02694    ast_cli(a->fd, "\n");
02695    return CLI_SUCCESS;
02696 }

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 2542 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, minivm_account::list, 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.

02543 {
02544    struct minivm_account *vmu;
02545 #define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
02546    int count = 0;
02547 
02548    switch (cmd) {
02549    case CLI_INIT:
02550       e->command = "minivm list accounts";
02551       e->usage =
02552          "Usage: minivm list accounts\n"
02553          "       Lists all mailboxes currently set up\n";
02554       return NULL;
02555    case CLI_GENERATE:
02556       return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
02557    }
02558 
02559    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
02560       return CLI_SHOWUSAGE;
02561    if ((a->argc == 5) && strcmp(a->argv[3],"for"))
02562       return CLI_SHOWUSAGE;
02563 
02564    AST_LIST_LOCK(&minivm_accounts);
02565    if (AST_LIST_EMPTY(&minivm_accounts)) {
02566       ast_cli(a->fd, "There are no voicemail users currently defined\n");
02567       AST_LIST_UNLOCK(&minivm_accounts);
02568       return CLI_FAILURE;
02569    }
02570    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
02571    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
02572    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02573       char tmp[256] = "";
02574       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
02575          count++;
02576          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
02577          ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, vmu->etemplate ? vmu->etemplate : "-", 
02578             vmu->ptemplate ? vmu->ptemplate : "-",
02579             vmu->zonetag ? vmu->zonetag : "-", 
02580             vmu->attachfmt ? vmu->attachfmt : "-",
02581             vmu->fullname);
02582       }
02583    }
02584    AST_LIST_UNLOCK(&minivm_accounts);
02585    ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
02586    return CLI_SUCCESS;
02587 }

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 2590 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_account::list, minivm_zone::msg_format, minivm_zone::name, minivm_zone::timezone, and ast_cli_entry::usage.

02591 {
02592    struct minivm_zone *zone;
02593 #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
02594    char *res = CLI_SUCCESS;
02595 
02596    switch (cmd) {
02597    case CLI_INIT:
02598       e->command = "minivm list zones";
02599       e->usage =
02600          "Usage: minivm list zones\n"
02601          "       Lists zone message formats\n";
02602       return NULL;
02603    case CLI_GENERATE:
02604       return NULL;
02605    }
02606 
02607    if (a->argc != e->args)
02608       return CLI_SHOWUSAGE;
02609 
02610    AST_LIST_LOCK(&minivm_zones);
02611    if (!AST_LIST_EMPTY(&minivm_zones)) {
02612       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
02613       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
02614       AST_LIST_TRAVERSE(&minivm_zones, zone, list) {
02615          ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
02616       }
02617    } else {
02618       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
02619       res = CLI_FAILURE;
02620    }
02621    AST_LIST_UNLOCK(&minivm_zones);
02622 
02623    return res;
02624 }

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(), chan, FALSE, and ast_channel::language.

Referenced by 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 1448 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, chan, 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().

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

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2340 of file app_minivm.c.

References apply_general_options(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set2_flag, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), ast_variable_retrieve(), chanvar, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_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, SENDMAIL, timezone_add(), timezone_destroy_list(), TRUE, var, vmaccounts_destroy_list(), and VOICEMAIL_CONFIG.

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

static int load_module ( void   )  [static]

Load mini voicemail module.

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

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

Referenced by load_config(), and unload_module().

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

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

Build message template from configuration.

Definition at line 490 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, minivm_account::list, LOG_ERROR, message_template_create(), message_template_parse_emailbody(), message_template_parse_filebody(), minivm_stats::templates, and var.

Referenced by load_config().

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

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

Create message template.

Definition at line 462 of file app_minivm.c.

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

Referenced by message_template_build().

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

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

Find named template.

Definition at line 552 of file app_minivm.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), and minivm_account::list.

Referenced by load_config(), and notify_new_message().

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

static void message_template_free ( struct minivm_template template  )  [static]

Release memory allocated by message template.

Definition at line 481 of file app_minivm.c.

References ast_free, and minivm_template::body.

Referenced by message_destroy_list().

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

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

Parse emailbody template from configuration file.

Definition at line 2255 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02256 {
02257    char *tmpread, *tmpwrite;
02258    char *emailbody = ast_strdup(configuration);
02259 
02260    /* substitute strings \t and \n into the apropriate characters */
02261    tmpread = tmpwrite = emailbody;
02262    while ((tmpwrite = strchr(tmpread,'\\'))) {
02263           int len = strlen("\n");
02264           switch (tmpwrite[1]) {
02265           case 'n':
02266             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02267             strncpy(tmpwrite, "\n", len);
02268             break;
02269           case 't':
02270             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02271             strncpy(tmpwrite, "\t", len);
02272             break;
02273           default:
02274             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02275           }
02276           tmpread = tmpwrite + len;
02277    }
02278    return emailbody; 
02279 }

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

Read message template from file.

Definition at line 2215 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().

02215                                                                    {
02216    char buf[BUFSIZ * 6];
02217    char readbuf[BUFSIZ];
02218    char filenamebuf[BUFSIZ];
02219    char *writepos;
02220    char *messagebody;
02221    FILE *fi;
02222    int lines = 0;
02223 
02224    if (ast_strlen_zero(filename))
02225       return NULL;
02226    if (*filename == '/') 
02227       ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
02228    else 
02229       snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
02230 
02231    if (!(fi = fopen(filenamebuf, "r"))) {
02232       ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
02233       return NULL;
02234    }
02235    writepos = buf;
02236    while (fgets(readbuf, sizeof(readbuf), fi)) {
02237       lines ++;
02238       if (writepos != buf) {
02239          *writepos = '\n';    /* Replace EOL with new line */
02240          writepos++;
02241       }
02242       ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
02243       writepos += strlen(readbuf) - 1;
02244    }
02245    fclose(fi);
02246    messagebody = ast_calloc(1, strlen(buf + 1));
02247    ast_copy_string(messagebody, buf, strlen(buf) + 1);
02248    ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
02249    ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
02250 
02251    return messagebody;
02252 }

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

Record specific messages for voicemail account.

Definition at line 1961 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, chan, 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(), TRUE, and minivm_account::username.

Referenced by load_module().

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

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 2699 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, minivm_account::pager, minivm_account::pincode, minivm_account::ptemplate, TRUE, minivm_account::username, var, and minivm_account::zonetag.

02700 {
02701    struct minivm_account *vmu;
02702    char *username, *domain, *colname;
02703 
02704    if (!(username = ast_strdupa(data))) {
02705       ast_log(LOG_ERROR, "Memory Error!\n");
02706       return -1;
02707    }
02708 
02709    if ((colname = strchr(username, ':'))) {
02710       *colname = '\0';
02711       colname++;
02712    } else {
02713       colname = "path";
02714    }
02715    if ((domain = strchr(username, '@'))) {
02716       *domain = '\0';
02717       domain++;
02718    }
02719    if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
02720       ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
02721       return 0;
02722    }
02723 
02724    if (!(vmu = find_account(domain, username, TRUE)))
02725       return 0;
02726 
02727    if (!strcasecmp(colname, "hasaccount")) {
02728       ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
02729    } else  if (!strcasecmp(colname, "fullname")) { 
02730       ast_copy_string(buf, vmu->fullname, len);
02731    } else  if (!strcasecmp(colname, "email")) { 
02732       if (!ast_strlen_zero(vmu->email))
02733          ast_copy_string(buf, vmu->email, len);
02734       else
02735          snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
02736    } else  if (!strcasecmp(colname, "pager")) { 
02737       ast_copy_string(buf, vmu->pager, len);
02738    } else  if (!strcasecmp(colname, "etemplate")) { 
02739       if (!ast_strlen_zero(vmu->etemplate))
02740          ast_copy_string(buf, vmu->etemplate, len);
02741       else
02742          ast_copy_string(buf, "email-default", len);
02743    } else  if (!strcasecmp(colname, "language")) { 
02744       ast_copy_string(buf, vmu->language, len);
02745    } else  if (!strcasecmp(colname, "timezone")) { 
02746       ast_copy_string(buf, vmu->zonetag, len);
02747    } else  if (!strcasecmp(colname, "ptemplate")) { 
02748       if (!ast_strlen_zero(vmu->ptemplate))
02749          ast_copy_string(buf, vmu->ptemplate, len);
02750       else
02751          ast_copy_string(buf, "email-default", len);
02752    } else  if (!strcasecmp(colname, "accountcode")) {
02753       ast_copy_string(buf, vmu->accountcode, len);
02754    } else  if (!strcasecmp(colname, "pincode")) {
02755       ast_copy_string(buf, vmu->pincode, len);
02756    } else  if (!strcasecmp(colname, "path")) {
02757       check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
02758    } else { /* Look in channel variables */
02759       struct ast_variable *var;
02760       int found = 0;
02761 
02762       for (var = vmu->chanvars ; var ; var = var->next)
02763          if (!strcmp(var->name, colname)) {
02764             ast_copy_string(buf, var->value, len);
02765             found = 1;
02766             break;
02767          }
02768    }
02769 
02770    if(ast_test_flag(vmu, MVM_ALLOCED))
02771       free_user(vmu);
02772 
02773    return 0;
02774 }

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

02852 {
02853    char *username, *domain, *countername;
02854    struct minivm_account *vmu = NULL;
02855    char userpath[BUFSIZ];
02856    int res;
02857 
02858    *buf = '\0';
02859 
02860    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
02861       ast_log(LOG_WARNING, "Memory error!\n");
02862       return -1;
02863    }
02864    if ((countername = strchr(username, ':'))) {
02865       *countername = '\0';
02866       countername++;
02867    } 
02868 
02869    if ((domain = strchr(username, '@'))) {
02870       *domain = '\0';
02871       domain++;
02872    }
02873 
02874    /* If we have neither username nor domain now, let's give up */
02875    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02876       ast_log(LOG_ERROR, "No account given\n");
02877       return -1;
02878    }
02879 
02880    if (ast_strlen_zero(countername)) {
02881       ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
02882       return -1;
02883    }
02884 
02885    /* We only have a domain, no username */
02886    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02887       domain = username;
02888       username = NULL;
02889    }
02890 
02891    /* If we can't find account or if the account is temporary, return. */
02892    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
02893       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
02894       return 0;
02895    }
02896 
02897    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
02898 
02899    /* We have the path, now read the counter file */
02900    res = access_counter_file(userpath, countername, 0, 0);
02901    if (res >= 0)
02902       snprintf(buf, len, "%d", res);
02903    return 0;
02904 }

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

02908 {
02909    char *username, *domain, *countername, *operand;
02910    char userpath[BUFSIZ];
02911    struct minivm_account *vmu;
02912    int change = 0;
02913    int operation = 0;
02914 
02915    if(!value)
02916       return -1;
02917    change = atoi(value);
02918 
02919    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
02920       ast_log(LOG_WARNING, "Memory error!\n");
02921       return -1;
02922    }
02923 
02924    if ((countername = strchr(username, ':'))) {
02925       *countername = '\0';
02926       countername++;
02927    } 
02928    if ((operand = strchr(countername, ':'))) {
02929       *operand = '\0';
02930       operand++;
02931    } 
02932 
02933    if ((domain = strchr(username, '@'))) {
02934       *domain = '\0';
02935       domain++;
02936    }
02937 
02938    /* If we have neither username nor domain now, let's give up */
02939    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02940       ast_log(LOG_ERROR, "No account given\n");
02941       return -1;
02942    }
02943 
02944    /* We only have a domain, no username */
02945    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
02946       domain = username;
02947       username = NULL;
02948    }
02949 
02950    if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
02951       ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
02952       return -1;
02953    }
02954 
02955    /* If we can't find account or if the account is temporary, return. */
02956    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
02957       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
02958       return 0;
02959    }
02960 
02961    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
02962    /* Now, find out our operator */
02963    if (*operand == 'i') /* Increment */
02964       operation = 2;
02965    else if (*operand == 'd') {
02966       change = change * -1;
02967       operation = 2;
02968    } else if (*operand == 's')
02969       operation = 1;
02970    else {
02971       ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
02972       return -1;
02973    }
02974 
02975    /* We have the path, now read the counter file */
02976    access_counter_file(userpath, countername, change, operation);
02977    return 0;
02978 }

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

Dialplan application to delete voicemail.

Definition at line 1926 of file app_minivm.c.

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

Referenced by load_module().

01927 {
01928    int res = 0;
01929    char filename[BUFSIZ];
01930       
01931    if (!ast_strlen_zero(data))
01932       ast_copy_string(filename, (char *) data, sizeof(filename));
01933    else
01934       ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
01935 
01936    if (ast_strlen_zero(filename)) {
01937       ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
01938       return res;
01939    } 
01940 
01941    /* Go ahead and delete audio files from system, they're not needed any more */
01942    /* We should look for both audio and text files here */
01943    if (ast_fileexists(filename, NULL, NULL) > 0) {
01944       res = vm_delete(filename);
01945       if (res) {
01946          ast_debug(2, "-_-_- Can't delete file: %s\n", filename);
01947          pbx_builtin_setvar_helper(chan, "MINIVM_DELETE_STATUS", "FAILED");
01948       } else {
01949          ast_debug(2, "-_-_- Deleted voicemail file :: %s \n", filename);
01950          pbx_builtin_setvar_helper(chan, "MINIVM_DELETE_STATUS", "SUCCESS");
01951       }
01952    } else {
01953       ast_debug(2, "-_-_- Filename does not exist: %s\n", filename);
01954       pbx_builtin_setvar_helper(chan, "MINIVM_DELETE_STATUS", "FAILED");
01955    }
01956 
01957    return res;
01958 }

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

Play voicemail prompts - either generic or user specific.

Definition at line 1740 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(), chan, check_dirpath(), minivm_account::domain, minivm_account::exit, find_account(), minivm_account::flags, free_user(), invent_message(), LOG_ERROR, minivm_app_options, MVM_ALLOCED, MVM_OPERATOR, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), SOUND_INTRO, TRUE, and minivm_account::username.

Referenced by load_module().

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

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

References ARRAY_LEN, ast_app_separate_args(), ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, chan, 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().

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

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

Dialplan function to record voicemail.

Definition at line 1684 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, chan, 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, and pbx_builtin_setvar_helper().

Referenced by load_module().

01685 {
01686    int res = 0;
01687    char *tmp;
01688    struct leave_vm_options leave_options;
01689    int argc;
01690    char *argv[2];
01691    struct ast_flags flags = { 0 };
01692    char *opts[OPT_ARG_ARRAY_SIZE];
01693       
01694    memset(&leave_options, 0, sizeof(leave_options));
01695 
01696    /* Answer channel if it's not already answered */
01697    if (chan->_state != AST_STATE_UP)
01698       ast_answer(chan);
01699 
01700    if (ast_strlen_zero(data))  {
01701       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01702       return -1;
01703    }
01704    tmp = ast_strdupa((char *)data);
01705    if (!tmp) {
01706       ast_log(LOG_ERROR, "Out of memory\n");
01707       return -1;
01708    }
01709    argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
01710    if (argc == 2) {
01711       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
01712          return -1;
01713       }
01714       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
01715       if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
01716          int gain;
01717 
01718          if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
01719             ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
01720             return -1;
01721          } else 
01722             leave_options.record_gain = (signed char) gain;
01723       }
01724    } 
01725 
01726    /* Now run the appliation and good luck to you! */
01727    res = leave_voicemail(chan, argv[0], &leave_options);
01728 
01729    if (res == ERROR_LOCK_PATH) {
01730       ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
01731       pbx_builtin_setvar_helper(chan, "MINIVM_RECORD_STATUS", "FAILED");
01732       res = 0;
01733    }
01734    pbx_builtin_setvar_helper(chan, "MINIVM_RECORD_STATUS", "SUCCESS");
01735 
01736    return res;
01737 }

static struct minivm_account* mvm_user_alloc ( void   )  [static]

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

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

Referenced by copy_message(), and minivm_notify_exec().

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

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 ast_channel_setoption(), AST_DIGIT_ANY, ast_log(), AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_streamfile(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_waitstream(), chan, global_maxsilence, global_silencethreshold, ast_channel::language, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, and vm_delete().

Referenced by leave_voicemail(), minivm_accmess_exec(), 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 '2':
01258          /* Review */
01259          ast_verb(3, "Reviewing the message\n");
01260          ast_streamfile(chan, recordfile, chan->language);
01261          cmd = ast_waitstream(chan, AST_DIGIT_ANY);
01262          break;
01263       case '3':
01264          message_exists = 0;
01265          /* Record */
01266          if (recorded == 1) 
01267             ast_verb(3, "Re-recording the message\n");
01268          else
01269             ast_verb(3, "Recording the message\n");
01270          if (recorded && outsidecaller) 
01271             cmd = ast_play_and_wait(chan, "beep");
01272          recorded = 1;
01273          /* 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 */
01274          if (record_gain)
01275             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
01276          if (ast_test_flag(vmu, MVM_OPERATOR))
01277             canceldtmf = "0";
01278          cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
01279          if (record_gain)
01280             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
01281          if (cmd == -1) /* User has hung up, no options to give */
01282             return cmd;
01283          if (cmd == '0')
01284             break;
01285          else if (cmd == '*')
01286             break;
01287          else {
01288             /* If all is well, a message exists */
01289             message_exists = 1;
01290             cmd = 0;
01291          }
01292          break;
01293       case '4':
01294       case '5':
01295       case '6':
01296       case '7':
01297       case '8':
01298       case '9':
01299       case '*':
01300       case '#':
01301          cmd = ast_play_and_wait(chan, "vm-sorry");
01302          break;
01303       case '0':
01304          if(!ast_test_flag(vmu, MVM_OPERATOR)) {
01305             cmd = ast_play_and_wait(chan, "vm-sorry");
01306             break;
01307          }
01308          if (message_exists || recorded) {
01309             cmd = ast_play_and_wait(chan, "vm-saveoper");
01310             if (!cmd)
01311                cmd = ast_waitfordigit(chan, 3000);
01312             if (cmd == '1') {
01313                ast_play_and_wait(chan, "vm-msgsaved");
01314                cmd = '0';
01315             } else {
01316                ast_play_and_wait(chan, "vm-deleted");
01317                vm_delete(recordfile);
01318                cmd = '0';
01319             }
01320          }
01321          return cmd;
01322       default:
01323          /* If the caller is an ouside caller, and the review option is enabled,
01324             allow them to review the message, but let the owner of the box review
01325             their OGM's */
01326          if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
01327             return cmd;
01328          if (message_exists) {
01329             cmd = ast_play_and_wait(chan, "vm-review");
01330          } else {
01331             cmd = ast_play_and_wait(chan, "vm-torerecord");
01332             if (!cmd)
01333                cmd = ast_waitfordigit(chan, 600);
01334          }
01335          
01336          if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
01337             cmd = ast_play_and_wait(chan, "vm-reachoper");
01338             if (!cmd)
01339                cmd = ast_waitfordigit(chan, 600);
01340          }
01341          if (!cmd)
01342             cmd = ast_waitfordigit(chan, 6000);
01343          if (!cmd) {
01344             attempts++;
01345          }
01346          if (attempts > max_attempts) {
01347             cmd = 't';
01348          }
01349       }
01350    }
01351    if (outsidecaller)  
01352       ast_play_and_wait(chan, "vm-goodbye");
01353    if (cmd == 't')
01354       cmd = 0;
01355    return cmd;
01356 }

static void populate_defaults ( struct minivm_account vmu  )  [static]

Set default values for Mini-Voicemail users.

Definition at line 757 of file app_minivm.c.

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

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

00758 {
00759    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00760    ast_copy_string(vmu->attachfmt, default_vmformat, sizeof(vmu->attachfmt));
00761    vmu->volgain = global_volgain;
00762 }

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 730 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, pbx_builtin_setvar_helper(), minivm_account::username, and var.

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

00731 {
00732    char callerid[256];
00733    struct ast_variable *var;
00734    
00735    if (!channel) {
00736       ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
00737       return;
00738    }
00739 
00740    for (var = vmu->chanvars ; var ; var = var->next)
00741                 pbx_builtin_setvar_helper(channel, var->name, var->value);
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 3058 of file app_minivm.c.

References load_config().

03059 {
03060    return(load_config(1));
03061 }

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

Run external notification for voicemail message.

Definition at line 1359 of file app_minivm.c.

References ast_debug, ast_safe_system(), ast_strlen_zero(), chan, 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().

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

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(), minivm_template::attachment, base_encode(), minivm_template::body, minivm_template::dateformat, minivm_account::domain, minivm_account::email, minivm_template::fromaddress, minivm_account::fullname, global_charset, global_mailcmd, minivm_account::list, LOG_WARNING, mailheader_quote(), MAXHOSTNAMELEN, MVM_MESSAGE_EMAIL, minivm_zone::name, minivm_template::name, option_debug, minivm_account::pager, pbx_substitute_variables_helper(), prep_email_sub_vars(), minivm_account::serveremail, minivm_template::subject, 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 *passdata;
01044       int vmlen = strlen(template->subject) * 3 + 200;
01045       if ((passdata = alloca(vmlen))) {
01046          pbx_substitute_variables_helper(ast, template->subject, passdata, vmlen);
01047          fprintf(p, "Subject: %s\n", passdata);
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", passdata);
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 *passdata;
01075       int vmlen = strlen(template->body)*3 + 200;
01076       if ((passdata = alloca(vmlen))) {
01077          pbx_substitute_variables_helper(ast, template->body, passdata, vmlen);
01078          ast_debug(3, "Message now: %s\n-----\n", passdata);
01079          fprintf(p, "%s\n", passdata);
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 2177 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, minivm_account::list, LOG_WARNING, strsep(), and minivm_stats::timezones.

Referenced by load_config().

02178 {
02179 
02180    struct minivm_zone *newzone;
02181    char *msg_format, *timezone;
02182 
02183    newzone = ast_calloc(1, sizeof(*newzone));
02184    if (newzone == NULL)
02185       return 0;
02186 
02187    msg_format = ast_strdupa(config);
02188    if (msg_format == NULL) {
02189       ast_log(LOG_WARNING, "Out of memory.\n");
02190       ast_free(newzone);
02191       return 0;
02192    }
02193 
02194    timezone = strsep(&msg_format, "|");
02195    if (!msg_format) {
02196       ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
02197       ast_free(newzone);
02198       return 0;
02199    }
02200          
02201    ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
02202    ast_copy_string(newzone->timezone, timezone, sizeof(newzone->timezone));
02203    ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
02204 
02205    AST_LIST_LOCK(&minivm_zones);
02206    AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
02207    AST_LIST_UNLOCK(&minivm_zones);
02208 
02209    global_stats.timezones++;
02210 
02211    return 0;
02212 }

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

Definition at line 2165 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

02166 {
02167    struct minivm_zone *this;
02168 
02169    AST_LIST_LOCK(&minivm_zones);
02170    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02171       free_zone(this);
02172       
02173    AST_LIST_UNLOCK(&minivm_zones);
02174 }

static int unload_module ( void   )  [static]

Unload mini voicemail module.

Definition at line 3084 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().

03085 {
03086    int res;
03087    
03088    res = ast_unregister_application(app_minivm_record);
03089    res |= ast_unregister_application(app_minivm_greet);
03090    res |= ast_unregister_application(app_minivm_notify);
03091    res |= ast_unregister_application(app_minivm_delete);
03092    res |= ast_unregister_application(app_minivm_accmess);
03093    ast_cli_unregister_multiple(cli_minivm, sizeof(cli_minivm)/sizeof(cli_minivm[0]));
03094    ast_custom_function_unregister(&minivm_account_function);
03095    ast_custom_function_unregister(&minivm_counter_function);
03096 
03097    message_destroy_list();    /* Destroy list of voicemail message templates */
03098    timezone_destroy_list();   /* Destroy list of timezones */
03099    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
03100 
03101    return res;
03102 }

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 minivm_delete_exec(), 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 2781 of file app_minivm.c.

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

02782 {
02783         switch (ast_lock_path(path)) {
02784         case AST_LOCK_TIMEOUT:
02785                 return -1;
02786         default:
02787                 return 0;
02788         }
02789 }

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, AST_LIST_UNLOCK, and minivm_account::list.

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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 3109 of file app_minivm.c.

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 223 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 222 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 220 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 221 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 219 of file app_minivm.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3109 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 2982 of file app_minivm.c.

Referenced by load_module(), and unload_module().

char default_vmformat[80] [static]

Definition at line 442 of file app_minivm.c.

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

char* descrip_minivm_accmess [static]

Definition at line 296 of file app_minivm.c.

char* descrip_minivm_delete [static]

Definition at line 285 of file app_minivm.c.

char* descrip_minivm_greet [static]

Definition at line 249 of file app_minivm.c.

char* descrip_minivm_notify [static]

Definition at line 266 of file app_minivm.c.

char* descrip_minivm_record [static]

Definition at line 226 of file app_minivm.c.

char global_charset[32] [static]

Global charset in messages

Definition at line 446 of file app_minivm.c.

Referenced by load_config(), and sendmail().

char global_externnotify[160] [static]

External notification application

Definition at line 440 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 441 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 439 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 437 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 436 of file app_minivm.c.

int global_saydurationminfo [static]

Definition at line 445 of file app_minivm.c.

Referenced by load_config().

int global_silencethreshold = 128 [static]

Definition at line 438 of file app_minivm.c.

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

struct minivm_stats global_stats [static]

Statistics for voicemail.

Definition at line 427 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 435 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 434 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 448 of file app_minivm.c.

Referenced by populate_defaults().

struct ast_flags globalflags = {0} [static]

Global voicemail flags

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

Referenced by minivm_accmess_exec().

struct ast_custom_function minivm_account_function [static]

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

Referenced by minivm_greet_exec(), and minivm_record_exec().

struct ast_custom_function minivm_counter_function [static]

Definition at line 2991 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_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Lock to protect voicemail system

Definition at line 429 of file app_minivm.c.

Referenced by load_config().

FILE* minivmlogfile

The minivm log file

Definition at line 432 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

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

Lock to protect voicemail system log file

Definition at line 430 of file app_minivm.c.

Referenced by leave_voicemail().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 216 of file app_minivm.c.

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

Definition at line 295 of file app_minivm.c.

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

Definition at line 284 of file app_minivm.c.

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

Definition at line 248 of file app_minivm.c.

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

Definition at line 265 of file app_minivm.c.

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

Definition at line 225 of file app_minivm.c.


Generated on Thu Jul 9 13:40:46 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7