Fri Nov 12 11:50:15 2010

Asterisk developer's documentation


app_minivm.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Message types for notification.

More...

Functions

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

Variables

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

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

Referenced by load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 427 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 426 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 597 of file app_minivm.c.

Referenced by message_template_create().

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

Default dateformat, can be overridden in configuration file.

Definition at line 596 of file app_minivm.c.

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 428 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100
#define FALSE   0

Definition at line 409 of file app_minivm.c.

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

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

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 431 of file app_minivm.c.

Referenced by load_config(), and play_message_callerid().

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

Definition at line 417 of file app_minivm.c.

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

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

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 415 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)

Review message

Definition at line 413 of file app_minivm.c.

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

#define MVM_SVMAIL   (1 << 3)

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

Referenced by load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 425 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 406 of file app_minivm.c.

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

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 436 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

Definition at line 434 of file app_minivm.c.

Referenced by create_dirpath().


Enumeration Type Documentation

anonymous enum
Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 458 of file app_minivm.c.

00458      {
00459    OPT_SILENT =      (1 << 0),
00460    OPT_BUSY_GREETING =    (1 << 1),
00461    OPT_UNAVAIL_GREETING = (1 << 2),
00462    OPT_TEMP_GREETING = (1 << 3),
00463    OPT_NAME_GREETING = (1 << 4),
00464    OPT_RECORDGAIN =  (1 << 5),
00465 } minivm_option_flags;

anonymous enum
Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 467 of file app_minivm.c.

00467      {
00468    OPT_ARG_RECORDGAIN = 0,
00469    OPT_ARG_ARRAY_SIZE = 1,
00470 } minivm_option_args;

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 440 of file app_minivm.c.

00440                      {
00441    MVM_MESSAGE_EMAIL,
00442    MVM_MESSAGE_PAGE
00443    /* For trunk: MVM_MESSAGE_JABBER, */
00444 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3350 of file app_minivm.c.

static void __unreg_module ( void   )  [static]

Definition at line 3350 of file app_minivm.c.

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

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

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

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

03037 {
03038    char filename[BUFSIZ];
03039    char readbuf[BUFSIZ];
03040    FILE *counterfile;
03041    int old = 0, counter = 0;
03042 
03043    /* Lock directory */
03044    if (vm_lock_path(directory)) {
03045       return -1;  /* Could not lock directory */
03046    }
03047    snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
03048    if (operand != 1) {
03049       counterfile = fopen(filename, "r");
03050       if (counterfile) {
03051          if(fgets(readbuf, sizeof(readbuf), counterfile)) {
03052             ast_debug(3, "Read this string from counter file: %s\n", readbuf);
03053             old = counter = atoi(readbuf);
03054          }
03055          fclose(counterfile);
03056       }
03057    }
03058    switch (operand) {
03059    case 0:  /* Read only */
03060       ast_unlock_path(directory);
03061       ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
03062       return counter;
03063       break;
03064    case 1: /* Set new value */
03065       counter = value;
03066       break;
03067    case 2: /* Change value */
03068       counter += value;
03069       if (counter < 0)  /* Don't allow counters to fall below zero */
03070          counter = 0;
03071       break;
03072    }
03073    
03074    /* Now, write the new value to the file */
03075    counterfile = fopen(filename, "w");
03076    if (!counterfile) {
03077       ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
03078       ast_unlock_path(directory);
03079       return -1;  /* Could not open file for writing */
03080    }
03081    fprintf(counterfile, "%d\n\n", counter);
03082    fclose(counterfile);
03083    ast_unlock_path(directory);
03084    ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
03085    return counter;
03086 }

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

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

02516 {
02517    int error = 0;
02518 
02519    while (var) {
02520       /* Mail command */
02521       if (!strcmp(var->name, "mailcmd")) {
02522          ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
02523       } else if (!strcmp(var->name, "maxgreet")) {
02524          global_maxgreet = atoi(var->value);
02525       } else if (!strcmp(var->name, "maxsilence")) {
02526          global_maxsilence = atoi(var->value);
02527          if (global_maxsilence > 0)
02528             global_maxsilence *= 1000;
02529       } else if (!strcmp(var->name, "logfile")) {
02530          if (!ast_strlen_zero(var->value) ) {
02531             if(*(var->value) == '/')
02532                ast_copy_string(global_logfile, var->value, sizeof(global_logfile));
02533             else
02534                snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
02535          }
02536       } else if (!strcmp(var->name, "externnotify")) {
02537          /* External voicemail notify application */
02538          ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
02539       } else if (!strcmp(var->name, "silencetreshold")) {
02540          /* Silence treshold */
02541          global_silencethreshold = atoi(var->value);
02542       } else if (!strcmp(var->name, "maxmessage")) {
02543          int x;
02544          if (sscanf(var->value, "%30d", &x) == 1) {
02545             global_vmmaxmessage = x;
02546          } else {
02547             error ++;
02548             ast_log(LOG_WARNING, "Invalid max message time length\n");
02549          }
02550       } else if (!strcmp(var->name, "minmessage")) {
02551          int x;
02552          if (sscanf(var->value, "%30d", &x) == 1) {
02553             global_vmminmessage = x;
02554             if (global_maxsilence <= global_vmminmessage)
02555                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
02556          } else {
02557             error ++;
02558             ast_log(LOG_WARNING, "Invalid min message time length\n");
02559          }
02560       } else if (!strcmp(var->name, "format")) {
02561          ast_copy_string(default_vmformat, var->value, sizeof(default_vmformat));
02562       } else if (!strcmp(var->name, "review")) {
02563          ast_set2_flag((&globalflags), ast_true(var->value), MVM_REVIEW);  
02564       } else if (!strcmp(var->name, "operator")) {
02565          ast_set2_flag((&globalflags), ast_true(var->value), MVM_OPERATOR);   
02566       }
02567       var = var->next;
02568    }
02569    return error;
02570 }

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

read buffer from file (base64 conversion)

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

00730 {
00731    int l;
00732 
00733    if (bio->ateof)
00734       return 0;
00735 
00736    if ((l = fread(bio->iobuf, 1, B64_BASEMAXINLINE,fi)) <= 0) {
00737       if (ferror(fi))
00738          return -1;
00739 
00740       bio->ateof = 1;
00741       return 0;
00742    }
00743 
00744    bio->iolen= l;
00745    bio->iocp= 0;
00746 
00747    return 1;
00748 }

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

read character from file to buffer (base64 conversion)

Definition at line 751 of file app_minivm.c.

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

Referenced by base_encode().

00752 {
00753    if (bio->iocp >= bio->iolen) {
00754       if (!b64_inbuf(bio, fi))
00755          return EOF;
00756    }
00757 
00758    return bio->iobuf[bio->iocp++];
00759 }

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

write buffer to file (base64 conversion)

Definition at line 762 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

00763 {
00764    if (bio->linelength >= B64_BASELINELEN) {
00765       if (fputs(EOL,so) == EOF)
00766          return -1;
00767 
00768       bio->linelength= 0;
00769    }
00770 
00771    if (putc(((unsigned char) c), so) == EOF)
00772       return -1;
00773 
00774    bio->linelength++;
00775 
00776    return 1;
00777 }

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

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

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

00781 {
00782    unsigned char dtable[B64_BASEMAXINLINE];
00783    int i,hiteof= 0;
00784    FILE *fi;
00785    struct b64_baseio bio;
00786 
00787    memset(&bio, 0, sizeof(bio));
00788    bio.iocp = B64_BASEMAXINLINE;
00789 
00790    if (!(fi = fopen(filename, "rb"))) {
00791       ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
00792       return -1;
00793    }
00794 
00795    for (i= 0; i<9; i++) {
00796       dtable[i]= 'A'+i;
00797       dtable[i+9]= 'J'+i;
00798       dtable[26+i]= 'a'+i;
00799       dtable[26+i+9]= 'j'+i;
00800    }
00801    for (i= 0; i < 8; i++) {
00802       dtable[i+18]= 'S'+i;
00803       dtable[26+i+18]= 's'+i;
00804    }
00805    for (i= 0; i < 10; i++) {
00806       dtable[52+i]= '0'+i;
00807    }
00808    dtable[62]= '+';
00809    dtable[63]= '/';
00810 
00811    while (!hiteof){
00812       unsigned char igroup[3], ogroup[4];
00813       int c,n;
00814 
00815       igroup[0]= igroup[1]= igroup[2]= 0;
00816 
00817       for (n= 0; n < 3; n++) {
00818          if ((c = b64_inchar(&bio, fi)) == EOF) {
00819             hiteof= 1;
00820             break;
00821          }
00822          igroup[n]= (unsigned char)c;
00823       }
00824 
00825       if (n> 0) {
00826          ogroup[0]= dtable[igroup[0]>>2];
00827          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
00828          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
00829          ogroup[3]= dtable[igroup[2]&0x3F];
00830 
00831          if (n<3) {
00832             ogroup[3]= '=';
00833 
00834             if (n<2)
00835                ogroup[2]= '=';
00836          }
00837 
00838          for (i= 0;i<4;i++)
00839             b64_ochar(&bio, ogroup[i], so);
00840       }
00841    }
00842 
00843    /* Put end of line - line feed */
00844    if (fputs(EOL, so) == EOF)
00845       return 0;
00846 
00847    fclose(fi);
00848 
00849    return 1;
00850 }

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

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

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

Definition at line 1276 of file app_minivm.c.

References FALSE, make_dir(), and TRUE.

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

01277 {
01278    struct stat filestat;
01279    make_dir(dest, len, domain, username, folder ? folder : "");
01280    if (stat(dest, &filestat)== -1)
01281       return FALSE;
01282    else
01283       return TRUE;
01284 }

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

Definition at line 2755 of file app_minivm.c.

References AST_LIST_TRAVERSE, ast_strdup, and minivm_account::domain.

Referenced by handle_minivm_show_users().

02756 {
02757    int which = 0;
02758    int wordlen;
02759    struct minivm_account *vmu;
02760    const char *domain = "";
02761 
02762    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
02763    if (pos > 4)
02764       return NULL;
02765    if (pos == 3)
02766       return (state == 0) ? ast_strdup("for") : NULL;
02767    wordlen = strlen(word);
02768    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02769       if (!strncasecmp(word, vmu->domain, wordlen)) {
02770          if (domain && strcmp(domain, vmu->domain) && ++which > state)
02771             return ast_strdup(vmu->domain);
02772          /* ignore repeated domains ? */
02773          domain = vmu->domain;
02774       }
02775    }
02776    return NULL;
02777 }

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

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

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

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

01295 {
01296    int res;
01297    make_dir(dest, len, domain, username, folder);
01298    if ((res = ast_mkdir(dest, 0777))) {
01299       ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01300       return -1;
01301    }
01302    ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
01303    return 0;
01304 }

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 2299 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_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().

