Wed Oct 28 13:31:28 2009

Asterisk developer's documentation


app_minivm.c File Reference

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

#include "asterisk.h"
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <time.h>
#include <dirent.h>
#include <locale.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/dsp.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/callerid.h"
#include "asterisk/event.h"

Include dependency graph for app_minivm.c:

Go to the source code of this file.

Data Structures

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

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"
#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  minivm_option_args { OPT_ARG_RECORDGAIN = 0, OPT_ARG_ARRAY_SIZE = 1 }
enum  minivm_option_flags {
  OPT_SILENT = (1 << 0), OPT_BUSY_GREETING = (1 << 1), OPT_UNAVAIL_GREETING = (1 << 2), OPT_TEMP_GREETING = (1 << 3),
  OPT_NAME_GREETING = (1 << 4), OPT_RECORDGAIN = (1 << 5)
}
enum  mvm_messagetype { MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE }
 Message types for notification. More...

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int access_counter_file (char *directory, char *countername, int value, int operand)
 Access counter file, lock directory, read and possibly write it again changed.
static int apply_general_options (struct ast_variable *var)
 Apply general configuration options.
static const char * ast_str_encode_mime (struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
static const char * ast_str_quote (struct ast_str **buf, ssize_t maxlen, const char *from)
static int b64_inbuf (struct b64_baseio *bio, FILE *fi)
static int b64_inchar (struct b64_baseio *bio, FILE *fi)
static int b64_ochar (struct b64_baseio *bio, int c, FILE *so)
static int base_encode (char *filename, FILE *so)
static int check_dirpath (char *dest, int len, char *domain, char *username, char *folder)
static int check_mime (const char *str)
static char * complete_minivm_show_users (const char *line, const char *word, int pos, int state)
static int create_dirpath (char *dest, int len, char *domain, char *username, char *folder)
static int create_vmaccount (char *name, struct ast_variable *var, int realtime)
 Append new mailbox to mailbox list from configuration file.
static struct minivm_accountfind_account (const char *domain, const char *username, int createtemp)
static struct minivm_accountfind_user_realtime (const char *domain, const char *username)
static void free_user (struct minivm_account *vmu)
static void free_zone (struct minivm_zone *z)
 Free Mini Voicemail timezone.
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)
static int leave_voicemail (struct ast_channel *chan, char *username, struct leave_vm_options *options)
static int load_config (int reload)
 Load minivoicemail configuration.
static int load_module (void)
 Load mini voicemail module.
static int make_dir (char *dest, int len, const char *domain, const char *username, const char *folder)
static void message_destroy_list (void)
static int message_template_build (const char *name, struct ast_variable *var)
static struct minivm_templatemessage_template_create (const char *name)
static struct minivm_templatemessage_template_find (const char *name)
static void message_template_free (struct minivm_template *template)
static char * message_template_parse_emailbody (const char *configuration)
 Parse emailbody template from configuration file.
static char * message_template_parse_filebody (const char *filename)
 Read message template from file.
static int minivm_accmess_exec (struct ast_channel *chan, const char *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, const char *data)
static int minivm_greet_exec (struct ast_channel *chan, const char *data)
static int minivm_mwi_exec (struct ast_channel *chan, const char *data)
static int minivm_notify_exec (struct ast_channel *chan, const char *data)
static int minivm_record_exec (struct ast_channel *chan, const char *data)
static struct minivm_accountmvm_user_alloc (void)
static int notify_new_message (struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct minivm_account *vmu, int *duration, const char *unlockdir, signed char record_gain)
static void populate_defaults (struct minivm_account *vmu)
static void prep_email_sub_vars (struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
static void queue_mwi_event (const char *mbx, const char *ctx, int urgent, int new, int old)
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)
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)
static int vm_lock_path (const char *path)
 lock directory
