Mon Oct 8 12:39:07 2012

Asterisk developer's documentation


app_minivm.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int access_counter_file (char *directory, char *countername, int value, int operand)
 Access counter file, lock directory, read and possibly write it again changed.
static int apply_general_options (struct ast_variable *var)
 Apply general configuration options.
static const char * ast_str_encode_mime (struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
static const char * ast_str_quote (struct ast_str **buf, ssize_t maxlen, const char *from)
static int b64_inbuf (struct b64_baseio *bio, FILE *fi)
static int b64_inchar (struct b64_baseio *bio, FILE *fi)
static int b64_ochar (struct b64_baseio *bio, int c, FILE *so)
static int base_encode (char *filename, FILE *so)
static int check_dirpath (char *dest, int len, char *domain, char *username, char *folder)
static int check_mime (const char *str)
static char * complete_minivm_show_users (const char *line, const char *word, int pos, int state)
static int create_dirpath (char *dest, int len, char *domain, char *username, char *folder)
static int create_vmaccount (char *name, struct ast_variable *var, int realtime)
 Append new mailbox to mailbox list from configuration file.
static struct minivm_accountfind_account (const char *domain, const char *username, int createtemp)
static struct minivm_accountfind_user_realtime (const char *domain, const char *username)
static void free_user (struct minivm_account *vmu)
static void free_zone (struct minivm_zone *z)
 Free Mini Voicemail timezone.
static int get_date (char *s, int len)
static char * handle_minivm_list_templates (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI routine for listing templates.
static char * handle_minivm_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload cofiguration.
static char * handle_minivm_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Show settings.
static char * handle_minivm_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show stats.
static char * handle_minivm_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list voicemail accounts.
static char * handle_minivm_show_zones (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail zones in the CLI.
static int invent_message (struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
static int leave_voicemail (struct ast_channel *chan, char *username, struct leave_vm_options *options)
static int load_config (int reload)
 Load minivoicemail configuration.
static int load_module (void)
 Load mini voicemail module.
static int make_dir (char *dest, int len, const char *domain, const char *username, const char *folder)
static void message_destroy_list (void)
static int message_template_build (const char *name, struct ast_variable *var)
static struct minivm_templatemessage_template_create (const char *name)
static struct minivm_templatemessage_template_find (const char *name)
static void message_template_free (struct minivm_template *template)
static char * message_template_parse_emailbody (const char *configuration)
 Parse emailbody template from configuration file.
static char * message_template_parse_filebody (const char *filename)
 Read message template from file.
static int minivm_accmess_exec (struct ast_channel *chan, const char *data)
 Record specific messages for voicemail account.
static int minivm_account_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${MINIVMACCOUNT()} Dialplan function - reads account data
static int minivm_counter_func_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${MINIVMCOUNTER()} Dialplan function - read counters
static int minivm_counter_func_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 ${MINIVMCOUNTER()} Dialplan function - changes counter data
static int minivm_delete_exec (struct ast_channel *chan, const char *data)
static int minivm_greet_exec (struct ast_channel *chan, const char *data)
static int minivm_mwi_exec (struct ast_channel *chan, const char *data)
static int minivm_notify_exec (struct ast_channel *chan, const char *data)
static int minivm_record_exec (struct ast_channel *chan, const char *data)
static struct minivm_accountmvm_user_alloc (void)
static int notify_new_message (struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct minivm_account *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain)
static void populate_defaults (struct minivm_account *vmu)
static void prep_email_sub_vars (struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
static void queue_mwi_event (const char *mbx, const char *ctx, int urgent, int new, int old)
static int reload (void)
 Reload mini voicemail module.
static void run_externnotify (struct ast_channel *chan, struct minivm_account *vmu)
 Run external notification for voicemail message.
static int sendmail (struct minivm_template *template, struct minivm_account *vmu, char *cidnum, char *cidname, const char *filename, char *format, int duration, int attach_user_voicemail, enum mvm_messagetype type, const char *counter)
static int timezone_add (const char *zonename, const char *config)
 Add time zone to memory list.
static void timezone_destroy_list (void)
 Clear list of timezones.
static int unload_module (void)
 Unload mini voicemail module.
static int vm_delete (char *file)
static int vm_lock_path (const char *path)
 lock directory
static void vmaccounts_destroy_list (void)

Variables

static 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, }
static char * app_minivm_accmess = "MinivmAccMess"
static char * app_minivm_delete = "MinivmDelete"
static char * app_minivm_greet = "MinivmGreet"
static char * app_minivm_mwi = "MinivmMWI"
static char * app_minivm_notify = "MinivmNotify"
static char * app_minivm_record = "MinivmRecord"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_minivm []
 CLI commands for Mini-voicemail.
static char default_vmformat [80]
static char global_externnotify [160]
static char global_logfile [PATH_MAX]
static char global_mailcmd [160]
static int global_maxgreet
static int global_maxsilence
static int global_saydurationminfo
static int global_silencethreshold = 128
static struct minivm_stats global_stats
 Statistics for voicemail.
static int global_vmmaxmessage
static int global_vmminmessage
static double global_volgain
static struct ast_flags globalflags = {0}
static struct ast_app_option minivm_accmess_options [128] = { [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 't' ] = { .flag = OPT_TEMP_GREETING }, [ 'n' ] = { .flag = OPT_NAME_GREETING },}
static struct ast_custom_function minivm_account_function
static struct ast_app_option minivm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 },}
static struct ast_custom_function minivm_counter_function
static ast_mutex_t minivmlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static FILE * minivmlogfile
static ast_mutex_t minivmloglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static char MVM_SPOOL_DIR [PATH_MAX]


Detailed Description

MiniVoiceMail - A Minimal Voicemail System for Asterisk.

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

See also

Definition in file app_minivm.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Default username for sending mail is asterisk@localhost

Definition at line 534 of file app_minivm.c.

Referenced by actual_load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 524 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 523 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 697 of file app_minivm.c.

Referenced by message_template_create().

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

Definition at line 696 of file app_minivm.c.

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 525 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100

Definition at line 530 of file app_minivm.c.

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

#define FALSE   0

Definition at line 506 of file app_minivm.c.

Referenced by __sip_ack(), __sip_semi_ack(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), AST_TEST_DEFINE(), ast_tzset(), build_peer(), cb_extensionstate(), cc_esc_publish_handler(), cc_handle_publish_error(), check_auth(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), do_monitor(), expire_register(), find_sdp(), function_sippeer(), handle_invite_replaces(), handle_request_invite(), handle_request_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(), pidf_validate_presence(), pidf_validate_tuple(), proc_session_timer(), process_crypto(), process_sdp(), process_sdp_a_audio(), process_sdp_a_image(), process_sdp_a_sendonly(), process_sdp_a_text(), process_sdp_a_video(), process_sdp_c(), process_sdp_o(), proxy_from_config(), proxy_update(), rcvfax_exec(), register_verify(), reload_config(), reqprep(), send_provisional_keepalive_full(), set_destination(), sip_addheader(), sip_answer(), sip_cc_monitor_request_cc(), sip_destroy_peer(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_is_xml_parsable(), sip_monitor_instance_destructor(), sip_parse_register_line(), sip_pidf_validate(), sip_poke_noanswer(), sip_prune_realtime(), sip_read(), sip_sendhtml(), sip_set_history(), sip_set_rtp_peer(), sip_set_udptl_peer(), sip_show_inuse(), sip_show_settings(), sip_show_user(), sip_show_users(), sndfax_exec(), stop_session_timer(), time1(), time2(), time2sub(), transmit_audio(), transmit_invite(), transmit_provisional_response(), transmit_publish(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_t38(), tzload(), tzparse(), update_call_counter(), and update_connectedline().

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

Referenced by handle_minivm_show_users().

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

Referenced by handle_minivm_show_zones().

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

Referenced by handle_minivm_list_templates().

#define MAX_DATETIME_FORMAT   512

Definition at line 527 of file app_minivm.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 528 of file app_minivm.c.

Referenced by actual_load_config(), and play_message_callerid().

#define MVM_ALLOCED   (1 << 13)

Definition at line 516 of file app_minivm.c.

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

#define MVM_ENVELOPE   (1 << 4)

Definition at line 514 of file app_minivm.c.

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

Definition at line 511 of file app_minivm.c.

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

#define MVM_PBXSKIP   (1 << 9)

Definition at line 515 of file app_minivm.c.

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 512 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)

Review message

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

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

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

Definition at line 520 of file app_minivm.c.

Referenced by actual_load_config(), and load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 522 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 503 of file app_minivm.c.

Referenced by __sip_ack(), __sip_autodestruct(), __sip_semi_ack(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), ast_tzset(), build_peer(), cc_esc_publish_handler(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), find_account(), find_sdp(), find_user_realtime(), function_sippeer(), get_sip_pvt_byid_locked(), gmtload(), handle_request_invite(), handle_request_notify(), handle_request_refer(), handle_response(), handle_response_invite(), handle_response_peerpoke(), interpret_t38_parameters(), leave_voicemail(), load_config(), local_attended_transfer(), manager_mutestream(), message_template_create(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), minivm_notify_exec(), parse_ok_contact(), parse_register_contact(), parse_sip_options(), pidf_validate_presence(), pidf_validate_tuple(), proc_session_timer(), process_crypto(), process_sdp(), process_sdp_a_audio(), process_sdp_a_image(), process_sdp_a_sendonly(), process_sdp_a_text(), process_sdp_a_video(), process_sdp_c(), process_sdp_o(), proxy_update(), rcvfax_exec(), reg_source_db(), register_verify(), reload_config(), reqprep(), respprep(), restart_session_timer(), set_destination(), sip_addheader(), sip_alloc(), sip_answer(), sip_cc_agent_respond(), sip_destroy(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_indicate(), sip_is_xml_parsable(), sip_park_thread(), sip_pidf_validate(), sip_prune_realtime(), sip_reload(), sip_request_call(), sip_scheddestroy(), sip_set_history(), sip_set_udptl_peer(), sip_show_channel(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_unregister(), sip_write(), sndfax_exec(), spandsp_fax_start(), st_get_se(), start_session_timer(), stop_session_timer(), temp_peer(), time1(), time2(), transmit_audio(), transmit_cc_notify(), transmit_invite(), transmit_publish(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_t38(), tzload(), and update_connectedline().

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 533 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

Definition at line 531 of file app_minivm.c.

Referenced by create_dirpath(), and leave_voicemail().


Enumeration Type Documentation

enum minivm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 564 of file app_minivm.c.

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

enum minivm_option_flags

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 555 of file app_minivm.c.

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

enum mvm_messagetype

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 537 of file app_minivm.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3582 of file app_minivm.c.

static void __unreg_module ( void   )  [static]

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

03297 {
03298    char filename[BUFSIZ];
03299    char readbuf[BUFSIZ];
03300    FILE *counterfile;
03301    int old = 0, counter = 0;
03302 
03303    /* Lock directory */
03304    if (vm_lock_path(directory)) {
03305       return -1;  /* Could not lock directory */
03306    }
03307    snprintf(filename, sizeof(filename), "%s/%s.counter", directory, countername);
03308    if (operand != 1) {
03309       counterfile = fopen(filename, "r");
03310       if (counterfile) {
03311          if(fgets(readbuf, sizeof(readbuf), counterfile)) {
03312             ast_debug(3, "Read this string from counter file: %s\n", readbuf);
03313             old = counter = atoi(readbuf);
03314          }
03315          fclose(counterfile);
03316       }
03317    }
03318    switch (operand) {
03319    case 0:  /* Read only */
03320       ast_unlock_path(directory);
03321       ast_debug(2, "MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
03322       return counter;
03323       break;
03324    case 1: /* Set new value */
03325       counter = value;
03326       break;
03327    case 2: /* Change value */
03328       counter += value;
03329       if (counter < 0)  /* Don't allow counters to fall below zero */
03330          counter = 0;
03331       break;
03332    }
03333    
03334    /* Now, write the new value to the file */
03335    counterfile = fopen(filename, "w");
03336    if (!counterfile) {
03337       ast_log(LOG_ERROR, "Could not open counter file for writing : %s - %s\n", filename, strerror(errno));
03338       ast_unlock_path(directory);
03339       return -1;  /* Could not open file for writing */
03340    }
03341    fprintf(counterfile, "%d\n\n", counter);
03342    fclose(counterfile);
03343    ast_unlock_path(directory);
03344    ast_debug(2, "MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
03345    return counter;
03346 }

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

Definition at line 2778 of file app_minivm.c.

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

Referenced by load_config().

02779 {
02780    int error = 0;
02781 
02782    while (var) {
02783       /* Mail command */
02784       if (!strcmp(var->name, "mailcmd")) {
02785          ast_copy_string(global_mailcmd, var->value, sizeof(global_mailcmd)); /* User setting */
02786       } else if (!strcmp(var->name, "maxgreet")) {
02787          global_maxgreet = atoi(var->value);
02788       } else if (!strcmp(var->name, "maxsilence")) {
02789          global_maxsilence = atoi(var->value);
02790          if (global_maxsilence > 0)
02791             global_maxsilence *= 1000;
02792       } else if (!strcmp(var->name, "logfile")) {
02793          if (!ast_strlen_zero(var->value) ) {
02794             if(*(var->value) == '/')
02795                ast_copy_string(global_logfile, var->value, sizeof(global_logfile));
02796             else
02797                snprintf(global_logfile, sizeof(global_logfile), "%s/%s", ast_config_AST_LOG_DIR, var->value);
02798          }
02799       } else if (!strcmp(var->name, "externnotify")) {
02800          /* External voicemail notify application */
02801          ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
02802       } else if (!strcmp(var->name, "silencetreshold")) {
02803          /* Silence treshold */
02804          global_silencethreshold = atoi(var->value);
02805       } else if (!strcmp(var->name, "maxmessage")) {
02806          int x;
02807          if (sscanf(var->value, "%30d", &x) == 1) {
02808             global_vmmaxmessage = x;
02809          } else {
02810             error ++;
02811             ast_log(LOG_WARNING, "Invalid max message time length\n");
02812          }
02813       } else if (!strcmp(var->name, "minmessage")) {
02814          int x;
02815          if (sscanf(var->value, "%30d", &x) == 1) {
02816             global_vmminmessage = x;
02817             if (global_maxsilence <= global_vmminmessage)
02818                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
02819          } else {
02820             error ++;
02821             ast_log(LOG_WARNING, "Invalid min message time length\n");
02822          }
02823       } else if (!strcmp(var->name, "format")) {
02824          ast_copy_string(default_vmformat, var->value, sizeof(default_vmformat));
02825       } else if (!strcmp(var->name, "review")) {
02826          ast_set2_flag((&globalflags), ast_true(var->value), MVM_REVIEW);  
02827       } else if (!strcmp(var->name, "operator")) {
02828          ast_set2_flag((&globalflags), ast_true(var->value), MVM_OPERATOR);   
02829       }
02830       var = var->next;
02831    }
02832    return error;
02833 }

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

Definition at line 1158 of file app_minivm.c.

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

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

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

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

Definition at line 1200 of file app_minivm.c.

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

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

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

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

Definition at line 836 of file app_minivm.c.

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

Referenced by b64_inchar().

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

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

Definition at line 859 of file app_minivm.c.

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

Referenced by base_encode().

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

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

Definition at line 871 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

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

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

Definition at line 890 of file app_minivm.c.

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

Referenced by add_email_attachment(), and sendmail().

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

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

Definition at line 1507 of file app_minivm.c.

References FALSE, make_dir(), and TRUE.

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

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

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

Definition at line 1129 of file app_minivm.c.

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

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

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

Definition at line 3017 of file app_minivm.c.

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

Referenced by handle_minivm_show_users().

03018 {
03019    int which = 0;
03020    int wordlen;
03021    struct minivm_account *vmu;
03022    const char *domain = "";
03023 
03024    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
03025    if (pos > 4)
03026       return NULL;
03027    if (pos == 3)
03028       return (state == 0) ? ast_strdup("for") : NULL;
03029    wordlen = strlen(word);
03030    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
03031       if (!strncasecmp(word, vmu->domain, wordlen)) {
03032          if (domain && strcmp(domain, vmu->domain) && ++which > state)
03033             return ast_strdup(vmu->domain);
03034          /* ignore repeated domains ? */
03035          domain = vmu->domain;
03036       }
03037    }
03038    return NULL;
03039 }

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

Definition at line 1526 of file app_minivm.c.

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

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

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

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

References ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), minivm_account::domain, global_stats, minivm_account::list, LOG_ERROR, ast_variable::next, populate_defaults(), minivm_account::username, var, and minivm_stats::voicemailaccounts.

Referenced by find_user_realtime(), and load_config().

02563 {
02564    struct minivm_account *vmu;
02565    char *domain;
02566    char *username;
02567    char accbuf[BUFSIZ];
02568 
02569    ast_debug(3, "Creating %s account for [%s]\n", realtime ? "realtime" : "static", name);
02570 
02571    ast_copy_string(accbuf, name, sizeof(accbuf));
02572    username = accbuf;
02573    domain = strchr(accbuf, '@');
02574    if (domain) {
02575       *domain = '\0';
02576       domain++;
02577    }
02578    if (ast_strlen_zero(domain)) {
02579       ast_log(LOG_ERROR, "No domain given for mini-voicemail account %s. Not configured.\n", name);
02580       return 0;
02581    }
02582 
02583    ast_debug(3, "Creating static account for user %s domain %s\n", username, domain);
02584 
02585    /* Allocate user account */
02586    vmu = ast_calloc(1, sizeof(*vmu));
02587    if (!vmu)
02588       return 0;
02589    
02590    ast_copy_string(vmu->domain, domain, sizeof(vmu->domain));
02591    ast_copy_string(vmu->username, username, sizeof(vmu->username));
02592 
02593    populate_defaults(vmu);
02594 
02595    ast_debug(3, "...Configuring account %s\n", name);
02596 
02597    while (var) {
02598       ast_debug(3, "Configuring %s = \"%s\" for account %s\n", var->name, var->value, name);
02599       if (!strcasecmp(var->name, "serveremail")) {
02600          ast_copy_string(vmu->serveremail, var->value, sizeof(vmu->serveremail));
02601       } else if (!strcasecmp(var->name, "email")) {
02602          ast_copy_string(vmu->email, var->value, sizeof(vmu->email));
02603       } else if (!strcasecmp(var->name, "accountcode")) {
02604          ast_copy_string(vmu->accountcode, var->value, sizeof(vmu->accountcode));
02605       } else if (!strcasecmp(var->name, "pincode")) {
02606          ast_copy_string(vmu->pincode, var->value, sizeof(vmu->pincode));
02607       } else if (!strcasecmp(var->name, "domain")) {
02608          ast_copy_string(vmu->domain, var->value, sizeof(vmu->domain));
02609       } else if (!strcasecmp(var->name, "language")) {
02610          ast_copy_string(vmu->language, var->value, sizeof(vmu->language));
02611       } else if (!strcasecmp(var->name, "timezone")) {
02612          ast_copy_string(vmu->zonetag, var->value, sizeof(vmu->zonetag));
02613       } else if (!strcasecmp(var->name, "externnotify")) {
02614          ast_copy_string(vmu->externnotify, var->value, sizeof(vmu->externnotify));
02615       } else if (!strcasecmp(var->name, "etemplate")) {
02616          ast_copy_string(vmu->etemplate, var->value, sizeof(vmu->etemplate));
02617       } else if (!strcasecmp(var->name, "ptemplate")) {
02618          ast_copy_string(vmu->ptemplate, var->value, sizeof(vmu->ptemplate));
02619       } else if (!strcasecmp(var->name, "fullname")) {
02620          ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
02621       } else if (!strcasecmp(var->name, "setvar")) {
02622          char *varval;
02623          char *varname = ast_strdupa(var->value);
02624          struct ast_variable *tmpvar;
02625 
02626          if (varname && (varval = strchr(varname, '='))) {
02627             *varval = '\0';
02628             varval++;
02629             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
02630                tmpvar->next = vmu->chanvars;
02631                vmu->chanvars = tmpvar;
02632             }
02633          }
02634       } else if (!strcasecmp(var->name, "pager")) {
02635          ast_copy_string(vmu->pager, var->value, sizeof(vmu->pager));
02636       } else if (!strcasecmp(var->name, "volgain")) {
02637          sscanf(var->value, "%30lf", &vmu->volgain);
02638       } else {
02639          ast_log(LOG_ERROR, "Unknown configuration option for minivm account %s : %s\n", name, var->name);
02640       }
02641       var = var->next;
02642    }
02643    ast_debug(3, "...Linking account %s\n", name);
02644    
02645    AST_LIST_LOCK(&minivm_accounts);
02646    AST_LIST_INSERT_TAIL(&minivm_accounts, vmu, list);
02647    AST_LIST_UNLOCK(&minivm_accounts);
02648 
02649    global_stats.voicemailaccounts++;
02650 
02651    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)" : "");
02652    return 0;
02653 }

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

Definition at line 1052 of file app_minivm.c.

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

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

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

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

Definition at line 1096 of file app_minivm.c.

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

Referenced by find_account(), and find_user().

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

static void free_user ( struct minivm_account vmu  )  [static]

Definition at line 974 of file app_minivm.c.

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

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

00975 {
00976    if (vmu->chanvars)
00977       ast_variables_destroy(vmu->chanvars);
00978    ast_free(vmu);
00979 }

static void free_zone ( struct minivm_zone z  )  [static]

Free Mini Voicemail timezone.

Definition at line 2656 of file app_minivm.c.

References ast_free.

Referenced by free_vm_zones(), and timezone_destroy_list().

02657 {
02658    ast_free(z);
02659 }

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

Definition at line 962 of file app_minivm.c.

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

Referenced by leave_voicemail(), and tds_log().

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

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

CLI routine for listing templates.

Definition at line 2976 of file app_minivm.c.

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

02977 {
02978    struct minivm_template *this;
02979 #define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
02980    int count = 0;
02981 
02982    switch (cmd) {
02983    case CLI_INIT:
02984       e->command = "minivm list templates";
02985       e->usage =
02986          "Usage: minivm list templates\n"
02987          "       Lists message templates for e-mail, paging and IM\n";
02988       return NULL;
02989    case CLI_GENERATE:
02990       return NULL;
02991    }
02992 
02993    if (a->argc > 3)
02994       return CLI_SHOWUSAGE;
02995 
02996    AST_LIST_LOCK(&message_templates);
02997    if (AST_LIST_EMPTY(&message_templates)) {
02998       ast_cli(a->fd, "There are no message templates defined\n");
02999       AST_LIST_UNLOCK(&message_templates);
03000       return CLI_FAILURE;
03001    }
03002    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "Template name", "Charset", "Locale", "Attach media", "Subject");
03003    ast_cli(a->fd, HVLT_OUTPUT_FORMAT, "-------------", "-------", "------", "------------", "-------");
03004    AST_LIST_TRAVERSE(&message_templates, this, list) {
03005       ast_cli(a->fd, HVLT_OUTPUT_FORMAT, this->name, 
03006          this->charset ? this->charset : "-", 
03007          this->locale ? this->locale : "-",
03008          this->attachment ? "Yes" : "No",
03009          this->subject ? this->subject : "-");
03010       count++;
03011    }
03012    AST_LIST_UNLOCK(&message_templates);
03013    ast_cli(a->fd, "\n * Total: %d minivoicemail message templates\n", count);
03014    return CLI_SUCCESS;
03015 }

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

Reload cofiguration.

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

03536 {
03537    
03538    switch (cmd) {
03539    case CLI_INIT:
03540       e->command = "minivm reload";
03541       e->usage =
03542          "Usage: minivm reload\n"
03543          "       Reload mini-voicemail configuration and reset statistics\n";
03544       return NULL;
03545    case CLI_GENERATE:
03546       return NULL;
03547    }
03548    
03549    reload();
03550    ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
03551    return CLI_SUCCESS;
03552 }

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

03128 {
03129    switch (cmd) {
03130    case CLI_INIT:
03131       e->command = "minivm show settings";
03132       e->usage =
03133          "Usage: minivm show settings\n"
03134          "       Display Mini-Voicemail general settings\n";
03135       return NULL;
03136    case CLI_GENERATE:
03137       return NULL;
03138    }
03139 
03140    ast_cli(a->fd, "* Mini-Voicemail general settings\n");
03141    ast_cli(a->fd, "  -------------------------------\n");
03142    ast_cli(a->fd, "\n");
03143    ast_cli(a->fd, "  Mail command (shell):               %s\n", global_mailcmd);
03144    ast_cli(a->fd, "  Max silence:                        %d\n", global_maxsilence);
03145    ast_cli(a->fd, "  Silence threshold:                  %d\n", global_silencethreshold);
03146    ast_cli(a->fd, "  Max message length (secs):          %d\n", global_vmmaxmessage);
03147    ast_cli(a->fd, "  Min message length (secs):          %d\n", global_vmminmessage);
03148    ast_cli(a->fd, "  Default format:                     %s\n", default_vmformat);
03149    ast_cli(a->fd, "  Extern notify (shell):              %s\n", global_externnotify);
03150    ast_cli(a->fd, "  Logfile:                            %s\n", global_logfile[0] ? global_logfile : "<disabled>");
03151    ast_cli(a->fd, "  Operator exit:                      %s\n", ast_test_flag(&globalflags, MVM_OPERATOR) ? "Yes" : "No");
03152    ast_cli(a->fd, "  Message review:                     %s\n", ast_test_flag(&globalflags, MVM_REVIEW) ? "Yes" : "No");
03153 
03154    ast_cli(a->fd, "\n");
03155    return CLI_SUCCESS;
03156 }

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

Show stats.

Definition at line 3159 of file app_minivm.c.

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

03160 {
03161    struct ast_tm timebuf;
03162    char buf[BUFSIZ];
03163 
03164    switch (cmd) {
03165    
03166    case CLI_INIT:
03167       e->command = "minivm show stats";
03168       e->usage =
03169          "Usage: minivm show stats\n"
03170          "       Display Mini-Voicemail counters\n";
03171       return NULL;
03172    case CLI_GENERATE:
03173       return NULL;
03174    }
03175 
03176    ast_cli(a->fd, "* Mini-Voicemail statistics\n");
03177    ast_cli(a->fd, "  -------------------------\n");
03178    ast_cli(a->fd, "\n");
03179    ast_cli(a->fd, "  Voicemail accounts:                  %5d\n", global_stats.voicemailaccounts);
03180    ast_cli(a->fd, "  Templates:                           %5d\n", global_stats.templates);
03181    ast_cli(a->fd, "  Timezones:                           %5d\n", global_stats.timezones);
03182    if (global_stats.receivedmessages == 0) {
03183       ast_cli(a->fd, "  Received messages since last reset:  <none>\n");
03184    } else {
03185       ast_cli(a->fd, "  Received messages since last reset:  %d\n", global_stats.receivedmessages);
03186       ast_localtime(&global_stats.lastreceived, &timebuf, NULL);
03187       ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
03188       ast_cli(a->fd, "  Last received voicemail:             %s\n", buf);
03189    }
03190    ast_localtime(&global_stats.reset, &timebuf, NULL);
03191    ast_strftime(buf, sizeof(buf), "%a %b %e %r %Z %Y", &timebuf);
03192    ast_cli(a->fd, "  Last reset:                          %s\n", buf);
03193 
03194    ast_cli(a->fd, "\n");
03195    return CLI_SUCCESS;
03196 }

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

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

03043 {
03044    struct minivm_account *vmu;
03045 #define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
03046    int count = 0;
03047 
03048    switch (cmd) {
03049    case CLI_INIT:
03050       e->command = "minivm list accounts";
03051       e->usage =
03052          "Usage: minivm list accounts\n"
03053          "       Lists all mailboxes currently set up\n";
03054       return NULL;
03055    case CLI_GENERATE:
03056       return complete_minivm_show_users(a->line, a->word, a->pos, a->n);
03057    }
03058 
03059    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
03060       return CLI_SHOWUSAGE;
03061    if ((a->argc == 5) && strcmp(a->argv[3],"for"))
03062       return CLI_SHOWUSAGE;
03063 
03064    AST_LIST_LOCK(&minivm_accounts);
03065    if (AST_LIST_EMPTY(&minivm_accounts)) {
03066       ast_cli(a->fd, "There are no voicemail users currently defined\n");
03067       AST_LIST_UNLOCK(&minivm_accounts);
03068       return CLI_FAILURE;
03069    }
03070    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "User", "E-Template", "P-template", "Zone", "Format", "Full name");
03071    ast_cli(a->fd, HMSU_OUTPUT_FORMAT, "----", "----------", "----------", "----", "------", "---------");
03072    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
03073       char tmp[256] = "";
03074       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(a->argv[4], vmu->domain))) {
03075          count++;
03076          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->username, vmu->domain);
03077          ast_cli(a->fd, HMSU_OUTPUT_FORMAT, tmp, vmu->etemplate ? vmu->etemplate : "-", 
03078             vmu->ptemplate ? vmu->ptemplate : "-",
03079             vmu->zonetag ? vmu->zonetag : "-", 
03080             vmu->attachfmt ? vmu->attachfmt : "-",
03081             vmu->fullname);
03082       }
03083    }
03084    AST_LIST_UNLOCK(&minivm_accounts);
03085    ast_cli(a->fd, "\n * Total: %d minivoicemail accounts\n", count);
03086    return CLI_SUCCESS;
03087 }

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

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