02300 {
02301    struct minivm_account *vmu;
02302    char *domain;
02303    char *username;
02304    char accbuf[BUFSIZ];
02305 
02306    ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
02307 
02308    ast_copy_string(accbuf, name, sizeof(accbuf));
02309    username = accbuf;
02310    domain = strchr(accbuf, '@');
02311    if (domain) {
02312       *domain = '\0';
02313       domain++;
02314    }
02315    if (ast_strlen_zero(domain)) {
02316       ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
02317       return 0;
02318    }
02319 
02320    ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
02321 
02322    /* Allocate user account */
02323    vmu = ast_calloc(1, sizeof(*vmu));
02324    if (!vmu)
02325       return 0;
02326    
02327    ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
02328    ast_copy_string(vmu->username, username, sizeof(vmu->username));
02329 
02330    populate_defaults(vmu);
02331 
02332    ast_debug(3, "...Configuring account %s\n", name);
02333 
02334    while (var) {
02335       ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
02336       if (!strcasecmp(var->name, "serveremail")) {
02337          ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
02338       } else if (!strcasecmp(var->name, "email")) {
02339          ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
02340       } else if (!strcasecmp(var->name, "accountcode")) {
02341          ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
02342       } else if (!strcasecmp(var->name, "pincode")) {
02343          ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
02344       } else if (!strcasecmp(var->name, "domain")) {
02345          ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
02346       } else if (!strcasecmp(var->name, "language")) {
02347          ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
02348       } else if (!strcasecmp(var->name, "timezone")) {
02349          ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
02350       } else if (!strcasecmp(var->name, "externnotify")) {
02351          ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
02352       } else if (!strcasecmp(var->name, "etemplate")) {
02353          ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
02354       } else if (!strcasecmp(var->name, "ptemplate")) {
02355          ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
02356       } else if (!strcasecmp(var->name, "fullname")) {
02357          ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
02358       } else if (!strcasecmp(var->name, "setvar")) {
02359          char *varval;
02360          char *varname = ast_strdupa(var->value);
02361          struct ast_variable *tmpvar;
02362 
02363          if (varname && (varval = strchr(varname, '='))) {
02364             *varval = '\0';
02365             varval++;
02366             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
02367                tmpvar->next = vmu->chanvars;
02368                vmu->chanvars = tmpvar;
02369             }
02370          }
02371       } else if (!strcasecmp(var->name, "pager")) {
02372          ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
02373       } else if (!strcasecmp(var->name, "volgain")) {
02374          sscanf(var->value, "%30lf", &vmu->volgain);
02375       } else {
02376          ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
02377       }
02378       var = var->next;
02379    }
02380    ast_debug(3, "...Linking account %s\n", name);
02381    
02382    AST_LIST_LOCK(&minivm_accounts);
02383    AST_LIST_INSERT_TAIL(&minivm_accounts, vmu, list);
02384    AST_LIST_UNLOCK(&minivm_accounts);
02385 
02386    global_stats.voicemailaccounts++;
02387 
02388    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)" : "");
02389    return 0;
02390 }

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

Find user from static memory object list.

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

00956 {
00957    struct minivm_account *vmu = NULL, *cur;
00958 
00959 
00960    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
00961       ast_log(LOG_NOTICE, "No username or domain? \n");
00962       return NULL;
00963    }
00964    ast_debug(3, "Looking for voicemail user %s in domain %s\n", username, domain);
00965 
00966    AST_LIST_LOCK(&minivm_accounts);
00967    AST_LIST_TRAVERSE(&minivm_accounts, cur, list) {
00968       /* Is this the voicemail account we're looking for? */
00969       if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
00970          break;
00971    }
00972    AST_LIST_UNLOCK(&minivm_accounts);
00973 
00974    if (cur) {
00975       ast_debug(3, "Found account for %s@%s\n", username, domain);
00976       vmu = cur;
00977 
00978    } else
00979       vmu = find_user_realtime(domain, username);
00980 
00981    if (createtemp && !vmu) {
00982       /* Create a temporary user, send e-mail and be gone */
00983       vmu = mvm_user_alloc();
00984       ast_set2_flag(vmu, TRUE, MVM_ALLOCED); 
00985       if (vmu) {
00986          ast_copy_string(vmu->username, username, sizeof(vmu->username));
00987          ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
00988          ast_debug(1, "Created temporary account\n");
00989       }
00990 
00991    }
00992    return vmu;
00993 }

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

Find user in realtime storage Returns pointer to minivm_account structure.

Definition at line 998 of file app_minivm.c.

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

Referenced by find_account().

00999 {
01000    struct ast_variable *var;
01001    struct minivm_account *retval;
01002    char name[MAXHOSTNAMELEN];
01003 
01004    retval = mvm_user_alloc();
01005    if (!retval)
01006       return NULL;
01007 
01008    if (username) 
01009       ast_copy_string(retval->username, username, sizeof(retval->username));
01010 
01011    populate_defaults(retval);
01012    var = ast_load_realtime("minivm", "username", username, "domain", domain, SENTINEL);
01013 
01014    if (!var) {
01015       ast_free(retval);
01016       return NULL;
01017    }
01018 
01019    snprintf(name, sizeof(name), "%s@%s", username, domain);
01020    create_vmaccount(name, var, TRUE);
01021 
01022    ast_variables_destroy(var);
01023    return retval;
01024 }

static void free_user ( struct minivm_account vmu  )  [static]

Free user structure - if it's allocated.

Definition at line 863 of file app_minivm.c.

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

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

00864 {
00865    if (vmu->chanvars)
00866       ast_variables_destroy(vmu->chanvars);
00867    ast_free(vmu);
00868 }

static void free_zone ( struct minivm_zone z  )  [static]

Free Mini Voicemail timezone.

Definition at line 2393 of file app_minivm.c.

References ast_free.

Referenced by timezone_destroy_list().

02394 {
02395    ast_free(z);
02396 }

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

Definition at line 852 of file app_minivm.c.

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

Referenced by leave_voicemail().

00853 {
00854    struct ast_tm tm;
00855    struct timeval now = ast_tvnow();
00856 
00857    ast_localtime(&now, &tm, NULL);
00858    return ast_strftime(s, len, "%a %b %e %r %Z %Y", &tm);
00859 }

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

02715 {
02716    struct minivm_template *this;
02717 #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
02718    int count = 0;
02719 
02720    switch (cmd) {
02721    case CLI_INIT:
02722       e->command = "minivm list templates";
02723       e->usage =
02724          "Usage: minivm list templates\n"
02725          "       Lists message templates for e-mail, paging and IM\n";
02726       return NULL;
02727    case CLI_GENERATE:
02728       return NULL;
02729    }
02730 
02731    if (a->argc > 3)
02732       return CLI_SHOWUSAGE;
02733 
02734    AST_LIST_LOCK(&message_templates);
02735    if (AST_LIST_EMPTY(&message_templates)) {
02736       ast_cli(a->fd, "There are no message templates defined\n");
02737       AST_LIST_UNLOCK(&message_templates);
02738       return CLI_FAILURE;
02739    }
02740    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
02741    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
02742    AST_LIST_TRAVERSE(&message_templates, this, list) {
02743       ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name, 
02744          this->charset ? this->charset : "-", 
02745          this->locale ? this->locale : "-",
02746          this->attachment ? "Yes" : "No",
02747          this->subject ? this->subject : "-");
02748       count++;
02749    }
02750    AST_LIST_UNLOCK(&message_templates);
02751    ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
02752    return CLI_SUCCESS;
02753 }

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

Reload cofiguration.

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

03304 {
03305    
03306    switch (cmd) {
03307    case CLI_INIT:
03308       e->command = "minivm reload";
03309       e->usage =
03310          "Usage: minivm reload\n"
03311          "       Reload mini-voicemail configuration and reset statistics\n";
03312       return NULL;
03313    case CLI_GENERATE:
03314       return NULL;
03315    }
03316    
03317    reload();
03318    ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
03319    return CLI_SUCCESS;
03320 }

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

02866 {
02867    switch (cmd) {
02868    case CLI_INIT:
02869       e->command = "minivm show settings";
02870       e->usage =
02871          "Usage: minivm show settings\n"
02872          "       Display Mini-Voicemail general settings\n";
02873       return NULL;
02874    case CLI_GENERATE:
02875       return NULL;
02876    }
02877 
02878    ast_cli(a->fd, "* Mini-Voicemail general settings\n");
02879    ast_cli(a->fd, "  -------------------------------\n");
02880    ast_cli(a->fd, "\n");
02881    ast_cli(a->fd, "  Mail command (shell):               %s\n", global_mailcmd);
02882    ast_cli(a->fd, "  Max silence:                        %d\n", global_maxsilence);
02883    ast_cli(a->fd, "  Silence threshold:                  %d\n", global_silencethreshold);
02884    ast_cli(a->fd, "  Max message length (secs):          %d\n", global_vmmaxmessage);
02885    ast_cli(a->fd, "  Min message length (secs):          %d\n", global_vmminmessage);
02886    ast_cli(a->fd, "  Default format:                     %s\n", default_vmformat);
02887    ast_cli(a->fd, "  Extern notify (shell):              %s\n", global_externnotify);
02888    ast_cli(a->fd, "  Logfile:                            %s\n", global_logfile[0] ? global_logfile : "<disabled>");
02889    ast_cli(a->fd, "  Operator exit:                      %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
02890    ast_cli(a->fd, "  Message review:                     %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
02891 
02892    ast_cli(a->fd, "\n");
02893    return CLI_SUCCESS;
02894 }

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

Show stats.

Definition at line 2897 of file app_minivm.c.

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

02898 {
02899    struct ast_tm timebuf;
02900    char buf[BUFSIZ];
02901 
02902    switch (cmd) {
02903    
02904    case CLI_INIT:
02905       e->command = "minivm show stats";
02906       e->usage =
02907          "Usage: minivm show stats\n"
02908          "       Display Mini-Voicemail counters\n";
02909       return NULL;
02910    case CLI_GENERATE:
02911       return NULL;
02912    }
02913 
02914    ast_cli(a->fd, "* Mini-Voicemail statistics\n");
02915    ast_cli(a->fd, "  -------------------------\n");
02916    ast_cli(a->fd, "\n");
02917    ast_cli(a->fd, "  Voicemail accounts:                  %5d\n", global_stats.voicemailaccounts);
02918    ast_cli(a->fd, "  Templates:                           %5d\n", global_stats.templates);
02919    ast_cli(a->fd, "  Timezones:                           %5d\n", global_stats.timezones);
02920    if (global_stats.receivedmessages == 0) {
02921       ast_cli(a->fd, "  Received messages since last reset:  <none>\n");
02922    } else {
02923       ast_cli(a->fd, "  Received messages since last reset:  %d\n", global_stats.receivedmessages);
02924       ast_localtime(&global_stats.lastreceived, &timebuf, NULL);
02925       ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
02926       ast_cli(a->fd, "  Last received voicemail:             %s\n", buf);
02927    }
02928    ast_localtime(&global_stats.reset, &timebuf, NULL);
02929    ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
02930    ast_cli(a->fd, "  Last reset:                          %s\n", buf);
02931 
02932    ast_cli(a->fd, "\n");
02933    return CLI_SUCCESS;
02934 }

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

02781 {
02782    struct minivm_account *vmu;
02783 #define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
02784    int count = 0;
02785 
02786    switch (cmd) {
02787    case CLI_INIT:
02788       e->command = "minivm list accounts";
02789       e->usage =
02790          "Usage: minivm list accounts\n"
02791          "       Lists all mailboxes currently set up\n";
02792       return NULL;
02793    case CLI_GENERATE:
02794       return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
02795    }
02796 
02797    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
02798       return CLI_SHOWUSAGE;
02799    if ((a->argc == 5) && strcmp(a->argv[3],"for"))
02800       return CLI_SHOWUSAGE;
02801 
02802    AST_LIST_LOCK(&minivm_accounts);
02803    if (AST_LIST_EMPTY(&minivm_accounts)) {
02804       ast_cli(a->fd, "There are no voicemail users currently defined\n");
02805       AST_LIST_UNLOCK(&minivm_accounts);
02806       return CLI_FAILURE;
02807    }
02808    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
02809    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
02810    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
02811       char tmp[256] = "";
02812       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
02813          count++;
02814          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
02815          ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, vmu->etemplate ? vmu->etemplate : "-", 
02816             vmu->ptemplate ? vmu->ptemplate : "-",
02817             vmu->zonetag ? vmu->zonetag : "-", 
02818             vmu->attachfmt ? vmu->attachfmt : "-",
02819             vmu->fullname);
02820       }
02821    }
02822    AST_LIST_UNLOCK(&minivm_accounts);
02823    ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
02824    return CLI_SUCCESS;
02825 }

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