static void vmaccounts_destroy_list (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mini VoiceMail (A minimal Voicemail e-mail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static char * app_minivm_accmess = "MinivmAccMess"
static char * app_minivm_delete = "MinivmDelete"
static char * app_minivm_greet = "MinivmGreet"
static char * app_minivm_mwi = "MinivmMWI"
static char * app_minivm_notify = "MinivmNotify"
static char * app_minivm_record = "MinivmRecord"
static 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 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
static ast_mutex_t minivmlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static FILE * minivmlogfile
static ast_mutex_t minivmloglock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char MVM_SPOOL_DIR [PATH_MAX]


Detailed Description

MiniVoiceMail - A Minimal Voicemail System for Asterisk.

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

See also

Definition in file app_minivm.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Default username for sending mail is asterisk@localhost

Definition at line 530 of file app_minivm.c.

Referenced by load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 520 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 519 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 693 of file app_minivm.c.

Referenced by message_template_create().

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

Definition at line 692 of file app_minivm.c.

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 521 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100

#define FALSE   0

Definition at line 502 of file app_minivm.c.

Referenced by __sip_ack(), __sip_semi_ack(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), ast_tzset(), build_peer(), cb_extensionstate(), check_auth(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), dialog_needdestroy(), do_monitor(), expire_register(), find_call(), find_sdp(), function_sippeer(), handle_invite_replaces(), handle_request_invite(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), handle_response(), handle_response_invite(), interpret_t38_parameters(), invent_message(), load_config(), minivm_accmess_exec(), minivm_counter_func_read(), minivm_counter_func_write(), parse_register_contact(), parse_sip_options(), proc_session_timer(), process_sdp(), proxy_update(), rcvfax_exec(), receive_message(), register_verify(), reload_config(), reqprep(), send_provisional_keepalive_full(), set_destination(), show_console(), sip_addheader(), sip_answer(), sip_destroy_peer(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_peer_hold(), sip_poke_noanswer(), sip_prune_realtime(), sip_read(), sip_register(), sip_sendhtml(), sip_set_history(), sip_set_rtp_peer(), sip_set_udptl_peer(), sip_show_inuse(), sip_show_settings(), sip_show_user(), sip_show_users(), sndfax_exec(), st_get_mode(), st_get_refresher(), st_get_se(), stop_session_timer(), time1(), time2(), time2sub(), transmit_audio(), transmit_fake_auth_response(), transmit_invite(), transmit_provisional_response(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), tzload(), tzparse(), update_call_counter(), and update_connectedline().

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

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

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

#define MAX_DATETIME_FORMAT   512

Definition at line 523 of file app_minivm.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 524 of file app_minivm.c.

Referenced by load_config(), and play_message_callerid().

#define MVM_ALLOCED   (1 << 13)

#define MVM_ENVELOPE   (1 << 4)

Definition at line 510 of file app_minivm.c.

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

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

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 508 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)

#define MVM_SVMAIL   (1 << 3)

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

Referenced by load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 518 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 499 of file app_minivm.c.

Referenced by __sip_ack(), __sip_autodestruct(), __sip_destroy(), __sip_semi_ack(), __sip_subscribe_mwi_do(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), ast_tzset(), build_peer(), check_auth(), check_dirpath(), check_peer_ok(), check_pendings(), cli_activate(), create_addr(), dialog_needdestroy(), find_account(), find_call(), find_sdp(), find_user_realtime(), function_sippeer(), get_sip_pvt_byid_locked(), gmtload(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_peerpoke(), interpret_t38_parameters(), leave_voicemail(), load_config(), local_attended_transfer(), manager_mutestream(), manager_sipnotify(), message_template_create(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), minivm_notify_exec(), parse_ok_contact(), parse_register_contact(), parse_sip_options(), proc_session_timer(), process_sdp(), proxy_update(), rcvfax_exec(), realtime_peer(), reg_source_db(), register_verify(), reload_config(), reqprep(), respprep(), restart_session_timer(), set_destination(), show_console(), sip_addheader(), sip_alloc(), sip_answer(), sip_cli_notify(), sip_destroy(), sip_destroy_peer(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_indicate(), sip_park_thread(), sip_poke_noanswer(), sip_poke_peer(), sip_prune_realtime(), sip_read(), sip_registry_destroy(), sip_reload(), sip_request_call(), sip_scheddestroy(), sip_send_mwi_to_peer(), sip_set_history(), sip_set_udptl_peer(), sip_show_channel(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_unregister(), sip_write(), sndfax_exec(), st_get_mode(), st_get_refresher(), st_get_se(), stop_session_timer(), temp_peer(), time1(), time2(), time2sub(), transmit_audio(), transmit_invite(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_t38(), tzload(), tzparse(), udptl_rx_packet(), unload_module(), update_call_counter(), and update_connectedline().

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 529 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

Definition at line 527 of file app_minivm.c.

Referenced by create_dirpath().


Enumeration Type Documentation

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 560 of file app_minivm.c.

00560                         {
00561    OPT_ARG_RECORDGAIN = 0,
00562    OPT_ARG_ARRAY_SIZE = 1,
00563 };

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 551 of file app_minivm.c.

00551                          {
00552    OPT_SILENT =      (1 << 0),
00553    OPT_BUSY_GREETING =    (1 << 1),
00554    OPT_UNAVAIL_GREETING = (1 << 2),
00555    OPT_TEMP_GREETING = (1 << 3),
00556    OPT_NAME_GREETING = (1 << 4),
00557    OPT_RECORDGAIN =  (1 << 5),
00558 };

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 533 of file app_minivm.c.

00533                      {
00534    MVM_MESSAGE_EMAIL,
00535    MVM_MESSAGE_PAGE
00536    /* For trunk: MVM_MESSAGE_JABBER, */
00537 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3546 of file app_minivm.c.

static void __unreg_module ( void   )  [static]

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

03261 {
03262    char filename[BUFSIZ];
03263    char readbuf[BUFSIZ];
03264    FILE *counterfile;
03265    int old = 0, counter = 0;
03266 
03267    /* Lock directory */
03268    if (vm_lock_path(directory)) {
03269       return -1;  /* Could not lock directory */
03270    }
03271    snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
03272    if (operand != 1) {
03273       counterfile = fopen(filename, "r");
03274       if (counterfile) {
03275          if(fgets(readbuf, sizeof(readbuf), counterfile)) {
03276             ast_debug(3, "Read this string from counter file: %s\n", readbuf);
03277             old = counter = atoi(readbuf);
03278          }
03279          fclose(counterfile);
03280       }
03281    }
03282    switch (operand) {
03283    case 0:  /* Read only */
03284       ast_unlock_path(directory);
03285       ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
03286       return counter;
03287       break;
03288    case 1: /* Set new value */
03289       counter = value;
03290       break;
03291    case 2: /* Change value */
03292       counter += value;
03293       if (counter < 0)  /* Don't allow counters to fall below zero */
03294          counter = 0;
03295       break;
03296    }
03297    
03298    /* Now, write the new value to the file */
03299    counterfile = fopen(filename, "w");
03300    if (!counterfile) {
03301       ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
03302       ast_unlock_path(directory);
03303       return -1;  /* Could not open file for writing */
03304    }
03305    fprintf(counterfile, "%d\n\n", counter);
03306    fclose(counterfile);
03307    ast_unlock_path(directory);
03308    ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
03309    return counter;
03310 }

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

Definition at line 2740 of file app_minivm.c.

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

Referenced by load_config().

02741 {
02742    int error = 0;
02743 
02744    while (var) {
02745       /* Mail command */
02746       if (!strcmp(var->name, "mailcmd")) {
02747          ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
02748       } else if (!strcmp(var->name, "maxgreet")) {
02749          global_maxgreet = atoi(var->value);
02750       } else if (!strcmp(var->name, "maxsilence")) {
02751          global_maxsilence = atoi(var->value);
02752          if (global_maxsilence > 0)
02753             global_maxsilence *= 1000;
02754       } else if (!strcmp(var->name, "logfile")) {
02755          if (!ast_strlen_zero(var->value) ) {
02756             if(*(var->value) == '/')
02757                ast_copy_string(global_logfile, var->value, sizeof(global_logfile));
02758             else
02759                snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
02760          }
02761       } else if (!strcmp(var->name, "externnotify")) {
02762          /* External voicemail notify application */
02763          ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
02764       } else if (!strcmp(var->name, "silencetreshold")) {
02765          /* Silence treshold */
02766          global_silencethreshold = atoi(var->value);
02767       } else if (!strcmp(var->name, "maxmessage")) {
02768          int x;
02769          if (sscanf(var->value, "%30d", &x) == 1) {
02770             global_vmmaxmessage = x;
02771          } else {
02772             error ++;
02773             ast_log(LOG_WARNING, "Invalid max message time length\n");
02774          }
02775       } else if (!strcmp(var->name, "minmessage")) {
02776          int x;
02777          if (sscanf(var->value, "%30d", &x) == 1) {
02778             global_vmminmessage = x;
02779             if (global_maxsilence <= global_vmminmessage)
02780                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
02781          } else {
02782             error ++;
02783             ast_log(LOG_WARNING, "Invalid min message time length\n");
02784          }
02785       } else if (!strcmp(var->name, "format")) {
02786          ast_copy_string(default_vmformat, var->value, sizeof(default_vmformat));
02787       } else if (!strcmp(var->name, "review")) {
02788          ast_set2_flag((&globalflags), ast_true(var->value), MVM_REVIEW);  
02789       } else if (!strcmp(var->name, "operator")) {
02790          ast_set2_flag((&globalflags), ast_true(var->value), MVM_OPERATOR);   
02791       }
02792       var = var->next;
02793    }
02794    return error;
02795 }

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

Definition at line 1154 of file app_minivm.c.

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

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

01155 {
01156    struct ast_str *tmp = ast_str_alloca(80);
01157    int first_section = 1;
01158    *end = '\0';
01159 
01160    ast_str_reset(*end);
01161    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
01162    for (; *start; start++) {
01163       int need_encoding = 0;
01164       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
01165          need_encoding = 1;
01166       }
01167       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
01168          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
01169          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
01170          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
01171          /* Start new line */
01172          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
01173          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
01174          first_section = 0;
01175       }
01176       if (need_encoding && *start == ' ') {
01177          ast_str_append(&tmp, -1, "_");
01178       } else if (need_encoding) {
01179          ast_str_append(&tmp, -1, "=%hhX", *start);
01180       } else {
01181          ast_str_append(&tmp, -1, "%c", *start);
01182       }
01183    }
01184    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
01185    return ast_str_buffer(*end);
01186 }

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

Definition at line 1196 of file app_minivm.c.

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

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

01197 {
01198    const char *ptr;
01199 
01200    /* We're only ever passing 0 to maxlen, so short output isn't possible */
01201    ast_str_set(buf, maxlen, "\"");
01202    for (ptr = from; *ptr; ptr++) {
01203       if (*ptr == '"' || *ptr == '\\') {
01204          ast_str_append(buf, maxlen, "\\%c", *ptr);
01205       } else {
01206          ast_str_append(buf, maxlen, "%c", *ptr);
01207       }
01208    }
01209    ast_str_append(buf, maxlen, "\"");
01210 
01211    return ast_str_buffer(*buf);
01212 }

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

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

00833 {
00834    int l;
00835 
00836    if (bio->ateof)
00837       return 0;
00838 
00839    if ((l = fread(bio->iobuf, 1, B64_BASEMAXINLINE,fi)) <= 0) {
00840       if (ferror(fi))
00841          return -1;
00842 
00843       bio->ateof = 1;
00844       return 0;
00845    }
00846 
00847    bio->iolen= l;
00848    bio->iocp= 0;
00849 
00850    return 1;
00851 }

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

Definition at line 855 of file app_minivm.c.

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

Referenced by base_encode().

00856 {
00857    if (bio->iocp >= bio->iolen) {
00858       if (!b64_inbuf(bio, fi))
00859          return EOF;
00860    }
00861 
00862    return bio->iobuf[bio->iocp++];
00863 }

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

Definition at line 867 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

00868 {
00869    if (bio->linelength >= B64_BASELINELEN) {
00870       if (fputs(EOL,so) == EOF)
00871          return -1;
00872 
00873       bio->linelength= 0;
00874    }
00875 
00876    if (putc(((unsigned char) c), so) == EOF)
00877       return -1;
00878 
00879    bio->linelength++;
00880 
00881    return 1;
00882 }

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

Definition at line 886 of file app_minivm.c.

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

Referenced by add_email_attachment(), and sendmail().

00887 {
00888    unsigned char dtable[B64_BASEMAXINLINE];
00889    int i,hiteof= 0;
00890    FILE *fi;
00891    struct b64_baseio bio;
00892 
00893    memset(&bio, 0, sizeof(bio));
00894    bio.iocp = B64_BASEMAXINLINE;
00895 
00896    if (!(fi = fopen(filename, "rb"))) {
00897       ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
00898       return -1;
00899    }
00900 
00901    for (i= 0; i<9; i++) {
00902       dtable[i]= 'A'+i;
00903       dtable[i+9]= 'J'+i;
00904       dtable[26+i]= 'a'+i;
00905       dtable[26+i+9]= 'j'+i;
00906    }
00907    for (i= 0; i < 8; i++) {
00908       dtable[i+18]= 'S'+i;
00909       dtable[26+i+18]= 's'+i;
00910    }
00911    for (i= 0; i < 10; i++) {
00912       dtable[52+i]= '0'+i;
00913    }
00914    dtable[62]= '+';
00915    dtable[63]= '/';
00916 
00917    while (!hiteof){
00918       unsigned char igroup[3], ogroup[4];
00919       int c,n;
00920 
00921       igroup[0]= igroup[1]= igroup[2]= 0;
00922 
00923       for (n= 0; n < 3; n++) {
00924          if ((c = b64_inchar(&bio, fi)) == EOF) {
00925             hiteof= 1;
00926             break;
00927          }
00928          igroup[n]= (unsigned char)c;
00929       }
00930 
00931       if (n> 0) {
00932          ogroup[0]= dtable[igroup[0]>>2];
00933          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
00934          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
00935          ogroup[3]= dtable[igroup[2]&0x3F];
00936 
00937          if (n<3) {
00938             ogroup[3]= '=';
00939 
00940             if (n<2)
00941                ogroup[2]= '=';
00942          }
00943 
00944          for (i= 0;i<4;i++)
00945             b64_ochar(&bio, ogroup[i], so);
00946       }
00947    }
00948 
00949    /* Put end of line - line feed */
00950    if (fputs(EOL, so) == EOF)
00951       return 0;
00952 
00953    fclose(fi);
00954 
00955    return 1;
00956 }

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

Definition at line 1486 of file app_minivm.c.

References FALSE, make_dir(), and TRUE.

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

01487 {
01488    struct stat filestat;
01489    make_dir(dest, len, domain, username, folder ? folder : "");
01490    if (stat(dest, &filestat)== -1)
01491       return FALSE;
01492    else
01493       return TRUE;
01494 }

static int check_mime ( const char *  str  )  [static]

Definition at line 1125 of file app_minivm.c.

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

01126 {
01127    for (; *str; str++) {
01128       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
01129          return 1;
01130       }
01131    }
01132    return 0;
01133 }

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

Definition at line 2979 of file app_minivm.c.

References AST_LIST_TRAVERSE, ast_strdup, and minivm_account::domain.

Referenced by handle_minivm_show_users().

02980 {
02981    int which = 0;
02982    int wordlen;
02983    struct minivm_account *vmu;
02984    const char *domain = "";
02985 
02986    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
02987    if (pos > 4)
02988       return NULL;
02989    if (pos == 3)
02990       return (state == 0) ? ast_strdup("for") : NULL;
02991    wordlen = strlen(word);
02992    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02993       if (!strncasecmp(word, vmu->domain, wordlen)) {
02994          if (domain && strcmp(domain, vmu->domain) && ++which > state)
02995             return ast_strdup(vmu->domain);
02996          /* ignore repeated domains ? */
02997          domain = vmu->domain;
02998       }
02999    }
03000    return NULL;
03001 }

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

Definition at line 1505 of file app_minivm.c.

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

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

01506 {
01507    int res;
01508    make_dir(dest, len, domain, username, folder);
01509    if ((res = ast_mkdir(dest, 0777))) {
01510       ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01511       return -1;
01512    }
01513    ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
01514    return 0;
01515 }

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

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

Referenced by find_user_realtime(), and load_config().

02525 {
02526    struct minivm_account *vmu;
02527    char *domain;
02528    char *username;
02529    char accbuf[BUFSIZ];
02530 
02531    ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
02532 
02533    ast_copy_string(accbuf, name, sizeof(accbuf));
02534    username = accbuf;
02535    domain = strchr(accbuf, '@');
02536    if (domain) {
02537       *domain = '\0';
02538       domain++;
02539    }
02540    if (ast_strlen_zero(domain)) {
02541       ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
02542       return 0;
02543    }
02544 
02545    ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
02546 
02547    /* Allocate user account */
02548    vmu = ast_calloc(1, sizeof(*vmu));
02549    if (!vmu)
02550       return 0;
02551    
02552    ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
02553    ast_copy_string(vmu->username, username, sizeof(vmu->username));
02554 
02555    populate_defaults(vmu);
02556 
02557    ast_debug(3, "...Configuring account %s\n", name);
02558 
02559    while (var) {
02560       ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
02561       if (!strcasecmp(var->name, "serveremail")) {
02562          ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
02563       } else if (!strcasecmp(var->name, "email")) {
02564          ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
02565       } else if (!strcasecmp(var->name, "accountcode")) {
02566          ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
02567       } else if (!strcasecmp(var->name, "pincode")) {
02568          ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
02569       } else if (!strcasecmp(var->name, "domain")) {
02570          ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
02571       } else if (!strcasecmp(var->name, "language")) {
02572          ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
02573       } else if (!strcasecmp(var->name, "timezone")) {
02574          ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
02575       } else if (!strcasecmp(var->name, "externnotify")) {
02576          ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
02577       } else if (!strcasecmp(var->name, "etemplate")) {
02578          ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
02579       } else if (!strcasecmp(var->name, "ptemplate")) {
02580          ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
02581       } else if (!strcasecmp(var->name, "fullname")) {
02582          ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
02583       } else if (!strcasecmp(var->name, "setvar")) {
02584          char *varval;
02585          char *varname = ast_strdupa(var->value);
02586          struct ast_variable *tmpvar;
02587 
02588          if (varname && (varval = strchr(varname, '='))) {
02589             *varval = '\0';
02590             varval++;
02591             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
02592                tmpvar->next = vmu->chanvars;
02593                vmu->chanvars = tmpvar;
02594             }
02595          }
02596       } else if (!strcasecmp(var->name, "pager")) {
02597          ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
02598       } else if (!strcasecmp(var->name, "volgain")) {
02599          sscanf(var->value, "%30lf", &vmu->volgain);
02600       } else {
02601          ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
02602       }
02603       var = var->next;
02604    }
02605    ast_debug(3, "...Linking account %s\n", name);
02606    
02607    AST_LIST_LOCK(&minivm_accounts);
02608    AST_LIST_INSERT_TAIL(&minivm_accounts, vmu, list);
02609    AST_LIST_UNLOCK(&minivm_accounts);
02610 
02611    global_stats.voicemailaccounts++;
02612 
02613    ast_debug(2, "MVM :: Created account %s@%s - tz %s etemplate %s %s\n", username, domain, ast_strlen_zero(vmu->zonetag) ? "" : vmu->zonetag, ast_strlen_zero(vmu->etemplate) ? "" : vmu->etemplate, realtime ? "(realtime)" : "");
02614    return 0;
02615 }

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

Definition at line 1048 of file app_minivm.c.

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

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

01049 {
01050    struct minivm_account *vmu = NULL, *cur;
01051 
01052 
01053    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
01054       ast_log(LOG_NOTICE, "No username or domain? \n");
01055       return NULL;
01056    }
01057    ast_debug(3, "Looking for voicemail user %s in domain %s\n", username, domain);
01058 
01059    AST_LIST_LOCK(&minivm_accounts);
01060    AST_LIST_TRAVERSE(&minivm_accounts, cur, list) {
01061       /* Is this the voicemail account we're looking for? */
01062       if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
01063          break;
01064    }
01065    AST_LIST_UNLOCK(&minivm_accounts);
01066 
01067    if (cur) {
01068       ast_debug(3, "Found account for %s@%s\n", username, domain);
01069       vmu = cur;
01070 
01071    } else
01072       vmu = find_user_realtime(domain, username);
01073 
01074    if (createtemp && !vmu) {
01075       /* Create a temporary user, send e-mail and be gone */
01076       vmu = mvm_user_alloc();
01077       ast_set2_flag(vmu, TRUE, MVM_ALLOCED); 
01078       if (vmu) {
01079          ast_copy_string(vmu->username, username, sizeof(vmu->username));
01080          ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
01081          ast_debug(1, "Created temporary account\n");
01082       }
01083 
01084    }
01085    return vmu;
01086 }

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

Definition at line 1092 of file app_minivm.c.

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

Referenced by find_account(), and find_user().

01093 {
01094    struct ast_variable *var;
01095    struct minivm_account *retval;
01096    char name[MAXHOSTNAMELEN];
01097 
01098    retval = mvm_user_alloc();
01099    if (!retval)
01100       return NULL;
01101 
01102    if (username) 
01103       ast_copy_string(retval->username, username, sizeof(retval->username));
01104 
01105    populate_defaults(retval);
01106    var = ast_load_realtime("minivm", "username", username, "domain", domain, SENTINEL);
01107 
01108    if (!var) {
01109       ast_free(retval);
01110       return NULL;
01111    }
01112 
01113    snprintf(name, sizeof(name), "%s@%s", username, domain);
01114    create_vmaccount(name, var, TRUE);
01115 
01116    ast_variables_destroy(var);
01117    return retval;
01118 }

static void free_user ( struct minivm_account vmu  )  [static]

static void free_zone ( struct minivm_zone z  )  [static]

Free Mini Voicemail timezone.

Definition at line 2618 of file app_minivm.c.

References ast_free.

Referenced by free_vm_zones(), and timezone_destroy_list().

02619 {
02620    ast_free(z);
02621 }

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

Definition at line 958 of file app_minivm.c.

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

Referenced by leave_voicemail(), and tds_log().

00959 {
00960    struct ast_tm tm;
00961    struct timeval now = ast_tvnow();
00962 
00963    ast_localtime(&now, &tm, NULL);
00964    return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
00965 }

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

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

02939 {
02940    struct minivm_template *this;
02941 #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
02942    int count = 0;
02943 
02944    switch (cmd) {
02945    case CLI_INIT:
02946       e->command = "minivm list templates";
02947       e->usage =
02948          "Usage: minivm list templates\n"
02949          "       Lists message templates for e-mail, paging and IM\n";
02950       return NULL;
02951    case CLI_GENERATE:
02952       return NULL;
02953    }
02954 
02955    if (a->argc > 3)
02956       return CLI_SHOWUSAGE;
02957 
02958    AST_LIST_LOCK(&message_templates);
02959    if (AST_LIST_EMPTY(&message_templates)) {
02960       ast_cli(a->fd, "There are no message templates defined\n");
02961       AST_LIST_UNLOCK(&message_templates);
02962       return CLI_FAILURE;
02963    }
02964    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
02965    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
02966    AST_LIST_TRAVERSE(&message_templates, this, list) {
02967       ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name, 
02968          this->charset ? this->charset : "-", 
02969          this->locale ? this->locale : "-",
02970          this->attachment ? "Yes" : "No",
02971          this->subject ? this->subject : "-");
02972       count++;
02973    }
02974    AST_LIST_UNLOCK(&message_templates);
02975    ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
02976    return CLI_SUCCESS;
02977 }

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