03091 {
03092    struct minivm_zone *zone;
03093 #define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
03094    char *res = CLI_SUCCESS;
03095 
03096    switch (cmd) {
03097    case CLI_INIT:
03098       e->command = "minivm list zones";
03099       e->usage =
03100          "Usage: minivm list zones\n"
03101          "       Lists zone message formats\n";
03102       return NULL;
03103    case CLI_GENERATE:
03104       return NULL;
03105    }
03106 
03107    if (a->argc != e->args)
03108       return CLI_SHOWUSAGE;
03109 
03110    AST_LIST_LOCK(&minivm_zones);
03111    if (!AST_LIST_EMPTY(&minivm_zones)) {
03112       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
03113       ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, "----", "--------", "--------------");
03114       AST_LIST_TRAVERSE(&minivm_zones, zone, list) {
03115          ast_cli(a->fd, HMSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
03116       }
03117    } else {
03118       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
03119       res = CLI_FAILURE;
03120    }
03121    AST_LIST_UNLOCK(&minivm_zones);
03122 
03123    return res;
03124 }

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

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

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

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

Definition at line 1846 of file app_minivm.c.

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

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

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

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2836 of file app_minivm.c.

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

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

static int load_module ( void   )  [static]

Load mini voicemail module.

Definition at line 3501 of file app_minivm.c.

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