02829 {
02830    struct minivm_zone *zone;
02831 #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
02832    char *res = CLI_SUCCESS;
02833 
02834    switch (cmd) {
02835    case CLI_INIT:
02836       e->command = "minivm list zones";
02837       e->usage =
02838          "Usage: minivm list zones\n"
02839          "       Lists zone message formats\n";
02840       return NULL;
02841    case CLI_GENERATE:
02842       return NULL;
02843    }
02844 
02845    if (a->argc != e->args)
02846       return CLI_SHOWUSAGE;
02847 
02848    AST_LIST_LOCK(&minivm_zones);
02849    if (!AST_LIST_EMPTY(&minivm_zones)) {
02850       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
02851       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
02852       AST_LIST_TRAVERSE(&minivm_zones, zone, list) {
02853          ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
02854       }
02855    } else {
02856       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
02857       res = CLI_FAILURE;
02858    }
02859    AST_LIST_UNLOCK(&minivm_zones);
02860 
02861    return res;
02862 }

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

Play intro message before recording voicemail.

Definition at line 1309 of file app_minivm.c.

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

Referenced by minivm_greet_exec().

01310 {
01311    int res;
01312    char fn[PATH_MAX];
01313 
01314    ast_debug(2, "Still preparing to play message ...\n");
01315 
01316    snprintf(fn, sizeof(fn), "%s%s/%s/greet", MVM_SPOOL_DIR, domain, username);
01317 
01318    if (ast_fileexists(fn, NULL, NULL) > 0) {
01319       res = ast_streamfile(chan, fn, chan->language);
01320       if (res) 
01321          return -1;
01322       res = ast_waitstream(chan, ecodes);
01323       if (res) 
01324          return res;
01325    } else {
01326       int numericusername = 1;
01327       char *i = username;
01328 
01329       ast_debug(2, "No personal prompts. Using default prompt set for language\n");
01330       
01331       while (*i)  {
01332          ast_debug(2, "Numeric? Checking %c\n", *i);
01333          if (!isdigit(*i)) {
01334             numericusername = FALSE;
01335             break;
01336          }
01337          i++;
01338       }
01339 
01340       if (numericusername) {
01341          if(ast_streamfile(chan, "vm-theperson", chan->language))
01342             return -1;
01343          if ((res = ast_waitstream(chan, ecodes)))
01344             return res;
01345    
01346          res = ast_say_digit_str(chan, username, ecodes, chan->language);
01347          if (res)
01348             return res;
01349       } else {
01350          if(ast_streamfile(chan, "vm-theextensionis", chan->language))
01351             return -1;
01352          if ((res = ast_waitstream(chan, ecodes)))
01353             return res;
01354       }
01355    }
01356 
01357    res = ast_streamfile(chan, busy ? "vm-isonphone" : "vm-isunavail", chan->language);
01358    if (res)
01359       return -1;
01360    res = ast_waitstream(chan, ecodes);
01361    return res;
01362 }

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

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

Definition at line 1604 of file app_minivm.c.

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

Referenced by minivm_record_exec().

01605 {
01606    char tmptxtfile[PATH_MAX];
01607    char callerid[256];
01608    FILE *txt;
01609    int res = 0, txtdes;
01610    int msgnum;
01611    int duration = 0;
01612    char date[256];
01613    char tmpdir[PATH_MAX];
01614    char ext_context[256] = "";
01615    char fmt[80];
01616    char *domain;
01617    char tmp[256] = "";
01618    struct minivm_account *vmu;
01619    int userdir;
01620 
01621    ast_copy_string(tmp, username, sizeof(tmp));
01622    username = tmp;
01623    domain = strchr(tmp, '@');
01624    if (domain) {
01625       *domain = '\0';
01626       domain++;
01627    }
01628 
01629    if (!(vmu = find_account(domain, username, TRUE))) {
01630       /* We could not find user, let's exit */
01631       ast_log(LOG_ERROR, "Can't allocate temporary account for '%s@%s'\n", username, domain);
01632       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01633       return 0;
01634    }
01635 
01636    /* Setup pre-file if appropriate */
01637    if (strcmp(vmu->domain, "localhost"))
01638       snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
01639    else
01640       ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
01641 
01642    /* The meat of recording the message...  All the announcements and beeps have been played*/
01643    if (ast_strlen_zero(vmu->attachfmt))
01644       ast_copy_string(fmt, default_vmformat, sizeof(fmt));
01645    else
01646       ast_copy_string(fmt, vmu->attachfmt, sizeof(fmt));
01647 
01648    if (ast_strlen_zero(fmt)) {
01649       ast_log(LOG_WARNING, "No format for saving voicemail? Default %s\n", default_vmformat);
01650       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01651       return res;
01652    }
01653    msgnum = 0;
01654 
01655    userdir = check_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
01656 
01657    /* If we have no user directory, use generic temporary directory */
01658    if (!userdir) {
01659       create_dirpath(tmpdir, sizeof(tmpdir), "0000_minivm_temp", "mediafiles", "");
01660       ast_debug(3, "Creating temporary directory %s\n", tmpdir);
01661    }
01662 
01663 
01664    snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
01665    
01666 
01667    /* XXX This file needs to be in temp directory */
01668    txtdes = mkstemp(tmptxtfile);
01669    if (txtdes < 0) {
01670       ast_log(LOG_ERROR, "Unable to create message file %s: %s\n", tmptxtfile, strerror(errno));
01671       res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
01672       if (!res)
01673          res = ast_waitstream(chan, "");
01674       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01675       return res;
01676    }
01677 
01678    if (res >= 0) {
01679       /* Unless we're *really* silent, try to send the beep */
01680       res = ast_streamfile(chan, "beep", chan->language);
01681       if (!res)
01682          res = ast_waitstream(chan, "");
01683    }
01684 
01685    /* OEJ XXX Maybe this can be turned into a log file? Hmm. */
01686    /* Store information */
01687    ast_debug(2, "Open file for metadata: %s\n", tmptxtfile);
01688 
01689    res = play_record_review(chan, NULL, tmptxtfile, global_vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
01690 
01691    txt = fdopen(txtdes, "w+");
01692    if (!txt) {
01693       ast_log(LOG_WARNING, "Error opening text file for output\n");
01694    } else {
01695       struct ast_tm tm;
01696       struct timeval now = ast_tvnow();
01697       char timebuf[30];
01698       char logbuf[BUFSIZ];
01699       get_date(date, sizeof(date));
01700       ast_localtime(&now, &tm, NULL);
01701       ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
01702       
01703       snprintf(logbuf, sizeof(logbuf),
01704          /* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
01705          "%s:%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
01706          username,
01707          chan->context,
01708          chan->macrocontext, 
01709          chan->exten,
01710          chan->priority,
01711          chan->name,
01712          ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
01713          date, 
01714          timebuf,
01715          duration,
01716          duration < global_vmminmessage ? "IGNORED" : "OK",
01717          vmu->accountcode
01718       ); 
01719       fprintf(txt, "%s", logbuf);
01720       if (minivmlogfile) {
01721          ast_mutex_lock(&minivmloglock);
01722          fprintf(minivmlogfile, "%s", logbuf);
01723          ast_mutex_unlock(&minivmloglock);
01724       }
01725 
01726       if (duration < global_vmminmessage) {
01727          ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, global_vmminmessage);
01728          fclose(txt);
01729          ast_filedelete(tmptxtfile, NULL);
01730          unlink(tmptxtfile);
01731          pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01732          return 0;
01733       } 
01734       fclose(txt); /* Close log file */
01735       if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
01736          ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
01737          unlink(tmptxtfile);
01738          pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01739          if(ast_test_flag(vmu, MVM_ALLOCED))
01740             free_user(vmu);
01741          return 0;
01742       }
01743 
01744       /* Set channel variables for the notify application */
01745       pbx_builtin_setvar_helper(chan, "MVM_FILENAME", tmptxtfile);
01746       snprintf(timebuf, sizeof(timebuf), "%d", duration);
01747       pbx_builtin_setvar_helper(chan, "MVM_DURATION", timebuf);
01748       pbx_builtin_setvar_helper(chan, "MVM_FORMAT", fmt);
01749 
01750    }
01751    global_stats.lastreceived = ast_tvnow();
01752    global_stats.receivedmessages++;
01753 // /* Go ahead and delete audio files from system, they're not needed any more */
01754 // if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
01755 //    ast_filedelete(tmptxtfile, NULL);
01756 //     /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
01757 //    ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
01758 // }
01759 
01760    if (res > 0)
01761       res = 0;
01762 
01763    if(ast_test_flag(vmu, MVM_ALLOCED))
01764       free_user(vmu);
01765 
01766    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
01767    return res;
01768 }

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2573 of file app_minivm.c.

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

Referenced by load_module(), and reload().

02574 {
02575    struct ast_config *cfg;
02576    struct ast_variable *var;
02577    char *cat;
02578    const char *chanvar;
02579    int error = 0;
02580    struct minivm_template *template;
02581    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02582 
02583    cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
02584    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02585       return 0;
02586    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02587       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
02588       return 0;
02589    }
02590 
02591    ast_mutex_lock(&minivmlock);
02592 
02593    /* Destroy lists to reconfigure */
02594    message_destroy_list();    /* Destroy list of voicemail message templates */
02595    timezone_destroy_list();   /* Destroy list of timezones */
02596    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
02597    ast_debug(2, "Destroyed memory objects...\n");
02598 
02599    /* First, set some default settings */
02600    global_externnotify[0] = '\0';
02601    global_logfile[0] = '\0';
02602    global_vmmaxmessage = 2000;
02603    global_maxgreet = 2000;
02604    global_vmminmessage = 0;
02605    strcpy(global_mailcmd, SENDMAIL);
02606    global_maxsilence = 0;
02607    global_saydurationminfo = 2;
02608    ast_copy_string(default_vmformat, "wav", sizeof(default_vmformat));
02609    ast_set2_flag((&globalflags), FALSE, MVM_REVIEW);  
02610    ast_set2_flag((&globalflags), FALSE, MVM_OPERATOR);   
02611    strcpy(global_charset, "ISO-8859-1");
02612    /* Reset statistics */
02613    memset(&global_stats, 0, sizeof(global_stats));
02614    global_stats.reset = ast_tvnow();
02615 
02616    global_silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
02617 
02618    /* Make sure we could load configuration file */
02619    if (!cfg) {
02620       ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
02621       ast_mutex_unlock(&minivmlock);
02622       return 0;
02623    }
02624 
02625    ast_debug(2, "Loaded configuration file, now parsing\n");
02626 
02627    /* General settings */
02628 
02629    cat = ast_category_browse(cfg, NULL);
02630    while (cat) {
02631       ast_debug(3, "Found configuration section [%s]\n", cat);
02632       if (!strcasecmp(cat, "general")) {
02633          /* Nothing right now */
02634          error += apply_general_options(ast_variable_browse(cfg, cat));
02635       } else if (!strncasecmp(cat, "template-", 9))  {
02636          /* Template */
02637          char *name = cat + 9;
02638 
02639          /* Now build and link template to list */
02640          error += message_template_build(name, ast_variable_browse(cfg, cat));
02641       } else {
02642          var = ast_variable_browse(cfg, cat);
02643          if (!strcasecmp(cat, "zonemessages")) {
02644             /* Timezones in this context */
02645             while (var) {
02646                timezone_add(var->name, var->value);
02647                var = var->next;
02648             }
02649          } else {
02650             /* Create mailbox from this */
02651             error += create_vmaccount(cat, var, FALSE);
02652          }
02653       }
02654       /* Find next section in configuration file */
02655       cat = ast_category_browse(cfg, cat);
02656    }
02657 
02658    /* Configure the default email template */
02659    message_template_build("email-default", NULL);
02660    template = message_template_find("email-default");
02661 
02662    /* Load date format config for voicemail mail */
02663    if ((chanvar = ast_variable_retrieve(cfg, "general", "emaildateformat"))) 
02664       ast_copy_string(template->dateformat, chanvar, sizeof(template->dateformat));
02665    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailfromstring")))
02666       ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
02667    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
02668       ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
02669    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
02670       ast_copy_string(template->charset, chanvar, sizeof(template->charset));
02671    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject"))) 
02672       ast_copy_string(template->subject, chanvar, sizeof(template->subject));
02673    if ((chanvar = ast_variable_retrieve(cfg, "general", "emailbody"))) 
02674       template->body = message_template_parse_emailbody(chanvar);
02675    template->attachment = TRUE;
02676 
02677    message_template_build("pager-default", NULL);
02678    template = message_template_find("pager-default");
02679    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
02680       ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
02681    if ((chanvar = ast_variable_retrieve(cfg, "general", "pageraddress")))
02682       ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
02683    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagercharset")))
02684       ast_copy_string(template->charset, chanvar, sizeof(template->charset));
02685    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagersubject")))
02686       ast_copy_string(template->subject, chanvar,sizeof(template->subject));
02687    if ((chanvar = ast_variable_retrieve(cfg, "general", "pagerbody"))) 
02688       template->body = message_template_parse_emailbody(chanvar);
02689    template->attachment = FALSE;
02690 
02691    if (error)
02692       ast_log(LOG_ERROR, "--- A total of %d errors found in mini-voicemail configuration\n", error);
02693 
02694    ast_mutex_unlock(&minivmlock);
02695    ast_config_destroy(cfg);
02696 
02697    /* Close log file if it's open and disabled */
02698    if(minivmlogfile)
02699       fclose(minivmlogfile);
02700 
02701    /* Open log file if it's enabled */
02702    if(!ast_strlen_zero(global_logfile)) {
02703       minivmlogfile = fopen(global_logfile, "a");
02704       if(!minivmlogfile)
02705          ast_log(LOG_ERROR, "Failed to open minivm log file %s : %s\n", global_logfile, strerror(errno));
02706       if (minivmlogfile)
02707          ast_debug(3, "Opened log file %s \n", global_logfile);
02708    }
02709 
02710    return 0;
02711 }

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