Reload cofiguration.

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

03500 {
03501    
03502    switch (cmd) {
03503    case CLI_INIT:
03504       e->command = "minivm reload";
03505       e->usage =
03506          "Usage: minivm reload\n"
03507          "       Reload mini-voicemail configuration and reset statistics\n";
03508       return NULL;
03509    case CLI_GENERATE:
03510       return NULL;
03511    }
03512    
03513    reload();
03514    ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
03515    return CLI_SUCCESS;
03516 }

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

03090 {
03091    switch (cmd) {
03092    case CLI_INIT:
03093       e->command = "minivm show settings";
03094       e->usage =
03095          "Usage: minivm show settings\n"
03096          "       Display Mini-Voicemail general settings\n";
03097       return NULL;
03098    case CLI_GENERATE:
03099       return NULL;
03100    }
03101 
03102    ast_cli(a->fd, "* Mini-Voicemail general settings\n");
03103    ast_cli(a->fd, "  -------------------------------\n");
03104    ast_cli(a->fd, "\n");
03105    ast_cli(a->fd, "  Mail command (shell):               %s\n", global_mailcmd);
03106    ast_cli(a->fd, "  Max silence:                        %d\n", global_maxsilence);
03107    ast_cli(a->fd, "  Silence threshold:                  %d\n", global_silencethreshold);
03108    ast_cli(a->fd, "  Max message length (secs):          %d\n", global_vmmaxmessage);
03109    ast_cli(a->fd, "  Min message length (secs):          %d\n", global_vmminmessage);
03110    ast_cli(a->fd, "  Default format:                     %s\n", default_vmformat);
03111    ast_cli(a->fd, "  Extern notify (shell):              %s\n", global_externnotify);
03112    ast_cli(a->fd, "  Logfile:                            %s\n", global_logfile[0] ? global_logfile : "<disabled>");
03113    ast_cli(a->fd, "  Operator exit:                      %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
03114    ast_cli(a->fd, "  Message review:                     %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
03115 
03116    ast_cli(a->fd, "\n");
03117    return CLI_SUCCESS;
03118 }

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

Show stats.

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

03122 {
03123    struct ast_tm timebuf;
03124    char buf[BUFSIZ];
03125 
03126    switch (cmd) {
03127    
03128    case CLI_INIT:
03129       e->command = "minivm show stats";
03130       e->usage =
03131          "Usage: minivm show stats\n"
03132          "       Display Mini-Voicemail counters\n";
03133       return NULL;
03134    case CLI_GENERATE:
03135       return NULL;
03136    }
03137 
03138    ast_cli(a->fd, "* Mini-Voicemail statistics\n");
03139    ast_cli(a->fd, "  -------------------------\n");
03140    ast_cli(a->fd, "\n");
03141    ast_cli(a->fd, "  Voicemail accounts:                  %5d\n", global_stats.voicemailaccounts);
03142    ast_cli(a->fd, "  Templates:                           %5d\n", global_stats.templates);
03143    ast_cli(a->fd, "  Timezones:                           %5d\n", global_stats.timezones);
03144    if (global_stats.receivedmessages == 0) {
03145       ast_cli(a->fd, "  Received messages since last reset:  <none>\n");
03146    } else {
03147       ast_cli(a->fd, "  Received messages since last reset:  %d\n", global_stats.receivedmessages);
03148       ast_localtime(&global_stats.lastreceived, &timebuf, NULL);
03149       ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
03150       ast_cli(a->fd, "  Last received voicemail:             %s\n", buf);
03151    }
03152    ast_localtime(&global_stats.reset, &timebuf, NULL);
03153    ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
03154    ast_cli(a->fd, "  Last reset:                          %s\n", buf);
03155 
03156    ast_cli(a->fd, "\n");
03157    return CLI_SUCCESS;
03158 }

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

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

03005 {
03006    struct minivm_account *vmu;
03007 #define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
03008    int count = 0;
03009 
03010    switch (cmd) {
03011    case CLI_INIT:
03012       e->command = "minivm list accounts";
03013       e->usage =
03014          "Usage: minivm list accounts\n"
03015          "       Lists all mailboxes currently set up\n";
03016       return NULL;
03017    case CLI_GENERATE:
03018       return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
03019    }
03020 
03021    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
03022       return CLI_SHOWUSAGE;
03023    if ((a->argc == 5) && strcmp(a->argv[3],"for"))
03024       return CLI_SHOWUSAGE;
03025 
03026    AST_LIST_LOCK(&minivm_accounts);
03027    if (AST_LIST_EMPTY(&minivm_accounts)) {
03028       ast_cli(a->fd, "There are no voicemail users currently defined\n");
03029       AST_LIST_UNLOCK(&minivm_accounts);
03030       return CLI_FAILURE;
03031    }
03032    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
03033    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
03034    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
03035       char tmp[256] = "";
03036       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
03037          count++;
03038          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
03039          ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, vmu->etemplate ? vmu->etemplate : "-", 
03040             vmu->ptemplate ? vmu->ptemplate : "-",
03041             vmu->zonetag ? vmu->zonetag : "-", 
03042             vmu->attachfmt ? vmu->attachfmt : "-",
03043             vmu->fullname);
03044       }
03045    }
03046    AST_LIST_UNLOCK(&minivm_accounts);
03047    ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
03048    return CLI_SUCCESS;
03049 }

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

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

03053 {
03054    struct minivm_zone *zone;
03055 #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
03056    char *res = CLI_SUCCESS;
03057 
03058    switch (cmd) {
03059    case CLI_INIT:
03060       e->command = "minivm list zones";
03061       e->usage =
03062          "Usage: minivm list zones\n"
03063          "       Lists zone message formats\n";
03064       return NULL;
03065    case CLI_GENERATE:
03066       return NULL;
03067    }
03068 
03069    if (a->argc != e->args)
03070       return CLI_SHOWUSAGE;
03071 
03072    AST_LIST_LOCK(&minivm_zones);
03073    if (!AST_LIST_EMPTY(&minivm_zones)) {
03074       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
03075       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
03076       AST_LIST_TRAVERSE(&minivm_zones, zone, list) {
03077          ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
03078       }
03079    } else {
03080       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
03081       res = CLI_FAILURE;
03082    }
03083    AST_LIST_UNLOCK(&minivm_zones);
03084 
03085    return res;
03086 }

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

Definition at line 1521 of file app_minivm.c.

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

Referenced by leave_voicemail(), and minivm_greet_exec().

01522 {
01523    int res;
01524    char fn[PATH_MAX];
01525 
01526    ast_debug(2, "Still preparing to play message ...\n");
01527 
01528    snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
01529 
01530    if (ast_fileexists(fn, NULL, NULL) > 0) {
01531       res = ast_streamfile(chan, fn, chan->language);
01532       if (res) 
01533          return -1;
01534       res = ast_waitstream(chan, ecodes);
01535       if (res) 
01536          return res;
01537    } else {
01538       int numericusername = 1;
01539       char *i = username;
01540 
01541       ast_debug(2, "No personal prompts. Using default prompt set for language\n");
01542 
01543       while (*i)  {
01544          ast_debug(2, "Numeric? Checking %c\n", *i);
01545          if (!isdigit(*i)) {
01546             numericusername = FALSE;
01547             break;
01548          }
01549          i++;
01550       }
01551 
01552       if (numericusername) {
01553          if (ast_streamfile(chan, "vm-theperson", chan->language))
01554             return -1;
01555          if ((res = ast_waitstream(chan, ecodes)))
01556             return res;
01557 
01558          res = ast_say_digit_str(chan, username, ecodes, chan->language);
01559          if (res)
01560             return res;
01561       } else {
01562          if (ast_streamfile(chan, "vm-theextensionis", chan->language))
01563             return -1;
01564          if ((res = ast_waitstream(chan, ecodes)))
01565             return res;
01566       }
01567    }
01568 
01569    res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", chan->language);
01570    if (res)
01571       return -1;
01572    res = ast_waitstream(chan, ecodes);
01573    return res;
01574 }

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

Definition at line 1822 of file app_minivm.c.

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

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

