Wed Jan 27 20:02:18 2016

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"

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  minivm_account
struct  minivm_stats
 Structure for gathering statistics. More...
struct  minivm_template
struct  minivm_zone
 Voicemail 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 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.
 AST_APP_OPTIONS (minivm_accmess_options,{AST_APP_OPTION('b', OPT_BUSY_GREETING), AST_APP_OPTION('u', OPT_UNAVAIL_GREETING), AST_APP_OPTION('t', OPT_TEMP_GREETING), AST_APP_OPTION('n', OPT_NAME_GREETING),})
 AST_APP_OPTIONS (minivm_app_options,{AST_APP_OPTION('s', OPT_SILENT), AST_APP_OPTION('b', OPT_BUSY_GREETING), AST_APP_OPTION('u', OPT_UNAVAIL_GREETING), AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),})
static AST_LIST_HEAD_STATIC (minivm_zones, minivm_zone)
 The list of e-mail time zones.
static AST_LIST_HEAD_STATIC (message_templates, minivm_template)
 The list of e-mail templates.
static AST_LIST_HEAD_STATIC (minivm_accounts, minivm_account)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Mini VoiceMail (A minimal Voicemail e-mail System)",.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (minivmloglock)
 AST_MUTEX_DEFINE_STATIC (minivmlock)
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, int *sound_duration, const char *unlockdir, signed char record_gain)
static void populate_defaults (struct minivm_account *vmu)
static void prep_email_sub_vars (struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
static void queue_mwi_event (const char *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 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_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_custom_function minivm_account_function
static struct ast_custom_function minivm_counter_function
static FILE * minivmlogfile
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 534 of file app_minivm.c.

Referenced by actual_load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 524 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 523 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 697 of file app_minivm.c.

Referenced by message_template_create().

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

Definition at line 696 of file app_minivm.c.

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 525 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100
#define FALSE   0

Definition at line 506 of file app_minivm.c.

Referenced by __sip_ack(), __sip_semi_ack(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), AST_TEST_DEFINE(), ast_tzset(), build_peer(), cb_extensionstate(), cc_handle_publish_error(), check_auth(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), do_monitor(), expire_register(), find_sdp(), function_sippeer(), handle_invite_replaces(), handle_request_invite(), handle_request_invite_st(), 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_crypto(), process_sdp(), process_sdp_a_audio(), process_sdp_a_image(), process_sdp_a_sendonly(), process_sdp_a_text(), process_sdp_a_video(), process_sdp_c(), process_sdp_o(), proxy_from_config(), proxy_update(), rcvfax_exec(), register_verify(), reload_config(), reqprep(), send_provisional_keepalive_full(), set_destination(), sip_addheader(), sip_answer(), sip_cc_monitor_request_cc(), sip_destroy_peer(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_is_xml_parsable(), sip_monitor_instance_destructor(), sip_parse_register_line(), sip_poke_noanswer(), sip_prune_realtime(), sip_read(), 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(), stop_session_timer(), time1(), time2(), time2sub(), transmit_audio(), transmit_fake_auth_response(), transmit_invite(), transmit_provisional_response(), transmit_publish(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_t38(), 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 527 of file app_minivm.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 528 of file app_minivm.c.

Referenced by actual_load_config(), and play_message_callerid().

#define MVM_ALLOCED   (1 << 13)
#define MVM_ENVELOPE   (1 << 4)

Definition at line 514 of file app_minivm.c.

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

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

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 512 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)
#define MVM_SVMAIL   (1 << 3)

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

Referenced by actual_load_config(), and load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 522 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 503 of file app_minivm.c.

Referenced by __sip_ack(), __sip_autodestruct(), __sip_semi_ack(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), ast_tzset(), build_peer(), check_auth(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), find_account(), find_sdp(), find_user_realtime(), function_sippeer(), get_sip_pvt_byid_locked(), gmtload(), handle_request_invite(), handle_request_invite_st(), handle_request_notify(), handle_request_refer(), handle_response(), handle_response_invite(), handle_response_peerpoke(), interpret_t38_parameters(), leave_voicemail(), load_config(), local_attended_transfer(), manager_mutestream(), 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_crypto(), process_sdp(), process_sdp_a_audio(), process_sdp_a_image(), process_sdp_a_sendonly(), process_sdp_a_text(), process_sdp_a_video(), process_sdp_c(), process_sdp_o(), proxy_update(), rcvfax_exec(), realtime_peer(), reg_source_db(), register_verify(), reload_config(), reqprep(), respprep(), restart_session_timer(), set_destination(), sip_addheader(), sip_alloc(), sip_answer(), sip_cc_agent_respond(), sip_destroy(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_indicate(), sip_is_xml_parsable(), sip_park_thread(), sip_prune_realtime(), sip_reload(), sip_request_call(), sip_scheddestroy(), 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(), spandsp_fax_start(), st_get_se(), start_session_timer(), stop_session_timer(), temp_peer(), time1(), time2(), time2sub(), transmit_audio(), transmit_cc_notify(), transmit_invite(), transmit_publish(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_t38(), tzload(), tzparse(), udptl_rx_packet(), and update_connectedline().

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 533 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

Definition at line 531 of file app_minivm.c.

Referenced by create_dirpath(), and leave_voicemail().


Enumeration Type Documentation

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 564 of file app_minivm.c.

00564                         {
00565    OPT_ARG_RECORDGAIN = 0,
00566    OPT_ARG_ARRAY_SIZE = 1,
00567 };

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 555 of file app_minivm.c.

00555                          {
00556    OPT_SILENT =      (1 << 0),
00557    OPT_BUSY_GREETING =    (1 << 1),
00558    OPT_UNAVAIL_GREETING = (1 << 2),
00559    OPT_TEMP_GREETING = (1 << 3),
00560    OPT_NAME_GREETING = (1 << 4),
00561    OPT_RECORDGAIN =  (1 << 5),
00562 };

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 537 of file app_minivm.c.

00537                      {
00538    MVM_MESSAGE_EMAIL,
00539    MVM_MESSAGE_PAGE
00540    /* For trunk: MVM_MESSAGE_JABBER, */
00541 };


Function Documentation

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 3264 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().

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

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

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

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

AST_APP_OPTIONS ( minivm_accmess_options   ) 
AST_APP_OPTIONS ( minivm_app_options   ) 
static AST_LIST_HEAD_STATIC ( minivm_zones  ,
minivm_zone   
) [static]

The list of e-mail time zones.

static AST_LIST_HEAD_STATIC ( message_templates  ,
minivm_template   
) [static]

The list of e-mail templates.

static AST_LIST_HEAD_STATIC ( minivm_accounts  ,
minivm_account   
) [static]
AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"Mini VoiceMail (A minimal Voicemail e-mail System)"  ,
load = load_module,
unload = unload_module,
reload = reload 
)
AST_MUTEX_DEFINE_STATIC ( minivmloglock   ) 

Lock to protect voicemail system log file

AST_MUTEX_DEFINE_STATIC ( minivmlock   ) 

Lock to protect voicemail system

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 1158 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 sendmail().

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

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

Definition at line 1199 of file app_minivm.c.

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

Referenced by sendmail().

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

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

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

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

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

Definition at line 859 of file app_minivm.c.

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

Referenced by base_encode().

00860 {
00861    if (bio->iocp >= bio->iolen) {
00862       if (!b64_inbuf(bio, fi))
00863          return EOF;
00864    }
00865 
00866    return bio->iobuf[bio->iocp++];
00867 }

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

Definition at line 871 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

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

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

Definition at line 890 of file app_minivm.c.

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

Referenced by sendmail().

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

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

Definition at line 1504 of file app_minivm.c.

References FALSE, make_dir(), and TRUE.

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

01505 {
01506    struct stat filestat;
01507    make_dir(dest, len, domain, username, folder ? folder : "");
01508    if (stat(dest, &filestat)== -1)
01509       return FALSE;
01510    else
01511       return TRUE;
01512 }

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

Definition at line 1129 of file app_minivm.c.

Referenced by sendmail().

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

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

Definition at line 2988 of file app_minivm.c.

References AST_LIST_TRAVERSE, ast_strdup, and minivm_account::domain.

Referenced by handle_minivm_show_users().

02989 {
02990    int which = 0;
02991    int wordlen;
02992    struct minivm_account *vmu;
02993    const char *domain = "";
02994 
02995    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
02996    if (pos > 4)
02997       return NULL;
02998    if (pos == 3)
02999       return (state == 0) ? ast_strdup("for") : NULL;
03000    wordlen = strlen(word);
03001    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
03002       if (!strncasecmp(word, vmu->domain, wordlen)) {
03003          if (domain && strcmp(domain, vmu->domain) && ++which > state)
03004             return ast_strdup(vmu->domain);
03005          /* ignore repeated domains ? */
03006          domain = vmu->domain;
03007       }
03008    }
03009    return NULL;
03010 }

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

Definition at line 1523 of file app_minivm.c.

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

Referenced by leave_voicemail(), minivm_counter_func_read(), and minivm_counter_func_write().

01524 {
01525    int res;
01526    make_dir(dest, len, domain, username, folder);
01527    if ((res = ast_mkdir(dest, 0777))) {
01528       ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01529       return -1;
01530    }
01531    ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
01532    return 0;
01533 }

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 2538 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().

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

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

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

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

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

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

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

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

References ast_free.

Referenced by timezone_destroy_list().

02633 {
02634    ast_free(z);
02635 }

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

Definition at line 962 of file app_minivm.c.

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

Referenced by leave_voicemail().

00963 {
00964    struct ast_tm tm;
00965    struct timeval now = ast_tvnow();
00966 
00967    ast_localtime(&now, &tm, NULL);
00968    return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
00969 }

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

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

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

Reload cofiguration.

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

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

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

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

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

Show stats.

Definition at line 3130 of file app_minivm.c.

References ast_cli(), ast_localtime(), ast_strftime(), 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.

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

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

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

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

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

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

Definition at line 1539 of file app_minivm.c.

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

Referenced by minivm_greet_exec().

01540 {
01541    int res;
01542    char fn[PATH_MAX];
01543 
01544    ast_debug(2, "Still preparing to play message ...\n");
01545 
01546    snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
01547 
01548    if (ast_fileexists(fn, NULL, NULL) > 0) {
01549       res = ast_streamfile(chan, fn, chan->language);
01550       if (res) 
01551          return -1;
01552       res = ast_waitstream(chan, ecodes);
01553       if (res) 
01554          return res;
01555    } else {
01556       int numericusername = 1;
01557       char *i = username;
01558 
01559       ast_debug(2, "No personal prompts. Using default prompt set for language\n");
01560 
01561       while (*i)  {
01562          ast_debug(2, "Numeric? Checking %c\n", *i);
01563          if (!isdigit(*i)) {
01564             numericusername = FALSE;
01565             break;
01566          }
01567          i++;
01568       }
01569 
01570       if (numericusername) {
01571          if (ast_streamfile(chan, "vm-theperson", chan->language))
01572             return -1;
01573          if ((res = ast_waitstream(chan, ecodes)))
01574             return res;
01575 
01576          res = ast_say_digit_str(chan, username, ecodes, chan->language);
01577          if (res)
01578             return res;
01579       } else {
01580          if (ast_streamfile(chan, "vm-theextensionis", chan->language))
01581             return -1;
01582          if ((res = ast_waitstream(chan, ecodes)))
01583             return res;
01584       }
01585    }
01586 
01587    res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", chan->language);
01588    if (res)
01589       return -1;
01590    res = ast_waitstream(chan, ecodes);
01591    return res;
01592 }

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

Definition at line 1843 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, ast_channel::caller, check_dirpath(), 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_party_caller::id, minivm_stats::lastreceived, LOG_ERROR, LOG_WARNING, ast_channel::macrocontext, minivmlogfile, MVM_ALLOCED, ast_party_id::name, ast_party_id::number, pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, minivm_stats::receivedmessages, leave_vm_options::record_gain, S_COR, ast_party_number::str, ast_party_name::str, TRUE, ast_party_number::valid, and ast_party_name::valid.

Referenced by minivm_record_exec().

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

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2807 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_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(), 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.

Referenced by load_module(), and reload().

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

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

References ast_strlen_zero().

Referenced by check_dirpath(), and create_dirpath().

01491 {
01492    return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
01493 }

static void message_destroy_list ( void   )  [static]

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

00824 {
00825    struct minivm_template *this;
00826    AST_LIST_LOCK(&message_templates);
00827    while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) {
00828       message_template_free(this);
00829    }
00830 
00831    AST_LIST_UNLOCK(&message_templates);
00832 }

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

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

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

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

Definition at line 708 of file app_minivm.c.

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

Referenced by message_template_build().

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

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

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

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

static void message_template_free ( struct minivm_template template  )  [static]

Definition at line 728 of file app_minivm.c.

References ast_free.

Referenced by message_destroy_list().

00729 {
00730    if (template->body)
00731       ast_free(template->body);
00732 
00733    ast_free (template);
00734 }

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

Parse emailbody template from configuration file.

Definition at line 2722 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02723 {
02724    char *tmpread, *tmpwrite;
02725    char *emailbody = ast_strdup(configuration);
02726 
02727    /* substitute strings \t and \n into the apropriate characters */
02728    tmpread = tmpwrite = emailbody;
02729    while ((tmpwrite = strchr(tmpread,'\\'))) {
02730           int len = strlen("\n");
02731           switch (tmpwrite[1]) {
02732           case 'n':
02733             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02734             strncpy(tmpwrite, "\n", len);
02735             break;
02736           case 't':
02737             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02738             strncpy(tmpwrite, "\t", len);
02739             break;
02740           default:
02741             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02742           }
02743           tmpread = tmpwrite + len;
02744    }
02745    return emailbody; 
02746 }

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

Read message template from file.

Definition at line 2682 of file app_minivm.c.

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

Referenced by message_template_build().

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

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

Record specific messages for voicemail account.

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

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

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

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

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

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

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

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

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

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

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

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

02403 {
02404    int res = 0;
02405    char filename[BUFSIZ];
02406 
02407    if (!ast_strlen_zero(data)) {
02408       ast_copy_string(filename, (char *) data, sizeof(filename));
02409    } else {
02410       ast_channel_lock(chan);
02411       ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
02412       ast_channel_unlock(chan);
02413    }
02414 
02415    if (ast_strlen_zero(filename)) {
02416       ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
02417       return res;
02418    } 
02419 
02420    /* Go ahead and delete audio files from system, they're not needed any more */
02421    /* We should look for both audio and text files here */
02422    if (ast_fileexists(filename, NULL, NULL) > 0) {
02423       res = vm_delete(filename);
02424       if (res) {
02425          ast_debug(2, "Can't delete file: %s\n", filename);
02426          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02427       } else {
02428          ast_debug(2, "Deleted voicemail file :: %s \n", filename);
02429          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
02430       }
02431    } else {
02432       ast_debug(2, "Filename does not exist: %s\n", filename);
02433       pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02434    }
02435 
02436    return res;
02437 }

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

Definition at line 2210 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(), ast_channel::caller, check_dirpath(), ast_channel::context, minivm_account::domain, minivm_account::exit, ast_channel::exten, find_account(), minivm_account::flags, free_user(), ast_party_caller::id, invent_message(), LOG_ERROR, ast_channel::macrocontext, MVM_ALLOCED, MVM_OPERATOR, ast_party_id::number, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), ast_channel::priority, S_COR, SOUND_INTRO, ast_party_number::str, TRUE, minivm_account::username, and ast_party_number::valid.

Referenced by load_module().

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

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

Definition at line 2040 of file app_minivm.c.

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

Referenced by load_module().

02041 {
02042    int argc;
02043    char *argv[4];
02044    int res = 0;
02045    char *tmpptr;
02046    char tmp[PATH_MAX];
02047    char *mailbox;
02048    char *domain;
02049    if (ast_strlen_zero(data))  {
02050       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02051       return -1;
02052    }
02053    tmpptr = ast_strdupa((char *)data);
02054    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02055    if (argc < 4) {
02056       ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
02057       return -1;
02058    }
02059    ast_copy_string(tmp, argv[0], sizeof(tmp));
02060    mailbox = tmp;
02061    domain = strchr(tmp, '@');
02062    if (domain) {
02063       *domain = '\0';
02064       domain++;
02065    }
02066    if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
02067       ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
02068       return -1;
02069    }
02070    queue_mwi_event(mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
02071 
02072    return res;
02073 }

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

Definition at line 2078 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::caller, minivm_account::domain, find_account(), format, free_user(), ast_party_caller::id, LOG_ERROR, LOG_WARNING, MVM_ALLOCED, ast_party_id::name, notify_new_message(), ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), S_COR, ast_party_name::str, ast_party_number::str, TRUE, minivm_account::username, ast_party_name::valid, and ast_party_number::valid.