Fix quote of mail headers for non-ascii characters.

Definition at line 911 of file app_minivm.c.

Referenced by sendmail().

00912 {
00913    char *ptr = to;
00914    *ptr++ = '"';
00915    for (; ptr < to + len - 1; from++) {
00916       if (*from == '"')
00917          *ptr++ = '\\';
00918       else if (*from == '\0')
00919          break;
00920       *ptr++ = *from;
00921    }
00922    if (ptr < to + len - 1)
00923       *ptr++ = '"';
00924    *ptr = '\0';
00925    return to;
00926 }

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

Create directory based on components.

Definition at line 1263 of file app_minivm.c.

References ast_strlen_zero().

Referenced by check_dirpath(), and create_dirpath().

01264 {
01265    return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
01266 }

static void message_destroy_list ( void   )  [static]

Clear list of templates.

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

00719 {
00720    struct minivm_template *this;
00721    AST_LIST_LOCK(&message_templates);
00722    while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) 
00723       message_template_free(this);
00724       
00725    AST_LIST_UNLOCK(&message_templates);
00726 }

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

Build message template from configuration.

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

00636 {
00637    struct minivm_template *template;
00638    int error = 0;
00639 
00640    template = message_template_create(name);
00641    if (!template) {
00642       ast_log(LOG_ERROR, "Out of memory, can't allocate message template object %s.\n", name);
00643       return -1;
00644    }
00645 
00646    while (var) {
00647       ast_debug(3, "Configuring template option %s = \"%s\" for template %s\n", var->name, var->value, name);
00648       if (!strcasecmp(var->name, "fromaddress")) {
00649          ast_copy_string(template->fromaddress, var->value, sizeof(template->fromaddress));
00650       } else if (!strcasecmp(var->name, "fromemail")) {
00651          ast_copy_string(template->serveremail, var->value, sizeof(template->serveremail));
00652       } else if (!strcasecmp(var->name, "subject")) {
00653          ast_copy_string(template->subject, var->value, sizeof(template->subject));
00654       } else if (!strcasecmp(var->name, "locale")) {
00655          ast_copy_string(template->locale, var->value, sizeof(template->locale));
00656       } else if (!strcasecmp(var->name, "attachmedia")) {
00657          template->attachment = ast_true(var->value);
00658       } else if (!strcasecmp(var->name, "dateformat")) {
00659          ast_copy_string(template->dateformat, var->value, sizeof(template->dateformat));
00660       } else if (!strcasecmp(var->name, "charset")) {
00661          ast_copy_string(template->charset, var->value, sizeof(template->charset));
00662       } else if (!strcasecmp(var->name, "templatefile")) {
00663          if (template->body) 
00664             ast_free(template->body);
00665          template->body = message_template_parse_filebody(var->value);
00666          if (!template->body) {
00667             ast_log(LOG_ERROR, "Error reading message body definition file %s\n", var->value);
00668             error++;
00669          }
00670       } else if (!strcasecmp(var->name, "messagebody")) {
00671          if (template->body) 
00672             ast_free(template->body);
00673          template->body = message_template_parse_emailbody(var->value);
00674          if (!template->body) {
00675             ast_log(LOG_ERROR, "Error parsing message body definition:\n          %s\n", var->value);
00676             error++;
00677          }
00678       } else {
00679          ast_log(LOG_ERROR, "Unknown message template configuration option \"%s=%s\"\n", var->name, var->value);
00680          error++;
00681       }
00682       var = var->next;
00683    }
00684    if (error)
00685       ast_log(LOG_ERROR, "-- %d errors found parsing message template definition %s\n", error, name);
00686 
00687    AST_LIST_LOCK(&message_templates);
00688    AST_LIST_INSERT_TAIL(&message_templates, template, list);
00689    AST_LIST_UNLOCK(&message_templates);
00690 
00691    global_stats.templates++;
00692 
00693    return error;
00694 }

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

Create message template.

Definition at line 607 of file app_minivm.c.

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

Referenced by message_template_build().

00608 {
00609    struct minivm_template *template;
00610 
00611    template = ast_calloc(1, sizeof(*template));
00612    if (!template)
00613       return NULL;
00614 
00615    /* Set some defaults for templates */
00616    ast_copy_string(template->name, name, sizeof(template->name));
00617    ast_copy_string(template->dateformat, DEFAULT_DATEFORMAT, sizeof(template->dateformat));
00618    ast_copy_string(template->charset, DEFAULT_CHARSET, sizeof(template->charset));
00619    ast_copy_string(template->subject, "New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}", sizeof(template->subject));
00620    template->attachment = TRUE;
00621 
00622    return template;
00623 }

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

Find named template.

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

00698 {
00699    struct minivm_template *this, *res = NULL;
00700 
00701    if (ast_strlen_zero(name))
00702       return NULL;
00703 
00704    AST_LIST_LOCK(&message_templates);
00705    AST_LIST_TRAVERSE(&message_templates, this, list) {
00706       if (!strcasecmp(this->name, name)) {
00707          res = this;
00708          break;
00709       }
00710    }
00711    AST_LIST_UNLOCK(&message_templates);
00712 
00713    return res;
00714 }

static void message_template_free ( struct minivm_template template  )  [static]

Release memory allocated by message template.

Definition at line 626 of file app_minivm.c.

References ast_free.

Referenced by message_destroy_list().

00627 {
00628    if (template->body)
00629       ast_free(template->body);
00630 
00631    ast_free (template);
00632 }

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

Parse emailbody template from configuration file.

Definition at line 2488 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02489 {
02490    char *tmpread, *tmpwrite;
02491    char *emailbody = ast_strdup(configuration);
02492 
02493    /* substitute strings \t and \n into the apropriate characters */
02494    tmpread = tmpwrite = emailbody;
02495    while ((tmpwrite = strchr(tmpread,'\\'))) {
02496           int len = strlen("\n");
02497           switch (tmpwrite[1]) {
02498           case 'n':
02499             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02500             strncpy(tmpwrite, "\n", len);
02501             break;
02502           case 't':
02503             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02504             strncpy(tmpwrite, "\t", len);
02505             break;
02506           default:
02507             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02508           }
02509           tmpread = tmpwrite + len;
02510    }
02511    return emailbody; 
02512 }

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

Read message template from file.

Definition at line 2448 of file app_minivm.c.

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

Referenced by message_template_build().

02448                                                                    {
02449    char buf[BUFSIZ * 6];
02450    char readbuf[BUFSIZ];
02451    char filenamebuf[BUFSIZ];
02452    char *writepos;
02453    char *messagebody;
02454    FILE *fi;
02455    int lines = 0;
02456 
02457    if (ast_strlen_zero(filename))
02458       return NULL;
02459    if (*filename == '/') 
02460       ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
02461    else 
02462       snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
02463 
02464    if (!(fi = fopen(filenamebuf, "r"))) {
02465       ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
02466       return NULL;
02467    }
02468    writepos = buf;
02469    while (fgets(readbuf, sizeof(readbuf), fi)) {
02470       lines ++;
02471       if (writepos != buf) {
02472          *writepos = '\n';    /* Replace EOL with new line */
02473          writepos++;
02474       }
02475       ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
02476       writepos += strlen(readbuf) - 1;
02477    }
02478    fclose(fi);
02479    messagebody = ast_calloc(1, strlen(buf + 1));
02480    ast_copy_string(messagebody, buf, strlen(buf) + 1);
02481    ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
02482    ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
02483 
02484    return messagebody;
02485 }

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

Record specific messages for voicemail account.

Definition at line 2195 of file app_minivm.c.

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

Referenced by load_module().