01823 {
01824    char tmptxtfile[PATH_MAX];
01825    char callerid[256];
01826    FILE *txt;
01827    int res = 0, txtdes;
01828    int msgnum;
01829    int duration = 0;
01830    char date[256];
01831    char tmpdir[PATH_MAX];
01832    char ext_context[256] = "";
01833    char fmt[80];
01834    char *domain;
01835    char tmp[256] = "";
01836    struct minivm_account *vmu;
01837    int userdir;
01838 
01839    ast_copy_string(tmp, username, sizeof(tmp));
01840    username = tmp;
01841    domain = strchr(tmp, '@');
01842    if (domain) {
01843       *domain = '\0';
01844       domain++;
01845    }
01846 
01847    if (!(vmu = find_account(domain, username, TRUE))) {
01848       /* We could not find user, let's exit */
01849       ast_log(LOG_ERROR, "Can't allocate temporary account for '%s@%s'\n", username, domain);
01850       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01851       return 0;
01852    }
01853 
01854    /* Setup pre-file if appropriate */
01855    if (strcmp(vmu->domain, "localhost"))
01856       snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
01857    else
01858       ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
01859 
01860    /* The meat of recording the message...  All the announcements and beeps have been played*/
01861    if (ast_strlen_zero(vmu->attachfmt))
01862       ast_copy_string(fmt, default_vmformat, sizeof(fmt));
01863    else
01864       ast_copy_string(fmt, vmu->attachfmt, sizeof(fmt));
01865 
01866    if (ast_strlen_zero(fmt)) {
01867       ast_log(LOG_WARNING, "No format for saving voicemail? Default %s\n", default_vmformat);
01868       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01869       return res;
01870    }
01871    msgnum = 0;
01872 
01873    userdir = check_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
01874 
01875    /* If we have no user directory, use generic temporary directory */
01876    if (!userdir) {
01877       create_dirpath(tmpdir, sizeof(tmpdir), "0000_minivm_temp", "mediafiles", "");
01878       ast_debug(3, "Creating temporary directory %s\n", tmpdir);
01879    }
01880 
01881 
01882    snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
01883 
01884    /* XXX This file needs to be in temp directory */
01885    txtdes = mkstemp(tmptxtfile);
01886    if (txtdes < 0) {
01887       ast_log(LOG_ERROR, "Unable to create message file %s: %s\n", tmptxtfile, strerror(errno));
01888       res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
01889       if (!res)
01890          res = ast_waitstream(chan, "");
01891       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01892       return res;
01893    }
01894 
01895    if (res >= 0) {
01896       /* Unless we're *really* silent, try to send the beep */
01897       res = ast_streamfile(chan, "beep", chan->language);
01898       if (!res)
01899          res = ast_waitstream(chan, "");
01900    }
01901 
01902    /* OEJ XXX Maybe this can be turned into a log file? Hmm. */
01903    /* Store information */
01904    ast_debug(2, "Open file for metadata: %s\n", tmptxtfile);
01905 
01906    res = play_record_review(chan, NULL, tmptxtfile, global_vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
01907 
01908    txt = fdopen(txtdes, "w+");
01909    if (!txt) {
01910       ast_log(LOG_WARNING, "Error opening text file for output\n");
01911    } else {
01912       struct ast_tm tm;
01913       struct timeval now = ast_tvnow();
01914       char timebuf[30];
01915       char logbuf[BUFSIZ];
01916       get_date(date, sizeof(date));
01917       ast_localtime(&now, &tm, NULL);
01918       ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
01919 
01920       snprintf(logbuf, sizeof(logbuf),
01921          /* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
01922          "%s:%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
01923          username,
01924          chan->context,
01925          chan->macrocontext, 
01926          chan->exten,
01927          chan->priority,
01928          chan->name,
01929          ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
01930          date, 
01931          timebuf,
01932          duration,
01933          duration < global_vmminmessage ? "IGNORED" : "OK",
01934          vmu->accountcode
01935       ); 
01936       fprintf(txt, "%s", logbuf);
01937       if (minivmlogfile) {
01938          ast_mutex_lock(&minivmloglock);
01939          fprintf(minivmlogfile, "%s", logbuf);
01940          ast_mutex_unlock(&minivmloglock);
01941       }
01942 
01943       if (duration < global_vmminmessage) {
01944          ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, global_vmminmessage);
01945          fclose(txt);
01946          ast_filedelete(tmptxtfile, NULL);
01947          unlink(tmptxtfile);
01948          pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01949          return 0;
01950       } 
01951       fclose(txt); /* Close log file */
01952       if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
01953          ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
01954          unlink(tmptxtfile);
01955          pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01956          if(ast_test_flag(vmu, MVM_ALLOCED))
01957             free_user(vmu);
01958          return 0;
01959       }
01960 
01961       /* Set channel variables for the notify application */
01962       pbx_builtin_setvar_helper(chan, "MVM_FILENAME", tmptxtfile);
01963       snprintf(timebuf, sizeof(timebuf), "%d", duration);
01964       pbx_builtin_setvar_helper(chan, "MVM_DURATION", timebuf);
01965       pbx_builtin_setvar_helper(chan, "MVM_FORMAT", fmt);
01966 
01967    }
01968    global_stats.lastreceived = ast_tvnow();
01969    global_stats.receivedmessages++;
01970 #if 0
01971    /* Go ahead and delete audio files from system, they're not needed any more */
01972    if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
01973       ast_filedelete(tmptxtfile, NULL);
01974        /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
01975       ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
01976    }
01977 #endif
01978 
01979    if (res > 0)
01980       res = 0;
01981 
01982    if(ast_test_flag(vmu, MVM_ALLOCED))
01983       free_user(vmu);
01984 
01985    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
01986    return res;
01987 }

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2798 of file app_minivm.c.

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

02799 {
02800    struct ast_config *cfg;
02801    struct ast_variable *var;
02802    char *cat;
02803    const char *chanvar;
02804    int error = 0;
02805    struct minivm_template *template;
02806    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02807 
02808    cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
02809    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02810       return 0;
02811    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02812       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
02813       return 0;
02814    }
02815 
02816    ast_mutex_lock(&minivmlock);
02817 
02818    /* Destroy lists to reconfigure */
02819    message_destroy_list();    /* Destroy list of voicemail message templates */
02820    timezone_destroy_list();   /* Destroy list of timezones */
02821    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
02822    ast_debug(2, "Destroyed memory objects...\n");
02823 
02824    /* First, set some default settings */
02825    global_externnotify[0] = '\0';
02826    global_logfile[0] = '\0';
02827    global_vmmaxmessage = 2000;
02828    global_maxgreet = 2000;
02829    global_vmminmessage = 0;
02830    strcpy(global_mailcmd, SENDMAIL);
02831    global_maxsilence = 0;
02832    global_saydurationminfo = 2;
02833    ast_copy_string(default_vmformat, "wav", sizeof(default_vmformat));
02834    ast_set2_flag((&globalflags), FALSE, MVM_REVIEW);  
02835    ast_set2_flag((&globalflags), FALSE, MVM_OPERATOR);   
02836    /* Reset statistics */
02837    memset(&global_stats, 0, sizeof(global_stats));
02838    global_stats.reset = ast_tvnow();
02839 
02840    global_silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
02841 
02842    /* Make sure we could load configuration file */
02843    if (!cfg) {
02844       ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
02845       ast_mutex_unlock(&minivmlock);
02846       return 0;
02847    }
02848 
02849    ast_debug(2, "Loaded configuration file, now parsing\n");
02850 
02851    /* General settings */
02852 
02853    cat = ast_category_browse(cfg, NULL);
02854    while (cat) {
02855       ast_debug(3, "Found configuration section [%s]\n", cat);
02856       if (!strcasecmp(cat, "general")) {
02857          /* Nothing right now */
02858          error += apply_general_options(ast_variable_browse(cfg, cat));
02859       } else if (!strncasecmp(cat, "template-", 9))  {
02860          /* Template */
02861          char *name = cat + 9;
02862 
02863          /* Now build and link template to list */
02864          error += message_template_build(name, ast_variable_browse(cfg, cat));
02865       } else {
02866          var = ast_variable_browse(cfg, cat);
02867          if (!strcasecmp(cat, "zonemessages")) {
02868             /* Timezones in this context */
02869             while (var) {
02870                timezone_add(var->name, var->value);
02871                var = var->next;
02872             }
02873          } else {
02874             /* Create mailbox from this */
02875             error += create_vmaccount(cat, var, FALSE);
02876          }
02877       }
02878       /* Find next section in configuration file */
02879       cat = ast_category_browse(cfg, cat);
02880    }
02881 
02882    /* Configure the default email template */
02883    message_template_build("email-default", NULL);
02884    template = message_template_find("email-default");
02885 
02886    /* Load date format config for voicemail mail */
02887    if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat"))) 
02888       ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
02889    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
02890       ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
02891    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
02892       ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
02893    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
02894       ast_copy_string(template->charset, chanvar, sizeof(template->charset));
02895    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject"))) 
02896       ast_copy_string(template->subject, chanvar, sizeof(template->subject));
02897    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody"))) 
02898       template->body = message_template_parse_emailbody(chanvar);
02899    template->attachment = TRUE;
02900 
02901    message_template_build("pager-default", NULL);
02902    template = message_template_find("pager-default");
02903    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
02904       ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
02905    if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
02906       ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
02907    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
02908       ast_copy_string(template->charset, chanvar, sizeof(template->charset));
02909    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
02910       ast_copy_string(template->subject, chanvar,sizeof(template->subject));
02911    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody"))) 
02912       template->body = message_template_parse_emailbody(chanvar);
02913    template->attachment = FALSE;
02914 
02915    if (error)
02916       ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
02917 
02918    ast_mutex_unlock(&minivmlock);
02919    ast_config_destroy(cfg);
02920 
02921    /* Close log file if it's open and disabled */
02922    if(minivmlogfile)
02923       fclose(minivmlogfile);
02924 
02925    /* Open log file if it's enabled */
02926    if(!ast_strlen_zero(global_logfile)) {
02927       minivmlogfile = fopen(global_logfile, "a");
02928       if(!minivmlogfile)
02929          ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
02930       if (minivmlogfile)
02931          ast_debug(3, "Opened log file %s \n", global_logfile);
02932    }
02933 
02934    return 0;
02935 }

static int load_module ( void   )  [static]

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

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

01473 {
01474    return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
01475 }

static void message_destroy_list ( void   )  [static]

Definition at line 819 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

00820 {
00821    struct minivm_template *this;
00822    AST_LIST_LOCK(&message_templates);
00823    while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) {
00824       message_template_free(this);
00825    }
00826 
00827    AST_LIST_UNLOCK(&message_templates);
00828 }

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

Definition at line 734 of file app_minivm.c.

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

Referenced by load_config().

00735 {
00736    struct minivm_template *template;
00737    int error = 0;
00738 
00739    template = message_template_create(name);
00740    if (!template) {
00741       ast_log(LOG_ERROR, "Out of memory, can't allocate message template object %s.\n", name);
00742       return -1;
00743    }
00744 
00745    while (var) {
00746       ast_debug(3, "Configuring template option %s = \"%s\" for template %s\n", var->name, var->value, name);
00747       if (!strcasecmp(var->name, "fromaddress")) {
00748          ast_copy_string(template->fromaddress, var->value, sizeof(template->fromaddress));
00749       } else if (!strcasecmp(var->name, "fromemail")) {
00750          ast_copy_string(template->serveremail, var->value, sizeof(template->serveremail));
00751       } else if (!strcasecmp(var->name, "subject")) {
00752          ast_copy_string(template->subject, var->value, sizeof(template->subject));
00753       } else if (!strcasecmp(var->name, "locale")) {
00754          ast_copy_string(template->locale, var->value, sizeof(template->locale));
00755       } else if (!strcasecmp(var->name, "attachmedia")) {
00756          template->attachment = ast_true(var->value);
00757       } else if (!strcasecmp(var->name, "dateformat")) {
00758          ast_copy_string(template->dateformat, var->value, sizeof(template->dateformat));
00759       } else if (!strcasecmp(var->name, "charset")) {
00760          ast_copy_string(template->charset, var->value, sizeof(template->charset));
00761       } else if (!strcasecmp(var->name, "templatefile")) {
00762          if (template->body) 
00763             ast_free(template->body);
00764          template->body = message_template_parse_filebody(var->value);
00765          if (!template->body) {
00766             ast_log(LOG_ERROR, "Error reading message body definition file %s\n", var->value);
00767             error++;
00768          }
00769       } else if (!strcasecmp(var->name, "messagebody")) {
00770          if (template->body) 
00771             ast_free(template->body);
00772          template->body = message_template_parse_emailbody(var->value);
00773          if (!template->body) {
00774             ast_log(LOG_ERROR, "Error parsing message body definition:\n          %s\n", var->value);
00775             error++;
00776          }
00777       } else {
00778          ast_log(LOG_ERROR, "Unknown message template configuration option \"%s=%s\"\n", var->name, var->value);
00779          error++;
00780       }
00781       var = var->next;
00782    }
00783    if (error)
00784       ast_log(LOG_ERROR, "-- %d errors found parsing message template definition %s\n", error, name);
00785 
00786    AST_LIST_LOCK(&message_templates);
00787    AST_LIST_INSERT_TAIL(&message_templates, template, list);
00788    AST_LIST_UNLOCK(&message_templates);
00789 
00790    global_stats.templates++;
00791 
00792    return error;
00793 }

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

Definition at line 704 of file app_minivm.c.

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

Referenced by message_template_build().