Referenced by load_module().

02079 {
02080    int argc;
02081    char *argv[2];
02082    int res = 0;
02083    char tmp[PATH_MAX];
02084    char *domain;
02085    char *tmpptr;
02086    struct minivm_account *vmu;
02087    char *username;
02088    const char *template = "";
02089    const char *filename;
02090    const char *format;
02091    const char *duration_string;
02092 
02093    if (ast_strlen_zero(data))  {
02094       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02095       return -1;
02096    }
02097    tmpptr = ast_strdupa((char *)data);
02098    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02099 
02100    if (argc == 2 && !ast_strlen_zero(argv[1]))
02101       template = argv[1];
02102 
02103    ast_copy_string(tmp, argv[0], sizeof(tmp));
02104    username = tmp;
02105    domain = strchr(tmp, '@');
02106    if (domain) {
02107       *domain = '\0';
02108       domain++;
02109    } 
02110    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
02111       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
02112       return -1;
02113    }
02114 
02115    if(!(vmu = find_account(domain, username, TRUE))) {
02116       /* We could not find user, let's exit */
02117       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
02118       pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
02119       return -1;
02120    }
02121 
02122    ast_channel_lock(chan);
02123    if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
02124       filename = ast_strdupa(filename);
02125    }
02126    ast_channel_unlock(chan);
02127    /* Notify of new message to e-mail and pager */
02128    if (!ast_strlen_zero(filename)) {
02129       ast_channel_lock(chan); 
02130       if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
02131          format = ast_strdupa(format);
02132       }
02133       if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
02134          duration_string = ast_strdupa(duration_string);
02135       }
02136       ast_channel_unlock(chan);
02137       res = notify_new_message(chan, template, vmu, filename, atoi(duration_string),
02138          format,
02139          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
02140          S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL));
02141    }
02142 
02143    pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
02144 
02145 
02146    if(ast_test_flag(vmu, MVM_ALLOCED))
02147       free_user(vmu);
02148 
02149    /* Ok, we're ready to rock and roll. Return to dialplan */
02150 
02151    return res;
02152 
02153 }

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

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