02196 {
02197    int argc = 0;
02198    char *argv[2];
02199    char filename[PATH_MAX];
02200    char tmp[PATH_MAX];
02201    char *domain;
02202    char *tmpptr = NULL;
02203    struct minivm_account *vmu;
02204    char *username = argv[0];
02205    struct ast_flags flags = { 0 };
02206    char *opts[OPT_ARG_ARRAY_SIZE];
02207    int error = FALSE;
02208    char *message = NULL;
02209    char *prompt = NULL;
02210    int duration;
02211    int cmd;
02212 
02213    if (ast_strlen_zero(data))  {
02214       ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
02215       error = TRUE;
02216    } else 
02217       tmpptr = ast_strdupa((char *)data);
02218    if (!error) {
02219       if (!tmpptr) {
02220          ast_log(LOG_ERROR, "Out of memory\n");
02221          error = TRUE;
02222       } else
02223          argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02224    }
02225 
02226    if (argc <=1) {
02227       ast_log(LOG_ERROR, "MinivmAccmess needs at least two arguments: account and option\n");
02228       error = TRUE;
02229    }
02230    if (!error && strlen(argv[1]) > 1) {
02231       ast_log(LOG_ERROR, "MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
02232       error = TRUE;
02233    }
02234 
02235    if (!error && ast_app_parse_options(minivm_accmess_options, &flags, opts, argv[1])) {
02236       ast_log(LOG_ERROR, "Can't parse option %s\n", argv[1]);
02237       error = TRUE;
02238    }
02239 
02240    if (error) {
02241       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02242       return -1;
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 0 %s\n", argv[0]);
02254       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02255       return -1;
02256    }
02257 
02258    if(!(vmu = find_account(domain, username, TRUE))) {
02259       /* We could not find user, let's exit */
02260       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
02261       pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "FAILED");
02262       return -1;
02263    }
02264 
02265    /* Answer channel if it's not already answered */
02266    if (chan->_state != AST_STATE_UP)
02267       ast_answer(chan);
02268    
02269    /* Here's where the action is */
02270    if (ast_test_flag(&flags, OPT_BUSY_GREETING)) {
02271       message = "busy";
02272       prompt = "vm-rec-busy";
02273    } else if (ast_test_flag(&flags, OPT_UNAVAIL_GREETING)) {
02274       message = "unavailable";
02275       prompt = "vm-rec-unv";
02276    } else if (ast_test_flag(&flags, OPT_TEMP_GREETING)) {
02277       message = "temp";
02278       prompt = "vm-rec-temp";
02279    } else if (ast_test_flag(&flags, OPT_NAME_GREETING)) {
02280       message = "greet";
02281       prompt = "vm-rec-name";
02282    }
02283    snprintf(filename,sizeof(filename), "%s%s/%s/%s", MVM_SPOOL_DIR, vmu->domain, vmu->username, message);
02284    /* Maybe we should check the result of play_record_review ? */
02285    cmd = play_record_review(chan, prompt, filename, global_maxgreet, default_vmformat, 0, vmu, &duration, NULL, FALSE);
02286 
02287    ast_debug(1, "Recorded new %s message in %s (duration %d)\n", message, filename, duration);
02288 
02289    if(ast_test_flag(vmu, MVM_ALLOCED))
02290       free_user(vmu);
02291 
02292    pbx_builtin_setvar_helper(chan, "MVM_ACCMESS_STATUS", "SUCCESS");
02293 
02294    /* Ok, we're ready to rock and roll. Return to dialplan */
02295    return 0;
02296 }

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

References minivm_account::accountcode, ast_copy_string(), ast_log(), 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.

02938 {
02939    struct minivm_account *vmu;
02940    char *username, *domain, *colname;
02941 
02942    if (!(username = ast_strdupa(data))) {
02943       ast_log(LOG_ERROR, "Memory Error!\n");
02944       return -1;
02945    }
02946 
02947    if ((colname = strchr(username, ':'))) {
02948       *colname = '\0';
02949       colname++;
02950    } else {
02951       colname = "path";
02952    }
02953    if ((domain = strchr(username, '@'))) {
02954       *domain = '\0';
02955       domain++;
02956    }
02957    if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
02958       ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
02959       return 0;
02960    }
02961 
02962    if (!(vmu = find_account(domain, username, TRUE)))
02963       return 0;
02964 
02965    if (!strcasecmp(colname, "hasaccount")) {
02966       ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
02967    } else  if (!strcasecmp(colname, "fullname")) { 
02968       ast_copy_string(buf, vmu->fullname, len);
02969    } else  if (!strcasecmp(colname, "email")) { 
02970       if (!ast_strlen_zero(vmu->email))
02971          ast_copy_string(buf, vmu->email, len);
02972       else
02973          snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
02974    } else  if (!strcasecmp(colname, "pager")) { 
02975       ast_copy_string(buf, vmu->pager, len);
02976    } else  if (!strcasecmp(colname, "etemplate")) { 
02977       if (!ast_strlen_zero(vmu->etemplate))
02978          ast_copy_string(buf, vmu->etemplate, len);
02979       else
02980          ast_copy_string(buf, "email-default", len);
02981    } else  if (!strcasecmp(colname, "language")) { 
02982       ast_copy_string(buf, vmu->language, len);
02983    } else  if (!strcasecmp(colname, "timezone")) { 
02984       ast_copy_string(buf, vmu->zonetag, len);
02985    } else  if (!strcasecmp(colname, "ptemplate")) { 
02986       if (!ast_strlen_zero(vmu->ptemplate))
02987          ast_copy_string(buf, vmu->ptemplate, len);
02988       else
02989          ast_copy_string(buf, "email-default", len);
02990    } else  if (!strcasecmp(colname, "accountcode")) {
02991       ast_copy_string(buf, vmu->accountcode, len);
02992    } else  if (!strcasecmp(colname, "pincode")) {
02993       ast_copy_string(buf, vmu->pincode, len);
02994    } else  if (!strcasecmp(colname, "path")) {
02995       check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
02996    } else { /* Look in channel variables */
02997       struct ast_variable *var;
02998       int found = 0;
02999 
03000       for (var = vmu->chanvars ; var ; var = var->next)
03001          if (!strcmp(var->name, colname)) {
03002             ast_copy_string(buf, var->value, len);
03003             found = 1;
03004             break;
03005          }
03006    }
03007 
03008    if(ast_test_flag(vmu, MVM_ALLOCED))
03009       free_user(vmu);
03010 
03011    return 0;
03012 }

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

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

03090 {
03091    char *username, *domain, *countername;
03092    struct minivm_account *vmu = NULL;
03093    char userpath[BUFSIZ];
03094    int res;
03095 
03096    *buf = '\0';
03097 
03098    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
03099       ast_log(LOG_WARNING, "Memory error!\n");
03100       return -1;
03101    }
03102    if ((countername = strchr(username, ':'))) {
03103       *countername = '\0';
03104       countername++;
03105    } 
03106 
03107    if ((domain = strchr(username, '@'))) {
03108       *domain = '\0';
03109       domain++;
03110    }
03111 
03112    /* If we have neither username nor domain now, let's give up */
03113    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03114       ast_log(LOG_ERROR, "No account given\n");
03115       return -1;
03116    }
03117 
03118    if (ast_strlen_zero(countername)) {
03119       ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
03120       return -1;
03121    }
03122 
03123    /* We only have a domain, no username */
03124    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03125       domain = username;
03126       username = NULL;
03127    }
03128 
03129    /* If we can't find account or if the account is temporary, return. */
03130    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
03131       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
03132       return 0;
03133    }
03134 
03135    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
03136 
03137    /* We have the path, now read the counter file */
03138    res = access_counter_file(userpath, countername, 0, 0);
03139    if (res >= 0)
03140       snprintf(buf, len, "%d", res);
03141    return 0;
03142 }

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

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

03146 {
03147    char *username, *domain, *countername, *operand;
03148    char userpath[BUFSIZ];
03149    struct minivm_account *vmu;
03150    int change = 0;
03151    int operation = 0;
03152 
03153    if(!value)
03154       return -1;
03155    change = atoi(value);
03156 
03157    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
03158       ast_log(LOG_WARNING, "Memory error!\n");
03159       return -1;
03160    }
03161 
03162    if ((countername = strchr(username, ':'))) {
03163       *countername = '\0';
03164       countername++;
03165    } 
03166    if ((operand = strchr(countername, ':'))) {
03167       *operand = '\0';
03168       operand++;
03169    } 
03170 
03171    if ((domain = strchr(username, '@'))) {
03172       *domain = '\0';
03173       domain++;
03174    }
03175 
03176    /* If we have neither username nor domain now, let's give up */
03177    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03178       ast_log(LOG_ERROR, "No account given\n");
03179       return -1;
03180    }
03181 
03182    /* We only have a domain, no username */
03183    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03184       domain = username;
03185       username = NULL;
03186    }
03187 
03188    if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
03189       ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
03190       return -1;
03191    }
03192 
03193    /* If we can't find account or if the account is temporary, return. */
03194    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
03195       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
03196       return 0;
03197    }
03198 
03199    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
03200    /* Now, find out our operator */
03201    if (*operand == 'i') /* Increment */
03202       operation = 2;
03203    else if (*operand == 'd') {
03204       change = change * -1;
03205       operation = 2;
03206    } else if (*operand == 's')
03207       operation = 1;
03208    else {
03209       ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
03210       return -1;
03211    }
03212 
03213    /* We have the path, now read the counter file */
03214    access_counter_file(userpath, countername, change, operation);
03215    return 0;
03216 }

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

Dialplan application to delete voicemail.

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

02158 {
02159    int res = 0;
02160    char filename[BUFSIZ];
02161       
02162    if (!ast_strlen_zero(data)) {
02163       ast_copy_string(filename, (char *) data, sizeof(filename));
02164    } else {
02165       ast_channel_lock(chan);
02166       ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
02167       ast_channel_unlock(chan);
02168    }
02169 
02170    if (ast_strlen_zero(filename)) {
02171       ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
02172       return res;
02173    } 
02174 
02175    /* Go ahead and delete audio files from system, they're not needed any more */
02176    /* We should look for both audio and text files here */
02177    if (ast_fileexists(filename, NULL, NULL) > 0) {
02178       res = vm_delete(filename);
02179       if (res) {
02180          ast_debug(2, "Can't delete file: %s\n", filename);
02181          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02182       } else {
02183          ast_debug(2, "Deleted voicemail file :: %s \n", filename);
02184          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
02185       }
02186    } else {
02187       ast_debug(2, "Filename does not exist: %s\n", filename);
02188       pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02189    }
02190 
02191    return res;
02192 }

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

Play voicemail prompts - either generic or user specific.

Definition at line 1971 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_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), check_dirpath(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, minivm_account::domain, minivm_account::exit, ast_channel::exten, find_account(), minivm_account::flags, free_user(), invent_message(), ast_channel::language, LOG_ERROR, ast_channel::macrocontext, minivm_app_options, MVM_ALLOCED, MVM_OPERATOR, OPT_ARG_ARRAY_SIZE, OPT_BUSY_GREETING, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), ast_channel::priority, SOUND_INTRO, TRUE, and minivm_account::username.

Referenced by load_module().

