Mon Jun 27 16:50:58 2011

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, 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 530 of file app_minivm.c.

Referenced by load_config().

#define B64_BASELINELEN   72

Line length for Base 64 endoded messages

Definition at line 520 of file app_minivm.c.

Referenced by b64_ochar().

#define B64_BASEMAXINLINE   256

Buffer size for Base 64 attachment encoding

Definition at line 519 of file app_minivm.c.

Referenced by b64_inbuf(), and base_encode().

#define DEFAULT_CHARSET   "ISO-8859-1"

Definition at line 693 of file app_minivm.c.

Referenced by message_template_create().

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

Definition at line 692 of file app_minivm.c.

Referenced by message_template_create().

#define EOL   "\r\n"

Definition at line 521 of file app_minivm.c.

Referenced by b64_ochar(), and base_encode().

#define ERROR_LOCK_PATH   -100

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

Referenced by __sip_ack(), __sip_semi_ack(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), ast_tzset(), build_peer(), cb_extensionstate(), cc_esc_publish_handler(), cc_handle_publish_error(), check_auth(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), dialog_needdestroy(), 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(), 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(), receive_message(), 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_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 523 of file app_minivm.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 524 of file app_minivm.c.

Referenced by load_config(), and play_message_callerid().

#define MVM_ALLOCED   (1 << 13)

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

#define MVM_OPERATOR   (1 << 1)

Operator exit during voicemail recording

Definition at line 507 of file app_minivm.c.

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

#define MVM_PBXSKIP   (1 << 9)

Definition at line 511 of file app_minivm.c.

#define MVM_REALTIME   (1 << 2)

This user is a realtime account

Definition at line 508 of file app_minivm.c.

#define MVM_REVIEW   (1 << 0)

Review message

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

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

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

Definition at line 516 of file app_minivm.c.

Referenced by load_config().

#define SOUND_INTRO   "vm-intro"

Definition at line 518 of file app_minivm.c.

Referenced by minivm_greet_exec().

#define TRUE   1

Definition at line 499 of file app_minivm.c.