00705 {
00706    struct minivm_template *template;
00707 
00708    template = ast_calloc(1, sizeof(*template));
00709    if (!template)
00710       return NULL;
00711 
00712    /* Set some defaults for templates */
00713    ast_copy_string(template->name, name, sizeof(template->name));
00714    ast_copy_string(template->dateformat, DEFAULT_DATEFORMAT, sizeof(template->dateformat));
00715    ast_copy_string(template->charset, DEFAULT_CHARSET, sizeof(template->charset));
00716    ast_copy_string(template->subject, "New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}", sizeof(template->subject));
00717    template->attachment = TRUE;
00718 
00719    return template;
00720 }

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

Definition at line 797 of file app_minivm.c.

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

Referenced by load_config(), and notify_new_message().

00798 {
00799    struct minivm_template *this, *res = NULL;
00800 
00801    if (ast_strlen_zero(name))
00802       return NULL;
00803 
00804    AST_LIST_LOCK(&message_templates);
00805    AST_LIST_TRAVERSE(&message_templates, this, list) {
00806       if (!strcasecmp(this->name, name)) {
00807          res = this;
00808          break;
00809       }
00810    }
00811    AST_LIST_UNLOCK(&message_templates);
00812 
00813    return res;
00814 }

static void message_template_free ( struct minivm_template template  )  [static]

Definition at line 724 of file app_minivm.c.

References ast_free.

Referenced by message_destroy_list().

00725 {
00726    if (template->body)
00727       ast_free(template->body);
00728 
00729    ast_free (template);
00730 }

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

Parse emailbody template from configuration file.

Definition at line 2713 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02714 {
02715    char *tmpread, *tmpwrite;
02716    char *emailbody = ast_strdup(configuration);
02717 
02718    /* substitute strings \t and \n into the apropriate characters */
02719    tmpread = tmpwrite = emailbody;
02720    while ((tmpwrite = strchr(tmpread,'\\'))) {
02721           int len = strlen("\n");
02722           switch (tmpwrite[1]) {
02723           case 'n':
02724             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02725             strncpy(tmpwrite, "\n", len);
02726             break;
02727           case 't':
02728             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02729             strncpy(tmpwrite, "\t", len);
02730             break;
02731           default:
02732             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02733           }
02734           tmpread = tmpwrite + len;
02735    }
02736    return emailbody; 
02737 }

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

Read message template from file.

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

02673                                                                    {
02674    char buf[BUFSIZ * 6];
02675    char readbuf[BUFSIZ];
02676    char filenamebuf[BUFSIZ];
02677    char *writepos;
02678    char *messagebody;
02679    FILE *fi;
02680    int lines = 0;
02681 
02682    if (ast_strlen_zero(filename))
02683       return NULL;
02684    if (*filename == '/') 
02685       ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
02686    else 
02687       snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
02688 
02689    if (!(fi = fopen(filenamebuf, "r"))) {
02690       ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
02691       return NULL;
02692    }
02693    writepos = buf;
02694    while (fgets(readbuf, sizeof(readbuf), fi)) {
02695       lines ++;
02696       if (writepos != buf) {
02697          *writepos = '\n';    /* Replace EOL with new line */
02698          writepos++;
02699       }
02700       ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
02701       writepos += strlen(readbuf) - 1;
02702    }
02703    fclose(fi);
02704    messagebody = ast_calloc(1, strlen(buf + 1));
02705    ast_copy_string(messagebody, buf, strlen(buf) + 1);
02706    ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
02707    ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
02708 
02709    return messagebody;
02710 }

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

Record specific messages for voicemail account.

Definition at line 2420 of file app_minivm.c.

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

Referenced by load_module().

02421 {
02422    int argc = 0;
02423    char *argv[2];
02424    char filename[PATH_MAX];
02425    char tmp[PATH_MAX];
02426    char *domain;
02427    char *tmpptr = NULL;
02428    struct minivm_account *vmu;
02429    char *username = argv[0];
02430    struct ast_flags flags = { 0 };
02431    char *opts[OPT_ARG_ARRAY_SIZE];
02432    int error = FALSE;
02433    char *message = NULL;
02434    char *prompt = NULL;
02435    int duration;
02436    int cmd;
02437 
02438    if (ast_strlen_zero(data))  {
02439       ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
02440       error = TRUE;
02441    } else 
02442       tmpptr = ast_strdupa((char *)data);
02443    if (!error) {
02444       if (!tmpptr) {
02445          ast_log(LOG_ERROR, "Out of memory\n");
02446          error = TRUE;
02447       } else
02448          argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02449    }
02450 
02451    if (argc <=1) {
02452       ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
02453       error = TRUE;
02454    }
02455    if (!error && strlen(argv[1]) > 1) {
02456       ast_log(LOG_ERROR, "MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
02457       error = TRUE;
02458    }
02459 
02460    if (!error && ast_app_parse_options(minivm_accmess_options, &flags, opts, argv[1])) {
02461       ast_log(LOG_ERROR, "Can't parse option %s\n", argv[1]);
02462       error = TRUE;
02463    }
02464 
02465    if (error) {
02466       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02467       return -1;
02468    }
02469 
02470    ast_copy_string(tmp, argv[0], sizeof(tmp));
02471    username = tmp;
02472    domain = strchr(tmp, '@');
02473    if (domain) {
02474       *domain = '\0';
02475       domain++;
02476    } 
02477    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
02478       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
02479       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02480       return -1;
02481    }
02482 
02483    if(!(vmu = find_account(domain, username, TRUE))) {
02484       /* We could not find user, let's exit */
02485       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
02486       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02487       return -1;
02488    }
02489 
02490    /* Answer channel if it's not already answered */
02491    if (chan->_state != AST_STATE_UP)
02492       ast_answer(chan);
02493    
02494    /* Here's where the action is */
02495    if (ast_test_flag(&flags, OPT_BUSY_GREETING)) {
02496       message = "busy";
02497       prompt = "vm-rec-busy";
02498    } else if (ast_test_flag(&flags, OPT_UNAVAIL_GREETING)) {
02499       message = "unavailable";
02500       prompt = "vm-rec-unv";
02501    } else if (ast_test_flag(&flags, OPT_TEMP_GREETING)) {
02502       message = "temp";
02503       prompt = "vm-rec-temp";
02504    } else if (ast_test_flag(&flags, OPT_NAME_GREETING)) {
02505       message = "greet";
02506       prompt = "vm-rec-name";
02507    }
02508    snprintf(filename,sizeof(filename), "%s%s/%s/%s", MVM_SPOOL_DIR, vmu->domain, vmu->username, message);
02509    /* Maybe we should check the result of play_record_review ? */
02510    cmd = play_record_review(chan, prompt, filename, global_maxgreet, default_vmformat, 0, vmu, &duration, NULL, FALSE);
02511 
02512    ast_debug(1, "Recorded new %s message in %s (duration %d)\n", message, filename, duration);
02513 
02514    if(ast_test_flag(vmu, MVM_ALLOCED))
02515       free_user(vmu);
02516 
02517    pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "SUCCESS");
02518 
02519    /* Ok, we're ready to rock and roll. Return to dialplan */
02520    return 0;
02521 }

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

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

03162 {
03163    struct minivm_account *vmu;
03164    char *username, *domain, *colname;
03165 
03166    if (!(username = ast_strdupa(data))) {
03167       ast_log(LOG_ERROR, "Memory Error!\n");
03168       return -1;
03169    }
03170 
03171    if ((colname = strchr(username, ':'))) {
03172       *colname = '\0';
03173       colname++;
03174    } else {
03175       colname = "path";
03176    }
03177    if ((domain = strchr(username, '@'))) {
03178       *domain = '\0';
03179       domain++;
03180    }
03181    if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
03182       ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
03183       return 0;
03184    }
03185 
03186    if (!(vmu = find_account(domain, username, TRUE)))
03187       return 0;
03188 
03189    if (!strcasecmp(colname, "hasaccount")) {
03190       ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
03191    } else  if (!strcasecmp(colname, "fullname")) { 
03192       ast_copy_string(buf, vmu->fullname, len);
03193    } else  if (!strcasecmp(colname, "email")) { 
03194       if (!ast_strlen_zero(vmu->email))
03195          ast_copy_string(buf, vmu->email, len);
03196       else
03197          snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
03198    } else  if (!strcasecmp(colname, "pager")) { 
03199       ast_copy_string(buf, vmu->pager, len);
03200    } else  if (!strcasecmp(colname, "etemplate")) { 
03201       if (!ast_strlen_zero(vmu->etemplate))
03202          ast_copy_string(buf, vmu->etemplate, len);
03203       else
03204          ast_copy_string(buf, "email-default", len);
03205    } else  if (!strcasecmp(colname, "language")) { 
03206       ast_copy_string(buf, vmu->language, len);
03207    } else  if (!strcasecmp(colname, "timezone")) { 
03208       ast_copy_string(buf, vmu->zonetag, len);
03209    } else  if (!strcasecmp(colname, "ptemplate")) { 
03210       if (!ast_strlen_zero(vmu->ptemplate))
03211          ast_copy_string(buf, vmu->ptemplate, len);
03212       else
03213          ast_copy_string(buf, "email-default", len);
03214    } else  if (!strcasecmp(colname, "accountcode")) {
03215       ast_copy_string(buf, vmu->accountcode, len);
03216    } else  if (!strcasecmp(colname, "pincode")) {
03217       ast_copy_string(buf, vmu->pincode, len);
03218    } else  if (!strcasecmp(colname, "path")) {
03219       check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
03220    } else { /* Look in channel variables */
03221       struct ast_variable *var;
03222       int found = 0;
03223 
03224       for (var = vmu->chanvars ; var ; var = var->next)
03225          if (!strcmp(var->name, colname)) {
03226             ast_copy_string(buf, var->value, len);
03227             found = 1;
03228             break;
03229          }
03230    }
03231 
03232    if(ast_test_flag(vmu, MVM_ALLOCED))
03233       free_user(vmu);
03234 
03235    return 0;
03236 }

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

03314 {
03315    char *username, *domain, *countername;
03316    struct minivm_account *vmu = NULL;
03317    char userpath[BUFSIZ];
03318    int res;
03319 
03320    *buf = '\0';
03321 
03322    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
03323       ast_log(LOG_WARNING, "Memory error!\n");
03324       return -1;
03325    }
03326    if ((countername = strchr(username, ':'))) {
03327       *countername = '\0';
03328       countername++;
03329    } 
03330 
03331    if ((domain = strchr(username, '@'))) {
03332       *domain = '\0';
03333       domain++;
03334    }
03335 
03336    /* If we have neither username nor domain now, let's give up */
03337    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03338       ast_log(LOG_ERROR, "No account given\n");
03339       return -1;
03340    }
03341 
03342    if (ast_strlen_zero(countername)) {
03343       ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
03344       return -1;
03345    }
03346 
03347    /* We only have a domain, no username */
03348    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03349       domain = username;
03350       username = NULL;
03351    }
03352 
03353    /* If we can't find account or if the account is temporary, return. */
03354    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
03355       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
03356       return 0;
03357    }
03358 
03359    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
03360 
03361    /* We have the path, now read the counter file */
03362    res = access_counter_file(userpath, countername, 0, 0);
03363    if (res >= 0)
03364       snprintf(buf, len, "%d", res);
03365    return 0;
03366 }

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

03370 {
03371    char *username, *domain, *countername, *operand;
03372    char userpath[BUFSIZ];
03373    struct minivm_account *vmu;
03374    int change = 0;
03375    int operation = 0;
03376 
03377    if(!value)
03378       return -1;
03379    change = atoi(value);
03380 
03381    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
03382       ast_log(LOG_WARNING, "Memory error!\n");
03383       return -1;
03384    }
03385 
03386    if ((countername = strchr(username, ':'))) {
03387       *countername = '\0';
03388       countername++;
03389    } 
03390    if ((operand = strchr(countername, ':'))) {
03391       *operand = '\0';
03392       operand++;
03393    } 
03394 
03395    if ((domain = strchr(username, '@'))) {
03396       *domain = '\0';
03397       domain++;
03398    }
03399 
03400    /* If we have neither username nor domain now, let's give up */
03401    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03402       ast_log(LOG_ERROR, "No account given\n");
03403       return -1;
03404    }
03405 
03406    /* We only have a domain, no username */
03407    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03408       domain = username;
03409       username = NULL;
03410    }
03411 
03412    if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
03413       ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
03414       return -1;
03415    }
03416 
03417    /* If we can't find account or if the account is temporary, return. */
03418    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
03419       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
03420       return 0;
03421    }
03422 
03423    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
03424    /* Now, find out our operator */
03425    if (*operand == 'i') /* Increment */
03426       operation = 2;
03427    else if (*operand == 'd') {
03428       change = change * -1;
03429       operation = 2;
03430    } else if (*operand == 's')
03431       operation = 1;
03432    else {
03433       ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
03434       return -1;
03435    }
03436 
03437    /* We have the path, now read the counter file */
03438    access_counter_file(userpath, countername, change, operation);
03439    return 0;
03440 }

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