02158 {
02159    int res = 0;
02160    char *tmp;
02161    struct leave_vm_options leave_options;
02162    int argc;
02163    char *argv[2];
02164    struct ast_flags flags = { 0 };
02165    char *opts[OPT_ARG_ARRAY_SIZE];
02166 
02167    memset(&leave_options, 0, sizeof(leave_options));
02168 
02169    /* Answer channel if it's not already answered */
02170    if (chan->_state != AST_STATE_UP)
02171       ast_answer(chan);
02172 
02173    if (ast_strlen_zero(data))  {
02174       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
02175       return -1;
02176    }
02177    tmp = ast_strdupa((char *)data);
02178    argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
02179    if (argc == 2) {
02180       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
02181          return -1;
02182       }
02183       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
02184       if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
02185          int gain;
02186 
02187          if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
02188             ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
02189             return -1;
02190          } else 
02191             leave_options.record_gain = (signed char) gain;
02192       }
02193    } 
02194 
02195    /* Now run the appliation and good luck to you! */
02196    res = leave_voicemail(chan, argv[0], &leave_options);
02197 
02198    if (res == ERROR_LOCK_PATH) {
02199       ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
02200       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
02201       res = 0;
02202    }
02203    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
02204 
02205    return res;
02206 }

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

Definition at line 1025 of file app_minivm.c.