Referenced by __sip_ack(), __sip_autodestruct(), __sip_destroy(), __sip_semi_ack(), __sip_subscribe_mwi_do(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), add_sdp(), ast_tzset(), build_peer(), cc_esc_publish_handler(), check_dirpath(), check_peer_ok(), check_pendings(), create_addr(), dialog_needdestroy(), find_account(), find_sdp(), find_user_realtime(), function_sippeer(), get_sip_pvt_byid_locked(), gmtload(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_peerpoke(), interpret_t38_parameters(), leave_voicemail(), load_config(), local_attended_transfer(), manager_mutestream(), manager_sipnotify(), message_template_create(), minivm_accmess_exec(), minivm_account_func_read(), minivm_greet_exec(), minivm_notify_exec(), parse_ok_contact(), parse_register_contact(), 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_cli_notify(), sip_destroy(), sip_destroy_peer(), sip_devicestate(), sip_do_debug_peer(), sip_hangup(), sip_indicate(), sip_is_xml_parsable(), sip_park_thread(), sip_pidf_validate(), sip_poke_noanswer(), sip_poke_peer(), sip_prune_realtime(), sip_registry_destroy(), sip_reload(), sip_request_call(), sip_scheddestroy(), sip_send_mwi_to_peer(), sip_set_history(), sip_set_udptl_peer(), sip_show_channel(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_unregister(), sip_write(), sndfax_exec(), spandsp_fax_start(), st_get_se(), 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(), unload_module(), and update_connectedline().

#define VOICEMAIL_CONFIG   "minivm.conf"

Definition at line 529 of file app_minivm.c.

#define VOICEMAIL_DIR_MODE   0700

Definition at line 527 of file app_minivm.c.

Referenced by create_dirpath(), and leave_voicemail().


Enumeration Type Documentation

enum minivm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_ARRAY_SIZE 

Definition at line 560 of file app_minivm.c.

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

enum minivm_option_flags

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_TEMP_GREETING 
OPT_NAME_GREETING 
OPT_RECORDGAIN 

Definition at line 551 of file app_minivm.c.

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

enum mvm_messagetype

Message types for notification.

Enumerator:
MVM_MESSAGE_EMAIL 
MVM_MESSAGE_PAGE 

Definition at line 533 of file app_minivm.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3565 of file app_minivm.c.

static void __unreg_module ( void   )  [static]

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

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

static int apply_general_options ( struct ast_variable var  )  [static]

Apply general configuration options.

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

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

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

Definition at line 1154 of file app_minivm.c.

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

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

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

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

Definition at line 1196 of file app_minivm.c.

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

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

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

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

Definition at line 832 of file app_minivm.c.

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

Referenced by b64_inchar().

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

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

Definition at line 855 of file app_minivm.c.

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

Referenced by base_encode().

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

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

Definition at line 867 of file app_minivm.c.

References B64_BASELINELEN, EOL, and b64_baseio::linelength.

Referenced by base_encode().

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

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

Definition at line 886 of file app_minivm.c.

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

Referenced by add_email_attachment(), and sendmail().

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

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

Definition at line 1486 of file app_minivm.c.

References FALSE, make_dir(), and TRUE.

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

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

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

Definition at line 1125 of file app_minivm.c.

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

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

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

Definition at line 2998 of file app_minivm.c.

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

Referenced by handle_minivm_show_users().

02999 {
03000    int which = 0;
03001    int wordlen;
03002    struct minivm_account *vmu;
03003    const char *domain = "";
03004 
03005    /* 0 - voicemail; 1 - list; 2 - accounts; 3 - for; 4 - <domain> */
03006    if (pos > 4)
03007       return NULL;
03008    if (pos == 3)
03009       return (state == 0) ? ast_strdup("for") : NULL;
03010    wordlen = strlen(word);
03011    AST_LIST_TRAVERSE(&minivm_accounts, vmu, list) {
03012       if (!strncasecmp(word, vmu->domain, wordlen)) {
03013          if (domain && strcmp(domain, vmu->domain) && ++which > state)
03014             return ast_strdup(vmu->domain);
03015          /* ignore repeated domains ? */
03016          domain = vmu->domain;
03017       }
03018    }
03019    return NULL;
03020 }

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

Definition at line 1505 of file app_minivm.c.

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

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

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

static int create_vmaccount ( char *  name,
struct ast_variable var,
int  realtime 
) [static]

Append new mailbox to mailbox list from configuration file.

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

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

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

Definition at line 1048 of file app_minivm.c.

References ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set2_flag, ast_strlen_zero(), minivm_account::domain, find_user_realtime(), 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().

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

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

Definition at line 1092 of file app_minivm.c.

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

Referenced by find_account(), and find_user().

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

static void free_user ( struct minivm_account vmu  )  [static]

Definition at line 970 of file app_minivm.c.

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

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

00971 {
00972    if (vmu->chanvars)
00973       ast_variables_destroy(vmu->chanvars);
00974    ast_free(vmu);
00975 }

static void free_zone ( struct minivm_zone z  )  [static]

Free Mini Voicemail timezone.

Definition at line 2637 of file app_minivm.c.

References ast_free.

Referenced by free_vm_zones(), and timezone_destroy_list().

02638 {
02639    ast_free(z);
02640 }

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

Definition at line 958 of file app_minivm.c.

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

Referenced by leave_voicemail(), and tds_log().

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

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

CLI routine for listing templates.

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

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

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

Reload cofiguration.

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

03519 {
03520    
03521    switch (cmd) {
03522    case CLI_INIT:
03523       e->command = "minivm reload";
03524       e->usage =
03525          "Usage: minivm reload\n"
03526          "       Reload mini-voicemail configuration and reset statistics\n";
03527       return NULL;
03528    case CLI_GENERATE:
03529       return NULL;
03530    }
03531    
03532    reload();
03533    ast_cli(a->fd, "\n-- Mini voicemail re-configured \n");
03534    return CLI_SUCCESS;
03535 }

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

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

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

Show stats.

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

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

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

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

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

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

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

Definition at line 1521 of file app_minivm.c.

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

Referenced by minivm_greet_exec().

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

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

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

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

static int load_config ( int  reload  )  [static]

Load minivoicemail configuration.

Definition at line 2817 of file app_minivm.c.

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

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

static int load_module ( void   )  [static]

Load mini voicemail module.

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

03485 {
03486    int res;
03487 
03488    res = ast_register_application_xml(app_minivm_record, minivm_record_exec);
03489    res = ast_register_application_xml(app_minivm_greet, minivm_greet_exec);
03490    res = ast_register_application_xml(app_minivm_notify, minivm_notify_exec);
03491    res = ast_register_application_xml(app_minivm_delete, minivm_delete_exec);
03492    res = ast_register_application_xml(app_minivm_accmess, minivm_accmess_exec);
03493    res = ast_register_application_xml(app_minivm_mwi, minivm_mwi_exec);
03494 
03495    ast_custom_function_register(&minivm_account_function);
03496    ast_custom_function_register(&minivm_counter_function);
03497    if (res)
03498       return(res);
03499 
03500    if ((res = load_config(0)))
03501       return(res);
03502 
03503    ast_cli_register_multiple(cli_minivm, ARRAY_LEN(cli_minivm));
03504 
03505    /* compute the location of the voicemail spool directory */
03506    snprintf(MVM_SPOOL_DIR, sizeof(MVM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
03507 
03508    return res;
03509 }

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

Definition at line 1472 of file app_minivm.c.

References ast_strlen_zero().

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

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

static void message_destroy_list ( void   )  [static]

Definition at line 819 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

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

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

Definition at line 734 of file app_minivm.c.

References ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_true(), global_stats, 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().

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

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

Definition at line 704 of file app_minivm.c.

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

Referenced by message_template_build().

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

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

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

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

static void message_template_free ( struct minivm_template template  )  [static]

Definition at line 724 of file app_minivm.c.

References ast_free, and minivm_template::body.

Referenced by message_destroy_list().

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

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

Parse emailbody template from configuration file.

Definition at line 2732 of file app_minivm.c.

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

Referenced by load_config(), and message_template_build().

02733 {
02734    char *tmpread, *tmpwrite;
02735    char *emailbody = ast_strdup(configuration);
02736 
02737    /* substitute strings \t and \n into the apropriate characters */
02738    tmpread = tmpwrite = emailbody;
02739    while ((tmpwrite = strchr(tmpread,'\\'))) {
02740           int len = strlen("\n");
02741           switch (tmpwrite[1]) {
02742           case 'n':
02743             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02744             strncpy(tmpwrite, "\n", len);
02745             break;
02746           case 't':
02747             memmove(tmpwrite + len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
02748             strncpy(tmpwrite, "\t", len);
02749             break;
02750           default:
02751             ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
02752           }
02753           tmpread = tmpwrite + len;
02754    }
02755    return emailbody; 
02756 }

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

Read message template from file.

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

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

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

Record specific messages for voicemail account.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static struct minivm_account* mvm_user_alloc ( void   )  [static]

Definition at line 1021 of file app_minivm.c.

References ast_calloc, and populate_defaults().

Referenced by find_account(), and find_user_realtime().

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

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

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

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

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

Definition at line 1592 of file app_minivm.c.

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

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

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

static void populate_defaults ( struct minivm_account vmu  )  [static]

Definition at line 1012 of file app_minivm.c.

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

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

01013 {
01014    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
01015    ast_copy_string(vmu->attachfmt, default_vmformat, sizeof(vmu->attachfmt));
01016    vmu->volgain = global_volgain;
01017 }

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

Definition at line 983 of file app_minivm.c.

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

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

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

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

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

01999 {
02000    struct ast_event *event;
02001    char *mailbox, *context;
02002 
02003    mailbox = ast_strdupa(mbx);
02004    context = ast_strdupa(ctx);
02005    if (ast_strlen_zero(context)) {
02006       context = "default";
02007    }
02008 
02009    if (!(event = ast_event_new(AST_EVENT_MWI,
02010          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02011          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02012          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
02013          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
02014          AST_EVENT_IE_END))) {
02015       return;
02016    }
02017 
02018    ast_event_queue_and_cache(event);
02019 }

static int reload ( void   )  [static]

Reload mini voicemail module.

Definition at line 3512 of file app_minivm.c.

References load_config().

03513 {
03514    return(load_config(1));
03515 }

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

Run external notification for voicemail message.

Definition at line 1724 of file app_minivm.c.

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

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

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

Definition at line 1216 of file app_minivm.c.

References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_random(), ast_safe_system(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_tvnow(), 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().

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

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

Add time zone to memory list.

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

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

static void timezone_destroy_list ( void   )  [static]

Clear list of timezones.

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

02644 {
02645    struct minivm_zone *this;
02646 
02647    AST_LIST_LOCK(&minivm_zones);
02648    while ((this = AST_LIST_REMOVE_HEAD(&minivm_zones, list))) 
02649       free_zone(this);
02650       
02651    AST_LIST_UNLOCK(&minivm_zones);
02652 }

static int unload_module ( void   )  [static]

Unload mini voicemail module.

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

03539 {
03540    int res;
03541    
03542    res = ast_unregister_application(app_minivm_record);
03543    res |= ast_unregister_application(app_minivm_greet);
03544    res |= ast_unregister_application(app_minivm_notify);
03545    res |= ast_unregister_application(app_minivm_delete);
03546    res |= ast_unregister_application(app_minivm_accmess);
03547    res |= ast_unregister_application(app_minivm_mwi);
03548 
03549    ast_cli_unregister_multiple(cli_minivm, ARRAY_LEN(cli_minivm));
03550    ast_custom_function_unregister(&minivm_account_function);
03551    ast_custom_function_unregister(&minivm_counter_function);
03552 
03553    message_destroy_list();    /* Destroy list of voicemail message templates */
03554    timezone_destroy_list();   /* Destroy list of timezones */
03555    vmaccounts_destroy_list(); /* Destroy list of voicemail accounts */
03556 
03557    return res;
03558 }

static int vm_delete ( char *  file  )  [static]

Definition at line 1578 of file app_minivm.c.

References ast_debug, and ast_filedelete().

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

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

static int vm_lock_path ( const char *  path  )  [static]

lock directory

only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason

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

03263 {
03264    switch (ast_lock_path(path)) {
03265    case AST_LOCK_TIMEOUT:
03266       return -1;
03267    default:
03268       return 0;
03269    }
03270 }

static void vmaccounts_destroy_list ( void   )  [static]

Definition at line 1036 of file app_minivm.c.

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

Referenced by load_config(), and unload_module().

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


Variable Documentation

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

Definition at line 3565 of file app_minivm.c.

char* app_minivm_accmess = "MinivmAccMess" [static]

Definition at line 546 of file app_minivm.c.

char* app_minivm_delete = "MinivmDelete" [static]

Definition at line 545 of file app_minivm.c.

char* app_minivm_greet = "MinivmGreet" [static]

Definition at line 543 of file app_minivm.c.

char* app_minivm_mwi = "MinivmMWI" [static]

Definition at line 547 of file app_minivm.c.

char* app_minivm_notify = "MinivmNotify" [static]

Definition at line 544 of file app_minivm.c.

char* app_minivm_record = "MinivmRecord" [static]

Definition at line 542 of file app_minivm.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3565 of file app_minivm.c.

struct ast_cli_entry cli_minivm[] [static]

CLI commands for Mini-voicemail.

Definition at line 3463 of file app_minivm.c.

Referenced by load_module(), and unload_module().

char default_vmformat[80] [static]

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

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

char global_logfile[PATH_MAX] [static]

Global log file for messages

Definition at line 682 of file app_minivm.c.

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

char global_mailcmd[160] [static]

Configurable mail cmd

Definition at line 680 of file app_minivm.c.

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

int global_maxgreet [static]

Maximum length of prompts

Definition at line 678 of file app_minivm.c.

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

int global_maxsilence [static]

Maximum silence during recording

Definition at line 677 of file app_minivm.c.

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

int global_saydurationminfo [static]

Definition at line 686 of file app_minivm.c.

Referenced by load_config().

int global_silencethreshold = 128 [static]

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

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

int global_vmmaxmessage [static]

Maximum duration of message

Definition at line 676 of file app_minivm.c.

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

int global_vmminmessage [static]

Minimum duration of messages

Definition at line 675 of file app_minivm.c.

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

double global_volgain [static]

Volume gain for voicmemail via e-mail

Definition at line 688 of file app_minivm.c.

Referenced by populate_defaults().

struct ast_flags globalflags = {0} [static]

Global voicemail flags

Definition at line 685 of file app_minivm.c.

Referenced by __expire_registry(), __find_callno(), 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 577 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 3478 of file app_minivm.c.

Referenced by load_module(), and unload_module().

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

Definition at line 570 of file app_minivm.c.

Referenced by minivm_greet_exec(), and minivm_record_exec().

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

Referenced by load_config().

FILE* minivmlogfile [static]

The minivm log file

Definition at line 673 of file app_minivm.c.

Referenced by leave_voicemail(), and load_config().

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

Lock to protect voicemail system log file

Definition at line 671 of file app_minivm.c.

Referenced by leave_voicemail().

char MVM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 539 of file app_minivm.c.


Generated on Mon Jun 27 16:50:59 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7