Definition at line 2382 of file app_minivm.c.

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

Referenced by load_module().

02383 {
02384    int res = 0;
02385    char filename[BUFSIZ];
02386 
02387    if (!ast_strlen_zero(data)) {
02388       ast_copy_string(filename, (char *) data, sizeof(filename));
02389    } else {
02390       ast_channel_lock(chan);
02391       ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
02392       ast_channel_unlock(chan);
02393    }
02394 
02395    if (ast_strlen_zero(filename)) {
02396       ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
02397       return res;
02398    } 
02399 
02400    /* Go ahead and delete audio files from system, they're not needed any more */
02401    /* We should look for both audio and text files here */
02402    if (ast_fileexists(filename, NULL, NULL) > 0) {
02403       res = vm_delete(filename);
02404       if (res) {
02405          ast_debug(2, "Can't delete file: %s\n", filename);
02406          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02407       } else {
02408          ast_debug(2, "Deleted voicemail file :: %s \n", filename);
02409          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
02410       }
02411    } else {
02412       ast_debug(2, "Filename does not exist: %s\n", filename);
02413       pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02414    }
02415 
02416    return res;
02417 }

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

Definition at line 2195 of file app_minivm.c.

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

Referenced by load_module().

02196 {
02197    struct leave_vm_options leave_options = { 0, '\0'};
02198    int argc;
02199    char *argv[2];
02200    struct ast_flags flags = { 0 };
02201    char *opts[OPT_ARG_ARRAY_SIZE];
02202    int res = 0;
02203    int ausemacro = 0;
02204    int ousemacro = 0;
02205    int ouseexten = 0;
02206    char tmp[PATH_MAX];
02207    char dest[PATH_MAX];
02208    char prefile[PATH_MAX] = "";
02209    char tempfile[PATH_MAX] = "";
02210    char ext_context[256] = "";
02211    char *domain;
02212    char ecodes[16] = "#";
02213    char *tmpptr;
02214    struct minivm_account *vmu;
02215    char *username = argv[0];
02216 
02217    if (ast_strlen_zero(data))  {
02218       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02219       return -1;
02220    }
02221    tmpptr = ast_strdupa((char *)data);
02222    if (!tmpptr) {
02223       ast_log(LOG_ERROR, "Out of memory\n");
02224       return -1;
02225    }
02226    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02227 
02228    if (argc == 2) {
02229       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1]))
02230          return -1;
02231       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
02232    }
02233 
02234    ast_copy_string(tmp, argv[0], sizeof(tmp));
02235    username = tmp;
02236    domain = strchr(tmp, '@');
02237    if (domain) {
02238       *domain = '\0';
02239       domain++;
02240    } 
02241    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
02242       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument:  %s\n", argv[0]);
02243       return -1;
02244    }
02245    ast_debug(1, "Trying to find configuration for user %s in domain %s\n", username, domain);
02246 
02247    if (!(vmu = find_account(domain, username, TRUE))) {
02248       ast_log(LOG_ERROR, "Could not allocate memory. \n");
02249       return -1;
02250    }
02251 
02252    /* Answer channel if it's not already answered */
02253    if (chan->_state != AST_STATE_UP)
02254       ast_answer(chan);
02255 
02256    /* Setup pre-file if appropriate */
02257    if (strcmp(vmu->domain, "localhost"))
02258       snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
02259    else
02260       ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
02261 
02262    if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
02263       res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
02264       if (res)
02265          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
02266    } else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
02267       res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
02268       if (res)
02269          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
02270    }
02271    /* Check for temporary greeting - it overrides busy and unavail */
02272    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
02273    if (!(res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
02274       ast_debug(2, "Temporary message directory does not exist, using default (%s)\n", tempfile);
02275       ast_copy_string(prefile, tempfile, sizeof(prefile));
02276    }
02277    ast_debug(2, "Preparing to play message ...\n");
02278 
02279    /* Check current or macro-calling context for special extensions */
02280    if (ast_test_flag(vmu, MVM_OPERATOR)) {
02281       if (!ast_strlen_zero(vmu->exit)) {
02282          if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
02283             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02284             ouseexten = 1;
02285          }
02286       } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
02287          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02288          ouseexten = 1;
02289       }
02290       else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
02291          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02292          ousemacro = 1;
02293       }
02294    }
02295 
02296    if (!ast_strlen_zero(vmu->exit)) {
02297       if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
02298          strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
02299    } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
02300       strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
02301    else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
02302       strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
02303       ausemacro = 1;
02304    }
02305 
02306    res = 0; /* Reset */
02307    /* Play the beginning intro if desired */
02308    if (!ast_strlen_zero(prefile)) {
02309       if (ast_streamfile(chan, prefile, chan->language) > -1) 
02310          res = ast_waitstream(chan, ecodes);
02311    } else {
02312       ast_debug(2, "%s doesn't exist, doing what we can\n", prefile);
02313       res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
02314    }
02315    if (res < 0) {
02316       ast_debug(2, "Hang up during prefile playback\n");
02317       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
02318       if(ast_test_flag(vmu, MVM_ALLOCED))
02319          free_user(vmu);
02320       return -1;
02321    }
02322    if (res == '#') {
02323       /* On a '#' we skip the instructions */
02324       ast_set_flag(&leave_options, OPT_SILENT);
02325       res = 0;
02326    }
02327    if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
02328       res = ast_streamfile(chan, SOUND_INTRO, chan->language);
02329       if (!res)
02330          res = ast_waitstream(chan, ecodes);
02331       if (res == '#') {
02332          ast_set_flag(&leave_options, OPT_SILENT);
02333          res = 0;
02334       }
02335    }
02336    if (res > 0)
02337       ast_stopstream(chan);
02338    /* Check for a '*' here in case the caller wants to escape from voicemail to something
02339       other than the operator -- an automated attendant or mailbox login for example */
02340    if (res == '*') {
02341       chan->exten[0] = 'a';
02342       chan->exten[1] = '\0';
02343       if (!ast_strlen_zero(vmu->exit)) {
02344          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02345       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
02346          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02347       }
02348       chan->priority = 0;
02349       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
02350       res = 0;
02351    } else if (res == '0') { /* Check for a '0' here */
02352       if(ouseexten || ousemacro) {
02353          chan->exten[0] = 'o';
02354          chan->exten[1] = '\0';
02355          if (!ast_strlen_zero(vmu->exit)) {
02356             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02357          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
02358             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02359          }
02360          ast_play_and_wait(chan, "transfer");
02361          chan->priority = 0;
02362          pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
02363       }
02364       res =  0;
02365    } else if (res < 0) {
02366       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
02367       res = -1;
02368    } else
02369       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "SUCCESS");
02370 
02371    if(ast_test_flag(vmu, MVM_ALLOCED))
02372       free_user(vmu);
02373 
02374 
02375    /* Ok, we're ready to rock and roll. Return to dialplan */
02376    return res;
02377 
02378 }

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

Definition at line 2016 of file app_minivm.c.

References ARRAY_LEN, ast_app_separate_args, ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), LOG_ERROR, mailbox, and queue_mwi_event().

Referenced by load_module().

02017 {
02018    int argc;
02019    char *argv[4];
02020    int res = 0;
02021    char *tmpptr;
02022    char tmp[PATH_MAX];
02023    char *mailbox;
02024    char *domain;
02025    if (ast_strlen_zero(data))  {
02026       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02027       return -1;
02028    }
02029    tmpptr = ast_strdupa((char *)data);
02030    if (!tmpptr) {
02031       ast_log(LOG_ERROR, "Out of memory\n");
02032       return -1;
02033    }
02034    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02035    if (argc < 4) {
02036       ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
02037       return -1;
02038    }
02039    ast_copy_string(tmp, argv[0], sizeof(tmp));
02040    mailbox = tmp;
02041    domain = strchr(tmp, '@');
02042    if (domain) {
02043       *domain = '\0';
02044       domain++;
02045    }
02046    if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
02047       ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
02048       return -1;
02049    }
02050    queue_mwi_event(mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
02051 
02052    return res;
02053 }

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

Definition at line 2058 of file app_minivm.c.

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

Referenced by load_module().

02059 {
02060    int argc;
02061    char *argv[2];
02062    int res = 0;
02063    char tmp[PATH_MAX];
02064    char *domain;
02065    char *tmpptr;
02066    struct minivm_account *vmu;
02067    char *username = argv[0];
02068    const char *template = "";
02069    const char *filename;
02070    const char *format;
02071    const char *duration_string;
02072 
02073    if (ast_strlen_zero(data))  {
02074       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02075       return -1;
02076    }
02077    tmpptr = ast_strdupa((char *)data);
02078    if (!tmpptr) {
02079       ast_log(LOG_ERROR, "Out of memory\n");
02080       return -1;
02081    }
02082    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02083 
02084    if (argc == 2 && !ast_strlen_zero(argv[1]))
02085       template = argv[1];
02086 
02087    ast_copy_string(tmp, argv[0], sizeof(tmp));
02088    username = tmp;
02089    domain = strchr(tmp, '@');
02090    if (domain) {
02091       *domain = '\0';
02092       domain++;
02093    } 
02094    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
02095       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
02096       return -1;
02097    }
02098 
02099    if(!(vmu = find_account(domain, username, TRUE))) {
02100       /* We could not find user, let's exit */
02101       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
02102       pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
02103       return -1;
02104    }
02105 
02106    ast_channel_lock(chan);
02107    if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
02108       filename = ast_strdupa(filename);
02109    }
02110    ast_channel_unlock(chan);
02111    /* Notify of new message to e-mail and pager */
02112    if (!ast_strlen_zero(filename)) {
02113       ast_channel_lock(chan); 
02114       if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
02115          format = ast_strdupa(format);
02116       }
02117       if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
02118          duration_string = ast_strdupa(duration_string);
02119       }
02120       ast_channel_unlock(chan);
02121       res = notify_new_message(chan, template, vmu, filename, atoi(duration_string), format, chan->cid.cid_num, chan->cid.cid_name);
02122    }
02123 
02124    pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
02125 
02126 
02127    if(ast_test_flag(vmu, MVM_ALLOCED))
02128       free_user(vmu);
02129 
02130    /* Ok, we're ready to rock and roll. Return to dialplan */
02131 
02132    return res;
02133 
02134 }

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

Definition at line 2138 of file app_minivm.c.

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

Referenced by load_module().

02139 {
02140    int res = 0;
02141    char *tmp;
02142    struct leave_vm_options leave_options;
02143    int argc;
02144    char *argv[2];
02145    struct ast_flags flags = { 0 };
02146    char *opts[OPT_ARG_ARRAY_SIZE];
02147 
02148    memset(&leave_options, 0, sizeof(leave_options));
02149 
02150    /* Answer channel if it's not already answered */
02151    if (chan->_state != AST_STATE_UP)
02152       ast_answer(chan);
02153 
02154    if (ast_strlen_zero(data))  {
02155       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02156       return -1;
02157    }
02158    tmp = ast_strdupa((char *)data);
02159    if (!tmp) {
02160       ast_log(LOG_ERROR, "Out of memory\n");
02161       return -1;
02162    }
02163    argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
02164    if (argc == 2) {
02165       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
02166          return -1;
02167       }
02168       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
02169       if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
02170          int gain;
02171 
02172          if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
02173             ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
02174             return -1;
02175          } else 
02176             leave_options.record_gain = (signed char) gain;
02177       }
02178    } 
02179 
02180    /* Now run the appliation and good luck to you! */
02181    res = leave_voicemail(chan, argv[0], &leave_options);
02182 
02183    if (res == ERROR_LOCK_PATH) {
02184       ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
02185       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
02186       res = 0;
02187    }
02188    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
02189 
02190    return res;
02191 }

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