References ast_calloc, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

01026 {
01027    struct minivm_account *new;
01028 
01029    new = ast_calloc(1, sizeof(*new));
01030    if (!new)
01031       return NULL;
01032    populate_defaults(new);
01033 
01034    return new;
01035 }

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

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_log(), ast_manager_event, 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, message_template_find(), MVM_MESSAGE_EMAIL, MVM_MESSAGE_PAGE, minivm_account::pager, pbx_builtin_getvar_helper(), minivm_account::ptemplate, run_externnotify(), sendmail(), and minivm_account::username.

Referenced by minivm_notify_exec().

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

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

Definition at line 1610 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, LOG_WARNING, MVM_OPERATOR, MVM_REVIEW, and vm_delete().

Referenced by leave_voicemail(), and minivm_accmess_exec().

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

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 987 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 sendmail().

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

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

Definition at line 2015 of file app_minivm.c.

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_strdupa, ast_strlen_zero(), context, and mailbox.

Referenced by minivm_mwi_exec().

02016 {
02017    struct ast_event *event;
02018    char *mailbox, *context;
02019 
02020    mailbox = ast_strdupa(mbx);
02021    context = ast_strdupa(ctx);
02022    if (ast_strlen_zero(context)) {
02023       context = "default";
02024    }
02025 
02026    if (!(event = ast_event_new(AST_EVENT_MWI,
02027          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02028          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02029          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
02030          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
02031          AST_EVENT_IE_END))) {
02032       return;
02033    }
02034 
02035    ast_event_queue_and_cache(event);
02036 }