03502 {
03503    int res;
03504 
03505    res = ast_register_application_xml(app_minivm_record, minivm_record_exec);
03506    res = ast_register_application_xml(app_minivm_greet, minivm_greet_exec);
03507    res = ast_register_application_xml(app_minivm_notify, minivm_notify_exec);
03508    res = ast_register_application_xml(app_minivm_delete, minivm_delete_exec);
03509    res = ast_register_application_xml(app_minivm_accmess, minivm_accmess_exec);
03510    res = ast_register_application_xml(app_minivm_mwi, minivm_mwi_exec);
03511 
03512    ast_custom_function_register(&minivm_account_function);
03513    ast_custom_function_register(&minivm_counter_function);
03514    if (res)
03515       return(res);
03516 
03517    if ((res = load_config(0)))
03518       return(res);
03519 
03520    ast_cli_register_multiple(cli_minivm, ARRAY_LEN(cli_minivm));
03521 
03522    /* compute the location of the voicemail spool directory */
03523    snprintf(MVM_SPOOL_DIR, sizeof(MVM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
03524 
03525    return res;
03526 }

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

Definition at line 1493 of file app_minivm.c.

References ast_strlen_zero().

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

01494 {
01495    return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
01496 }

static void message_destroy_list ( void   )  [static]

Definition at line 823 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

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

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

Definition at line 738 of file app_minivm.c.

References ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_true(), global_stats, minivm_account::list, LOG_ERROR, message_template_create(), message_template_parse_emailbody(), message_template_parse_filebody(), minivm_stats::templates, and var.

Referenced by load_config().

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

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

Definition at line 708 of file app_minivm.c.

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

Referenced by message_template_build().

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

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

Definition at line 801 of file app_minivm.c.

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

Referenced by load_config(), and notify_new_message().

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

static void message_template_free ( struct minivm_template template  )  [static]

Definition at line 728 of file app_minivm.c.

References ast_free, and minivm_template::body.

Referenced by message_destroy_list().

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

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

Parse emailbody template from configuration file.

Definition at line 2751 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02752 {
02753    char *tmpread, *tmpwrite;
02754    char *emailbody = ast_strdup(configuration);
02755 
02756    /* substitute strings \t and \n into the apropriate characters */
02757    tmpread = tmpwrite = emailbody;
02758    while ((tmpwrite = strchr(tmpread,'\\'))) {
02759           int len = strlen("\n");
02760           switch (tmpwrite[1]) {
02761           case 'n':
02762             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02763             strncpy(tmpwrite, "\n", len);
02764             break;
02765           case 't':
02766             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02767             strncpy(tmpwrite, "\t", len);
02768             break;
02769           default:
02770             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02771           }
02772           tmpread = tmpwrite + len;
02773    }
02774    return emailbody; 
02775 }

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

Read message template from file.

Definition at line 2711 of file app_minivm.c.

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

Referenced by message_template_build().

02711                                                                    {
02712    char buf[BUFSIZ * 6];
02713    char readbuf[BUFSIZ];
02714    char filenamebuf[BUFSIZ];
02715    char *writepos;
02716    char *messagebody;
02717    FILE *fi;
02718    int lines = 0;
02719 
02720    if (ast_strlen_zero(filename))
02721       return NULL;
02722    if (*filename == '/') 
02723       ast_copy_string(filenamebuf, filename, sizeof(filenamebuf));
02724    else 
02725       snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
02726 
02727    if (!(fi = fopen(filenamebuf, "r"))) {
02728       ast_log(LOG_ERROR, "Can't read message template from file: %s\n", filenamebuf);
02729       return NULL;
02730    }
02731    writepos = buf;
02732    while (fgets(readbuf, sizeof(readbuf), fi)) {
02733       lines ++;
02734       if (writepos != buf) {
02735          *writepos = '\n';    /* Replace EOL with new line */
02736          writepos++;
02737       }
02738       ast_copy_string(writepos, readbuf, sizeof(buf) - (writepos - buf));
02739       writepos += strlen(readbuf) - 1;
02740    }
02741    fclose(fi);
02742    messagebody = ast_calloc(1, strlen(buf + 1));
02743    ast_copy_string(messagebody, buf, strlen(buf) + 1);
02744    ast_debug(4, "---> Size of allocation %d\n", (int) strlen(buf + 1) );
02745    ast_debug(4, "---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
02746 
02747    return messagebody;
02748 }

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

Record specific messages for voicemail account.

Definition at line 2459 of file app_minivm.c.

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

Referenced by load_module().

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

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

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

03200 {
03201    struct minivm_account *vmu;
03202    char *username, *domain, *colname;
03203 
03204    if (!(username = ast_strdupa(data))) {
03205       ast_log(LOG_ERROR, "Memory Error!\n");
03206       return -1;
03207    }
03208 
03209    if ((colname = strchr(username, ':'))) {
03210       *colname = '\0';
03211       colname++;
03212    } else {
03213       colname = "path";
03214    }
03215    if ((domain = strchr(username, '@'))) {
03216       *domain = '\0';
03217       domain++;
03218    }
03219    if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
03220       ast_log(LOG_ERROR, "This function needs a username and a domain: username@domain\n");
03221       return 0;
03222    }
03223 
03224    if (!(vmu = find_account(domain, username, TRUE)))
03225       return 0;
03226 
03227    if (!strcasecmp(colname, "hasaccount")) {
03228       ast_copy_string(buf, (ast_test_flag(vmu, MVM_ALLOCED) ? "0" : "1"), len);
03229    } else  if (!strcasecmp(colname, "fullname")) { 
03230       ast_copy_string(buf, vmu->fullname, len);
03231    } else  if (!strcasecmp(colname, "email")) { 
03232       if (!ast_strlen_zero(vmu->email))
03233          ast_copy_string(buf, vmu->email, len);
03234       else
03235          snprintf(buf, len, "%s@%s", vmu->username, vmu->domain);
03236    } else  if (!strcasecmp(colname, "pager")) { 
03237       ast_copy_string(buf, vmu->pager, len);
03238    } else  if (!strcasecmp(colname, "etemplate")) { 
03239       if (!ast_strlen_zero(vmu->etemplate))
03240          ast_copy_string(buf, vmu->etemplate, len);
03241       else
03242          ast_copy_string(buf, "email-default", len);
03243    } else  if (!strcasecmp(colname, "language")) { 
03244       ast_copy_string(buf, vmu->language, len);
03245    } else  if (!strcasecmp(colname, "timezone")) { 
03246       ast_copy_string(buf, vmu->zonetag, len);
03247    } else  if (!strcasecmp(colname, "ptemplate")) { 
03248       if (!ast_strlen_zero(vmu->ptemplate))
03249          ast_copy_string(buf, vmu->ptemplate, len);
03250       else
03251          ast_copy_string(buf, "email-default", len);
03252    } else  if (!strcasecmp(colname, "accountcode")) {
03253       ast_copy_string(buf, vmu->accountcode, len);
03254    } else  if (!strcasecmp(colname, "pincode")) {
03255       ast_copy_string(buf, vmu->pincode, len);
03256    } else  if (!strcasecmp(colname, "path")) {
03257       check_dirpath(buf, len, vmu->domain, vmu->username, NULL);
03258    } else { /* Look in channel variables */
03259       struct ast_variable *var;
03260 
03261       for (var = vmu->chanvars ; var ; var = var->next)
03262          if (!strcmp(var->name, colname)) {
03263             ast_copy_string(buf, var->value, len);
03264             break;
03265          }
03266    }
03267 
03268    if(ast_test_flag(vmu, MVM_ALLOCED))
03269       free_user(vmu);
03270 
03271    return 0;
03272 }

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

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

03350 {
03351    char *username, *domain, *countername;
03352    struct minivm_account *vmu = NULL;
03353    char userpath[BUFSIZ];
03354    int res;
03355 
03356    *buf = '\0';
03357 
03358    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
03359       ast_log(LOG_WARNING, "Memory error!\n");
03360       return -1;
03361    }
03362    if ((countername = strchr(username, ':'))) {
03363       *countername = '\0';
03364       countername++;
03365    } 
03366 
03367    if ((domain = strchr(username, '@'))) {
03368       *domain = '\0';
03369       domain++;
03370    }
03371 
03372    /* If we have neither username nor domain now, let's give up */
03373    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03374       ast_log(LOG_ERROR, "No account given\n");
03375       return -1;
03376    }
03377 
03378    if (ast_strlen_zero(countername)) {
03379       ast_log(LOG_ERROR, "This function needs two arguments: Account:countername\n");
03380       return -1;
03381    }
03382 
03383    /* We only have a domain, no username */
03384    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03385       domain = username;
03386       username = NULL;
03387    }
03388 
03389    /* If we can't find account or if the account is temporary, return. */
03390    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
03391       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
03392       return 0;
03393    }
03394 
03395    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
03396 
03397    /* We have the path, now read the counter file */
03398    res = access_counter_file(userpath, countername, 0, 0);
03399    if (res >= 0)
03400       snprintf(buf, len, "%d", res);
03401    return 0;
03402 }

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

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