Definition at line 1021 of file app_minivm.c.

References ast_calloc, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

01022 {
01023    struct minivm_account *new;
01024 
01025    new = ast_calloc(1, sizeof(*new));
01026    if (!new)
01027       return NULL;
01028    populate_defaults(new);
01029 
01030    return new;
01031 }

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

Definition at line 1742 of file app_minivm.c.

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

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

01743 {
01744    char *stringp;
01745    struct minivm_template *etemplate;
01746    char *messageformat;
01747    int res = 0;
01748    char oldlocale[100];
01749    const char *counter;
01750 
01751    if (!ast_strlen_zero(vmu->attachfmt)) {
01752       if (strstr(format, vmu->attachfmt)) {
01753          format = vmu->attachfmt;
01754       } else {
01755          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);
01756       }
01757    }
01758 
01759    etemplate = message_template_find(vmu->etemplate);
01760    if (!etemplate)
01761       etemplate = message_template_find(templatename);
01762    if (!etemplate)
01763       etemplate = message_template_find("email-default");
01764 
01765    /* Attach only the first format */
01766    stringp = messageformat = ast_strdupa(format);
01767    strsep(&stringp, "|");
01768 
01769    if (!ast_strlen_zero(etemplate->locale)) {
01770       char *new_locale;
01771       ast_copy_string(oldlocale, setlocale(LC_TIME, NULL), sizeof(oldlocale));
01772       ast_debug(2, "Changing locale from %s to %s\n", oldlocale, etemplate->locale);
01773       new_locale = setlocale(LC_TIME, etemplate->locale);
01774       if (new_locale == NULL) {
01775          ast_log(LOG_WARNING, "-_-_- Changing to new locale did not work. Locale: %s\n", etemplate->locale);
01776       }
01777    }
01778 
01779 
01780 
01781    /* Read counter if available */
01782    ast_channel_lock(chan);
01783    if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
01784       counter = ast_strdupa(counter);
01785    }
01786    ast_channel_unlock(chan);
01787 
01788    if (ast_strlen_zero(counter)) {
01789       ast_debug(2, "MVM_COUNTER not found\n");
01790    } else {
01791       ast_debug(2, "MVM_COUNTER found - will use it with value %s\n", counter);
01792    }
01793 
01794    res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_EMAIL, counter);
01795 
01796    if (res == 0 && !ast_strlen_zero(vmu->pager))  {
01797       /* Find template for paging */
01798       etemplate = message_template_find(vmu->ptemplate);
01799       if (!etemplate)
01800          etemplate = message_template_find("pager-default");
01801       if (etemplate->locale) {
01802          ast_copy_string(oldlocale, setlocale(LC_TIME, ""), sizeof(oldlocale));
01803          setlocale(LC_TIME, etemplate->locale);
01804       }
01805 
01806       res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_PAGE, counter);
01807    }
01808 
01809    manager_event(EVENT_FLAG_CALL, "MiniVoiceMail", "Action: SentNotification\rn\nMailbox: %s@%s\r\nCounter: %s\r\n", vmu->username, vmu->domain, counter);
01810 
01811    run_externnotify(chan, vmu);     /* Run external notification */
01812 
01813    if (etemplate->locale) {
01814       setlocale(LC_TIME, oldlocale); /* Rest to old locale */
01815    }
01816    return res;
01817 }

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]

Definition at line 1592 of file app_minivm.c.

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

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

01595 {
01596    int cmd = 0;
01597    int max_attempts = 3;
01598    int attempts = 0;
01599    int recorded = 0;
01600    int message_exists = 0;
01601    signed char zero_gain = 0;
01602    char *acceptdtmf = "#";
01603    char *canceldtmf = "";
01604 
01605    /* Note that urgent and private are for flagging messages as such in the future */
01606 
01607    /* barf if no pointer passed to store duration in */
01608    if (duration == NULL) {
01609       ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
01610       return -1;
01611    }
01612 
01613    cmd = '3';   /* Want to start by recording */
01614 
01615    while ((cmd >= 0) && (cmd != 't')) {
01616       switch (cmd) {
01617       case '1':
01618          ast_verb(3, "Saving message as is\n");
01619          ast_stream_and_wait(chan, "vm-msgsaved", "");
01620          cmd = 't';
01621          break;
01622       case '2':
01623          /* Review */
01624          ast_verb(3, "Reviewing the message\n");
01625          ast_streamfile(chan, recordfile, chan->language);
01626          cmd = ast_waitstream(chan, AST_DIGIT_ANY);
01627          break;
01628       case '3':
01629          message_exists = 0;
01630          /* Record */
01631          if (recorded == 1) 
01632             ast_verb(3, "Re-recording the message\n");
01633          else
01634             ast_verb(3, "Recording the message\n");
01635          if (recorded && outsidecaller) 
01636             cmd = ast_play_and_wait(chan, "beep");
01637          recorded = 1;
01638          /* 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 */
01639          if (record_gain)
01640             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
01641          if (ast_test_flag(vmu, MVM_OPERATOR))
01642             canceldtmf = "0";
01643          cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
01644          if (record_gain)
01645             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
01646          if (cmd == -1) /* User has hung up, no options to give */
01647             return cmd;
01648          if (cmd == '0')
01649             break;
01650          else if (cmd == '*')
01651             break;
01652          else {
01653             /* If all is well, a message exists */
01654             message_exists = 1;
01655             cmd = 0;
01656          }
01657          break;
01658       case '4':
01659       case '5':
01660       case '6':
01661       case '7':
01662       case '8':
01663       case '9':
01664       case '*':
01665       case '#':
01666          cmd = ast_play_and_wait(chan, "vm-sorry");
01667          break;
01668       case '0':
01669          if(!ast_test_flag(vmu, MVM_OPERATOR)) {
01670             cmd = ast_play_and_wait(chan, "vm-sorry");
01671             break;
01672          }
01673          if (message_exists || recorded) {
01674             cmd = ast_play_and_wait(chan, "vm-saveoper");
01675             if (!cmd)
01676                cmd = ast_waitfordigit(chan, 3000);
01677             if (cmd == '1') {
01678                ast_play_and_wait(chan, "vm-msgsaved");
01679                cmd = '0';
01680             } else {
01681                ast_play_and_wait(chan, "vm-deleted");
01682                vm_delete(recordfile);
01683                cmd = '0';
01684             }
01685          }
01686          return cmd;
01687       default:
01688          /* If the caller is an ouside caller, and the review option is enabled,
01689             allow them to review the message, but let the owner of the box review
01690             their OGM's */
01691          if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
01692             return cmd;
01693          if (message_exists) {
01694             cmd = ast_play_and_wait(chan, "vm-review");
01695          } else {
01696             cmd = ast_play_and_wait(chan, "vm-torerecord");
01697             if (!cmd)
01698                cmd = ast_waitfordigit(chan, 600);
01699          }
01700 
01701          if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
01702             cmd = ast_play_and_wait(chan, "vm-reachoper");
01703             if (!cmd)
01704                cmd = ast_waitfordigit(chan, 600);
01705          }
01706          if (!cmd)
01707             cmd = ast_waitfordigit(chan, 6000);
01708          if (!cmd) {
01709             attempts++;
01710          }
01711          if (attempts > max_attempts) {
01712             cmd = 't';
01713          }
01714       }
01715    }
01716    if (outsidecaller)
01717       ast_play_and_wait(chan, "vm-goodbye");
01718    if (cmd == 't')
01719       cmd = 0;
01720    return cmd;
01721 }

static void populate_defaults ( struct minivm_account vmu  )  [static]

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

Definition at line 983 of file app_minivm.c.

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

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

00984 {
00985    char callerid[256];
00986    struct ast_variable *var;
00987    
00988    if (!channel) {
00989       ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
00990       return;
00991    }
00992 
00993    for (var = vmu->chanvars ; var ; var = var->next) {
00994       pbx_builtin_setvar_helper(channel, var->name, var->value);
00995    }
00996 
00997    /* Prepare variables for substition in email body and subject */
00998    pbx_builtin_setvar_helper(channel, "MVM_NAME", vmu->fullname);
00999    pbx_builtin_setvar_helper(channel, "MVM_DUR", dur);
01000    pbx_builtin_setvar_helper(channel, "MVM_DOMAIN", vmu->domain);
01001    pbx_builtin_setvar_helper(channel, "MVM_USERNAME", vmu->username);
01002    pbx_builtin_setvar_helper(channel, "MVM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
01003    pbx_builtin_setvar_helper(channel, "MVM_CIDNAME", (cidname ? cidname : "an unknown caller"));
01004    pbx_builtin_setvar_helper(channel, "MVM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
01005    pbx_builtin_setvar_helper(channel, "MVM_DATE", date);
01006    if (!ast_strlen_zero(counter))
01007       pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
01008 }

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

static int reload ( void   )  [static]

Reload mini voicemail module.

Definition at line 3493 of file app_minivm.c.

References load_config().

03494 {
03495    return(load_config(1));
03496 }

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

Run external notification for voicemail message.

Definition at line 1724 of file app_minivm.c.

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

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

01725 {
01726    char arguments[BUFSIZ];
01727 
01728    if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify))
01729       return;
01730 
01731    snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&", 
01732       ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify, 
01733       vmu->username, vmu->domain,
01734       chan->cid.cid_name, chan->cid.cid_num);
01735 
01736    ast_debug(1, "Executing: %s\n", arguments);
01737    ast_safe_system(arguments);
01738 }

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

Definition at line 1216 of file app_minivm.c.