01972 {
01973    struct leave_vm_options leave_options = { 0, '\0'};
01974    int argc;
01975    char *argv[2];
01976    struct ast_flags flags = { 0 };
01977    char *opts[OPT_ARG_ARRAY_SIZE];
01978    int res = 0;
01979    int ausemacro = 0;
01980    int ousemacro = 0;
01981    int ouseexten = 0;
01982    char tmp[PATH_MAX];
01983    char dest[PATH_MAX];
01984    char prefile[PATH_MAX] = "";
01985    char tempfile[PATH_MAX] = "";
01986    char ext_context[256] = "";
01987    char *domain;
01988    char ecodes[16] = "#";
01989    char *tmpptr;
01990    struct minivm_account *vmu;
01991    char *username = argv[0];
01992 
01993    if (ast_strlen_zero(data))  {
01994       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01995       return -1;
01996    }
01997    tmpptr = ast_strdupa((char *)data);
01998    if (!tmpptr) {
01999       ast_log(LOG_ERROR, "Out of memory\n");
02000       return -1;
02001    }
02002    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
02003 
02004    if (argc == 2) {
02005       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1]))
02006          return -1;
02007       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
02008    }
02009 
02010    ast_copy_string(tmp, argv[0], sizeof(tmp));
02011    username = tmp;
02012    domain = strchr(tmp, '@');
02013    if (domain) {
02014       *domain = '\0';
02015       domain++;
02016    } 
02017    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
02018       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument:  %s\n", argv[0]);
02019       return -1;
02020    }
02021    ast_debug(1, "Trying to find configuration for user %s in domain %s\n", username, domain);
02022 
02023    if (!(vmu = find_account(domain, username, TRUE))) {
02024       ast_log(LOG_ERROR, "Could not allocate memory. \n");
02025       return -1;
02026    }
02027 
02028    /* Answer channel if it's not already answered */
02029    if (chan->_state != AST_STATE_UP)
02030       ast_answer(chan);
02031 
02032    /* Setup pre-file if appropriate */
02033    if (strcmp(vmu->domain, "localhost"))
02034       snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
02035    else
02036       ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
02037 
02038    if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
02039       res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
02040       if (res)
02041          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
02042    } else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
02043       res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
02044       if (res)
02045          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
02046    }
02047    /* Check for temporary greeting - it overrides busy and unavail */
02048    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
02049    if (!(res = check_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
02050       ast_debug(2, "Temporary message directory does not exist, using default (%s)\n", tempfile);
02051       ast_copy_string(prefile, tempfile, sizeof(prefile));
02052    }
02053    ast_debug(2, "Preparing to play message ...\n");
02054 
02055    /* Check current or macro-calling context for special extensions */
02056    if (ast_test_flag(vmu, MVM_OPERATOR)) {
02057       if (!ast_strlen_zero(vmu->exit)) {
02058          if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
02059             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02060             ouseexten = 1;
02061          }
02062       } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
02063          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02064          ouseexten = 1;
02065       }
02066       else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
02067          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02068          ousemacro = 1;
02069       }
02070    }
02071 
02072    if (!ast_strlen_zero(vmu->exit)) {
02073       if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
02074          strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
02075    } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
02076       strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
02077    else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
02078       strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
02079       ausemacro = 1;
02080    }
02081 
02082    res = 0; /* Reset */
02083    /* Play the beginning intro if desired */
02084    if (!ast_strlen_zero(prefile)) {
02085       if (ast_streamfile(chan, prefile, chan->language) > -1) 
02086          res = ast_waitstream(chan, ecodes);
02087    } else {
02088       ast_debug(2, "%s doesn't exist, doing what we can\n", prefile);
02089       res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
02090    }
02091    if (res < 0) {
02092       ast_debug(2, "Hang up during prefile playback\n");
02093       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
02094       if(ast_test_flag(vmu, MVM_ALLOCED))
02095          free_user(vmu);
02096       return -1;
02097    }
02098    if (res == '#') {
02099       /* On a '#' we skip the instructions */
02100       ast_set_flag(&leave_options, OPT_SILENT);
02101       res = 0;
02102    }
02103    if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
02104       res = ast_streamfile(chan, SOUND_INTRO, chan->language);
02105       if (!res)
02106          res = ast_waitstream(chan, ecodes);
02107       if (res == '#') {
02108          ast_set_flag(&leave_options, OPT_SILENT);
02109          res = 0;
02110       }
02111    }
02112    if (res > 0)
02113       ast_stopstream(chan);
02114    /* Check for a '*' here in case the caller wants to escape from voicemail to something
02115       other than the operator -- an automated attendant or mailbox login for example */
02116    if (res == '*') {
02117       chan->exten[0] = 'a';
02118       chan->exten[1] = '\0';
02119       if (!ast_strlen_zero(vmu->exit)) {
02120          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02121       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
02122          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02123       }
02124       chan->priority = 0;
02125       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
02126       res = 0;
02127    } else if (res == '0') { /* Check for a '0' here */
02128       if(ouseexten || ousemacro) {
02129          chan->exten[0] = 'o';
02130          chan->exten[1] = '\0';
02131          if (!ast_strlen_zero(vmu->exit)) {
02132             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02133          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
02134             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02135          }
02136          ast_play_and_wait(chan, "transfer");
02137          chan->priority = 0;
02138          pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "USEREXIT");
02139       }
02140       res =  0;
02141    } else if (res < 0) {
02142       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "FAILED");
02143       res = -1;
02144    } else
02145       pbx_builtin_setvar_helper(chan, "MVM_GREET_STATUS", "SUCCESS");
02146 
02147    if(ast_test_flag(vmu, MVM_ALLOCED))
02148       free_user(vmu);
02149 
02150 
02151    /* Ok, we're ready to rock and roll. Return to dialplan */
02152    return res;
02153 
02154 }

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

Send MWI using interal Asterisk event subsystem.

Definition at line 1795 of file app_minivm.c.

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

Referenced by load_module().

01796 {
01797    int argc;
01798    char *argv[4];
01799    int res = 0;
01800    char *tmpptr;
01801    char tmp[PATH_MAX];
01802    char *mailbox;
01803    char *domain;
01804    if (ast_strlen_zero(data))  {
01805                 ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01806                 return -1;
01807         }
01808         tmpptr = ast_strdupa((char *)data);
01809         if (!tmpptr) {
01810                 ast_log(LOG_ERROR, "Out of memory\n");
01811                 return -1;
01812         }
01813         argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
01814    if (argc < 4) {
01815       ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
01816       return -1;
01817    }
01818         ast_copy_string(tmp, argv[0], sizeof(tmp));
01819         mailbox = tmp;
01820         domain = strchr(tmp, '@');
01821         if (domain) {
01822                 *domain = '\0';
01823                 domain++;
01824         }
01825         if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
01826                 ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
01827                 return -1;
01828         }
01829    queue_mwi_event(mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
01830 
01831    return res;
01832 }

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

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

Definition at line 1836 of file app_minivm.c.

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

Referenced by load_module().

01837 {
01838    int argc;
01839    char *argv[2];
01840    int res = 0;
01841    char tmp[PATH_MAX];
01842    char *domain;
01843    char *tmpptr;
01844    struct minivm_account *vmu;
01845    char *username = argv[0];
01846    const char *template = "";
01847    const char *filename;
01848    const char *format;
01849    const char *duration_string;
01850    
01851    if (ast_strlen_zero(data))  {
01852       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01853       return -1;
01854    }
01855    tmpptr = ast_strdupa((char *)data);
01856    if (!tmpptr) {
01857       ast_log(LOG_ERROR, "Out of memory\n");
01858       return -1;
01859    }
01860    argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
01861 
01862    if (argc == 2 && !ast_strlen_zero(argv[1]))
01863       template = argv[1];
01864 
01865    ast_copy_string(tmp, argv[0], sizeof(tmp));
01866    username = tmp;
01867    domain = strchr(tmp, '@');
01868    if (domain) {
01869       *domain = '\0';
01870       domain++;
01871    } 
01872    if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
01873       ast_log(LOG_ERROR, "Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
01874       return -1;
01875    }
01876 
01877    if(!(vmu = find_account(domain, username, TRUE))) {
01878       /* We could not find user, let's exit */
01879       ast_log(LOG_WARNING, "Could not allocate temporary memory for '%s@%s'\n", username, domain);
01880       pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", "FAILED");
01881       return -1;
01882    }
01883 
01884    ast_channel_lock(chan);
01885    if ((filename = pbx_builtin_getvar_helper(chan, "MVM_FILENAME"))) {
01886       filename = ast_strdupa(filename);
01887    }
01888    ast_channel_unlock(chan);
01889    /* Notify of new message to e-mail and pager */
01890    if (!ast_strlen_zero(filename)) {
01891       ast_channel_lock(chan); 
01892       if ((format = pbx_builtin_getvar_helper(chan, "MVM_FORMAT"))) {
01893          format = ast_strdupa(format);
01894       }
01895       if ((duration_string = pbx_builtin_getvar_helper(chan, "MVM_DURATION"))) {
01896          duration_string = ast_strdupa(duration_string);
01897       }
01898       ast_channel_unlock(chan);
01899       res = notify_new_message(chan, template, vmu, filename, atoi(duration_string), format, chan->cid.cid_num, chan->cid.cid_name);
01900    }
01901 
01902    pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
01903 
01904 
01905    if(ast_test_flag(vmu, MVM_ALLOCED))
01906       free_user(vmu);
01907 
01908    /* Ok, we're ready to rock and roll. Return to dialplan */
01909 
01910    return res;
01911 
01912 }

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

Dialplan function to record voicemail.

Definition at line 1915 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_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, minivm_account::flags, leave_voicemail(), LOG_ERROR, LOG_WARNING, minivm_app_options, OPT_ARG_ARRAY_SIZE, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and leave_vm_options::record_gain.

Referenced by load_module().

01916 {
01917    int res = 0;
01918    char *tmp;
01919    struct leave_vm_options leave_options;
01920    int argc;
01921    char *argv[2];
01922    struct ast_flags flags = { 0 };
01923    char *opts[OPT_ARG_ARRAY_SIZE];
01924       
01925    memset(&leave_options, 0, sizeof(leave_options));
01926 
01927    /* Answer channel if it's not already answered */
01928    if (chan->_state != AST_STATE_UP)
01929       ast_answer(chan);
01930 
01931    if (ast_strlen_zero(data))  {
01932       ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
01933       return -1;
01934    }
01935    tmp = ast_strdupa((char *)data);
01936    if (!tmp) {
01937       ast_log(LOG_ERROR, "Out of memory\n");
01938       return -1;
01939    }
01940    argc = ast_app_separate_args(tmp, ',', argv, ARRAY_LEN(argv));
01941    if (argc == 2) {
01942       if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
01943          return -1;
01944       }
01945       ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING );
01946       if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
01947          int gain;
01948 
01949          if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
01950             ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
01951             return -1;
01952          } else 
01953             leave_options.record_gain = (signed char) gain;
01954       }
01955    } 
01956 
01957    /* Now run the appliation and good luck to you! */
01958    res = leave_voicemail(chan, argv[0], &leave_options);
01959 
01960    if (res == ERROR_LOCK_PATH) {
01961       ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
01962       pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "FAILED");
01963       res = 0;
01964    }
01965    pbx_builtin_setvar_helper(chan, "MVM_RECORD_STATUS", "SUCCESS");
01966 
01967    return res;
01968 }

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

Allocate new vm user and set default values.

Definition at line 930 of file app_minivm.c.

References ast_calloc, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

00931 {
00932    struct minivm_account *new;
00933 
00934    new = ast_calloc(1, sizeof(*new));
00935    if (!new)
00936       return NULL;
00937    populate_defaults(new);
00938 
00939    return new;
00940 }

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

Send message to voicemail account owner.

Definition at line 1527 of file app_minivm.c.

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

Referenced by minivm_notify_exec().