03406 {
03407    char *username, *domain, *countername, *operand;
03408    char userpath[BUFSIZ];
03409    struct minivm_account *vmu;
03410    int change = 0;
03411    int operation = 0;
03412 
03413    if(!value)
03414       return -1;
03415    change = atoi(value);
03416 
03417    if (!(username = ast_strdupa(data))) { /* Copy indata to local buffer */
03418       ast_log(LOG_WARNING, "Memory error!\n");
03419       return -1;
03420    }
03421 
03422    if ((countername = strchr(username, ':'))) {
03423       *countername = '\0';
03424       countername++;
03425    } 
03426    if ((operand = strchr(countername, ':'))) {
03427       *operand = '\0';
03428       operand++;
03429    } 
03430 
03431    if ((domain = strchr(username, '@'))) {
03432       *domain = '\0';
03433       domain++;
03434    }
03435 
03436    /* If we have neither username nor domain now, let's give up */
03437    if (ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03438       ast_log(LOG_ERROR, "No account given\n");
03439       return -1;
03440    }
03441 
03442    /* We only have a domain, no username */
03443    if (!ast_strlen_zero(username) && ast_strlen_zero(domain)) {
03444       domain = username;
03445       username = NULL;
03446    }
03447 
03448    if (ast_strlen_zero(operand) || ast_strlen_zero(countername)) {
03449       ast_log(LOG_ERROR, "Writing to this function requires three arguments: Account:countername:operand\n");
03450       return -1;
03451    }
03452 
03453    /* If we can't find account or if the account is temporary, return. */
03454    if (!ast_strlen_zero(username) && !(vmu = find_account(domain, username, FALSE))) {
03455       ast_log(LOG_ERROR, "Minivm account does not exist: %s@%s\n", username, domain);
03456       return 0;
03457    }
03458 
03459    create_dirpath(userpath, sizeof(userpath), domain, username, NULL);
03460    /* Now, find out our operator */
03461    if (*operand == 'i') /* Increment */
03462       operation = 2;
03463    else if (*operand == 'd') {
03464       change = change * -1;
03465       operation = 2;
03466    } else if (*operand == 's')
03467       operation = 1;
03468    else {
03469       ast_log(LOG_ERROR, "Unknown operator: %s\n", operand);
03470       return -1;
03471    }
03472 
03473    /* We have the path, now read the counter file */
03474    access_counter_file(userpath, countername, change, operation);
03475    return 0;
03476 }

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

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