References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_random(), ast_safe_system(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_tvnow(), base_encode(), check_mime(), minivm_account::domain, minivm_account::email, minivm_account::fullname, global_mailcmd, LOG_WARNING, MAXHOSTNAMELEN, MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_zone::name, option_debug, minivm_account::pager, prep_email_sub_vars(), minivm_account::serveremail, minivm_zone::timezone, minivm_account::username, minivm_account::volgain, and minivm_account::zonetag.

Referenced by forward_message(), and notify_new_message().

01217 {
01218    FILE *p = NULL;
01219    int pfd;
01220    char email[256] = "";
01221    char who[256] = "";
01222    char date[256];
01223    char bound[256];
01224    char fname[PATH_MAX];
01225    char dur[PATH_MAX];
01226    char tmp[80] = "/tmp/astmail-XXXXXX";
01227    char tmp2[PATH_MAX];
01228    struct timeval now;
01229    struct ast_tm tm;
01230    struct minivm_zone *the_zone = NULL;
01231    struct ast_channel *ast;
01232    char *finalfilename;
01233    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
01234    char *fromaddress;
01235    char *fromemail;
01236 
01237    if (!str1 || !str2) {
01238       ast_free(str1);
01239       ast_free(str2);
01240       return -1;
01241    }
01242 
01243    if (type == MVM_MESSAGE_EMAIL) {
01244       if (vmu && !ast_strlen_zero(vmu->email)) {
01245          ast_copy_string(email, vmu->email, sizeof(email)); 
01246       } else if (!ast_strlen_zero(vmu->username) && !ast_strlen_zero(vmu->domain))
01247          snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
01248    } else if (type == MVM_MESSAGE_PAGE) {
01249       ast_copy_string(email, vmu->pager, sizeof(email));
01250    }
01251 
01252    if (ast_strlen_zero(email)) {
01253       ast_log(LOG_WARNING, "No address to send message to.\n");
01254       return -1;  
01255    }
01256 
01257    ast_debug(3, "Sending mail to %s@%s - Using template %s\n", vmu->username, vmu->domain, template->name);
01258 
01259    if (!strcmp(format, "wav49"))
01260       format = "WAV";
01261 
01262 
01263    /* If we have a gain option, process it now with sox */
01264    if (type == MVM_MESSAGE_EMAIL && (vmu->volgain < -.001 || vmu->volgain > .001) ) {
01265       char newtmp[PATH_MAX];
01266       char tmpcmd[PATH_MAX];
01267       int tmpfd;
01268 
01269       ast_copy_string(newtmp, "/tmp/XXXXXX", sizeof(newtmp));
01270       ast_debug(3, "newtmp: %s\n", newtmp);
01271       tmpfd = mkstemp(newtmp);
01272       snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, filename, format, newtmp, format);
01273       ast_safe_system(tmpcmd);
01274       finalfilename = newtmp;
01275       ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->volgain, vmu->username);
01276    } else {
01277       finalfilename = ast_strdupa(filename);
01278    }
01279 
01280    /* Create file name */
01281    snprintf(fname, sizeof(fname), "%s.%s", finalfilename, format);
01282 
01283    if (template->attachment)
01284       ast_debug(1, "Attaching file '%s', format '%s', uservm is '%d'\n", finalfilename, format, attach_user_voicemail);
01285 
01286    /* Make a temporary file instead of piping directly to sendmail, in case the mail
01287       command hangs */
01288    pfd = mkstemp(tmp);
01289    if (pfd > -1) {
01290       p = fdopen(pfd, "w");
01291       if (!p) {
01292          close(pfd);
01293          pfd = -1;
01294       }
01295       ast_debug(1, "Opening temp file for e-mail: %s\n", tmp);
01296    }
01297    if (!p) {
01298       ast_log(LOG_WARNING, "Unable to open temporary file '%s'\n", tmp);
01299       return -1;
01300    }
01301    /* Allocate channel used for chanvar substitution */
01302    ast = ast_dummy_channel_alloc();
01303 
01304    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
01305 
01306    /* Does this user have a timezone specified? */
01307    if (!ast_strlen_zero(vmu->zonetag)) {
01308       /* Find the zone in the list */
01309       struct minivm_zone *z;
01310       AST_LIST_LOCK(&minivm_zones);
01311       AST_LIST_TRAVERSE(&minivm_zones, z, list) {
01312          if (strcmp(z->name, vmu->zonetag)) 
01313             continue;
01314          the_zone = z;
01315       }
01316       AST_LIST_UNLOCK(&minivm_zones);
01317    }
01318 
01319    now = ast_tvnow();
01320    ast_localtime(&now, &tm, the_zone ? the_zone->timezone : NULL);
01321    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
01322 
01323    /* Start printing the email to the temporary file */
01324    fprintf(p, "Date: %s\n", date);
01325 
01326    /* Set date format for voicemail mail */
01327    ast_strftime(date, sizeof(date), template->dateformat, &tm);
01328 
01329 
01330    /* Populate channel with channel variables for substitution */
01331    prep_email_sub_vars(ast, vmu, cidnum, cidname, dur, date, counter);
01332 
01333    /* Find email address to use */
01334    /* If there's a server e-mail adress in the account, user that, othterwise template */
01335    fromemail = ast_strlen_zero(vmu->serveremail) ?  template->serveremail : vmu->serveremail;
01336 
01337    /* Find name to user for server e-mail */
01338    fromaddress = ast_strlen_zero(template->fromaddress) ? "" : template->fromaddress;
01339 
01340    /* If needed, add hostname as domain */
01341    if (ast_strlen_zero(fromemail))
01342       fromemail = "asterisk";
01343 
01344    if (strchr(fromemail, '@'))
01345       ast_copy_string(who, fromemail, sizeof(who));
01346    else  {
01347       char host[MAXHOSTNAMELEN];
01348       gethostname(host, sizeof(host)-1);
01349       snprintf(who, sizeof(who), "%s@%s", fromemail, host);
01350    }
01351 
01352    if (ast_strlen_zero(fromaddress)) {
01353       fprintf(p, "From: Asterisk PBX <%s>\n", who);
01354    } else {
01355       ast_debug(4, "Fromaddress template: %s\n", fromaddress);
01356       ast_str_substitute_variables(&str1, 0, ast, fromaddress);
01357       if (check_mime(ast_str_buffer(str1))) {
01358          int first_line = 1;
01359          char *ptr;
01360          ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
01361          while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
01362             *ptr = '\0';
01363             fprintf(p, "%s %s\n", first_line ? "From:" : "", ast_str_buffer(str2));
01364             first_line = 0;
01365             /* Substring is smaller, so this will never grow */
01366             ast_str_set(&str2, 0, "%s", ptr + 1);
01367          }
01368          fprintf(p, "%s %s <%s>\n", first_line ? "From:" : "", ast_str_buffer(str2), who);
01369       } else {
01370          fprintf(p, "From: %s <%s>\n", ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
01371       }
01372    } 
01373 
01374    fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
01375 
01376    if (ast_strlen_zero(vmu->email)) {
01377       snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
01378    } else {
01379       ast_copy_string(email, vmu->email, sizeof(email));
01380    }
01381 
01382    if (check_mime(vmu->fullname)) {
01383       int first_line = 1;
01384       char *ptr;
01385       ast_str_encode_mime(&str2, 0, template->charset, vmu->fullname, strlen("To: "), strlen(email) + 3);
01386       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
01387          *ptr = '\0';
01388          fprintf(p, "%s %s\n", first_line ? "To:" : "", ast_str_buffer(str2));
01389          first_line = 0;
01390          /* Substring is smaller, so this will never grow */
01391          ast_str_set(&str2, 0, "%s", ptr + 1);
01392       }
01393       fprintf(p, "%s %s <%s>\n", first_line ? "To:" : "", ast_str_buffer(str2), email);
01394    } else {
01395       fprintf(p, "To: %s <%s>\n", ast_str_quote(&str2, 0, vmu->fullname), email);
01396    }
01397 
01398    if (!ast_strlen_zero(template->subject)) {
01399       ast_str_substitute_variables(&str1, 0, ast, template->subject);
01400       if (check_mime(ast_str_buffer(str1))) {
01401          int first_line = 1;
01402          char *ptr;
01403          ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("Subject: "), 0);
01404          while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
01405             *ptr = '\0';
01406             fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
01407             first_line = 0;
01408             /* Substring is smaller, so this will never grow */
01409             ast_str_set(&str2, 0, "%s", ptr + 1);
01410          }
01411          fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
01412       } else {
01413          fprintf(p, "Subject: %s\n", ast_str_buffer(str1));
01414       }
01415    } else {
01416       fprintf(p, "Subject: New message in mailbox %s@%s\n", vmu->username, vmu->domain);
01417       ast_debug(1, "Using default subject for this email \n");
01418    }
01419 
01420    if (option_debug > 2)
01421       fprintf(p, "X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->username, vmu->domain);
01422    fprintf(p, "MIME-Version: 1.0\n");
01423 
01424    /* Something unique. */
01425    snprintf(bound, sizeof(bound), "voicemail_%s%d%d", vmu->username, (int)getpid(), (unsigned int)ast_random());
01426 
01427    fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
01428 
01429    fprintf(p, "--%s\n", bound);
01430    fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", template->charset);
01431    if (!ast_strlen_zero(template->body)) {
01432       ast_str_substitute_variables(&str1, 0, ast, template->body);
01433       ast_debug(3, "Message now: %s\n-----\n", ast_str_buffer(str1));
01434       fprintf(p, "%s\n", ast_str_buffer(str1));
01435    } else {
01436       fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
01437          "in mailbox %s from %s, on %s so you might\n"
01438          "want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname, 
01439          dur,  vmu->username, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
01440       ast_debug(3, "Using default message body (no template)\n-----\n");
01441    }
01442    /* Eww. We want formats to tell us their own MIME type */
01443    if (template->attachment) {
01444       char *ctype = "audio/x-";
01445       ast_debug(3, "Attaching file to message: %s\n", fname);
01446       if (!strcasecmp(format, "ogg"))
01447          ctype = "application/";
01448 
01449       fprintf(p, "--%s\n", bound);
01450       fprintf(p, "Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
01451       fprintf(p, "Content-Transfer-Encoding: base64\n");
01452       fprintf(p, "Content-Description: Voicemail sound attachment.\n");
01453       fprintf(p, "Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter : "", format);
01454 
01455       base_encode(fname, p);
01456       fprintf(p, "\n\n--%s--\n.\n", bound);
01457    }
01458    fclose(p);
01459    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", global_mailcmd, tmp, tmp);
01460    ast_safe_system(tmp2);
01461    ast_debug(1, "Sent message to %s with command '%s' - %s\n", vmu->email, global_mailcmd, template->attachment ? "(media attachment)" : "");
01462    ast_debug(3, "Actual command used: %s\n", tmp2);
01463    if (ast)
01464       ast = ast_channel_release(ast);
01465    ast_free(str1);
01466    ast_free(str2);
01467    return 0;
01468 }

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

Add time zone to memory list.

Definition at line 2636 of file app_minivm.c.

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

Referenced by load_config().

02637 {
02638    struct minivm_zone *newzone;
02639    char *msg_format, *timezone_str;
02640 
02641    newzone = ast_calloc(1, sizeof(*newzone));
02642    if (newzone == NULL)
02643       return 0;
02644 
02645    msg_format = ast_strdupa(config);
02646    if (msg_format == NULL) {
02647       ast_log(LOG_WARNING, "Out of memory.\n");
02648       ast_free(newzone);
02649       return 0;
02650    }
02651 
02652    timezone_str = strsep(&msg_format, "|");
02653    if (!msg_format) {
02654       ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
02655       ast_free(newzone);
02656       return 0;
02657    }
02658          
02659    ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
02660    ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
02661    ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
02662 
02663    AST_LIST_LOCK(&minivm_zones);
02664    AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
02665    AST_LIST_UNLOCK(&minivm_zones);
02666 
02667    global_stats.timezones++;
02668 
02669    return 0;
02670 }

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

Definition at line 2624 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

02625 {
02626    struct minivm_zone *this;
02627 
02628    AST_LIST_LOCK(&minivm_zones);
02629    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02630       free_zone(this);
02631       
02632    AST_LIST_UNLOCK(&minivm_zones);
02633 }

static int unload_module ( void   )  [static]

static int vm_delete ( char *  file  )  [static]

Definition at line 1578 of file app_minivm.c.

References ast_debug, and ast_filedelete().

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

01579 {
01580    int res;
01581 
01582    ast_debug(1, "Deleting voicemail file %s\n", file);
01583 
01584    res = unlink(file);  /* Remove the meta data file */
01585    res |=  ast_filedelete(file, NULL); /* remove the media file */
01586    return res;
01587 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

03244 {
03245    switch (ast_lock_path(path)) {
03246    case AST_LOCK_TIMEOUT:
03247       return -1;
03248    default:
03249       return 0;
03250    }
03251 }

static void vmaccounts_destroy_list ( void   )  [static]

Definition at line 1036 of file app_minivm.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.

Referenced by load_config(), and unload_module().

01037 {
01038    struct minivm_account *this;
01039    AST_LIST_LOCK(&minivm_accounts);
01040    while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list))) 
01041       ast_free(this);
01042    AST_LIST_UNLOCK(&minivm_accounts);
01043 }


Variable Documentation

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

Definition at line 3546 of file app_minivm.c.

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 546 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 545 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 543 of file app_minivm.c.

char* app_minivm_mwi = "MinivmMWI" [static]

Definition at line 547 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 544 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 542 of file app_minivm.c.

Definition at line 3546 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 3444 of file app_minivm.c.

Referenced by load_module(), and unload_module().

char default_vmformat[80] [static]

char global_externnotify[160] [static]

External notification application

Definition at line 681 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 682 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 680 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 678 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 677 of file app_minivm.c.

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

Definition at line 686 of file app_minivm.c.

Referenced by load_config().

int global_silencethreshold = 128 [static]

struct minivm_stats global_stats [static]

Statistics for voicemail.

Definition at line 668 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 676 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 675 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 688 of file app_minivm.c.

Referenced by populate_defaults().

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]

Definition at line 577 of file app_minivm.c.

Referenced by minivm_accmess_exec().

Initial value:

 {
   .name = "MINIVMACCOUNT",
   .read = minivm_account_func_read,
}

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

Referenced by minivm_greet_exec(), and minivm_record_exec().

Initial value:

 {
   .name = "MINIVMCOUNTER",
   .read = minivm_counter_func_read,
   .write = minivm_counter_func_write,
}

Definition at line 3453 of file app_minivm.c.

Referenced by load_module(), and unload_module().

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

Lock to protect voicemail system

Definition at line 670 of file app_minivm.c.

Referenced by load_config().

FILE* minivmlogfile [static]

The minivm log file

Definition at line 673 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

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

Lock to protect voicemail system log file

Definition at line 671 of file app_minivm.c.

Referenced by leave_voicemail().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 539 of file app_minivm.c.


Generated on Wed Oct 28 13:31:29 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6