01528 {
01529    char *stringp;
01530    struct minivm_template *etemplate;
01531    char *messageformat;
01532    int res = 0;
01533    char oldlocale[100];
01534    const char *counter;
01535 
01536    if (!ast_strlen_zero(vmu->attachfmt)) {
01537       if (strstr(format, vmu->attachfmt)) {
01538          format = vmu->attachfmt;
01539       } else 
01540          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);
01541    }
01542 
01543    etemplate = message_template_find(vmu->etemplate);
01544    if (!etemplate)
01545       etemplate = message_template_find(templatename);
01546    if (!etemplate)
01547       etemplate = message_template_find("email-default");
01548 
01549    /* Attach only the first format */
01550    stringp = messageformat = ast_strdupa(format);
01551    strsep(&stringp, "|");
01552 
01553    if (!ast_strlen_zero(etemplate->locale)) {
01554       char *new_locale;
01555       ast_copy_string(oldlocale, setlocale(LC_TIME, NULL), sizeof(oldlocale));
01556       ast_debug(2, "Changing locale from %s to %s\n", oldlocale, etemplate->locale);
01557       new_locale = setlocale(LC_TIME, etemplate->locale);
01558       if (new_locale == NULL) {
01559          ast_log(LOG_WARNING, "-_-_- Changing to new locale did not work. Locale: %s\n", etemplate->locale);
01560       }
01561    }
01562 
01563 
01564 
01565    /* Read counter if available */
01566    ast_channel_lock(chan);
01567    if ((counter = pbx_builtin_getvar_helper(chan, "MVM_COUNTER"))) {
01568       counter = ast_strdupa(counter);
01569    }
01570    ast_channel_unlock(chan);
01571 
01572    if (ast_strlen_zero(counter)) {
01573       ast_debug(2, "MVM_COUNTER not found\n");
01574    } else {
01575       ast_debug(2, "MVM_COUNTER found - will use it with value %s\n", counter);
01576    }
01577 
01578    res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_EMAIL, counter);
01579 
01580    if (res == 0 && !ast_strlen_zero(vmu->pager))  {
01581       /* Find template for paging */
01582       etemplate = message_template_find(vmu->ptemplate);
01583       if (!etemplate)
01584          etemplate = message_template_find("pager-default");
01585       if (etemplate->locale) {
01586          ast_copy_string(oldlocale, setlocale(LC_TIME, ""), sizeof(oldlocale));
01587          setlocale(LC_TIME, etemplate->locale);
01588       }
01589 
01590       res = sendmail(etemplate, vmu, cidnum, cidname, filename, messageformat, duration, etemplate->attachment, MVM_MESSAGE_PAGE, counter);
01591    }
01592 
01593    manager_event(EVENT_FLAG_CALL, "MiniVoiceMail", "Action: SentNotification\rn\nMailbox: %s@%s\r\nCounter: %s\r\n", vmu->username, vmu->domain, counter);
01594 
01595    run_externnotify(chan, vmu);     /* Run external notification */
01596 
01597    if (etemplate->locale) 
01598       setlocale(LC_TIME, oldlocale); /* Rest to old locale */
01599    return res;
01600 }

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

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

Definition at line 1378 of file app_minivm.c.

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

Referenced by leave_voicemail(), and minivm_accmess_exec().

01381 {
01382    int cmd = 0;
01383    int max_attempts = 3;
01384    int attempts = 0;
01385    int recorded = 0;
01386    int message_exists = 0;
01387    signed char zero_gain = 0;
01388    char *acceptdtmf = "#";
01389    char *canceldtmf = "";
01390 
01391    /* Note that urgent and private are for flagging messages as such in the future */
01392  
01393    /* barf if no pointer passed to store duration in */
01394    if (duration == NULL) {
01395       ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
01396       return -1;
01397    }
01398 
01399    cmd = '3';   /* Want to start by recording */
01400  
01401    while ((cmd >= 0) && (cmd != 't')) {
01402       switch (cmd) {
01403       case '1':
01404          ast_verb(3, "Saving message as is\n");
01405          ast_stream_and_wait(chan, "vm-msgsaved", "");
01406          cmd = 't';
01407          break;
01408       case '2':
01409          /* Review */
01410          ast_verb(3, "Reviewing the message\n");
01411          ast_streamfile(chan, recordfile, chan->language);
01412          cmd = ast_waitstream(chan, AST_DIGIT_ANY);
01413          break;
01414       case '3':
01415          message_exists = 0;
01416          /* Record */
01417          if (recorded == 1) 
01418             ast_verb(3, "Re-recording the message\n");
01419          else
01420             ast_verb(3, "Recording the message\n");
01421          if (recorded && outsidecaller) 
01422             cmd = ast_play_and_wait(chan, "beep");
01423          recorded = 1;
01424          /* 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 */
01425          if (record_gain)
01426             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
01427          if (ast_test_flag(vmu, MVM_OPERATOR))
01428             canceldtmf = "0";
01429          cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
01430          if (record_gain)
01431             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
01432          if (cmd == -1) /* User has hung up, no options to give */
01433             return cmd;
01434          if (cmd == '0')
01435             break;
01436          else if (cmd == '*')
01437             break;
01438          else {
01439             /* If all is well, a message exists */
01440             message_exists = 1;
01441             cmd = 0;
01442          }
01443          break;
01444       case '4':
01445       case '5':
01446       case '6':
01447       case '7':
01448       case '8':
01449       case '9':
01450       case '*':
01451       case '#':
01452          cmd = ast_play_and_wait(chan, "vm-sorry");
01453          break;
01454       case '0':
01455          if(!ast_test_flag(vmu, MVM_OPERATOR)) {
01456             cmd = ast_play_and_wait(chan, "vm-sorry");
01457             break;
01458          }
01459          if (message_exists || recorded) {
01460             cmd = ast_play_and_wait(chan, "vm-saveoper");
01461             if (!cmd)
01462                cmd = ast_waitfordigit(chan, 3000);
01463             if (cmd == '1') {
01464                ast_play_and_wait(chan, "vm-msgsaved");
01465                cmd = '0';
01466             } else {
01467                ast_play_and_wait(chan, "vm-deleted");
01468                vm_delete(recordfile);
01469                cmd = '0';
01470             }
01471          }
01472          return cmd;
01473       default:
01474          /* If the caller is an ouside caller, and the review option is enabled,
01475             allow them to review the message, but let the owner of the box review
01476             their OGM's */
01477          if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
01478             return cmd;
01479          if (message_exists) {
01480             cmd = ast_play_and_wait(chan, "vm-review");
01481          } else {
01482             cmd = ast_play_and_wait(chan, "vm-torerecord");
01483             if (!cmd)
01484                cmd = ast_waitfordigit(chan, 600);
01485          }
01486          
01487          if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
01488             cmd = ast_play_and_wait(chan, "vm-reachoper");
01489             if (!cmd)
01490                cmd = ast_waitfordigit(chan, 600);
01491          }
01492          if (!cmd)
01493             cmd = ast_waitfordigit(chan, 6000);
01494          if (!cmd) {
01495             attempts++;
01496          }
01497          if (attempts > max_attempts) {
01498             cmd = 't';
01499          }
01500       }
01501    }
01502    if (outsidecaller)  
01503       ast_play_and_wait(chan, "vm-goodbye");
01504    if (cmd == 't')
01505       cmd = 0;
01506    return cmd;
01507 }

static void populate_defaults ( struct minivm_account vmu  )  [static]

Set default values for Mini-Voicemail users.

Definition at line 903 of file app_minivm.c.

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

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

00904 {
00905    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00906    ast_copy_string(vmu->attachfmt, default_vmformat, sizeof(vmu->attachfmt));
00907    vmu->volgain = global_volgain;
00908 }

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

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

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

00876 {
00877    char callerid[256];
00878    struct ast_variable *var;
00879    
00880    if (!channel) {
00881       ast_log(LOG_ERROR, "No allocated channel, giving up...\n");
00882       return;
00883    }
00884 
00885    for (var = vmu->chanvars ; var ; var = var->next) {
00886       pbx_builtin_setvar_helper(channel, var->name, var->value);
00887    }
00888 
00889    /* Prepare variables for substition in email body and subject */
00890    pbx_builtin_setvar_helper(channel, "MVM_NAME", vmu->fullname);
00891    pbx_builtin_setvar_helper(channel, "MVM_DUR", dur);
00892    pbx_builtin_setvar_helper(channel, "MVM_DOMAIN", vmu->domain);
00893    pbx_builtin_setvar_helper(channel, "MVM_USERNAME", vmu->username);
00894    pbx_builtin_setvar_helper(channel, "MVM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
00895    pbx_builtin_setvar_helper(channel, "MVM_CIDNAME", (cidname ? cidname : "an unknown caller"));
00896    pbx_builtin_setvar_helper(channel, "MVM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
00897    pbx_builtin_setvar_helper(channel, "MVM_DATE", date);
00898    if (!ast_strlen_zero(counter))
00899       pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
00900 }

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

Queue a message waiting event.

Definition at line 1771 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_strlen_zero(), context, and mailbox.

Referenced by minivm_mwi_exec().

01772 {
01773    struct ast_event *event;
01774    char *mailbox, *context;
01775 
01776    mailbox = ast_strdupa(mbx);
01777    context = ast_strdupa(ctx);
01778    if (ast_strlen_zero(context)) {
01779       context = "default";
01780    }
01781 
01782    if (!(event = ast_event_new(AST_EVENT_MWI,
01783          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
01784          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
01785          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
01786          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
01787          AST_EVENT_IE_END))) {
01788       return;
01789    }
01790 
01791    ast_event_queue_and_cache(event);
01792 }

static int reload ( void   )  [static]

Reload mini voicemail module.

Definition at line 3297 of file app_minivm.c.

References load_config().

03298 {
03299    return(load_config(1));
03300 }

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

Run external notification for voicemail message.

Definition at line 1510 of file app_minivm.c.

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

Referenced by notify_new_message().

01511 {
01512    char arguments[BUFSIZ];
01513 
01514    if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify))
01515       return;
01516 
01517    snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&", 
01518       ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify, 
01519       vmu->username, vmu->domain,
01520       chan->cid.cid_name, chan->cid.cid_num);
01521 
01522    ast_debug(1, "Executing: %s\n", arguments);
01523    ast_safe_system(arguments);
01524 }

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

Send voicemail with audio file as an attachment.

Definition at line 1027 of file app_minivm.c.

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

Referenced by notify_new_message().