02422 {
02423    int res = 0;
02424    char filename[BUFSIZ];
02425 
02426    if (!ast_strlen_zero(data)) {
02427       ast_copy_string(filename, (char *) data, sizeof(filename));
02428    } else {
02429       ast_channel_lock(chan);
02430       ast_copy_string(filename, pbx_builtin_getvar_helper(chan, "MVM_FILENAME"), sizeof(filename));
02431       ast_channel_unlock(chan);
02432    }
02433 
02434    if (ast_strlen_zero(filename)) {
02435       ast_log(LOG_ERROR, "No filename given in application arguments or channel variable MVM_FILENAME\n");
02436       return res;
02437    } 
02438 
02439    /* Go ahead and delete audio files from system, they're not needed any more */
02440    /* We should look for both audio and text files here */
02441    if (ast_fileexists(filename, NULL, NULL) > 0) {
02442       res = vm_delete(filename);
02443       if (res) {
02444          ast_debug(2, "Can't delete file: %s\n", filename);
02445          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02446       } else {
02447          ast_debug(2, "Deleted voicemail file :: %s \n", filename);
02448          pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "SUCCESS");
02449       }
02450    } else {
02451       ast_debug(2, "Filename does not exist: %s\n", filename);
02452       pbx_builtin_setvar_helper(chan, "MVM_DELETE_STATUS", "FAILED");
02453    }
02454 
02455    return res;
02456 }

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