static int reload ( void   )  [static]

Reload mini voicemail module.

Definition at line 3492 of file app_minivm.c.

References load_config().

Referenced by handle_minivm_reload().

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

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

Run external notification for voicemail message.

Definition at line 1742 of file app_minivm.c.

References ast_debug, ast_safe_system(), ast_strlen_zero(), ast_channel::caller, minivm_account::domain, minivm_account::externnotify, global_externnotify, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_party_number::str, ast_party_name::str, minivm_account::username, ast_party_number::valid, and ast_party_name::valid.

Referenced by notify_new_message().

01743 {
01744    char arguments[BUFSIZ];
01745 
01746    if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify))
01747       return;
01748 
01749    snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&", 
01750       ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify, 
01751       vmu->username, vmu->domain,
01752       (chan->caller.id.name.valid && chan->caller.id.name.str)
01753          ? chan->caller.id.name.str : "",
01754       (chan->caller.id.number.valid && chan->caller.id.number.str)
01755          ? chan->caller.id.number.str : "");
01756 
01757    ast_debug(1, "Executing: %s\n", arguments);
01758    ast_safe_system(arguments);
01759 }

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

References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_random(), ast_safe_system(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_tvnow(), base_encode(), check_mime(), minivm_account::domain, minivm_account::email, errno, 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 notify_new_message().

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

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

Add time zone to memory list.

Definition at line 2650 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, minivm_zone::timezone, and minivm_stats::timezones.

Referenced by load_config().

02651 {
02652    struct minivm_zone *newzone;
02653    char *msg_format, *timezone_str;
02654 
02655    newzone = ast_calloc(1, sizeof(*newzone));
02656    if (newzone == NULL)
02657       return 0;
02658 
02659    msg_format = ast_strdupa(config);
02660 
02661    timezone_str = strsep(&msg_format, "|");
02662    if (!msg_format) {
02663       ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
02664       ast_free(newzone);
02665       return 0;
02666    }
02667          
02668    ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
02669    ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
02670    ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
02671 
02672    AST_LIST_LOCK(&minivm_zones);
02673    AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
02674    AST_LIST_UNLOCK(&minivm_zones);
02675 
02676    global_stats.timezones++;
02677 
02678    return 0;
02679 }

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

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

02639 {
02640    struct minivm_zone *this;
02641 
02642    AST_LIST_LOCK(&minivm_zones);
02643    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02644       free_zone(this);
02645       
02646    AST_LIST_UNLOCK(&minivm_zones);
02647 }

static int unload_module ( void   )  [static]
static int vm_delete ( char *  file  )  [static]

Definition at line 1596 of file app_minivm.c.

References ast_debug, and ast_filedelete().

Referenced by minivm_delete_exec(), and play_record_review().

01597 {
01598    int res;
01599 
01600    ast_debug(1, "Deleting voicemail file %s\n", file);
01601 
01602    res = unlink(file);  /* Remove the meta data file */
01603    res |=  ast_filedelete(file, NULL); /* remove the media file */
01604    return res;
01605 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

Referenced by access_counter_file().

03248 {
03249    switch (ast_lock_path(path)) {
03250    case AST_LOCK_TIMEOUT:
03251       return -1;
03252    default:
03253       return 0;
03254    }
03255 }

static void vmaccounts_destroy_list ( void   )  [static]

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

01041 {
01042    struct minivm_account *this;
01043    AST_LIST_LOCK(&minivm_accounts);
01044    while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list))) 
01045       ast_free(this);
01046    AST_LIST_UNLOCK(&minivm_accounts);
01047 }


Variable Documentation

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 550 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 549 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 547 of file app_minivm.c.

char* app_minivm_mwi = "MinivmMWI" [static]

Definition at line 551 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 548 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 546 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 3443 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 685 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 686 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 684 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 682 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 681 of file app_minivm.c.

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

Definition at line 690 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 672 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 680 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 679 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 692 of file app_minivm.c.

Referenced by populate_defaults().

struct ast_flags globalflags = {0} [static]

Global voicemail flags

Definition at line 689 of file app_minivm.c.

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

Initial value:
 {
   .name = "MINIVMACCOUNT",
   .read = minivm_account_func_read,
}

Definition at line 3458 of file app_minivm.c.

Referenced by load_module(), and unload_module().

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

Definition at line 3452 of file app_minivm.c.

Referenced by load_module(), and unload_module().

FILE* minivmlogfile [static]

The minivm log file

Definition at line 677 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 543 of file app_minivm.c.


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1