01028 {
01029    FILE *p = NULL;
01030    int pfd;
01031    char email[256] = "";
01032    char who[256] = "";
01033    char date[256];
01034    char bound[256];
01035    char fname[PATH_MAX];
01036    char dur[PATH_MAX];
01037    char tmp[80] = "/tmp/astmail-XXXXXX";
01038    char tmp2[PATH_MAX];
01039    struct timeval now;
01040    struct ast_tm tm;
01041    struct minivm_zone *the_zone = NULL;
01042    int len_passdata;
01043    struct ast_channel *ast;
01044    char *finalfilename;
01045    char *passdata = NULL;
01046    char *passdata2 = NULL;
01047    char *fromaddress;
01048    char *fromemail;
01049 
01050    if (type == MVM_MESSAGE_EMAIL) {
01051       if (vmu && !ast_strlen_zero(vmu->email)) {
01052          ast_copy_string(email, vmu->email, sizeof(email)); 
01053       } else if (!ast_strlen_zero(vmu->username) && !ast_strlen_zero(vmu->domain))
01054          snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
01055    } else if (type == MVM_MESSAGE_PAGE) {
01056       ast_copy_string(email, vmu->pager, sizeof(email));
01057    }
01058 
01059    if (ast_strlen_zero(email)) {
01060       ast_log(LOG_WARNING, "No address to send message to.\n");
01061       return -1;  
01062    }
01063 
01064    ast_debug(3, "Sending mail to %s@%s - Using template %s\n", vmu->username, vmu->domain, template->name);
01065 
01066    if (!strcmp(format, "wav49"))
01067       format = "WAV";
01068 
01069 
01070    /* If we have a gain option, process it now with sox */
01071    if (type == MVM_MESSAGE_EMAIL && (vmu->volgain < -.001 || vmu->volgain > .001) ) {
01072       char newtmp[PATH_MAX];
01073       char tmpcmd[PATH_MAX];
01074       int tmpfd;
01075 
01076       ast_copy_string(newtmp, "/tmp/XXXXXX", sizeof(newtmp));
01077       ast_debug(3, "newtmp: %s\n", newtmp);
01078       tmpfd = mkstemp(newtmp);
01079       snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, filename, format, newtmp, format);
01080       ast_safe_system(tmpcmd);
01081       finalfilename = newtmp;
01082       ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->volgain, vmu->username);
01083    } else {
01084       finalfilename = ast_strdupa(filename);
01085    }
01086 
01087    /* Create file name */
01088    snprintf(fname, sizeof(fname), "%s.%s", finalfilename, format);
01089 
01090    if (template->attachment)
01091       ast_debug(1, "Attaching file '%s', format '%s', uservm is '%d'\n", finalfilename, format, attach_user_voicemail);
01092 
01093    /* Make a temporary file instead of piping directly to sendmail, in case the mail
01094       command hangs */
01095    pfd = mkstemp(tmp);
01096    if (pfd > -1) {
01097       p = fdopen(pfd, "w");
01098       if (!p) {
01099          close(pfd);
01100          pfd = -1;
01101       }
01102       ast_debug(1, "Opening temp file for e-mail: %s\n", tmp);
01103    }
01104    if (!p) {
01105       ast_log(LOG_WARNING, "Unable to open temporary file '%s'\n", tmp);
01106       return -1;
01107    }
01108    /* Allocate channel used for chanvar substitution */
01109    ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
01110 
01111 
01112    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
01113 
01114    /* Does this user have a timezone specified? */
01115    if (!ast_strlen_zero(vmu->zonetag)) {
01116       /* Find the zone in the list */
01117       struct minivm_zone *z;
01118       AST_LIST_LOCK(&minivm_zones);
01119       AST_LIST_TRAVERSE(&minivm_zones, z, list) {
01120          if (strcmp(z->name, vmu->zonetag)) 
01121             continue;
01122          the_zone = z;
01123       }
01124       AST_LIST_UNLOCK(&minivm_zones);
01125    }
01126 
01127    now = ast_tvnow();
01128    ast_localtime(&now, &tm, the_zone ? the_zone->timezone : NULL);
01129    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
01130 
01131    /* Start printing the email to the temporary file */
01132    fprintf(p, "Date: %s\n", date);
01133 
01134    /* Set date format for voicemail mail */
01135    ast_strftime(date, sizeof(date), template->dateformat, &tm);
01136 
01137 
01138    /* Populate channel with channel variables for substitution */
01139    prep_email_sub_vars(ast, vmu, cidnum, cidname, dur, date, counter);
01140 
01141    /* Find email address to use */
01142    /* If there's a server e-mail adress in the account, user that, othterwise template */
01143    fromemail = ast_strlen_zero(vmu->serveremail) ?  template->serveremail : vmu->serveremail;
01144 
01145    /* Find name to user for server e-mail */
01146    fromaddress = ast_strlen_zero(template->fromaddress) ? "" : template->fromaddress;
01147 
01148    /* If needed, add hostname as domain */
01149    if (ast_strlen_zero(fromemail))
01150       fromemail = "asterisk";
01151 
01152    if (strchr(fromemail, '@'))
01153       ast_copy_string(who, fromemail, sizeof(who));
01154    else  {
01155       char host[MAXHOSTNAMELEN];
01156       gethostname(host, sizeof(host)-1);
01157       snprintf(who, sizeof(who), "%s@%s", fromemail, host);
01158    }
01159 
01160    if (ast_strlen_zero(fromaddress)) {
01161       fprintf(p, "From: Asterisk PBX <%s>\n", who);
01162    } else {
01163       /* Allocate a buffer big enough for variable substitution */
01164       int vmlen = strlen(fromaddress) * 3 + 200;
01165 
01166       ast_debug(4, "Fromaddress template: %s\n", fromaddress);
01167       if ((passdata = alloca(vmlen))) {
01168          pbx_substitute_variables_helper(ast, fromaddress, passdata, vmlen);
01169          len_passdata = strlen(passdata) * 2 + 3;
01170          passdata2 = alloca(len_passdata);
01171          fprintf(p, "From: %s <%s>\n", mailheader_quote(passdata, passdata2, len_passdata), who);
01172       } else  {
01173          ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01174          fclose(p);
01175          return -1;  
01176       }
01177    } 
01178    ast_debug(4, "Fromstring now: %s\n", ast_strlen_zero(passdata) ? "-default-" : passdata);
01179 
01180    fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
01181    len_passdata = strlen(vmu->fullname) * 2 + 3;
01182    passdata2 = alloca(len_passdata);
01183    if (!ast_strlen_zero(vmu->email))
01184       fprintf(p, "To: %s <%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->email);
01185    else
01186       fprintf(p, "To: %s <%s@%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->username, vmu->domain);
01187 
01188    if (!ast_strlen_zero(template->subject)) {
01189       char *pass_data;
01190       int vmlen = strlen(template->subject) * 3 + 200;
01191       if ((pass_data = alloca(vmlen))) {
01192          pbx_substitute_variables_helper(ast, template->subject, pass_data, vmlen);
01193          fprintf(p, "Subject: %s\n", pass_data);
01194       } else {
01195          ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01196          fclose(p);
01197          return -1;  
01198       }
01199 
01200       ast_debug(4, "Subject now: %s\n", pass_data);
01201 
01202    } else  {
01203       fprintf(p, "Subject: New message in mailbox %s@%s\n", vmu->username, vmu->domain);
01204       ast_debug(1, "Using default subject for this email \n");
01205    }
01206 
01207 
01208    if (option_debug > 2)
01209       fprintf(p, "X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->username, vmu->domain);
01210    fprintf(p, "MIME-Version: 1.0\n");
01211 
01212    /* Something unique. */
01213    snprintf(bound, sizeof(bound), "voicemail_%s%d%d", vmu->username, (int)getpid(), (unsigned int)ast_random());
01214 
01215    fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
01216 
01217    fprintf(p, "--%s\n", bound);
01218    fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", global_charset);
01219    if (!ast_strlen_zero(template->body)) {
01220       char *pass_data;
01221       int vmlen = strlen(template->body)*3 + 200;
01222       if ((pass_data = alloca(vmlen))) {
01223          pbx_substitute_variables_helper(ast, template->body, pass_data, vmlen);
01224          ast_debug(3, "Message now: %s\n-----\n", pass_data);
01225          fprintf(p, "%s\n", pass_data);
01226       } else
01227          ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01228    } else {
01229       fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
01230 
01231          "in mailbox %s from %s, on %s so you might\n"
01232          "want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname, 
01233          dur,  vmu->username, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
01234       ast_debug(3, "Using default message body (no template)\n-----\n");
01235    }
01236    /* Eww. We want formats to tell us their own MIME type */
01237    if (template->attachment) {
01238       char *ctype = "audio/x-";
01239       ast_debug(3, "Attaching file to message: %s\n", fname);
01240       if (!strcasecmp(format, "ogg"))
01241          ctype = "application/";
01242    
01243       fprintf(p, "--%s\n", bound);
01244       fprintf(p, "Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
01245       fprintf(p, "Content-Transfer-Encoding: base64\n");
01246       fprintf(p, "Content-Description: Voicemail sound attachment.\n");
01247       fprintf(p, "Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter : "", format);
01248 
01249       base_encode(fname, p);
01250       fprintf(p, "\n\n--%s--\n.\n", bound);
01251    }
01252    fclose(p);
01253    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", global_mailcmd, tmp, tmp);
01254    ast_safe_system(tmp2);
01255    ast_debug(1, "Sent message to %s with command '%s' - %s\n", vmu->email, global_mailcmd, template->attachment ? "(media attachment)" : "");
01256    ast_debug(3, "Actual command used: %s\n", tmp2);
01257    if (ast)
01258       ast_channel_free(ast);
01259    return 0;
01260 }

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

Add time zone to memory list.

Definition at line 2411 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(), global_stats, LOG_WARNING, minivm_zone::msg_format, minivm_zone::name, minivm_zone::timezone, and minivm_stats::timezones.

Referenced by load_config().

02412 {
02413    struct minivm_zone *newzone;
02414    char *msg_format, *timezone_str;
02415 
02416    newzone = ast_calloc(1, sizeof(*newzone));
02417    if (newzone == NULL)
02418       return 0;
02419 
02420    msg_format = ast_strdupa(config);
02421    if (msg_format == NULL) {
02422       ast_log(LOG_WARNING, "Out of memory.\n");
02423       ast_free(newzone);
02424       return 0;
02425    }
02426 
02427    timezone_str = strsep(&msg_format, "|");
02428    if (!msg_format) {
02429       ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
02430       ast_free(newzone);
02431       return 0;
02432    }
02433          
02434    ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
02435    ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
02436    ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
02437 
02438    AST_LIST_LOCK(&minivm_zones);
02439    AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
02440    AST_LIST_UNLOCK(&minivm_zones);
02441 
02442    global_stats.timezones++;
02443 
02444    return 0;
02445 }

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

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

02400 {
02401    struct minivm_zone *this;
02402 
02403    AST_LIST_LOCK(&minivm_zones);
02404    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02405       free_zone(this);
02406       
02407    AST_LIST_UNLOCK(&minivm_zones);
02408 }

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

Delete media files and attribute file.

Definition at line 1365 of file app_minivm.c.

References ast_debug, and ast_filedelete().

Referenced by minivm_delete_exec(), and play_record_review().

01366 {
01367    int res;
01368 
01369    ast_debug(1, "Deleting voicemail file %s\n", file);
01370 
01371    res = unlink(file);  /* Remove the meta data file */
01372    res |=  ast_filedelete(file, NULL); /* remove the media file */
01373    return res;
01374 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

Referenced by access_counter_file().

03020 {
03021    switch (ast_lock_path(path)) {
03022    case AST_LOCK_TIMEOUT:
03023       return -1;
03024    default:
03025       return 0;
03026    }
03027 }

static void vmaccounts_destroy_list ( void   )  [static]

Clear list of users.

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

00945 {
00946    struct minivm_account *this;
00947    AST_LIST_LOCK(&minivm_accounts);
00948    while ((this = AST_LIST_REMOVE_HEAD(&minivm_accounts, list))) 
00949       ast_free(this);
00950    AST_LIST_UNLOCK(&minivm_accounts);
00951 }


Variable Documentation

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

Definition at line 3350 of file app_minivm.c.

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 453 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 452 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 450 of file app_minivm.c.

char* app_minivm_mwi = "MinivmMWI" [static]

Definition at line 454 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 451 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 449 of file app_minivm.c.

Definition at line 3350 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 3220 of file app_minivm.c.

Referenced by load_module(), and unload_module().

char default_vmformat[80] [static]
char global_charset[32] [static]

Global charset in messages

Definition at line 591 of file app_minivm.c.

Referenced by load_config(), and sendmail().

char global_externnotify[160] [static]

External notification application

Definition at line 585 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 586 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 584 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 582 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 581 of file app_minivm.c.

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

Definition at line 590 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 572 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 580 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 579 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 593 of file app_minivm.c.

Referenced by populate_defaults().

struct ast_flags globalflags = {0} [static]

Global voicemail flags

Definition at line 589 of file app_minivm.c.

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

struct ast_app_option minivm_accmess_options[128] = { [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 't' ] = { .flag = OPT_TEMP_GREETING }, [ 'n' ] = { .flag = OPT_NAME_GREETING },} [static]

Definition at line 484 of file app_minivm.c.

Referenced by minivm_accmess_exec().

Definition at line 3248 of file app_minivm.c.

Referenced by load_module(), and unload_module().

struct ast_app_option minivm_app_options[128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 },} [static]

Definition at line 477 of file app_minivm.c.

Referenced by minivm_greet_exec(), and minivm_record_exec().

Definition at line 3229 of file app_minivm.c.

Referenced by load_module(), and unload_module().

enum { ... } minivm_option_args
enum { ... } minivm_option_flags
ast_mutex_t minivmlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Lock to protect voicemail system

Definition at line 574 of file app_minivm.c.

Referenced by load_config().

The minivm log file

Definition at line 577 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

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

Lock to protect voicemail system log file

Definition at line 575 of file app_minivm.c.

Referenced by leave_voicemail().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 446 of file app_minivm.c.


Generated by  doxygen 1.6.2