Definition at line 2225 of file app_minivm.c.

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

Referenced by load_module().

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

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

Definition at line 2043 of file app_minivm.c.

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

Referenced by load_module().

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

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

Definition at line 2085 of file app_minivm.c.

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

Referenced by load_module().

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

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

Definition at line 2168 of file app_minivm.c.

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

Referenced by load_module().

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

static struct minivm_account* mvm_user_alloc ( void   )  [static]

Definition at line 1025 of file app_minivm.c.

References ast_calloc, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

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

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

Definition at line 1766 of file app_minivm.c.

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

Referenced by copy_message(), and minivm_notify_exec().

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

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

Definition at line 1613 of file app_minivm.c.

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

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

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

static void populate_defaults ( struct minivm_account vmu  )  [static]

Definition at line 1016 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 actual_load_config(), append_mailbox(), AST_TEST_DEFINE(), create_vmaccount(), find_user_realtime(), and mvm_user_alloc().

01017 {
01018    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
01019    ast_copy_string(vmu->attachfmt, default_vmformat, sizeof(vmu->attachfmt));
01020    vmu->volgain = global_volgain;
01021 }

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

Definition at line 987 of file app_minivm.c.

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

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

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

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

Definition at line 2018 of file app_minivm.c.

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

Referenced by append_mailbox(), minivm_mwi_exec(), notify_new_message(), poll_subscribed_mailbox(), and vm_execmain().

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

static int reload ( void   )  [static]

Reload mini voicemail module.

Definition at line 3529 of file app_minivm.c.

References load_config().

03530 {
03531    return(load_config(1));
03532 }

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

Run external notification for voicemail message.

Definition at line 1745 of file app_minivm.c.

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

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

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

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

Definition at line 1220 of file app_minivm.c.

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

Referenced by forward_message(), and notify_new_message().

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

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

Add time zone to memory list.

Definition at line 2674 of file app_minivm.c.

References ast_calloc, ast_copy_string(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strdupa, global_stats, minivm_account::list, LOG_WARNING, strsep(), and minivm_stats::timezones.

Referenced by load_config().

02675 {
02676    struct minivm_zone *newzone;
02677    char *msg_format, *timezone_str;
02678 
02679    newzone = ast_calloc(1, sizeof(*newzone));
02680    if (newzone == NULL)
02681       return 0;
02682 
02683    msg_format = ast_strdupa(config);
02684    if (msg_format == NULL) {
02685       ast_log(LOG_WARNING, "Out of memory.\n");
02686       ast_free(newzone);
02687       return 0;
02688    }
02689 
02690    timezone_str = strsep(&msg_format, "|");
02691    if (!msg_format) {
02692       ast_log(LOG_WARNING, "Invalid timezone definition : %s\n", zonename);
02693       ast_free(newzone);
02694       return 0;
02695    }
02696          
02697    ast_copy_string(newzone->name, zonename, sizeof(newzone->name));
02698    ast_copy_string(newzone->timezone, timezone_str, sizeof(newzone->timezone));
02699    ast_copy_string(newzone->msg_format, msg_format, sizeof(newzone->msg_format));
02700 
02701    AST_LIST_LOCK(&minivm_zones);
02702    AST_LIST_INSERT_TAIL(&minivm_zones, newzone, list);
02703    AST_LIST_UNLOCK(&minivm_zones);
02704 
02705    global_stats.timezones++;
02706 
02707    return 0;
02708 }

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

Definition at line 2662 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

02663 {
02664    struct minivm_zone *this;
02665 
02666    AST_LIST_LOCK(&minivm_zones);
02667    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02668       free_zone(this);
02669       
02670    AST_LIST_UNLOCK(&minivm_zones);
02671 }

static int unload_module ( void   )  [static]

Unload mini voicemail module.

Definition at line 3555 of file app_minivm.c.

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

03556 {
03557    int res;
03558    
03559    res = ast_unregister_application(app_minivm_record);
03560    res |= ast_unregister_application(app_minivm_greet);
03561    res |= ast_unregister_application(app_minivm_notify);
03562    res |= ast_unregister_application(app_minivm_delete);
03563    res |= ast_unregister_application(app_minivm_accmess);
03564    res |= ast_unregister_application(app_minivm_mwi);
03565 
03566    ast_cli_unregister_multiple(cli_minivm, ARRAY_LEN(cli_minivm));
03567    ast_custom_function_unregister(&minivm_account_function);
03568    ast_custom_function_unregister(&minivm_counter_function);
03569 
03570    message_destroy_list();    /* Destroy list of voicemail message templates */
03571    timezone_destroy_list();   /* Destroy list of timezones */
03572    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
03573 
03574    return res;
03575 }

static int vm_delete ( char *  file  )  [static]

Definition at line 1599 of file app_minivm.c.

References ast_debug, and ast_filedelete().

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

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

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

03280 {
03281    switch (ast_lock_path(path)) {
03282    case AST_LOCK_TIMEOUT:
03283       return -1;
03284    default:
03285       return 0;
03286    }
03287 }

static void vmaccounts_destroy_list ( void   )  [static]

Definition at line 1040 of file app_minivm.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and minivm_account::list.

Referenced by load_config(), and unload_module().

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


Variable Documentation

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

Definition at line 3582 of file app_minivm.c.

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 550 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 549 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 547 of file app_minivm.c.

char* app_minivm_mwi = "MinivmMWI" [static]

Definition at line 551 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 548 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 546 of file app_minivm.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3582 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 3480 of file app_minivm.c.

Referenced by load_module(), and unload_module().

char default_vmformat[80] [static]

Definition at line 687 of file app_minivm.c.

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

char global_externnotify[160] [static]

External notification application

Definition at line 685 of file app_minivm.c.

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

char global_logfile[PATH_MAX] [static]

Global log file for messages

Definition at line 686 of file app_minivm.c.

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

char global_mailcmd[160] [static]

Configurable mail cmd

Definition at line 684 of file app_minivm.c.

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

int global_maxgreet [static]

Maximum length of prompts

Definition at line 682 of file app_minivm.c.

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

int global_maxsilence [static]

Maximum silence during recording

Definition at line 681 of file app_minivm.c.

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

int global_saydurationminfo [static]

Definition at line 690 of file app_minivm.c.

Referenced by load_config().

int global_silencethreshold = 128 [static]

Definition at line 683 of file app_minivm.c.

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

struct minivm_stats global_stats [static]

Statistics for voicemail.

Definition at line 672 of file app_minivm.c.

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

int global_vmmaxmessage [static]

Maximum duration of message

Definition at line 680 of file app_minivm.c.

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

int global_vmminmessage [static]

Minimum duration of messages

Definition at line 679 of file app_minivm.c.

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

double global_volgain [static]

Volume gain for voicmemail via e-mail

Definition at line 692 of file app_minivm.c.

Referenced by populate_defaults().

struct ast_flags globalflags = {0} [static]

Global voicemail flags

Definition at line 689 of file app_minivm.c.

Referenced by __expire_registry(), __find_callno(), actual_load_config(), aji_build_publish_skeleton(), aji_create_client(), aji_load_config(), aji_pubsub_subscribe(), apply_general_options(), build_peer(), build_user(), check_access(), find_or_create(), find_user(), find_user_realtime(), forward_message(), handle_minivm_show_settings(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), populate_defaults(), realtime_update_peer(), send_trunk(), sendmail(), set_config(), set_config_destroy(), socket_process(), update_registry(), and vm_execmain().

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

Referenced by minivm_accmess_exec().

struct ast_custom_function minivm_account_function [static]

Initial value:

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

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

Referenced by minivm_greet_exec(), and minivm_record_exec().

struct ast_custom_function minivm_counter_function [static]

Initial value:

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

Definition at line 3489 of file app_minivm.c.

Referenced by load_module(), and unload_module().

ast_mutex_t minivmlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Lock to protect voicemail system

Definition at line 674 of file app_minivm.c.

Referenced by load_config().

FILE* minivmlogfile [static]

The minivm log file

Definition at line 677 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

ast_mutex_t minivmloglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Lock to protect voicemail system log file

Definition at line 675 of file app_minivm.c.

Referenced by leave_voicemail().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 543 of file app_minivm.c.


Generated on Mon Oct 8 12:39:08 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7