Wed Oct 28 11:45:48 2009

Asterisk developer's documentation


app_voicemail.c File Reference

Comedian Mail - Voicemail System. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <time.h>
#include <dirent.h>
#include "asterisk/logger.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/adsi.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/stringfields.h"
#include "asterisk/smdi.h"
#include "asterisk/event.h"

Include dependency graph for app_voicemail.c:

Go to the source code of this file.

Data Structures

struct  ast_vm_user
struct  baseio
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  mwi_sub
 An MWI subscription. More...
struct  mwi_subs
struct  users
 list of users found in the config file More...
struct  vm_state
struct  vm_zone
struct  zones

Defines

#define ASTERISK_USERNAME   "asterisk"
#define BASELINELEN   72
#define BASEMAXINLINE   256
#define CHUNKSIZE   65536
#define COMMAND_TIMEOUT   5000
#define COPY(a, b, c, d, e, f, g, h)   (copy_plain_file(g,h));
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"
#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"
#define DEFAULT_POLL_FREQ   30
#define DELETE(a, b, c, d)   (vm_delete(c))
#define DISPOSE(a, b)
#define ENDL   "\n"
#define eol   "\r\n"
#define ERROR_LOCK_PATH   -100
#define ERROR_MAILBOX_FULL   -200
#define EXISTS(a, b, c, d)   (ast_fileexists(c, NULL, d) > 0)
#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"
#define MAX_DATETIME_FORMAT   512
#define MAX_NUM_CID_CONTEXTS   10
#define MAXMSG   100
#define MAXMSGLIMIT   9999
#define PWDCHANGE_EXTERNAL   (1 << 2)
#define PWDCHANGE_INTERNAL   (1 << 1)
#define RENAME(a, b, c, d, e, f, g, h)   (rename_file(g,h));
#define RETRIEVE(a, b, c, d)
#define SENDMAIL   "/usr/sbin/sendmail -t"
#define SMDI_MWI_WAIT_TIMEOUT   1000
#define STORE(a, b, c, d, e, f, g, h, i)
#define tdesc   "Comedian Mail (Voicemail System)"
#define VALID_DTMF   "1234567890*#"
#define VM_ALLOCED   (1 << 13)
#define VM_ATTACH   (1 << 11)
#define VM_DELETE   (1 << 12)
#define VM_DIRECFORWARD   (1 << 10)
#define VM_ENVELOPE   (1 << 4)
#define VM_FORCEGREET   (1 << 8)
#define VM_FORCENAME   (1 << 7)
#define VM_MOVEHEARD   (1 << 16)
#define VM_OPERATOR   (1 << 1)
#define VM_PBXSKIP   (1 << 9)
#define VM_REVIEW   (1 << 0)
#define VM_SAYCID   (1 << 2)
#define VM_SAYDURATION   (1 << 5)
#define VM_SEARCH   (1 << 14)
#define VM_SKIPAFTERCMD   (1 << 6)
#define VM_SVMAIL   (1 << 3)
#define VM_TEMPGREETWARN   (1 << 15)
#define VOICEMAIL_CONFIG   "voicemail.conf"
#define VOICEMAIL_DIR_MODE   0777
#define VOICEMAIL_FILE_MODE   0666

Enumerations

enum  {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER
}
enum  {
  OPT_SILENT = (1 << 0), OPT_BUSY_GREETING = (1 << 1), OPT_UNAVAIL_GREETING = (1 << 2), OPT_RECORDGAIN = (1 << 3),
  OPT_PREPEND_MAILBOX = (1 << 4), OPT_AUTOPLAY = (1 << 6), OPT_DTMFEXIT = (1 << 7)
}
enum  { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }

Functions

static void __fini_mwi_subs (void)
static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static void __init_mwi_subs (void)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static void adsi_begin (struct ast_channel *chan, int *useadsi)
static void adsi_delete (struct ast_channel *chan, struct vm_state *vms)
static void adsi_folders (struct ast_channel *chan, int start, char *label)
static void adsi_goodbye (struct ast_channel *chan)
static int adsi_load_vmail (struct ast_channel *chan, int *useadsi)
static void adsi_login (struct ast_channel *chan)
static int adsi_logo (unsigned char *buf)
static void adsi_message (struct ast_channel *chan, struct vm_state *vms)
static void adsi_password (struct ast_channel *chan)
static void adsi_status (struct ast_channel *chan, struct vm_state *vms)
static void adsi_status2 (struct ast_channel *chan, struct vm_state *vms)
static int advanced_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
static int append_mailbox (const char *context, const char *mbox, const char *data)
static void apply_option (struct ast_vm_user *vmu, const char *var, const char *value)
static void apply_options (struct ast_vm_user *vmu, const char *options)
static void apply_options_full (struct ast_vm_user *retval, struct ast_variable *var)
static int base_encode (char *filename, FILE *so)
static int change_password_realtime (struct ast_vm_user *vmu, const char *password)
static int check_mime (const char *str)
 Check if the string would need encoding within the MIME standard, to avoid confusing certain mail software that expects messages to be 7-bit clean.
static int close_mailbox (struct vm_state *vms, struct ast_vm_user *vmu)
static char * complete_voicemail_show_users (const char *line, const char *word, int pos, int state)
static int copy (char *infile, char *outfile)
static int copy_message (struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt, char *dir)
static void copy_plain_file (char *frompath, char *topath)
static int count_messages (struct ast_vm_user *vmu, char *dir)
static int create_dirpath (char *dest, int len, const char *context, const char *ext, const char *folder)
 basically mkdir -p $dest/$context/$ext/$folder
static int dialout (struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
static char * encode_mime_str (const char *start, char *end, size_t endsize, size_t preamble, size_t postamble)
 Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain control characters.
static struct ast_vm_userfind_or_create (const char *context, const char *mbox)
static struct ast_vm_userfind_user (struct ast_vm_user *ivm, const char *context, const char *mailbox)
static struct ast_vm_userfind_user_realtime (struct ast_vm_user *ivm, const char *context, const char *mailbox)
static int forward_message (struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int flag, signed char record_gain)
static void free_user (struct ast_vm_user *vmu)
static void free_vm_users (void)
 Free the users structure.
static void free_vm_zones (void)
 Free the zones structure.
static void free_zone (struct vm_zone *z)
static int get_date (char *s, int len)
static int get_folder (struct ast_channel *chan, int start)
 get_folder: Folder menu Plays "press 1 for INBOX messages" etc. Should possibly be internationalized
static int get_folder2 (struct ast_channel *chan, char *fn, int start)
static char * handle_voicemail_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload voicemail configuration from the CLI.
static char * handle_voicemail_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail users in the CLI.
static char * handle_voicemail_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 has_voicemail (const char *mailbox, const char *folder)
static int inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
static int inbuf (struct baseio *bio, FILE *fi)
static int inchar (struct baseio *bio, FILE *fi)
static int invent_message (struct ast_channel *chan, struct ast_vm_user *vmu, char *ext, int busy, char *ecodes)
static int is_valid_dtmf (const char *key)
static int last_message_index (struct ast_vm_user *vmu, char *dir)
 A negative return value indicates an error.
static int leave_voicemail (struct ast_channel *chan, char *ext, struct leave_vm_options *options)
static int load_config (int reload)
static int load_module (void)
static int make_dir (char *dest, int len, const char *context, const char *ext, const char *folder)
static void make_email_file (FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap)
 Creates the email file to be sent to indicate a new voicemail exists for a user.
static int make_file (char *dest, const int len, const char *dir, const int num)
 Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.
static int manager_list_voicemail_users (struct mansession *s, const struct message *m)
 Manager list voicemail users command.
static void * mb_poll_thread (void *data)
static const char * mbox (int id)
static int messagecount (const char *context, const char *mailbox, const char *folder)
static void mwi_sub_destroy (struct mwi_sub *mwi_sub)
static void mwi_sub_event_cb (const struct ast_event *event, void *userdata)
static void mwi_unsub_event_cb (const struct ast_event *event, void *userdata)
static int notify_new_message (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
static int ochar (struct baseio *bio, int c, FILE *so)
static int open_mailbox (struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int play_greeting (struct ast_channel *chan, struct ast_vm_user *vmu, char *filename, char *ecodes)
static int play_message (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int play_message_callerid (struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
static int play_message_category (struct ast_channel *chan, const char *category)
static int play_message_datetime (struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static int play_message_duration (struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir, signed char record_gain, struct vm_state *vms)
static void poll_subscribed_mailboxes (void)
static void populate_defaults (struct ast_vm_user *vmu)
static void prep_email_sub_vars (struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, char *passdata, size_t passdatasize, const char *category)
static void queue_mwi_event (const char *mbox, int new, int old)
static char * quote (const char *from, char *to, size_t len)
static int reload (void)
static void rename_file (char *sfn, char *dfn)
static int resequence_mailbox (struct ast_vm_user *vmu, char *dir)
static int reset_user_pw (const char *context, const char *mailbox, const char *newpass)
static void run_externnotify (char *context, char *extension)
static int save_to_folder (struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
static int say_and_wait (struct ast_channel *chan, int num, const char *language)
static int sendmail (char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category)
static int sendpage (char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category)
static char * show_users_realtime (int fd, const char *context)
static void start_poll_thread (void)
static void stop_poll_thread (void)
static char * strip_control (const char *input, char *buf, size_t buflen)
static char * substitute_escapes (const char *value)
static int unload_module (void)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int maxlogins, int silent)
static int vm_box_exists (struct ast_channel *chan, void *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_it (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_zh (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
static void vm_change_password_shell (struct ast_vm_user *vmu, char *newpassword)
static int vm_delete (char *file)
 Removes the voicemail sound and information file.
static int vm_exec (struct ast_channel *chan, void *data)
static int vm_execmain (struct ast_channel *chan, void *data)
static int vm_forwardoptions (struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfmts, char *context, signed char record_gain, long *duration, struct vm_state *vms)
static int vm_instructions (struct ast_channel *chan, struct vm_state *vms, int skipadvanced)
static int vm_instructions_en (struct ast_channel *chan, struct vm_state *vms, int skipadvanced)
static int vm_instructions_zh (struct ast_channel *chan, struct vm_state *vms, int skipadvanced)
static int vm_intro (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_cz (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_de (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_en (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_es (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_fr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_gr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_it (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_multilang (struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_intro_nl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_no (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt_BR (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_se (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_zh (struct ast_channel *chan, struct vm_state *vms)
static int vm_lock_path (const char *path)
 Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.
static FILE * vm_mkftemp (char *template)
static int vm_newuser (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_play_folder_name (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_gr (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_pl (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_ua (struct ast_channel *chan, char *mbox)
static int vm_tempgreeting (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vmauthenticate (struct ast_channel *chan, void *data)
static struct ast_tmvmu_tm (const struct ast_vm_user *vmu, struct ast_tm *tm)
 fill in *tm for current time according to the proper timezone, if any. Return tm so it can be used as a function argument.
static int wait_file (struct ast_channel *chan, struct vm_state *vms, char *file)
static int wait_file2 (struct ast_channel *chan, struct vm_state *vms, char *file)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static char * addesc = "Comedian Mail"
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
static int adsiver = 1
static char * app = "VoiceMail"
static char * app2 = "VoiceMailMain"
static char * app3 = "MailboxExists"
static char * app4 = "VMAuthenticate"
static const struct
ast_module_info
ast_module_info = &__mod_info
static char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char * descrip_vm
static char * descrip_vm_box_exists
static char * descrip_vmain
static char * descrip_vmauthenticate
static char dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static struct ast_custom_function mailbox_exists_acf
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static struct ast_event_submwi_sub_sub
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerfromstring [100]
static char * pagersubject = NULL
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char * synopsis_vm = "Leave a Voicemail message"
static char * synopsis_vm_box_exists
static char * synopsis_vmain = "Check Voicemail messages"
static char * synopsis_vmauthenticate = "Authenticate with Voicemail passwords"
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_app_option vm_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 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 },}
enum { ... }  vm_box
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
enum { ... }  vm_option_args
enum { ... }  vm_option_flags
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
static char vmfmts [80]
static int vmmaxsecs
static int vmminsecs
static double volgain
static char zonetag [80]


Detailed Description

Comedian Mail - Voicemail System.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
Unixodbc - http://www.unixodbc.org
ExtRef:
A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/
See also
Note:
For information about voicemail IMAP storage, read doc/imapstorage.txt

This module requires res_adsi to load. This needs to be optional during compilation.

This file is now almost impossible to work with, due to all #ifdefs. Feels like the database code before realtime. Someone - please come up with a plan to clean this up.

Definition in file app_voicemail.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 189 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 210 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 211 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 186 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 182 of file app_voicemail.c.

#define COPY ( a,
b,
c,
d,
e,
f,
g,
 )     (copy_plain_file(g,h));

Definition at line 465 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 194 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 196 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 197 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 195 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 198 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 609 of file app_voicemail.c.

Referenced by load_config().

#define DELETE ( a,
b,
c,
 )     (vm_delete(c))

#define DISPOSE ( a,
 ) 

#define ENDL   "\n"

Referenced by make_email_file().

#define eol   "\r\n"

Definition at line 212 of file app_voicemail.c.

Referenced by base_encode(), and ochar().

#define ERROR_LOCK_PATH   -100

Definition at line 234 of file app_voicemail.c.

#define ERROR_MAILBOX_FULL   -200

Definition at line 235 of file app_voicemail.c.

Referenced by close_mailbox(), and save_to_folder().

#define EXISTS ( a,
b,
c,
 )     (ast_fileexists(c, NULL, d) > 0)

Definition at line 463 of file app_voicemail.c.

Referenced by close_mailbox(), resequence_mailbox(), and save_to_folder().

#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"

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

#define INTRO   "vm-intro"

Definition at line 205 of file app_voicemail.c.

Referenced by leave_voicemail(), and play_record_review().

#define MAX_DATETIME_FORMAT   512

Definition at line 214 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 215 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 207 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

Definition at line 208 of file app_voicemail.c.

Referenced by apply_option(), last_message_index(), and load_config().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 477 of file app_voicemail.c.

Referenced by load_config(), vm_newuser(), and vm_options().

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 476 of file app_voicemail.c.

Referenced by load_config(), vm_newuser(), and vm_options().

#define RENAME ( a,
b,
c,
d,
e,
f,
g,
 )     (rename_file(g,h));

Definition at line 464 of file app_voicemail.c.

Referenced by close_mailbox(), resequence_mailbox(), and save_to_folder().

#define RETRIEVE ( a,
b,
c,
 ) 

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

Definition at line 203 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 180 of file app_voicemail.c.

Referenced by run_externnotify().

#define STORE ( a,
b,
c,
d,
e,
f,
g,
h,
 ) 

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 486 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 199 of file app_voicemail.c.

Referenced by is_valid_dtmf().

#define VM_ALLOCED   (1 << 13)

Definition at line 230 of file app_voicemail.c.

Referenced by find_user(), find_user_realtime(), free_user(), and free_vm_users().

#define VM_ATTACH   (1 << 11)

#define VM_DELETE   (1 << 12)

Definition at line 229 of file app_voicemail.c.

Referenced by apply_option(), manager_list_voicemail_users(), and notify_new_message().

#define VM_DIRECFORWARD   (1 << 10)

directory_forward

Definition at line 227 of file app_voicemail.c.

Referenced by forward_message(), and load_config().

#define VM_ENVELOPE   (1 << 4)

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 225 of file app_voicemail.c.

Referenced by apply_option(), load_config(), vm_execmain(), and vm_newuser().

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 224 of file app_voicemail.c.

Referenced by apply_option(), load_config(), vm_execmain(), and vm_newuser().

#define VM_MOVEHEARD   (1 << 16)

Move a "heard" message to Old after listening to it

Definition at line 233 of file app_voicemail.c.

Referenced by apply_option(), close_mailbox(), and load_config().

#define VM_OPERATOR   (1 << 1)

#define VM_PBXSKIP   (1 << 9)

Definition at line 226 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

#define VM_REVIEW   (1 << 0)

#define VM_SAYCID   (1 << 2)

#define VM_SAYDURATION   (1 << 5)

Definition at line 222 of file app_voicemail.c.

Referenced by apply_option(), load_config(), and play_message().

#define VM_SEARCH   (1 << 14)

Definition at line 231 of file app_voicemail.c.

Referenced by find_or_create(), find_user(), find_user_realtime(), and load_config().

#define VM_SKIPAFTERCMD   (1 << 6)

Definition at line 223 of file app_voicemail.c.

Referenced by load_config(), and vm_execmain().

#define VM_SVMAIL   (1 << 3)

Definition at line 220 of file app_voicemail.c.

Referenced by apply_option(), load_config(), and vm_execmain().

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 232 of file app_voicemail.c.

Referenced by apply_option(), load_config(), and vm_intro().

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 188 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 184 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 185 of file app_voicemail.c.

Referenced by copy(), leave_voicemail(), make_email_file(), and vm_mkftemp().


Enumeration Type Documentation

anonymous enum

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 238 of file app_voicemail.c.

00238      {
00239    NEW_FOLDER,
00240    OLD_FOLDER,
00241    WORK_FOLDER,
00242    FAMILY_FOLDER,
00243    FRIENDS_FOLDER,
00244    GREETINGS_FOLDER
00245 } vm_box;

anonymous enum

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 

Definition at line 247 of file app_voicemail.c.

00247      {
00248    OPT_SILENT =           (1 << 0),
00249    OPT_BUSY_GREETING =    (1 << 1),
00250    OPT_UNAVAIL_GREETING = (1 << 2),
00251    OPT_RECORDGAIN =       (1 << 3),
00252    OPT_PREPEND_MAILBOX =  (1 << 4),
00253    OPT_AUTOPLAY =         (1 << 6),
00254    OPT_DTMFEXIT =         (1 << 7),
00255 } vm_option_flags;

anonymous enum

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 257 of file app_voicemail.c.

00257      {
00258    OPT_ARG_RECORDGAIN = 0,
00259    OPT_ARG_PLAYFOLDER = 1,
00260    OPT_ARG_DTMFEXIT   = 2,
00261    /* This *must* be the last value in this enum! */
00262    OPT_ARG_ARRAY_SIZE = 3,
00263 } vm_option_args;


Function Documentation

static void __fini_mwi_subs ( void   )  [static]

Definition at line 636 of file app_voicemail.c.

00653 {0};

static int __has_voicemail ( const char *  context,
const char *  mailbox,
const char *  folder,
int  shortcircuit 
) [static]

Definition at line 4190 of file app_voicemail.c.

References ast_strlen_zero().

Referenced by has_voicemail(), inboxcount(), and messagecount().

04191    {
04192       DIR *dir;
04193       struct dirent *de;
04194       char fn[256];
04195       int ret = 0;
04196 
04197       /* If no mailbox, return immediately */
04198       if (ast_strlen_zero(mailbox))
04199          return 0;
04200 
04201       if (ast_strlen_zero(folder))
04202          folder = "INBOX";
04203       if (ast_strlen_zero(context))
04204          context = "default";
04205 
04206       snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
04207 
04208       if (!(dir = opendir(fn)))
04209          return 0;
04210 
04211       while ((de = readdir(dir))) {
04212          if (!strncasecmp(de->d_name, "msg", 3)) {
04213             if (shortcircuit) {
04214                ret = 1;
04215                break;
04216             } else if (!strncasecmp(de->d_name + 8, "txt", 3))
04217                ret++;
04218          }
04219       }
04220 
04221       closedir(dir);
04222 
04223       return ret;
04224    }

static void __init_mwi_subs ( void   )  [static]

Definition at line 636 of file app_voicemail.c.

00653 {0};

static void __reg_module ( void   )  [static]

Definition at line 10302 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

Definition at line 10302 of file app_voicemail.c.

static int acf_mailbox_exists ( struct ast_channel chan,
const char *  cmd,
char *  args,
char *  buf,
size_t  len 
) [static]

Definition at line 8594 of file app_voicemail.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strlen_zero(), find_user(), and LOG_ERROR.

08595 {
08596    struct ast_vm_user svm;
08597    AST_DECLARE_APP_ARGS(arg,
08598       AST_APP_ARG(mbox);
08599       AST_APP_ARG(context);
08600    );
08601 
08602    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
08603 
08604    if (ast_strlen_zero(arg.mbox)) {
08605       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
08606       return -1;
08607    }
08608 
08609    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
08610    return 0;
08611 }

static void adsi_begin ( struct ast_channel chan,
int *  useadsi 
) [static]

Definition at line 5034 of file app_voicemail.c.

References adsi_load_vmail(), adsifdn, adsiver, ast_adsi_available, ast_adsi_load_session, ast_log(), and LOG_WARNING.

Referenced by vm_authenticate(), and vm_execmain().

05035    {
05036       int x;
05037       if (!ast_adsi_available(chan))
05038          return;
05039       x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05040       if (x < 0)
05041          return;
05042       if (!x) {
05043          if (adsi_load_vmail(chan, useadsi)) {
05044             ast_log(LOG_WARNING, "Unable to upload voicemail scripts\n");
05045             return;
05046          }
05047       } else
05048          *useadsi = 1;
05049    }

static void adsi_delete ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 5223 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_set_keys, ast_adsi_transmit_message, ast_adsi_voice_mode, vm_state::curmsg, vm_state::deleted, and vm_state::lastmsg.

Referenced by vm_execmain().

05224    {
05225       int bytes = 0;
05226       unsigned char buf[256];
05227       unsigned char keys[8];
05228 
05229       int x;
05230 
05231       if (!ast_adsi_available(chan))
05232          return;
05233 
05234       /* New meaning for keys */
05235       for (x = 0; x < 5; x++)
05236          keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05237 
05238       keys[6] = 0x0;
05239       keys[7] = 0x0;
05240 
05241       if (!vms->curmsg) {
05242          /* No prev key, provide "Folder" instead */
05243          keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05244       }
05245       if (vms->curmsg >= vms->lastmsg) {
05246          /* If last message ... */
05247          if (vms->curmsg) {
05248             /* but not only message, provide "Folder" instead */
05249             keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05250          } else {
05251             /* Otherwise if only message, leave blank */
05252             keys[3] = 1;
05253          }
05254       }
05255 
05256       /* If deleted, show "undeleted" */
05257       if (vms->deleted[vms->curmsg]) 
05258          keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05259 
05260       /* Except "Exit" */
05261       keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05262       bytes += ast_adsi_set_keys(buf + bytes, keys);
05263       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05264 
05265       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05266    }

static void adsi_folders ( struct ast_channel chan,
int  start,
char *  label 
) [static]

Definition at line 5099 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_keys, ast_adsi_set_line, ast_adsi_transmit_message, and ast_adsi_voice_mode.

Referenced by vm_execmain().

05100    {
05101       unsigned char buf[256];
05102       int bytes = 0;
05103       unsigned char keys[8];
05104       int x, y;
05105 
05106       if (!ast_adsi_available(chan))
05107          return;
05108 
05109       for (x = 0; x < 5; x++) {
05110          y = ADSI_KEY_APPS + 12 + start + x;
05111          if (y > ADSI_KEY_APPS + 12 + 4)
05112             y = 0;
05113          keys[x] = ADSI_KEY_SKT | y;
05114       }
05115       keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05116       keys[6] = 0;
05117       keys[7] = 0;
05118 
05119       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05120       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05121       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05122       bytes += ast_adsi_set_keys(buf + bytes, keys);
05123       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05124 
05125       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05126    }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 5371 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_line, ast_adsi_transmit_message, and ast_adsi_voice_mode.

Referenced by vm_execmain().

05372    {
05373       unsigned char buf[256];
05374       int bytes = 0;
05375 
05376       if (!ast_adsi_available(chan))
05377          return;
05378       bytes += adsi_logo(buf + bytes);
05379       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
05380       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
05381       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05382       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05383 
05384       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05385    }

static int adsi_load_vmail ( struct ast_channel chan,
int *  useadsi 
) [static]

Definition at line 4905 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ADSI_MSG_DOWNLOAD, adsifdn, adsisec, adsiver, ast_adsi_begin_download, ast_adsi_data_mode, ast_adsi_display, ast_adsi_download_disconnect, ast_adsi_end_download, ast_adsi_load_session, ast_adsi_load_soft_key, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, ast_debug, mbox(), and num.

Referenced by adsi_begin().

04906    {
04907       unsigned char buf[256];
04908       int bytes = 0;
04909       int x;
04910       char num[5];
04911 
04912       *useadsi = 0;
04913       bytes += ast_adsi_data_mode(buf + bytes);
04914       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04915 
04916       bytes = 0;
04917       bytes += adsi_logo(buf);
04918       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
04919 #ifdef DISPLAY
04920       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
04921 #endif
04922       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04923       bytes += ast_adsi_data_mode(buf + bytes);
04924       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04925 
04926       if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
04927          bytes = 0;
04928          bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
04929          bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
04930          bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04931          bytes += ast_adsi_voice_mode(buf + bytes, 0);
04932          ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04933          return 0;
04934       }
04935 
04936 #ifdef DISPLAY
04937       /* Add a dot */
04938       bytes = 0;
04939       bytes += ast_adsi_logo(buf);
04940       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
04941       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
04942       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04943       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04944 #endif
04945       bytes = 0;
04946       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
04947       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
04948       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
04949       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
04950       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
04951       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
04952       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
04953 
04954 #ifdef DISPLAY
04955       /* Add another dot */
04956       bytes = 0;
04957       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
04958       bytes += ast_adsi_voice_mode(buf + bytes, 0);
04959 
04960       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04961       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04962 #endif
04963 
04964       bytes = 0;
04965       /* These buttons we load but don't use yet */
04966       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
04967       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
04968       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
04969       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
04970       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
04971       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
04972       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
04973 
04974 #ifdef DISPLAY
04975       /* Add another dot */
04976       bytes = 0;
04977       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
04978       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04979       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04980 #endif
04981 
04982       bytes = 0;
04983       for (x = 0; x < 5; x++) {
04984          snprintf(num, sizeof(num), "%d", x);
04985          bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
04986       }
04987       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
04988       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
04989 
04990 #ifdef DISPLAY
04991       /* Add another dot */
04992       bytes = 0;
04993       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
04994       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04995       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04996 #endif
04997 
04998       if (ast_adsi_end_download(chan)) {
04999          bytes = 0;
05000          bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
05001          bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05002          bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05003          bytes += ast_adsi_voice_mode(buf + bytes, 0);
05004          ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05005          return 0;
05006       }
05007       bytes = 0;
05008       bytes += ast_adsi_download_disconnect(buf + bytes);
05009       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05010       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05011 
05012       ast_debug(1, "Done downloading scripts...\n");
05013 
05014 #ifdef DISPLAY
05015       /* Add last dot */
05016       bytes = 0;
05017       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
05018       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05019 #endif
05020       ast_debug(1, "Restarting session...\n");
05021 
05022       bytes = 0;
05023       /* Load the session now */
05024       if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
05025          *useadsi = 1;
05026          bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
05027       } else
05028          bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
05029 
05030       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05031       return 0;
05032    }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 5051 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_input_control, ast_adsi_input_format, ast_adsi_load_soft_key, ast_adsi_set_keys, ast_adsi_set_line, ast_adsi_transmit_message, and ast_adsi_voice_mode.

Referenced by vm_authenticate().

05052    {
05053       unsigned char buf[256];
05054       int bytes = 0;
05055       unsigned char keys[8];
05056       int x;
05057       if (!ast_adsi_available(chan))
05058          return;
05059 
05060       for (x = 0; x < 8; x++)
05061          keys[x] = 0;
05062       /* Set one key for next */
05063       keys[3] = ADSI_KEY_APPS + 3;
05064 
05065       bytes += adsi_logo(buf + bytes);
05066       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05067       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
05068       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05069       bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
05070       bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05071       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05072       bytes += ast_adsi_set_keys(buf + bytes, keys);
05073       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05074       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05075    }

static int adsi_logo ( unsigned char *  buf  )  [static]

Definition at line 4897 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display.

Referenced by adsi_goodbye(), adsi_load_vmail(), adsi_login(), vm_newuser(), vm_options(), and vm_tempgreeting().

04898    {
04899       int bytes = 0;
04900       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
04901       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
04902       return bytes;
04903    }

static void adsi_message ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 5128 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_keys, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, ast_callerid_parse(), ast_copy_string(), ast_strlen_zero(), vm_state::curbox, vm_state::curmsg, vm_state::deleted, vm_state::fn, vm_state::lastmsg, name, num, and strsep().

Referenced by play_message(), and vm_execmain().

05129    {
05130       int bytes = 0;
05131       unsigned char buf[256]; 
05132       char buf1[256], buf2[256];
05133       char fn2[PATH_MAX];
05134 
05135       char cid[256] = "";
05136       char *val;
05137       char *name, *num;
05138       char datetime[21] = "";
05139       FILE *f;
05140 
05141       unsigned char keys[8];
05142 
05143       int x;
05144 
05145       if (!ast_adsi_available(chan))
05146          return;
05147 
05148       /* Retrieve important info */
05149       snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
05150       f = fopen(fn2, "r");
05151       if (f) {
05152          while (!feof(f)) {   
05153             if (!fgets((char *)buf, sizeof(buf), f)) {
05154                continue;
05155             }
05156             if (!feof(f)) {
05157                char *stringp = NULL;
05158                stringp = (char *)buf;
05159                strsep(&stringp, "=");
05160                val = strsep(&stringp, "=");
05161                if (!ast_strlen_zero(val)) {
05162                   if (!strcmp((char *)buf, "callerid"))
05163                      ast_copy_string(cid, val, sizeof(cid));
05164                   if (!strcmp((char *)buf, "origdate"))
05165                      ast_copy_string(datetime, val, sizeof(datetime));
05166                }
05167             }
05168          }
05169          fclose(f);
05170       }
05171       /* New meaning for keys */
05172       for (x = 0; x < 5; x++)
05173          keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05174       keys[6] = 0x0;
05175       keys[7] = 0x0;
05176 
05177       if (!vms->curmsg) {
05178          /* No prev key, provide "Folder" instead */
05179          keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05180       }
05181       if (vms->curmsg >= vms->lastmsg) {
05182          /* If last message ... */
05183          if (vms->curmsg) {
05184             /* but not only message, provide "Folder" instead */
05185             keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05186             bytes += ast_adsi_voice_mode(buf + bytes, 0);
05187 
05188          } else {
05189             /* Otherwise if only message, leave blank */
05190             keys[3] = 1;
05191          }
05192       }
05193 
05194       if (!ast_strlen_zero(cid)) {
05195          ast_callerid_parse(cid, &name, &num);
05196          if (!name)
05197             name = num;
05198       } else
05199          name = "Unknown Caller";
05200 
05201       /* If deleted, show "undeleted" */
05202 
05203       if (vms->deleted[vms->curmsg])
05204          keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05205 
05206       /* Except "Exit" */
05207       keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05208       snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
05209          strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
05210       snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
05211 
05212       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05213       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05214       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
05215       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
05216       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05217       bytes += ast_adsi_set_keys(buf + bytes, keys);
05218       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05219 
05220       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05221    }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 5077 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_input_control, ast_adsi_input_format, ast_adsi_set_keys, ast_adsi_set_line, ast_adsi_transmit_message, and ast_adsi_voice_mode.

Referenced by vm_authenticate().

05078    {
05079       unsigned char buf[256];
05080       int bytes = 0;
05081       unsigned char keys[8];
05082       int x;
05083       if (!ast_adsi_available(chan))
05084          return;
05085 
05086       for (x = 0; x < 8; x++)
05087          keys[x] = 0;
05088       /* Set one key for next */
05089       keys[3] = ADSI_KEY_APPS + 3;
05090 
05091       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05092       bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05093       bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05094       bytes += ast_adsi_set_keys(buf + bytes, keys);
05095       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05096       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05097    }

static void adsi_status ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 5268 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_keys, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_execmain().

05269    {
05270       unsigned char buf[256] = "";
05271       char buf1[256] = "", buf2[256] = "";
05272       int bytes = 0;
05273       unsigned char keys[8];
05274       int x;
05275 
05276       char *newm = (vms->newmessages == 1) ? "message" : "messages";
05277       char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
05278       if (!ast_adsi_available(chan))
05279          return;
05280       if (vms->newmessages) {
05281          snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
05282          if (vms->oldmessages) {
05283             strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
05284             snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
05285          } else {
05286             snprintf(buf2, sizeof(buf2), "%s.", newm);
05287          }
05288       } else if (vms->oldmessages) {
05289          snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
05290          snprintf(buf2, sizeof(buf2), "%s.", oldm);
05291       } else {
05292          strcpy(buf1, "You have no messages.");
05293          buf2[0] = ' ';
05294          buf2[1] = '\0';
05295       }
05296       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05297       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05298       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05299 
05300       for (x = 0; x < 6; x++)
05301          keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05302       keys[6] = 0;
05303       keys[7] = 0;
05304 
05305       /* Don't let them listen if there are none */
05306       if (vms->lastmsg < 0)
05307          keys[0] = 1;
05308       bytes += ast_adsi_set_keys(buf + bytes, keys);
05309 
05310       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05311 
05312       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05313    }

static void adsi_status2 ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 5315 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_keys, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, vm_state::curbox, and vm_state::lastmsg.

Referenced by vm_execmain().

05316    {
05317       unsigned char buf[256] = "";
05318       char buf1[256] = "", buf2[256] = "";
05319       int bytes = 0;
05320       unsigned char keys[8];
05321       int x;
05322 
05323       char *mess = (vms->lastmsg == 0) ? "message" : "messages";
05324 
05325       if (!ast_adsi_available(chan))
05326          return;
05327 
05328       /* Original command keys */
05329       for (x = 0; x < 6; x++)
05330          keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05331 
05332       keys[6] = 0;
05333       keys[7] = 0;
05334 
05335       if ((vms->lastmsg + 1) < 1)
05336          keys[0] = 0;
05337 
05338       snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
05339          strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
05340 
05341       if (vms->lastmsg + 1)
05342          snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
05343       else
05344          strcpy(buf2, "no messages.");
05345       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05346       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05347       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
05348       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05349       bytes += ast_adsi_set_keys(buf + bytes, keys);
05350 
05351       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05352 
05353       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05354       
05355    }

static int advanced_options ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  msg,
int  option,
signed char  record_gain 
) [static]

Definition at line 9910 of file app_voicemail.c.

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::fn2, vm_state::heard, leave_voicemail(), LOG_WARNING, ast_vm_user::mailbox, make_file(), name, num, play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

09911 {
09912    int res = 0;
09913    char filename[PATH_MAX];
09914    struct ast_config *msg_cfg = NULL;
09915    const char *origtime, *context;
09916    char *name, *num;
09917    int retries = 0;
09918    char *cid;
09919    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
09920 
09921    vms->starting = 0; 
09922 
09923    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
09924 
09925    /* Retrieve info from VM attribute file */
09926 
09927    make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
09928    snprintf(filename, sizeof(filename), "%s.txt", vms->fn2);
09929    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
09930    msg_cfg = ast_config_load(filename, config_flags);
09931    DISPOSE(vms->curdir, vms->curmsg);
09932    if (!msg_cfg) {
09933       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
09934       return 0;
09935    }
09936 
09937    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
09938       ast_config_destroy(msg_cfg);
09939       return 0;
09940    }
09941 
09942    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
09943 
09944    context = ast_variable_retrieve(msg_cfg, "message", "context");
09945    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
09946       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
09947    switch (option) {
09948    case 3:
09949       if (!res)
09950          res = play_message_datetime(chan, vmu, origtime, filename);
09951       if (!res)
09952          res = play_message_callerid(chan, vms, cid, context, 0);
09953 
09954       res = 't';
09955       break;
09956 
09957    case 2:  /* Call back */
09958 
09959       if (ast_strlen_zero(cid))
09960          break;
09961 
09962       ast_callerid_parse(cid, &name, &num);
09963       while ((res > -1) && (res != 't')) {
09964          switch (res) {
09965          case '1':
09966             if (num) {
09967                /* Dial the CID number */
09968                res = dialout(chan, vmu, num, vmu->callback);
09969                if (res) {
09970                   ast_config_destroy(msg_cfg);
09971                   return 9;
09972                }
09973             } else {
09974                res = '2';
09975             }
09976             break;
09977 
09978          case '2':
09979             /* Want to enter a different number, can only do this if there's a dialout context for this user */
09980             if (!ast_strlen_zero(vmu->dialout)) {
09981                res = dialout(chan, vmu, NULL, vmu->dialout);
09982                if (res) {
09983                   ast_config_destroy(msg_cfg);
09984                   return 9;
09985                }
09986             } else {
09987                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
09988                res = ast_play_and_wait(chan, "vm-sorry");
09989             }
09990             ast_config_destroy(msg_cfg);
09991             return res;
09992          case '*':
09993             res = 't';
09994             break;
09995          case '3':
09996          case '4':
09997          case '5':
09998          case '6':
09999          case '7':
10000          case '8':
10001          case '9':
10002          case '0':
10003 
10004             res = ast_play_and_wait(chan, "vm-sorry");
10005             retries++;
10006             break;
10007          default:
10008             if (num) {
10009                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
10010                res = ast_play_and_wait(chan, "vm-num-i-have");
10011                if (!res)
10012                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
10013                if (!res)
10014                   res = ast_play_and_wait(chan, "vm-tocallnum");
10015                /* Only prompt for a caller-specified number if there is a dialout context specified */
10016                if (!ast_strlen_zero(vmu->dialout)) {
10017                   if (!res)
10018                      res = ast_play_and_wait(chan, "vm-calldiffnum");
10019                }
10020             } else {
10021                res = ast_play_and_wait(chan, "vm-nonumber");
10022                if (!ast_strlen_zero(vmu->dialout)) {
10023                   if (!res)
10024                      res = ast_play_and_wait(chan, "vm-toenternumber");
10025                }
10026             }
10027             if (!res)
10028                res = ast_play_and_wait(chan, "vm-star-cancel");
10029             if (!res)
10030                res = ast_waitfordigit(chan, 6000);
10031             if (!res) {
10032                retries++;
10033                if (retries > 3)
10034                   res = 't';
10035             }
10036             break; 
10037             
10038          }
10039          if (res == 't')
10040             res = 0;
10041          else if (res == '*')
10042             res = -1;
10043       }
10044       break;
10045       
10046    case 1:  /* Reply */
10047       /* Send reply directly to sender */
10048       if (ast_strlen_zero(cid))
10049          break;
10050 
10051       ast_callerid_parse(cid, &name, &num);
10052       if (!num) {
10053          ast_verb(3, "No CID number available, no reply sent\n");
10054          if (!res)
10055             res = ast_play_and_wait(chan, "vm-nonumber");
10056          ast_config_destroy(msg_cfg);
10057          return res;
10058       } else {
10059          struct ast_vm_user vmu2;
10060          if (find_user(&vmu2, vmu->context, num)) {
10061             struct leave_vm_options leave_options;
10062             char mailbox[AST_MAX_EXTENSION * 2 + 2];
10063             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
10064 
10065             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
10066             
10067             memset(&leave_options, 0, sizeof(leave_options));
10068             leave_options.record_gain = record_gain;
10069             res = leave_voicemail(chan, mailbox, &leave_options);
10070             if (!res)
10071                res = 't';
10072             ast_config_destroy(msg_cfg);
10073             return res;
10074          } else {
10075             /* Sender has no mailbox, can't reply */
10076             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
10077             ast_play_and_wait(chan, "vm-nobox");
10078             res = 't';
10079             ast_config_destroy(msg_cfg);
10080             return res;
10081          }
10082       } 
10083       res = 0;
10084 
10085       break;
10086    }
10087 
10088 #ifndef IMAP_STORAGE
10089    ast_config_destroy(msg_cfg);
10090 
10091    if (!res) {
10092       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
10093       vms->heard[msg] = 1;
10094       res = wait_file(chan, vms, vms->fn);
10095    }
10096 #endif
10097    return res;
10098 }

static int append_mailbox ( const char *  context,
const char *  mbox,
const char *  data 
) [static]

Definition at line 8514 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_strdupa, ast_vm_user::email, find_or_create(), ast_vm_user::fullname, inboxcount(), ast_vm_user::pager, ast_vm_user::password, populate_defaults(), queue_mwi_event(), s, and strsep().

Referenced by load_config().

08515 {
08516    /* Assumes lock is already held */
08517    char *tmp;
08518    char *stringp;
08519    char *s;
08520    struct ast_vm_user *vmu;
08521    char *mailbox_full;
08522    int new = 0, old = 0;
08523 
08524    tmp = ast_strdupa(data);
08525 
08526    if (!(vmu = find_or_create(context, mbox)))
08527       return -1;
08528    
08529    populate_defaults(vmu);
08530 
08531    stringp = tmp;
08532    if ((s = strsep(&stringp, ","))) 
08533       ast_copy_string(vmu->password, s, sizeof(vmu->password));
08534    if (stringp && (s = strsep(&stringp, ","))) 
08535       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
08536    if (stringp && (s = strsep(&stringp, ","))) 
08537       ast_copy_string(vmu->email, s, sizeof(vmu->email));
08538    if (stringp && (s = strsep(&stringp, ","))) 
08539       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
08540    if (stringp && (s = strsep(&stringp, ","))) 
08541       apply_options(vmu, s);
08542 
08543    mailbox_full = alloca(strlen(mbox) + strlen(context) + 1);
08544    strcpy(mailbox_full, mbox);
08545    strcat(mailbox_full, "@");
08546    strcat(mailbox_full, context);
08547 
08548    inboxcount(mailbox_full, &new, &old);
08549    queue_mwi_event(mailbox_full, new, old);
08550 
08551    return 0;
08552 }

static void apply_option ( struct ast_vm_user vmu,
const char *  var,
const char *  value 
) [static]

Definition at line 730 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_log(), ast_set2_flag, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::exit, ast_vm_user::language, LOG_WARNING, ast_vm_user::maxdeletedmsg, MAXMSG, ast_vm_user::maxmsg, MAXMSGLIMIT, ast_vm_user::maxsecs, ast_vm_user::saydurationm, ast_vm_user::serveremail, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SVMAIL, VM_TEMPGREETWARN, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by apply_options(), and apply_options_full().

00731 {
00732    int x;
00733    if (!strcasecmp(var, "attach")) {
00734       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00735    } else if (!strcasecmp(var, "attachfmt")) {
00736       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00737    } else if (!strcasecmp(var, "serveremail")) {
00738       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00739    } else if (!strcasecmp(var, "language")) {
00740       ast_copy_string(vmu->language, value, sizeof(vmu->language));
00741    } else if (!strcasecmp(var, "tz")) {
00742       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00743 #ifdef IMAP_STORAGE
00744    } else if (!strcasecmp(var, "imapuser")) {
00745       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00746       vmu->imapversion = imapversion;
00747    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
00748       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00749       vmu->imapversion = imapversion;
00750    } else if (!strcasecmp(var, "imapvmshareid")) {
00751       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
00752       vmu->imapversion = imapversion;
00753 #endif
00754    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00755       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
00756    } else if (!strcasecmp(var, "saycid")) {
00757       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
00758    } else if (!strcasecmp(var, "sendvoicemail")) {
00759       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
00760    } else if (!strcasecmp(var, "review")) {
00761       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00762    } else if (!strcasecmp(var, "tempgreetwarn")) {
00763       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
00764    } else if (!strcasecmp(var, "operator")) {
00765       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
00766    } else if (!strcasecmp(var, "envelope")) {
00767       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
00768    } else if (!strcasecmp(var, "moveheard")) {
00769       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
00770    } else if (!strcasecmp(var, "sayduration")) {
00771       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
00772    } else if (!strcasecmp(var, "saydurationm")) {
00773       if (sscanf(value, "%30d", &x) == 1) {
00774          vmu->saydurationm = x;
00775       } else {
00776          ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
00777       }
00778    } else if (!strcasecmp(var, "forcename")) {
00779       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
00780    } else if (!strcasecmp(var, "forcegreetings")) {
00781       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
00782    } else if (!strcasecmp(var, "callback")) {
00783       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00784    } else if (!strcasecmp(var, "dialout")) {
00785       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00786    } else if (!strcasecmp(var, "exitcontext")) {
00787       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00788    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
00789       vmu->maxsecs = atoi(value);
00790       if (vmu->maxsecs <= 0) {
00791          ast_log(LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
00792          vmu->maxsecs = vmmaxsecs;
00793       } else {
00794          vmu->maxsecs = atoi(value);
00795       }
00796       if (!strcasecmp(var, "maxmessage"))
00797          ast_log(LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
00798    } else if (!strcasecmp(var, "maxmsg")) {
00799       vmu->maxmsg = atoi(value);
00800       if (vmu->maxmsg <= 0) {
00801          ast_log(LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
00802          vmu->maxmsg = MAXMSG;
00803       } else if (vmu->maxmsg > MAXMSGLIMIT) {
00804          ast_log(LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00805          vmu->maxmsg = MAXMSGLIMIT;
00806       }
00807    } else if (!strcasecmp(var, "backupdeleted")) {
00808       if (sscanf(value, "%30d", &x) == 1)
00809          vmu->maxdeletedmsg = x;
00810       else if (ast_true(value))
00811          vmu->maxdeletedmsg = MAXMSG;
00812       else
00813          vmu->maxdeletedmsg = 0;
00814 
00815       if (vmu->maxdeletedmsg < 0) {
00816          ast_log(LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
00817          vmu->maxdeletedmsg = MAXMSG;
00818       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
00819          ast_log(LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
00820          vmu->maxdeletedmsg = MAXMSGLIMIT;
00821       }
00822    } else if (!strcasecmp(var, "volgain")) {
00823       sscanf(value, "%30lf", &vmu->volgain);
00824    } else if (!strcasecmp(var, "options")) {
00825       apply_options(vmu, value);
00826    }
00827 }

static void apply_options ( struct ast_vm_user vmu,
const char *  options 
) [static]

Definition at line 844 of file app_voicemail.c.

References apply_option(), ast_strdupa, s, strsep(), and var.

Referenced by append_mailbox(), and apply_option().

00845 {  /* Destructively Parse options and apply */
00846    char *stringp;
00847    char *s;
00848    char *var, *value;
00849    stringp = ast_strdupa(options);
00850    while ((s = strsep(&stringp, "|"))) {
00851       value = s;
00852       if ((var = strsep(&value, "=")) && value) {
00853          apply_option(vmu, var, value);
00854       }
00855    }  
00856 }

static void apply_options_full ( struct ast_vm_user retval,
struct ast_variable var 
) [static]

Definition at line 858 of file app_voicemail.c.

References apply_option(), ast_copy_string(), ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, ast_vm_user::fullname, ast_variable::name, ast_variable::next, ast_vm_user::pager, ast_vm_user::password, ast_vm_user::uniqueid, and ast_variable::value.

Referenced by find_user_realtime(), and load_config().

00859 {
00860    struct ast_variable *tmp;
00861    tmp = var;
00862    while (tmp) {
00863       if (!strcasecmp(tmp->name, "vmsecret")) {
00864          ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00865       } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) { /* don't overwrite vmsecret if it exists */
00866          if (ast_strlen_zero(retval->password))
00867             ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00868       } else if (!strcasecmp(tmp->name, "uniqueid")) {
00869          ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
00870       } else if (!strcasecmp(tmp->name, "pager")) {
00871          ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
00872       } else if (!strcasecmp(tmp->name, "email")) {
00873          ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
00874       } else if (!strcasecmp(tmp->name, "fullname")) {
00875          ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
00876       } else if (!strcasecmp(tmp->name, "context")) {
00877          ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
00878 #ifdef IMAP_STORAGE
00879       } else if (!strcasecmp(tmp->name, "imapuser")) {
00880          ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
00881          retval->imapversion = imapversion;
00882       } else if (!strcasecmp(tmp->name, "imappassword") || !strcasecmp(tmp->name, "imapsecret")) {
00883          ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
00884          retval->imapversion = imapversion;
00885       } else if (!strcasecmp(tmp->name, "imapvmshareid")) {
00886          ast_copy_string(retval->imapvmshareid, tmp->value, sizeof(retval->imapvmshareid));
00887          retval->imapversion = imapversion;
00888 #endif
00889       } else
00890          apply_option(retval, tmp->name, tmp->value);
00891       tmp = tmp->next;
00892    } 
00893 }

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

Definition at line 3275 of file app_voicemail.c.

References ast_log(), BASEMAXINLINE, eol, errno, inchar(), baseio::iocp, LOG_WARNING, and ochar().

03276 {
03277    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
03278       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
03279       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
03280       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
03281    int i, hiteof = 0;
03282    FILE *fi;
03283    struct baseio bio;
03284 
03285    memset(&bio, 0, sizeof(bio));
03286    bio.iocp = BASEMAXINLINE;
03287 
03288    if (!(fi = fopen(filename, "rb"))) {
03289       ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
03290       return -1;
03291    }
03292 
03293    while (!hiteof) {
03294       unsigned char igroup[3], ogroup[4];
03295       int c, n;
03296 
03297       igroup[0] = igroup[1] = igroup[2] = 0;
03298 
03299       for (n = 0; n < 3; n++) {
03300          if ((c = inchar(&bio, fi)) == EOF) {
03301             hiteof = 1;
03302             break;
03303          }
03304 
03305          igroup[n] = (unsigned char)c;
03306       }
03307 
03308       if (n > 0) {
03309          ogroup[0] = dtable[igroup[0] >> 2];
03310          ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
03311          ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
03312          ogroup[3] = dtable[igroup[2] & 0x3F];
03313 
03314          if (n < 3) {
03315             ogroup[3] = '=';
03316 
03317             if (n < 2)
03318                ogroup[2] = '=';
03319          }
03320 
03321          for (i = 0; i < 4; i++)
03322             ochar(&bio, ogroup[i], so);
03323       }
03324    }
03325 
03326    fclose(fi);
03327    
03328    if (fputs(eol, so) == EOF)
03329       return 0;
03330 
03331    return 1;
03332 }

static int change_password_realtime ( struct ast_vm_user vmu,
const char *  password 
) [static]

Definition at line 829 of file app_voicemail.c.

References ast_copy_string(), ast_strlen_zero(), ast_update_realtime(), ast_vm_user::password, and ast_vm_user::uniqueid.

Referenced by vm_change_password().

00830 {
00831    int res = -1;
00832    if (!strcmp(vmu->password, password)) {
00833       /* No change (but an update would return 0 rows updated, so we opt out here) */
00834       return 0;
00835    } else if (!ast_strlen_zero(vmu->uniqueid)) {
00836       if (ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, NULL) > 0) {
00837          ast_copy_string(vmu->password, password, sizeof(vmu->password));
00838          res = 0;
00839       }
00840    }
00841    return res;
00842 }

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

Check if the string would need encoding within the MIME standard, to avoid confusing certain mail software that expects messages to be 7-bit clean.

Definition at line 3432 of file app_voicemail.c.

Referenced by make_email_file().

03433 {
03434    for (; *str; str++) {
03435       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
03436          return 1;
03437       }
03438    }
03439    return 0;
03440 }

static int close_mailbox ( struct vm_state vms,
struct ast_vm_user vmu 
) [static]

Definition at line 6284 of file app_voicemail.c.

References ast_check_realtime(), ast_debug, ast_log(), ast_test_flag, ast_unlock_path(), ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, DELETE, vm_state::deleted, ERROR_LOCK_PATH, ERROR_MAILBOX_FULL, EXISTS, vm_state::fn, vm_state::fn2, vm_state::heard, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by vm_execmain().

06285 {
06286    int x = 0;
06287 #ifndef IMAP_STORAGE
06288    int res = 0, nummsg;
06289 #endif
06290 
06291    if (vms->lastmsg <= -1)
06292       goto done;
06293 
06294    vms->curmsg = -1; 
06295 #ifndef IMAP_STORAGE
06296    /* Get the deleted messages fixed */ 
06297    if (vm_lock_path(vms->curdir))
06298       return ERROR_LOCK_PATH;
06299 
06300    for (x = 0; x < vmu->maxmsg; x++) { 
06301       if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) { 
06302          /* Save this message.  It's not in INBOX or hasn't been heard */ 
06303          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
06304          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
06305             break;
06306          vms->curmsg++; 
06307          make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg); 
06308          if (strcmp(vms->fn, vms->fn2)) { 
06309             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
06310          } 
06311       } else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { 
06312          /* Move to old folder before deleting */ 
06313          res = save_to_folder(vmu, vms, x, 1);
06314          if (res == ERROR_LOCK_PATH || res == ERROR_MAILBOX_FULL) {
06315             /* If save failed do not delete the message */
06316             ast_log(LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
06317             vms->deleted[x] = 0;
06318             vms->heard[x] = 0;
06319             --x;
06320          }
06321       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
06322          /* Move to deleted folder */ 
06323          res = save_to_folder(vmu, vms, x, 10);
06324          if (res == ERROR_LOCK_PATH) {
06325             /* If save failed do not delete the message */
06326             vms->deleted[x] = 0;
06327             vms->heard[x] = 0;
06328             --x;
06329          }
06330       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
06331          /* If realtime storage enabled - we should explicitly delete this message,
06332          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
06333          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
06334          if (EXISTS(vms->curdir, x, vms->fn, NULL))
06335             DELETE(vms->curdir, x, vms->fn, vmu);
06336       }
06337    } 
06338 
06339    /* Delete ALL remaining messages */
06340    nummsg = x - 1;
06341    for (x = vms->curmsg + 1; x <= nummsg; x++) {
06342       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
06343       if (EXISTS(vms->curdir, x, vms->fn, NULL))
06344          DELETE(vms->curdir, x, vms->fn, vmu);
06345    }
06346    ast_unlock_path(vms->curdir);
06347 #else
06348    if (vms->deleted) {
06349       for (x = 0; x < vmu->maxmsg; x++) { 
06350          if (vms->deleted[x]) { 
06351             ast_debug(3, "IMAP delete of %d\n", x);
06352             DELETE(vms->curdir, x, vms->fn, vmu);
06353          }
06354       }
06355    }
06356 #endif
06357 
06358 done:
06359    if (vms->deleted)
06360       memset(vms->deleted, 0, vmu->maxmsg * sizeof(int)); 
06361    if (vms->heard)
06362       memset(vms->heard, 0, vmu->maxmsg * sizeof(int)); 
06363 
06364    return 0;
06365 }

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

Definition at line 8698 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

08699 {
08700    int which = 0;
08701    int wordlen;
08702    struct ast_vm_user *vmu;
08703    const char *context = "";
08704 
08705    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
08706    if (pos > 4)
08707       return NULL;
08708    if (pos == 3)
08709       return (state == 0) ? ast_strdup("for") : NULL;
08710    wordlen = strlen(word);
08711    AST_LIST_TRAVERSE(&users, vmu, list) {
08712       if (!strncasecmp(word, vmu->context, wordlen)) {
08713          if (context && strcmp(context, vmu->context) && ++which > state)
08714             return ast_strdup(vmu->context);
08715          /* ignore repeated contexts ? */
08716          context = vmu->context;
08717       }
08718    }
08719    return NULL;
08720 }

static int copy ( char *  infile,
char *  outfile 
) [static]

Definition at line 3107 of file app_voicemail.c.

References ast_log(), errno, LOG_WARNING, and VOICEMAIL_FILE_MODE.

03108 {
03109    int ifd;
03110    int ofd;
03111    int res;
03112    int len;
03113    char buf[4096];
03114 
03115 #ifdef HARDLINK_WHEN_POSSIBLE
03116    /* Hard link if possible; saves disk space & is faster */
03117    if (link(infile, outfile)) {
03118 #endif
03119       if ((ifd = open(infile, O_RDONLY)) < 0) {
03120          ast_log(LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03121          return -1;
03122       }
03123       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03124          ast_log(LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03125          close(ifd);
03126          return -1;
03127       }
03128       do {
03129          len = read(ifd, buf, sizeof(buf));
03130          if (len < 0) {
03131             ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03132             close(ifd);
03133             close(ofd);
03134             unlink(outfile);
03135          }
03136          if (len) {
03137             res = write(ofd, buf, len);
03138             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03139                ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03140                close(ifd);
03141                close(ofd);
03142                unlink(outfile);
03143             }
03144          }
03145       } while (len);
03146       close(ifd);
03147       close(ofd);
03148       return 0;
03149 #ifdef HARDLINK_WHEN_POSSIBLE
03150    } else {
03151       /* Hard link succeeded */
03152       return 0;
03153    }
03154 #endif
03155 }

static int copy_message ( struct ast_channel chan,
struct ast_vm_user vmu,
int  imbox,
int  msgnum,
long  duration,
struct ast_vm_user recip,
char *  fmt,
char *  dir 
) [static]

Definition at line 4149 of file app_voicemail.c.

References ast_copy_string(), ast_log(), ast_unlock_path(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, COPY, create_dirpath(), ERROR_LOCK_PATH, last_message_index(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_dir(), make_file(), mbox(), notify_new_message(), S_OR, and vm_lock_path().

Referenced by forward_message(), and leave_voicemail().

04150    {
04151       char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
04152       const char *frombox = mbox(imbox);
04153       int recipmsgnum;
04154 
04155       ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
04156 
04157       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04158       
04159       if (!dir)
04160          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
04161       else
04162          ast_copy_string(fromdir, dir, sizeof(fromdir));
04163 
04164       make_file(frompath, sizeof(frompath), fromdir, msgnum);
04165       make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04166 
04167       if (vm_lock_path(todir))
04168          return ERROR_LOCK_PATH;
04169 
04170       recipmsgnum = last_message_index(recip, todir) + 1;
04171       if (recipmsgnum < recip->maxmsg) {
04172          make_file(topath, sizeof(topath), todir, recipmsgnum);
04173          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
04174       } else {
04175          ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
04176       }
04177       ast_unlock_path(todir);
04178       notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
04179       
04180       return 0;
04181    }

static void copy_plain_file ( char *  frompath,
char *  topath 
) [static]

Definition at line 3157 of file app_voicemail.c.

References ast_check_realtime(), ast_filecopy(), ast_load_realtime(), ast_store_realtime(), ast_variables_destroy(), copy(), exten, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by forward_message().

03158 {
03159    char frompath2[PATH_MAX], topath2[PATH_MAX];
03160    struct ast_variable *tmp, *var = NULL;
03161    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
03162    ast_filecopy(frompath, topath, NULL);
03163    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
03164    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
03165    if (ast_check_realtime("voicemail_data")) {
03166       var = ast_load_realtime("voicemail_data", "filename", frompath, NULL);
03167       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
03168       for (tmp = var; tmp; tmp = tmp->next) {
03169          if (!strcasecmp(tmp->name, "origmailbox")) {
03170             origmailbox = tmp->value;
03171          } else if (!strcasecmp(tmp->name, "context")) {
03172             context = tmp->value;
03173          } else if (!strcasecmp(tmp->name, "macrocontext")) {
03174             macrocontext = tmp->value;
03175          } else if (!strcasecmp(tmp->name, "exten")) {
03176             exten = tmp->value;
03177          } else if (!strcasecmp(tmp->name, "priority")) {
03178             priority = tmp->value;
03179          } else if (!strcasecmp(tmp->name, "callerchan")) {
03180             callerchan = tmp->value;
03181          } else if (!strcasecmp(tmp->name, "callerid")) {
03182             callerid = tmp->value;
03183          } else if (!strcasecmp(tmp->name, "origdate")) {
03184             origdate = tmp->value;
03185          } else if (!strcasecmp(tmp->name, "origtime")) {
03186             origtime = tmp->value;
03187          } else if (!strcasecmp(tmp->name, "category")) {
03188             category = tmp->value;
03189          } else if (!strcasecmp(tmp->name, "duration")) {
03190             duration = tmp->value;
03191          }
03192       }
03193       ast_store_realtime("voicemail_data", "filename", topath, "origmailbox", origmailbox, "context", context, "macrocontext", macrocontext, "exten", exten, "priority", priority, "callerchan", callerchan, "callerid", callerid, "origdate", origdate, "origtime", origtime, "category", category, "duration", duration, NULL);
03194    }
03195    copy(frompath2, topath2);
03196    ast_variables_destroy(var);
03197 }

static int count_messages ( struct ast_vm_user vmu,
char *  dir 
) [static]

Definition at line 3032 of file app_voicemail.c.

References ast_unlock_path(), ERROR_LOCK_PATH, and vm_lock_path().

Referenced by leave_voicemail(), manager_list_voicemail_users(), and open_mailbox().

03033 {
03034    /* Find all .txt files - even if they are not in sequence from 0000 */
03035 
03036    int vmcount = 0;
03037    DIR *vmdir = NULL;
03038    struct dirent *vment = NULL;
03039 
03040    if (vm_lock_path(dir))
03041       return ERROR_LOCK_PATH;
03042 
03043    if ((vmdir = opendir(dir))) {
03044       while ((vment = readdir(vmdir))) {
03045          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) 
03046             vmcount++;
03047       }
03048       closedir(vmdir);
03049    }
03050    ast_unlock_path(dir);
03051    
03052    return vmcount;
03053 }

static int create_dirpath ( char *  dest,
int  len,
const char *  context,
const char *  ext,
const char *  folder 
) [static]

basically mkdir -p $dest/$context/$ext/$folder

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

Definition at line 1116 of file app_voicemail.c.

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

01117 {
01118    mode_t   mode = VOICEMAIL_DIR_MODE;
01119    int res;
01120 
01121    make_dir(dest, len, context, ext, folder);
01122    if ((res = ast_mkdir(dest, mode))) {
01123       ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01124       return -1;
01125    }
01126    return 0;
01127 }

static int dialout ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  num,
char *  outgoing_context 
) [static]

Definition at line 9853 of file app_voicemail.c.

References ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_verb, ast_waitfordigit(), ast_channel::context, ast_channel::exten, and ast_channel::priority.

Referenced by advanced_options(), and vm_execmain().

09854 {
09855    int cmd = 0;
09856    char destination[80] = "";
09857    int retries = 0;
09858 
09859    if (!num) {
09860       ast_verb(3, "Destination number will be entered manually\n");
09861       while (retries < 3 && cmd != 't') {
09862          destination[1] = '\0';
09863          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
09864          if (!cmd)
09865             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
09866          if (!cmd)
09867             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
09868          if (!cmd) {
09869             cmd = ast_waitfordigit(chan, 6000);
09870             if (cmd)
09871                destination[0] = cmd;
09872          }
09873          if (!cmd) {
09874             retries++;
09875          } else {
09876 
09877             if (cmd < 0)
09878                return 0;
09879             if (cmd == '*') {
09880                ast_verb(3, "User hit '*' to cancel outgoing call\n");
09881                return 0;
09882             }
09883             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination)-1, 6000, 10000, "#")) < 0) 
09884                retries++;
09885             else
09886                cmd = 't';
09887          }
09888       }
09889       if (retries >= 3) {
09890          return 0;
09891       }
09892       
09893    } else {
09894       ast_verb(3, "Destination number is CID number '%s'\n", num);
09895       ast_copy_string(destination, num, sizeof(destination));
09896    }
09897 
09898    if (!ast_strlen_zero(destination)) {
09899       if (destination[strlen(destination) -1 ] == '*')
09900          return 0; 
09901       ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
09902       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
09903       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
09904       chan->priority = 0;
09905       return 9;
09906    }
09907    return 0;
09908 }

static char* encode_mime_str ( const char *  start,
char *  end,
size_t  endsize,
size_t  preamble,
size_t  postamble 
) [static]

Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain control characters.

Additionally, if the encoded string would exceed the MIME limit of 76 characters per line, then the encoding will be broken up into multiple sections, separated by a space character, in order to facilitate breaking up the associated header across multiple lines.

Parameters:
start A string to be encoded
end An expandable buffer for holding the result
preamble The length of the first line already used for this string, to ensure that each line maintains a maximum length of 76 chars.
postamble the length of any additional characters appended to the line, used to ensure proper field wrapping.
Return values:
The encoded string.

Definition at line 3458 of file app_voicemail.c.

References charset.

Referenced by make_email_file().

03459 {
03460    char tmp[80];
03461    int first_section = 1;
03462    size_t endlen = 0, tmplen = 0;
03463    *end = '\0';
03464 
03465    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03466    for (; *start; start++) {
03467       int need_encoding = 0;
03468       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
03469          need_encoding = 1;
03470       }
03471       if ((first_section && need_encoding && preamble + tmplen > 70) ||
03472          (first_section && !need_encoding && preamble + tmplen > 72) ||
03473          (!first_section && need_encoding && tmplen > 70) ||
03474          (!first_section && !need_encoding && tmplen > 72)) {
03475          /* Start new line */
03476          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
03477          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03478          first_section = 0;
03479       }
03480       if (need_encoding && *start == ' ') {
03481          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
03482       } else if (need_encoding) {
03483          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
03484       } else {
03485          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
03486       }
03487    }
03488    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
03489    return end;
03490 }

static struct ast_vm_user* find_or_create ( const char *  context,
const char *  mbox 
) [static, read]

Definition at line 8482 of file app_voicemail.c.

References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_test_flag, ast_vm_user::context, globalflags, LOG_WARNING, ast_vm_user::mailbox, and VM_SEARCH.

Referenced by append_mailbox(), and load_config().

08483 {
08484    struct ast_vm_user *vmu;
08485 
08486    AST_LIST_TRAVERSE(&users, vmu, list) {
08487       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mbox, vmu->mailbox)) {
08488          if (strcasecmp(vmu->context, context)) {
08489             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
08490                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
08491                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
08492                   \n\tamend your voicemail.conf file to avoid this situation.\n", mbox);
08493          }
08494          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", mbox);
08495          return NULL;
08496       }
08497       if (!strcasecmp(context, vmu->context) && !strcasecmp(mbox, vmu->mailbox)) {
08498          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", mbox, context);
08499          return NULL;
08500       }
08501    }
08502    
08503    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
08504       return NULL;
08505    
08506    ast_copy_string(vmu->context, context, sizeof(vmu->context));
08507    ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
08508 
08509    AST_LIST_INSERT_TAIL(&users, vmu, list);
08510    
08511    return vmu;
08512 }

static struct ast_vm_user* find_user ( struct ast_vm_user ivm,
const char *  context,
const char *  mailbox 
) [static, read]

Definition at line 939 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_malloc, ast_set2_flag, ast_test_flag, find_user_realtime(), globalflags, VM_ALLOCED, and VM_SEARCH.

00940 {
00941    /* This function could be made to generate one from a database, too */
00942    struct ast_vm_user *vmu = NULL, *cur;
00943    AST_LIST_LOCK(&users);
00944 
00945    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
00946       context = "default";
00947 
00948    AST_LIST_TRAVERSE(&users, cur, list) {
00949 #ifdef IMAP_STORAGE
00950       if (cur->imapversion != imapversion) {
00951          continue;
00952       }
00953 #endif
00954       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
00955          break;
00956       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
00957          break;
00958    }
00959    if (cur) {
00960       /* Make a copy, so that on a reload, we have no race */
00961       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
00962          memcpy(vmu, cur, sizeof(*vmu));
00963          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
00964          AST_LIST_NEXT(vmu, list) = NULL;
00965       }
00966    } else
00967       vmu = find_user_realtime(ivm, context, mailbox);
00968    AST_LIST_UNLOCK(&users);
00969    return vmu;
00970 }

static struct ast_vm_user* find_user_realtime ( struct ast_vm_user ivm,
const char *  context,
const char *  mailbox 
) [static, read]

Definition at line 910 of file app_voicemail.c.

References apply_options_full(), ast_calloc, ast_copy_string(), ast_free, ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), globalflags, ast_vm_user::mailbox, populate_defaults(), var, VM_ALLOCED, and VM_SEARCH.

00911 {
00912    struct ast_variable *var;
00913    struct ast_vm_user *retval;
00914 
00915    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
00916       if (!ivm)
00917          ast_set_flag(retval, VM_ALLOCED);   
00918       else
00919          memset(retval, 0, sizeof(*retval));
00920       if (mailbox) 
00921          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
00922       populate_defaults(retval);
00923       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
00924          var = ast_load_realtime("voicemail", "mailbox", mailbox, NULL);
00925       else
00926          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, NULL);
00927       if (var) {
00928          apply_options_full(retval, var);
00929          ast_variables_destroy(var);
00930       } else { 
00931          if (!ivm) 
00932             ast_free(retval);
00933          retval = NULL;
00934       }  
00935    } 
00936    return retval;
00937 }

static int forward_message ( struct ast_channel chan,
char *  context,
struct vm_state vms,
struct ast_vm_user sender,
char *  fmt,
int  flag,
signed char  record_gain 
) [static]

Definition at line 5618 of file app_voicemail.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, ast_channel::context, copy_message(), copy_plain_file(), create_dirpath(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), vm_state::fn, free_user(), globalflags, ast_channel::language, leave_voicemail(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_vm_user::mailbox, make_file(), pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), s, S_OR, sendmail(), STORE, strsep(), vm_state::username, VM_ATTACH, VM_DIRECFORWARD, and vm_forwardoptions().

Referenced by vm_execmain().

05619    {
05620 #ifdef IMAP_STORAGE
05621       int todircount = 0;
05622       struct vm_state *dstvms;
05623 #endif
05624       char username[70] = "";
05625       char fn[PATH_MAX]; /* for playback of name greeting */
05626       char ecodes[16] = "#";
05627       int res = 0, cmd = 0;
05628       struct ast_vm_user *receiver = NULL, *vmtmp;
05629       AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
05630       char *stringp;
05631       const char *s;
05632       int saved_messages = 0, found = 0;
05633       int valid_extensions = 0;
05634       char *dir;
05635       int curmsg;
05636 
05637       if (vms == NULL) return -1;
05638       dir = vms->curdir;
05639       curmsg = vms->curmsg;
05640       
05641       while (!res && !valid_extensions) {
05642          int use_directory = 0;
05643          if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
05644             int done = 0;
05645             int retries = 0;
05646             cmd = 0;
05647             while ((cmd >= 0) && !done) {
05648                if (cmd)
05649                   retries = 0;
05650                switch (cmd) {
05651                case '1': 
05652                   use_directory = 0;
05653                   done = 1;
05654                   break;
05655                case '2': 
05656                   use_directory = 1;
05657                   done = 1;
05658                   break;
05659                case '*': 
05660                   cmd = 't';
05661                   done = 1;
05662                   break;
05663                default: 
05664                   /* Press 1 to enter an extension press 2 to use the directory */
05665                   cmd = ast_play_and_wait(chan, "vm-forward");
05666                   if (!cmd)
05667                      cmd = ast_waitfordigit(chan, 3000);
05668                   if (!cmd)
05669                      retries++;
05670                   if (retries > 3) {
05671                      cmd = 't';
05672                      done = 1;
05673                   }
05674                   
05675                }
05676             }
05677             if (cmd < 0 || cmd == 't')
05678                break;
05679          }
05680          
05681          if (use_directory) {
05682             /* use app_directory */
05683             
05684             char old_context[sizeof(chan->context)];
05685             char old_exten[sizeof(chan->exten)];
05686             int old_priority;
05687             struct ast_app* app;
05688 
05689             app = pbx_findapp("Directory");
05690             if (app) {
05691                char vmcontext[256];
05692                /* make backup copies */
05693                memcpy(old_context, chan->context, sizeof(chan->context));
05694                memcpy(old_exten, chan->exten, sizeof(chan->exten));
05695                old_priority = chan->priority;
05696                
05697                /* call the the Directory, changes the channel */
05698                snprintf(vmcontext, sizeof(vmcontext), "%s||v", context ? context : "default");
05699                res = pbx_exec(chan, app, vmcontext);
05700                
05701                ast_copy_string(username, chan->exten, sizeof(username));
05702                
05703                /* restore the old context, exten, and priority */
05704                memcpy(chan->context, old_context, sizeof(chan->context));
05705                memcpy(chan->exten, old_exten, sizeof(chan->exten));
05706                chan->priority = old_priority;
05707                
05708             } else {
05709                ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
05710                ast_clear_flag((&globalflags), VM_DIRECFORWARD);
05711             }
05712          } else {
05713             /* Ask for an extension */
05714             res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
05715             if (res)
05716                break;
05717             if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
05718                break;
05719          }
05720          
05721          /* start all over if no username */
05722          if (ast_strlen_zero(username))
05723             continue;
05724          stringp = username;
05725          s = strsep(&stringp, "*");
05726          /* start optimistic */
05727          valid_extensions = 1;
05728          while (s) {
05729             /* Don't forward to ourselves but allow leaving a message for ourselves (flag == 1).  find_user is going to malloc since we have a NULL as first argument */
05730             if ((flag == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
05731                AST_LIST_INSERT_HEAD(&extensions, receiver, list);
05732                found++;
05733             } else {
05734                while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
05735                   free_user(receiver);
05736                }
05737                ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
05738                valid_extensions = 0;
05739                break;
05740             }
05741 
05742             /* play name if available, else play extension number */
05743             snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
05744             RETRIEVE(fn, -1, s, receiver->context);
05745             if (ast_fileexists(fn, NULL, NULL) > 0) {
05746                res = ast_stream_and_wait(chan, fn, ecodes);
05747                if (res) {
05748                   DISPOSE(fn, -1);
05749                   return res;
05750                }
05751             } else {
05752                res = ast_say_digit_str(chan, s, ecodes, chan->language);
05753             }
05754             DISPOSE(fn, -1);
05755 
05756             s = strsep(&stringp, "*");
05757          }
05758          /* break from the loop of reading the extensions */
05759          if (valid_extensions)
05760             break;
05761          /* "I am sorry, that's not a valid extension.  Please try again." */
05762          res = ast_play_and_wait(chan, "pbx-invalid");
05763       }
05764       /* check if we're clear to proceed */
05765       if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
05766          return res;
05767       if (flag==1) {
05768          struct leave_vm_options leave_options;
05769          char mailbox[AST_MAX_EXTENSION * 2 + 2];
05770          /* Make sure that context doesn't get set as a literal "(null)" (or else find_user won't find it) */
05771          if (context)
05772             snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
05773          else
05774             ast_copy_string(mailbox, username, sizeof(mailbox));
05775 
05776          /* Send VoiceMail */
05777          memset(&leave_options, 0, sizeof(leave_options));
05778          leave_options.record_gain = record_gain;
05779          cmd = leave_voicemail(chan, mailbox, &leave_options);
05780       } else {
05781          /* Forward VoiceMail */
05782          long duration = 0;
05783          char origmsgfile[PATH_MAX], msgfile[PATH_MAX];
05784          struct vm_state vmstmp;
05785          memcpy(&vmstmp, vms, sizeof(vmstmp));
05786 
05787          make_file(origmsgfile, sizeof(origmsgfile), dir, curmsg);
05788          create_dirpath(vmstmp.curdir, sizeof(vmstmp.curdir), sender->context, vmstmp.username, "tmp");
05789          make_file(msgfile, sizeof(msgfile), vmstmp.curdir, curmsg);
05790          
05791          RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
05792          
05793          /* Alter a surrogate file, only */
05794          copy_plain_file(origmsgfile, msgfile);
05795 
05796          cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp);
05797          if (!cmd) {
05798             AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
05799 #ifdef IMAP_STORAGE
05800                char *myserveremail = serveremail;
05801                int attach_user_voicemail;
05802                /* get destination mailbox */
05803                dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, 0);
05804                if (!dstvms) {
05805                   dstvms = create_vm_state_from_user(vmtmp);
05806                }
05807                if (dstvms) {
05808                   init_mailstream(dstvms, 0);
05809                   if (!dstvms->mailstream) {
05810                      ast_log(LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
05811                   } else {
05812                      STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms);
05813                      run_externnotify(vmtmp->context, vmtmp->mailbox); 
05814                   }
05815                } else {
05816                   ast_log(LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
05817                }
05818                if (!ast_strlen_zero(vmtmp->serveremail))
05819                   myserveremail = vmtmp->serveremail;
05820                attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
05821                /* NULL category for IMAP storage */
05822                sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, dstvms->curbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vms->fn, fmt, duration, attach_user_voicemail, chan, NULL);
05823 #else
05824                copy_message(chan, sender, -1, curmsg, duration, vmtmp, fmt, vmstmp.curdir);
05825 #endif
05826                saved_messages++;
05827                AST_LIST_REMOVE_CURRENT(list);
05828                free_user(vmtmp);
05829                if (res)
05830                   break;
05831             }
05832             AST_LIST_TRAVERSE_SAFE_END;
05833             if (saved_messages > 0) {
05834                /* give confirmation that the message was saved */
05835                /* commented out since we can't forward batches yet
05836                if (saved_messages == 1)
05837                   res = ast_play_and_wait(chan, "vm-message");
05838                else
05839                   res = ast_play_and_wait(chan, "vm-messages");
05840                if (!res)
05841                   res = ast_play_and_wait(chan, "vm-saved"); */
05842                res = ast_play_and_wait(chan, "vm-msgsaved");
05843             }  
05844          }
05845          /* Remove surrogate file */
05846          DISPOSE(dir, curmsg);
05847       }
05848 
05849       /* If anything failed above, we still have this list to free */
05850       while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
05851          free_user(vmtmp);
05852       return res ? res : cmd;
05853    }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1152 of file app_voicemail.c.

References ast_free, ast_test_flag, and VM_ALLOCED.

01153 {
01154    if (ast_test_flag(vmu, VM_ALLOCED))
01155       ast_free(vmu);
01156 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 9128 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_set_flag, free_user(), and VM_ALLOCED.

Referenced by load_config(), and unload_module().

09129 {
09130    struct ast_vm_user *cur;
09131    AST_LIST_LOCK(&users);
09132    while ((cur = AST_LIST_REMOVE_HEAD(&users, list))) {
09133       ast_set_flag(cur, VM_ALLOCED);
09134       free_user(cur);
09135    }
09136    AST_LIST_UNLOCK(&users);
09137 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 9140 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

09141 {
09142    struct vm_zone *zcur;
09143    AST_LIST_LOCK(&zones);
09144    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
09145       free_zone(zcur);
09146    AST_LIST_UNLOCK(&zones);
09147 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 3973 of file app_voicemail.c.

References ast_free.

03974 {
03975    ast_free(z);
03976 }

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

Definition at line 3910 of file app_voicemail.c.

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

03911 {
03912    struct ast_tm tm;
03913    struct timeval t = ast_tvnow();
03914    
03915    ast_localtime(&t, &tm, "UTC");
03916 
03917    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
03918 }

static int get_folder ( struct ast_channel chan,
int  start 
) [static]

get_folder: Folder menu Plays "press 1 for INBOX messages" etc. Should possibly be internationalized

Definition at line 5391 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_waitfordigit(), ast_channel::language, mbox(), and vm_play_folder_name().

Referenced by get_folder2().

05392    {
05393       int x;
05394       int d;
05395       char fn[PATH_MAX];
05396       d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
05397       if (d)
05398          return d;
05399       for (x = start; x < 5; x++) { /* For all folders */
05400          if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
05401             return d;
05402          d = ast_play_and_wait(chan, "vm-for"); /* "for" */
05403          if (d)
05404             return d;
05405          snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
05406          d = vm_play_folder_name(chan, fn);
05407          if (d)
05408             return d;
05409          d = ast_waitfordigit(chan, 500);
05410          if (d)
05411             return d;
05412       }
05413       d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
05414       if (d)
05415          return d;
05416       d = ast_waitfordigit(chan, 4000);
05417       return d;
05418    }

static int get_folder2 ( struct ast_channel chan,
char *  fn,
int  start 
) [static]

Definition at line 5420 of file app_voicemail.c.

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

05421    {
05422       int res = 0;
05423       res = ast_play_and_wait(chan, fn);  /* Folder name */
05424       while (((res < '0') || (res > '9')) &&
05425             (res != '#') && (res >= 0)) {
05426          res = get_folder(chan, 0);
05427       }
05428       return res;
05429    }

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

Reload voicemail configuration from the CLI.

Definition at line 8833 of file app_voicemail.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, load_config(), and ast_cli_entry::usage.

08834 {
08835    switch (cmd) {
08836    case CLI_INIT:
08837       e->command = "voicemail reload";
08838       e->usage =
08839          "Usage: voicemail reload\n"
08840          "       Reload voicemail configuration\n";
08841       return NULL;
08842    case CLI_GENERATE:
08843       return NULL;
08844    }
08845 
08846    if (a->argc != e->args)
08847       return CLI_SHOWUSAGE;
08848 
08849    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
08850    load_config(1);
08851    
08852    return CLI_SUCCESS;
08853 }

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

Show a list of voicemail users in the CLI.

Definition at line 8723 of file app_voicemail.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_check_realtime(), ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_voicemail_show_users(), ast_vm_user::context, ast_cli_args::fd, ast_vm_user::fullname, HVSU_OUTPUT_FORMAT, inboxcount(), ast_cli_args::line, ast_vm_user::mailbox, ast_cli_args::n, ast_cli_args::pos, show_users_realtime(), ast_cli_entry::usage, ast_cli_args::word, and ast_vm_user::zonetag.

08724 {
08725    struct ast_vm_user *vmu;
08726 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
08727    const char *context = NULL;
08728    int users_counter = 0;
08729 
08730    switch (cmd) {
08731    case CLI_INIT:
08732       e->command = "voicemail show users";
08733       e->usage =
08734          "Usage: voicemail show users [for <context>]\n"
08735          "       Lists all mailboxes currently set up\n";
08736       return NULL;
08737    case CLI_GENERATE:
08738       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
08739    }  
08740 
08741    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
08742       return CLI_SHOWUSAGE;
08743    if (a->argc == 5) {
08744       if (strcmp(a->argv[3], "for"))
08745          return CLI_SHOWUSAGE;
08746       context = a->argv[4];
08747    }
08748 
08749    if (ast_check_realtime("voicemail")) {
08750       if (!context) {
08751          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
08752          return CLI_SHOWUSAGE;
08753       }
08754       return show_users_realtime(a->fd, context);
08755    }
08756 
08757    AST_LIST_LOCK(&users);
08758    if (AST_LIST_EMPTY(&users)) {
08759       ast_cli(a->fd, "There are no voicemail users currently defined\n");
08760       AST_LIST_UNLOCK(&users);
08761       return CLI_FAILURE;
08762    }
08763    if (a->argc == 3)
08764       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
08765    else {
08766       int count = 0;
08767       AST_LIST_TRAVERSE(&users, vmu, list) {
08768          if (!strcmp(context, vmu->context))
08769             count++;
08770       }
08771       if (count) {
08772          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
08773       } else {
08774          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
08775          AST_LIST_UNLOCK(&users);
08776          return CLI_FAILURE;
08777       }
08778    }
08779    AST_LIST_TRAVERSE(&users, vmu, list) {
08780       int newmsgs = 0, oldmsgs = 0;
08781       char count[12], tmp[256] = "";
08782 
08783       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
08784          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
08785          inboxcount(tmp, &newmsgs, &oldmsgs);
08786          snprintf(count, sizeof(count), "%d", newmsgs);
08787          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
08788          users_counter++;
08789       }
08790    }
08791    AST_LIST_UNLOCK(&users);
08792    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
08793    return CLI_SUCCESS;
08794 }

static char* handle_voicemail_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 8797 of file app_voicemail.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, HVSZ_OUTPUT_FORMAT, vm_zone::msg_format, vm_zone::name, vm_zone::timezone, and ast_cli_entry::usage.

08798 {
08799    struct vm_zone *zone;
08800 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
08801    char *res = CLI_SUCCESS;
08802 
08803    switch (cmd) {
08804    case CLI_INIT:
08805       e->command = "voicemail show zones";
08806       e->usage =
08807          "Usage: voicemail show zones\n"
08808          "       Lists zone message formats\n";
08809       return NULL;
08810    case CLI_GENERATE:
08811       return NULL;
08812    }
08813 
08814    if (a->argc != e->args)
08815       return CLI_SHOWUSAGE;
08816 
08817    AST_LIST_LOCK(&zones);
08818    if (!AST_LIST_EMPTY(&zones)) {
08819       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
08820       AST_LIST_TRAVERSE(&zones, zone, list) {
08821          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
08822       }
08823    } else {
08824       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
08825       res = CLI_FAILURE;
08826    }
08827    AST_LIST_UNLOCK(&zones);
08828 
08829    return res;
08830 }

static int has_voicemail ( const char *  mailbox,
const char *  folder 
) [static]

Definition at line 4227 of file app_voicemail.c.

References __has_voicemail(), ast_copy_string(), and strsep().

04228    {
04229       char tmp[256], *tmp2 = tmp, *mbox, *context;
04230       ast_copy_string(tmp, mailbox, sizeof(tmp));
04231       while ((mbox = strsep(&tmp2, ","))) {
04232          if ((context = strchr(mbox, '@')))
04233             *context++ = '\0';
04234          else
04235             context = "default";
04236          if (__has_voicemail(context, mbox, folder, 1))
04237             return 1;
04238       }
04239       return 0;
04240    }

static int inboxcount ( const char *  mailbox,
int *  newmsgs,
int *  oldmsgs 
) [static]

Definition at line 4243 of file app_voicemail.c.

References __has_voicemail(), ast_copy_string(), ast_strlen_zero(), and strsep().

Referenced by append_mailbox(), handle_voicemail_show_users(), leave_voicemail(), load_module(), manager_list_voicemail_users(), poll_subscribed_mailboxes(), and run_externnotify().

04244    {
04245       char tmp[256];
04246       char *context;
04247 
04248       /* If no mailbox, return immediately */
04249       if (ast_strlen_zero(mailbox))
04250          return 0;
04251 
04252       if (newmsgs)
04253          *newmsgs = 0;
04254       if (oldmsgs)
04255          *oldmsgs = 0;
04256 
04257       if (strchr(mailbox, ',')) {
04258          int tmpnew, tmpold;
04259          char *mb, *cur;
04260 
04261          ast_copy_string(tmp, mailbox, sizeof(tmp));
04262          mb = tmp;
04263          while ((cur = strsep(&mb, ", "))) {
04264             if (!ast_strlen_zero(cur)) {
04265                if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
04266                   return -1;
04267                else {
04268                   if (newmsgs)
04269                      *newmsgs += tmpnew; 
04270                   if (oldmsgs)
04271                      *oldmsgs += tmpold;
04272                }
04273             }
04274          }
04275          return 0;
04276       }
04277 
04278       ast_copy_string(tmp, mailbox, sizeof(tmp));
04279       
04280       if ((context = strchr(tmp, '@')))
04281          *context++ = '\0';
04282       else
04283          context = "default";
04284 
04285       if (newmsgs)
04286          *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
04287       if (oldmsgs)
04288          *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
04289 
04290       return 0;
04291    }

static int inbuf ( struct baseio bio,
FILE *  fi 
) [static]

Definition at line 3227 of file app_voicemail.c.

References baseio::ateof, BASEMAXINLINE, baseio::iobuf, baseio::iocp, and baseio::iolen.

Referenced by ast_eivr_getvariable(), ast_eivr_setvariable(), inchar(), and sip_addheader().

03228 {
03229    int l;
03230 
03231    if (bio->ateof)
03232       return 0;
03233 
03234    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
03235       if (ferror(fi))
03236          return -1;
03237 
03238       bio->ateof = 1;
03239       return 0;
03240    }
03241 
03242    bio->iolen = l;
03243    bio->iocp = 0;
03244 
03245    return 1;
03246 }

static int inchar ( struct baseio bio,
FILE *  fi 
) [static]

Definition at line 3248 of file app_voicemail.c.

References inbuf(), baseio::iobuf, baseio::iocp, and baseio::iolen.

Referenced by base_encode().

03249 {
03250    if (bio->iocp >= bio->iolen) {
03251       if (!inbuf(bio, fi))
03252          return EOF;
03253    }
03254 
03255    return bio->iobuf[bio->iocp++];
03256 }

static int invent_message ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  ext,
int  busy,
char *  ecodes 
) [static]

Definition at line 3945 of file app_voicemail.c.

References ast_log(), ast_say_digit_str(), ast_stream_and_wait(), ast_vm_user::context, create_dirpath(), ast_channel::language, LOG_WARNING, and play_greeting().

03946 {
03947    int res;
03948    char fn[PATH_MAX];
03949    char dest[PATH_MAX];
03950 
03951    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, ext);
03952 
03953    if ((res = create_dirpath(dest, sizeof(dest), vmu->context, ext, ""))) {
03954       ast_log(LOG_WARNING, "Failed to make directory(%s)\n", fn);
03955       return -1;
03956    }
03957 
03958    res = play_greeting(chan, vmu, fn, ecodes);
03959    if (res == -2) {
03960       /* File did not exist */
03961       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
03962       if (res)
03963          return res;
03964       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
03965    }
03966    if (res)
03967       return res;
03968 
03969    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
03970    return res;
03971 }

static int is_valid_dtmf ( const char *  key  )  [static]

Definition at line 895 of file app_voicemail.c.

References ast_log(), ast_strdupa, LOG_WARNING, and VALID_DTMF.

Referenced by load_config().

00896 {
00897    int i;
00898    char *local_key = ast_strdupa(key);
00899 
00900    for (i = 0; i < strlen(key); ++i) {
00901       if (!strchr(VALID_DTMF, *local_key)) {
00902          ast_log(LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
00903          return 0;
00904       }
00905       local_key++;
00906    }
00907    return 1;
00908 }

static int last_message_index ( struct ast_vm_user vmu,
char *  dir 
) [static]

A negative return value indicates an error.

Note:
Should always be called with a lock already set on dir.

Definition at line 3074 of file app_voicemail.c.

References map, ast_vm_user::maxmsg, and MAXMSGLIMIT.

Referenced by copy_message(), leave_voicemail(), open_mailbox(), and save_to_folder().

03075 {
03076    int x;
03077    unsigned char map[MAXMSGLIMIT] = "";
03078    DIR *msgdir;
03079    struct dirent *msgdirent;
03080    int msgdirint;
03081 
03082    /* Reading the entire directory into a file map scales better than
03083    * doing a stat repeatedly on a predicted sequence.  I suspect this
03084    * is partially due to stat(2) internally doing a readdir(2) itself to
03085    * find each file. */
03086    if (!(msgdir = opendir(dir))) {
03087       return -1;
03088    }
03089 
03090    while ((msgdirent = readdir(msgdir))) {
03091       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03092          map[msgdirint] = 1;
03093    }
03094    closedir(msgdir);
03095 
03096    for (x = 0; x < vmu->maxmsg; x++) {
03097       if (map[x] == 0)
03098          break;
03099    }
03100 
03101    return x - 1;
03102 }

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

Definition at line 4343 of file app_voicemail.c.

References ast_callerid_merge(), ast_canmatch_extension(), ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer, ast_str_create(), ast_str_set(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verb, ast_waitstream(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, ast_channel::exten, find_user(), free_user(), get_date(), inboxcount(), INTRO, invent_message(), ast_channel::language, last_message_index(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_channel::name, vm_state::newmessages, notify_new_message(), OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_greeting(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, S_OR, STORE, strsep(), transfer, vm_lock_path(), VM_OPERATOR, and VOICEMAIL_FILE_MODE.

04344 {
04345 #ifdef IMAP_STORAGE
04346    int newmsgs, oldmsgs;
04347 #endif
04348    char txtfile[PATH_MAX], tmptxtfile[PATH_MAX];
04349    struct vm_state *vms = NULL;
04350    char callerid[256];
04351    FILE *txt;
04352    char date[256];
04353    int txtdes;
04354    int res = 0;
04355    int msgnum;
04356    int duration = 0;
04357    int ausemacro = 0;
04358    int ousemacro = 0;
04359    int ouseexten = 0;
04360    int rtmsgid = 0;
04361    char tmpid[16];
04362    char tmpdur[16];
04363    char priority[16];
04364    char origtime[16];
04365    char dir[PATH_MAX], tmpdir[PATH_MAX];
04366    char fn[PATH_MAX];
04367    char prefile[PATH_MAX] = "";
04368    char tempfile[PATH_MAX] = "";
04369    char ext_context[256] = "";
04370    char fmt[80];
04371    char *context;
04372    char ecodes[17] = "#";
04373    char *tmpptr;
04374    struct ast_str *tmp = ast_str_create(16);
04375    struct ast_vm_user *vmu;
04376    struct ast_vm_user svm;
04377    const char *category = NULL, *code, *alldtmf = "0123456789ABCD*#";
04378 
04379    ast_str_set(&tmp, 0, "%s", ext);
04380    ext = ast_str_buffer(tmp);
04381    if ((context = strchr(ext, '@'))) {
04382       *context++ = '\0';
04383       tmpptr = strchr(context, '&');
04384    } else {
04385       tmpptr = strchr(ext, '&');
04386    }
04387 
04388    if (tmpptr) {
04389       *tmpptr++ = '\0';
04390    }
04391 
04392    category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
04393 
04394    ast_debug(3, "Before find_user\n");
04395    if (!(vmu = find_user(&svm, context, ext))) {
04396       ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
04397       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04398       ast_free(tmp);
04399       return res;
04400    }
04401    /* Setup pre-file if appropriate */
04402    if (strcmp(vmu->context, "default")) {
04403       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
04404    } else {
04405       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
04406    }
04407    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
04408       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
04409    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
04410       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
04411    }
04412    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
04413    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
04414       ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
04415       ast_free(tmp);
04416       return -1;
04417    }
04418    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
04419    if (ast_fileexists(tempfile, NULL, NULL) > 0) {
04420       ast_copy_string(prefile, tempfile, sizeof(prefile));
04421    }
04422    DISPOSE(tempfile, -1);
04423    /* It's easier just to try to make it than to check for its existence */
04424    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
04425 
04426    /* Check current or macro-calling context for special extensions */
04427    if (ast_test_flag(vmu, VM_OPERATOR)) {
04428       if (!ast_strlen_zero(vmu->exit)) {
04429          if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
04430             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
04431             ouseexten = 1;
04432          }
04433       } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
04434          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
04435          ouseexten = 1;
04436       } else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
04437          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
04438          ousemacro = 1;
04439       }
04440    }
04441 
04442    if (!ast_strlen_zero(vmu->exit)) {
04443       if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num)) {
04444          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
04445       }
04446    } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num)) {
04447       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
04448    } else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
04449       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
04450       ausemacro = 1;
04451    }
04452 
04453    if (ast_test_flag(options, OPT_DTMFEXIT)) {
04454       for (code = alldtmf; *code; code++) {
04455          char e[2] = "";
04456          e[0] = *code;
04457          if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num)) {
04458             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
04459          }
04460       }
04461    }
04462 
04463    /* Play the beginning intro if desired */
04464    if (!ast_strlen_zero(prefile)) {
04465       res = play_greeting(chan, vmu, prefile, ecodes);
04466       if (res == -2) {
04467          /* The file did not exist */
04468          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
04469          res = invent_message(chan, vmu, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
04470       }
04471       if (res < 0) {
04472          ast_debug(1, "Hang up during prefile playback\n");
04473          free_user(vmu);
04474          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04475          ast_free(tmp);
04476          return -1;
04477       }
04478    }
04479    if (res == '#') {
04480       /* On a '#' we skip the instructions */
04481       ast_set_flag(options, OPT_SILENT);
04482       res = 0;
04483    }
04484    if (!res && !ast_test_flag(options, OPT_SILENT)) {
04485       res = ast_stream_and_wait(chan, INTRO, ecodes);
04486       if (res == '#') {
04487          ast_set_flag(options, OPT_SILENT);
04488          res = 0;
04489       }
04490    }
04491    if (res > 0) {
04492       ast_stopstream(chan);
04493    }
04494    /* Check for a '*' here in case the caller wants to escape from voicemail to something
04495     * other than the operator -- an automated attendant or mailbox login for example */
04496    if (res == '*') {
04497       chan->exten[0] = 'a';
04498       chan->exten[1] = '\0';
04499       if (!ast_strlen_zero(vmu->exit)) {
04500          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
04501       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
04502          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
04503       }
04504       chan->priority = 0;
04505       free_user(vmu);
04506       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
04507       ast_free(tmp);
04508       return 0;
04509    }
04510 
04511    /* Check for a '0' here */
04512    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
04513 transfer:
04514       if (ouseexten || ousemacro) {
04515          chan->exten[0] = 'o';
04516          chan->exten[1] = '\0';
04517          if (!ast_strlen_zero(vmu->exit)) {
04518             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
04519          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
04520             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
04521          }
04522          ast_play_and_wait(chan, "transfer");
04523          chan->priority = 0;
04524          free_user(vmu);
04525          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
04526       }
04527       ast_free(tmp);
04528       return 0;
04529    }
04530 
04531    /* Allow all other digits to exit Voicemail and return to the dialplan */
04532    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
04533       if (!ast_strlen_zero(options->exitcontext)) {
04534          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
04535       }
04536       free_user(vmu);
04537       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
04538       return res;
04539    }
04540 
04541    if (res < 0) {
04542       free_user(vmu);
04543       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04544       ast_free(tmp);
04545       return -1;
04546    }
04547    /* The meat of recording the message...  All the announcements and beeps have been played*/
04548    ast_copy_string(fmt, vmfmts, sizeof(fmt));
04549    if (!ast_strlen_zero(fmt)) {
04550       msgnum = 0;
04551 
04552 #ifdef IMAP_STORAGE
04553       /* Is ext a mailbox? */
04554       /* must open stream for this user to get info! */
04555       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
04556       if (res < 0) {
04557          ast_log(LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
04558          ast_free(tmp);
04559          return -1;
04560       }
04561       if (!(vms = get_vm_state_by_mailbox(ext, 0))) {
04562          /* It is possible under certain circumstances that inboxcount did not
04563           * create a vm_state when it was needed. This is a catchall which will
04564           * rarely be used.
04565           */
04566          if (!(vms = create_vm_state_from_user(vmu))) {
04567             ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
04568             ast_free(tmp);
04569             return -1;
04570          }
04571       }
04572       vms->newmessages++;
04573 
04574       /* here is a big difference! We add one to it later */
04575       msgnum = newmsgs + oldmsgs;
04576       ast_debug(3, "Messagecount set to %d\n", msgnum);
04577       snprintf(fn, sizeof(fn), "%s/imap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
04578       /* set variable for compatibility */
04579       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
04580 
04581       /* Check if mailbox is full */
04582       check_quota(vms, imapfolder);
04583       if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
04584          ast_debug(1, "*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
04585          ast_play_and_wait(chan, "vm-mailboxfull");
04586          ast_free(tmp);
04587          return -1;
04588       }
04589 
04590       /* Check if we have exceeded maxmsg */
04591       if (msgnum >= vmu->maxmsg) {
04592          ast_log(LOG_WARNING, "Unable to leave message since we will exceed the maximum number of messages allowed (%u > %u)\n", msgnum, vmu->maxmsg);
04593          ast_play_and_wait(chan, "vm-mailboxfull");
04594          ast_free(tmp);
04595          return -1;
04596       }
04597 #else
04598       if (count_messages(vmu, dir) >= vmu->maxmsg) {
04599          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
04600          if (!res) {
04601             res = ast_waitstream(chan, "");
04602          }
04603          ast_log(LOG_WARNING, "No more messages possible\n");
04604          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04605          goto leave_vm_out;
04606       }
04607 
04608 #endif
04609       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
04610       txtdes = mkstemp(tmptxtfile);
04611       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
04612       if (txtdes < 0) {
04613          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
04614          if (!res) {
04615             res = ast_waitstream(chan, "");
04616          }
04617          ast_log(LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
04618          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04619          goto leave_vm_out;
04620       }
04621 
04622       /* Now play the beep once we have the message number for our next message. */
04623       if (res >= 0) {
04624          /* Unless we're *really* silent, try to send the beep */
04625          res = ast_stream_and_wait(chan, "beep", "");
04626       }
04627 
04628       /* Store information in real-time storage */
04629       if (ast_check_realtime("voicemail_data")) {
04630          snprintf(priority, sizeof(priority), "%d", chan->priority);
04631          snprintf(origtime, sizeof(origtime), "%ld", (long)time(NULL));
04632          get_date(date, sizeof(date));
04633          rtmsgid = ast_store_realtime("voicemail_data", "origmailbox", ext, "context", chan->context, "macrocontext", chan->macrocontext, "exten", chan->exten, "priority", priority, "callerchan", chan->name, "callerid", ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"), "origdate", date, "origtime", origtime, "category", category ? category : "", NULL);
04634       }
04635 
04636       /* Store information */
04637       txt = fdopen(txtdes, "w+");
04638       if (txt) {
04639          get_date(date, sizeof(date));
04640          fprintf(txt, 
04641             ";\n"
04642             "; Message Information file\n"
04643             ";\n"
04644             "[message]\n"
04645             "origmailbox=%s\n"
04646             "context=%s\n"
04647             "macrocontext=%s\n"
04648             "exten=%s\n"
04649             "priority=%d\n"
04650             "callerchan=%s\n"
04651             "callerid=%s\n"
04652             "origdate=%s\n"
04653             "origtime=%ld\n"
04654             "category=%s\n",
04655             ext,
04656             chan->context,
04657             chan->macrocontext, 
04658             chan->exten,
04659             chan->priority,
04660             chan->name,
04661             ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
04662             date, (long)time(NULL),
04663             category ? category : "");
04664       } else {
04665          ast_log(LOG_WARNING, "Error opening text file for output\n");
04666       }
04667       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms);
04668 
04669       if (txt) {
04670          if (duration < vmminsecs) {
04671             fclose(txt);
04672             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminsecs);
04673             ast_filedelete(tmptxtfile, NULL);
04674             unlink(tmptxtfile);
04675             if (ast_check_realtime("voicemail_data")) {
04676                snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
04677                ast_destroy_realtime("voicemail_data", "id", tmpid, NULL);
04678             }
04679          } else {
04680             fprintf(txt, "duration=%d\n", duration);
04681             fclose(txt);
04682             if (vm_lock_path(dir)) {
04683                ast_log(LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
04684                /* Delete files */
04685                ast_filedelete(tmptxtfile, NULL);
04686                unlink(tmptxtfile);
04687             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
04688                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
04689                unlink(tmptxtfile);
04690                ast_unlock_path(dir);
04691                if (ast_check_realtime("voicemail_data")) {
04692                   snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
04693                   ast_destroy_realtime("voicemail_data", "id", tmpid, NULL);
04694                }
04695             } else {
04696 #ifndef IMAP_STORAGE
04697                msgnum = last_message_index(vmu, dir) + 1;
04698 #endif
04699                make_file(fn, sizeof(fn), dir, msgnum);
04700 
04701                /* assign a variable with the name of the voicemail file */ 
04702 #ifndef IMAP_STORAGE
04703                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
04704 #else
04705                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
04706 #endif
04707 
04708                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
04709                ast_filerename(tmptxtfile, fn, NULL);
04710                rename(tmptxtfile, txtfile);
04711 
04712                /* Properly set permissions on voicemail text descriptor file.
04713                Unfortunately mkstemp() makes this file 0600 on most unix systems. */
04714                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0) {
04715                   ast_log(LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
04716                }
04717 
04718                ast_unlock_path(dir);
04719                if (ast_check_realtime("voicemail_data")) {
04720                   snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
04721                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
04722                   ast_update_realtime("voicemail_data", "id", tmpid, "filename", fn, "duration", tmpdur, NULL);
04723                }
04724                /* We must store the file first, before copying the message, because
04725                 * ODBC storage does the entire copy with SQL.
04726                 */
04727                if (ast_fileexists(fn, NULL, NULL) > 0) {
04728                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms);
04729                }
04730 
04731                /* Are there to be more recipients of this message? */
04732                while (tmpptr) {
04733                   struct ast_vm_user recipu, *recip;
04734                   char *exten, *context;
04735 
04736                   exten = strsep(&tmpptr, "&");
04737                   context = strchr(exten, '@');
04738                   if (context) {
04739                      *context = '\0';
04740                      context++;
04741                   }
04742                   if ((recip = find_user(&recipu, context, exten))) {
04743                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir);
04744                      free_user(recip);
04745                   }
04746                }
04747                /* Notification and disposal needs to happen after the copy, though. */
04748                if (ast_fileexists(fn, NULL, NULL)) {
04749 #ifdef IMAP_STORAGE
04750                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
04751 #else
04752                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
04753 #endif
04754                   DISPOSE(dir, msgnum);
04755                }
04756             }
04757          }
04758       }
04759       if (res == '0') {
04760          goto transfer;
04761       } else if (res > 0) {
04762          res = 0;
04763       }
04764 
04765       if (duration < vmminsecs) {
04766          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
04767          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04768       } else {
04769          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
04770       }
04771    } else {
04772       ast_log(LOG_WARNING, "No format for saving voicemail?\n");
04773    }
04774 leave_vm_out:
04775    free_user(vmu);
04776 
04777    ast_free(tmp);
04778    return res;
04779 }

static int load_config ( int  reload  )  [static]

Definition at line 9194 of file app_voicemail.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_option(), ast_copy_string(), ast_debug, ast_false(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, ast_vm_user::context, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), ast_variable::lineno, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, LOG_ERROR, LOG_WARNING, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, vm_zone::msg_format, vm_zone::name, ast_variable::name, ast_variable::next, pagerbody, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, saydurationminfo, SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), vm_zone::timezone, ast_variable::value, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, and VOICEMAIL_CONFIG.

09195 {
09196    struct ast_vm_user *cur;
09197    struct ast_config *cfg, *ucfg;
09198    char *cat;
09199    struct ast_variable *var;
09200    const char *val;
09201    char *q, *stringp;
09202    int x;
09203    int tmpadsi[4];
09204    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
09205 
09206    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
09207       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
09208          return 0;
09209       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
09210       cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
09211    } else {
09212       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
09213       ucfg = ast_config_load("users.conf", config_flags);
09214    }
09215 #ifdef IMAP_STORAGE
09216    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
09217 #endif
09218    /* set audio control prompts */
09219    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
09220    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
09221    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
09222    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
09223    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
09224 
09225    /* Free all the users structure */  
09226    free_vm_users();
09227 
09228    /* Free all the zones structure */
09229    free_vm_zones();
09230 
09231    AST_LIST_LOCK(&users);  
09232 
09233    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
09234 
09235    if (cfg) {
09236       /* General settings */
09237 
09238       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
09239          val = "default";
09240       ast_copy_string(userscontext, val, sizeof(userscontext));
09241       /* Attach voice message to mail message ? */
09242       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
09243          val = "yes";
09244       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
09245 
09246       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
09247          val = "no";
09248       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
09249 
09250       volgain = 0.0;
09251       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
09252          sscanf(val, "%30lf", &volgain);
09253 
09254 #ifdef ODBC_STORAGE
09255       strcpy(odbc_database, "asterisk");
09256       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
09257          ast_copy_string(odbc_database, val, sizeof(odbc_database));
09258       }
09259       strcpy(odbc_table, "voicemessages");
09260       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
09261          ast_copy_string(odbc_table, val, sizeof(odbc_table));
09262       }
09263 #endif      
09264       /* Mail command */
09265       strcpy(mailcmd, SENDMAIL);
09266       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
09267          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
09268 
09269       maxsilence = 0;
09270       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
09271          maxsilence = atoi(val);
09272          if (maxsilence > 0)
09273             maxsilence *= 1000;
09274       }
09275       
09276       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
09277          maxmsg = MAXMSG;
09278       } else {
09279          maxmsg = atoi(val);
09280          if (maxmsg <= 0) {
09281             ast_log(LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
09282             maxmsg = MAXMSG;
09283          } else if (maxmsg > MAXMSGLIMIT) {
09284             ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
09285             maxmsg = MAXMSGLIMIT;
09286          }
09287       }
09288 
09289       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
09290          maxdeletedmsg = 0;
09291       } else {
09292          if (sscanf(val, "%30d", &x) == 1)
09293             maxdeletedmsg = x;
09294          else if (ast_true(val))
09295             maxdeletedmsg = MAXMSG;
09296          else
09297             maxdeletedmsg = 0;
09298 
09299          if (maxdeletedmsg < 0) {
09300             ast_log(LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
09301             maxdeletedmsg = MAXMSG;
09302          } else if (maxdeletedmsg > MAXMSGLIMIT) {
09303             ast_log(LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
09304             maxdeletedmsg = MAXMSGLIMIT;
09305          }
09306       }
09307 
09308       /* Load date format config for voicemail mail */
09309       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
09310          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
09311       }
09312 
09313       /* External password changing command */
09314       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
09315          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
09316          pwdchange = PWDCHANGE_EXTERNAL;
09317       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
09318          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
09319          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
09320       }
09321 
09322 #ifdef IMAP_STORAGE
09323       /* IMAP server address */
09324       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
09325          ast_copy_string(imapserver, val, sizeof(imapserver));
09326       } else {
09327          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
09328       }
09329       /* IMAP server port */
09330       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
09331          ast_copy_string(imapport, val, sizeof(imapport));
09332       } else {
09333          ast_copy_string(imapport, "143", sizeof(imapport));
09334       }
09335       /* IMAP server flags */
09336       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
09337          ast_copy_string(imapflags, val, sizeof(imapflags));
09338       }
09339       /* IMAP server master username */
09340       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
09341          ast_copy_string(authuser, val, sizeof(authuser));
09342       }
09343       /* IMAP server master password */
09344       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
09345          ast_copy_string(authpassword, val, sizeof(authpassword));
09346       }
09347       /* Expunge on exit */
09348       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
09349          if (ast_false(val))
09350             expungeonhangup = 0;
09351          else
09352             expungeonhangup = 1;
09353       } else {
09354          expungeonhangup = 1;
09355       }
09356       /* IMAP voicemail folder */
09357       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
09358          ast_copy_string(imapfolder, val, sizeof(imapfolder));
09359       } else {
09360          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
09361       }
09362       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
09363          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
09364       }
09365       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
09366          imapgreetings = ast_true(val);
09367       } else {
09368          imapgreetings = 0;
09369       }
09370       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
09371          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
09372       } else {
09373          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
09374       }
09375 
09376       /* There is some very unorthodox casting done here. This is due
09377        * to the way c-client handles the argument passed in. It expects a 
09378        * void pointer and casts the pointer directly to a long without
09379        * first dereferencing it. */
09380       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
09381          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
09382       } else {
09383          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
09384       }
09385 
09386       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
09387          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
09388       } else {
09389          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
09390       }
09391 
09392       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
09393          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
09394       } else {
09395          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
09396       }
09397 
09398       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
09399          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
09400       } else {
09401          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
09402       }
09403 
09404       /* Increment configuration version */
09405       imapversion++;
09406 #endif
09407       /* External voicemail notify application */
09408       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
09409          ast_copy_string(externnotify, val, sizeof(externnotify));
09410          ast_debug(1, "found externnotify: %s\n", externnotify);
09411       } else {
09412          externnotify[0] = '\0';
09413       }
09414 
09415       /* SMDI voicemail notification */
09416       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
09417          ast_debug(1, "Enabled SMDI voicemail notification\n");
09418          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
09419             smdi_iface = ast_smdi_interface_find ? ast_smdi_interface_find(val) : NULL;
09420          } else {
09421             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
09422             smdi_iface = ast_smdi_interface_find ? ast_smdi_interface_find("/dev/ttyS0") : NULL;
09423          }
09424          if (!smdi_iface) {
09425             ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
09426          }
09427       }
09428 
09429       /* Silence treshold */
09430       silencethreshold = 256;
09431       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
09432          silencethreshold = atoi(val);
09433       
09434       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
09435          val = ASTERISK_USERNAME;
09436       ast_copy_string(serveremail, val, sizeof(serveremail));
09437       
09438       vmmaxsecs = 0;
09439       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
09440          if (sscanf(val, "%30d", &x) == 1) {
09441             vmmaxsecs = x;
09442          } else {
09443             ast_log(LOG_WARNING, "Invalid max message time length\n");
09444          }
09445       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
09446          static int maxmessage_deprecate = 0;
09447          if (maxmessage_deprecate == 0) {
09448             maxmessage_deprecate = 1;
09449             ast_log(LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
09450          }
09451          if (sscanf(val, "%30d", &x) == 1) {
09452             vmmaxsecs = x;
09453          } else {
09454             ast_log(LOG_WARNING, "Invalid max message time length\n");
09455          }
09456       }
09457 
09458       vmminsecs = 0;
09459       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
09460          if (sscanf(val, "%30d", &x) == 1) {
09461             vmminsecs = x;
09462             if (maxsilence / 1000 >= vmminsecs) {
09463                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
09464             }
09465          } else {
09466             ast_log(LOG_WARNING, "Invalid min message time length\n");
09467          }
09468       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
09469          static int maxmessage_deprecate = 0;
09470          if (maxmessage_deprecate == 0) {
09471             maxmessage_deprecate = 1;
09472             ast_log(LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
09473          }
09474          if (sscanf(val, "%30d", &x) == 1) {
09475             vmminsecs = x;
09476             if (maxsilence / 1000 >= vmminsecs) {
09477                ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
09478             }
09479          } else {
09480             ast_log(LOG_WARNING, "Invalid min message time length\n");
09481          }
09482       }
09483 
09484       val = ast_variable_retrieve(cfg, "general", "format");
09485       if (!val)
09486          val = "wav";   
09487       ast_copy_string(vmfmts, val, sizeof(vmfmts));
09488 
09489       skipms = 3000;
09490       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
09491          if (sscanf(val, "%30d", &x) == 1) {
09492             maxgreet = x;
09493          } else {
09494             ast_log(LOG_WARNING, "Invalid max message greeting length\n");
09495          }
09496       }
09497 
09498       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
09499          if (sscanf(val, "%30d", &x) == 1) {
09500             skipms = x;
09501          } else {
09502             ast_log(LOG_WARNING, "Invalid skipms value\n");
09503          }
09504       }
09505 
09506       maxlogins = 3;
09507       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
09508          if (sscanf(val, "%30d", &x) == 1) {
09509             maxlogins = x;
09510          } else {
09511             ast_log(LOG_WARNING, "Invalid max failed login attempts\n");
09512          }
09513       }
09514 
09515       /* Force new user to record name ? */
09516       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
09517          val = "no";
09518       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
09519 
09520       /* Force new user to record greetings ? */
09521       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
09522          val = "no";
09523       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
09524 
09525       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
09526          ast_debug(1, "VM_CID Internal context string: %s\n", val);
09527          stringp = ast_strdupa(val);
09528          for (x = 0; x < MAX_NUM_CID_CONTEXTS; x++) {
09529             if (!ast_strlen_zero(stringp)) {
09530                q = strsep(&stringp, ",");
09531                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
09532                   q++;
09533                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
09534                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
09535             } else {
09536                cidinternalcontexts[x][0] = '\0';
09537             }
09538          }
09539       }
09540       if (!(val = ast_variable_retrieve(cfg, "general", "review"))) {
09541          ast_debug(1, "VM Review Option disabled globally\n");
09542          val = "no";
09543       }
09544       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
09545 
09546       /* Temporary greeting reminder */
09547       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
09548          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
09549          val = "no";
09550       } else {
09551          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
09552       }
09553       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
09554 
09555       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))) {
09556          ast_debug(1, "VM Operator break disabled globally\n");
09557          val = "no";
09558       }
09559       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
09560 
09561       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
09562          ast_debug(1, "VM CID Info before msg disabled globally\n");
09563          val = "no";
09564       } 
09565       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
09566 
09567       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))) {
09568          ast_debug(1, "Send Voicemail msg disabled globally\n");
09569          val = "no";
09570       }
09571       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
09572    
09573       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
09574          ast_debug(1, "ENVELOPE before msg enabled globally\n");
09575          val = "yes";
09576       }
09577       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
09578 
09579       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
09580          ast_debug(1, "Move Heard enabled globally\n");
09581          val = "yes";
09582       }
09583       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
09584 
09585       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
09586          ast_debug(1, "Duration info before msg enabled globally\n");
09587          val = "yes";
09588       }
09589       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
09590 
09591       saydurationminfo = 2;
09592       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
09593          if (sscanf(val, "%30d", &x) == 1) {
09594             saydurationminfo = x;
09595          } else {
09596             ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
09597          }
09598       }
09599 
09600       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
09601          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
09602          val = "no";
09603       }
09604       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
09605 
09606       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
09607          ast_copy_string(dialcontext, val, sizeof(dialcontext));
09608          ast_debug(1, "found dialout context: %s\n", dialcontext);
09609       } else {
09610          dialcontext[0] = '\0';  
09611       }
09612       
09613       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
09614          ast_copy_string(callcontext, val, sizeof(callcontext));
09615          ast_debug(1, "found callback context: %s\n", callcontext);
09616       } else {
09617          callcontext[0] = '\0';
09618       }
09619 
09620       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
09621          ast_copy_string(exitcontext, val, sizeof(exitcontext));
09622          ast_debug(1, "found operator context: %s\n", exitcontext);
09623       } else {
09624          exitcontext[0] = '\0';
09625       }
09626       
09627       /* load password sounds configuration */
09628       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
09629          ast_copy_string(vm_password, val, sizeof(vm_password));
09630       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
09631          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
09632       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
09633          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
09634       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
09635          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
09636       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
09637          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
09638       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
09639          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
09640       }
09641       /* load configurable audio prompts */
09642       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
09643          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
09644       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
09645          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
09646       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
09647          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
09648       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
09649          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
09650       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
09651          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
09652 
09653       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
09654          val = "no";
09655       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
09656 
09657       poll_freq = DEFAULT_POLL_FREQ;
09658       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
09659          if (sscanf(val, "%30u", &poll_freq) != 1) {
09660             poll_freq = DEFAULT_POLL_FREQ;
09661             ast_log(LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
09662          }
09663       }
09664 
09665       poll_mailboxes = 0;
09666       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
09667          poll_mailboxes = ast_true(val);
09668 
09669       if (ucfg) { 
09670          for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
09671             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
09672                continue;
09673             if ((cur = find_or_create(userscontext, cat))) {
09674                populate_defaults(cur);
09675                apply_options_full(cur, ast_variable_browse(ucfg, cat));
09676                ast_copy_string(cur->context, userscontext, sizeof(cur->context));
09677             }
09678          }
09679          ast_config_destroy(ucfg);
09680       }
09681       cat = ast_category_browse(cfg, NULL);
09682       while (cat) {
09683          if (strcasecmp(cat, "general")) {
09684             var = ast_variable_browse(cfg, cat);
09685             if (strcasecmp(cat, "zonemessages")) {
09686                /* Process mailboxes in this context */
09687                while (var) {
09688                   append_mailbox(cat, var->name, var->value);
09689                   var = var->next;
09690                }
09691             } else {
09692                /* Timezones in this context */
09693                while (var) {
09694                   struct vm_zone *z;
09695                   if ((z = ast_malloc(sizeof(*z)))) {
09696                      char *msg_format, *timezone;
09697                      msg_format = ast_strdupa(var->value);
09698                      timezone = strsep(&msg_format, "|");
09699                      if (msg_format) {
09700                         ast_copy_string(z->name, var->name, sizeof(z->name));
09701                         ast_copy_string(z->timezone, timezone, sizeof(z->timezone));
09702                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
09703                         AST_LIST_LOCK(&zones);
09704                         AST_LIST_INSERT_HEAD(&zones, z, list);
09705                         AST_LIST_UNLOCK(&zones);
09706                      } else {
09707                         ast_log(LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
09708                         ast_free(z);
09709                      }
09710                   } else {
09711                      AST_LIST_UNLOCK(&users);
09712                      ast_config_destroy(cfg);
09713                      return -1;
09714                   }
09715                   var = var->next;
09716                }
09717             }
09718          }
09719          cat = ast_category_browse(cfg, cat);
09720       }
09721       memset(fromstring, 0, sizeof(fromstring));
09722       memset(pagerfromstring, 0, sizeof(pagerfromstring));
09723       strcpy(charset, "ISO-8859-1");
09724       if (emailbody) {
09725          ast_free(emailbody);
09726          emailbody = NULL;
09727       }
09728       if (emailsubject) {
09729          ast_free(emailsubject);
09730          emailsubject = NULL;
09731       }
09732       if (pagerbody) {
09733          ast_free(pagerbody);
09734          pagerbody = NULL;
09735       }
09736       if (pagersubject) {
09737          ast_free(pagersubject);
09738          pagersubject = NULL;
09739       }
09740       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
09741          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
09742       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
09743          ast_copy_string(fromstring, val, sizeof(fromstring));
09744       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
09745          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
09746       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
09747          ast_copy_string(charset, val, sizeof(charset));
09748       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
09749          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
09750          for (x = 0; x < 4; x++) {
09751             memcpy(&adsifdn[x], &tmpadsi[x], 1);
09752          }
09753       }
09754       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
09755          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
09756          for (x = 0; x < 4; x++) {
09757             memcpy(&adsisec[x], &tmpadsi[x], 1);
09758          }
09759       }
09760       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
09761          if (atoi(val)) {
09762             adsiver = atoi(val);
09763          }
09764       }
09765       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
09766          ast_copy_string(zonetag, val, sizeof(zonetag));
09767       }
09768       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
09769          emailsubject = ast_strdup(val);
09770       }
09771       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
09772          emailbody = substitute_escapes(val);
09773       }
09774       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
09775          pagersubject = ast_strdup(val);
09776       }
09777       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
09778          pagerbody = substitute_escapes(val);
09779       }
09780       AST_LIST_UNLOCK(&users);
09781       ast_config_destroy(cfg);
09782 
09783       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
09784          start_poll_thread();
09785       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
09786          stop_poll_thread();;
09787 
09788       return 0;
09789    } else {
09790       AST_LIST_UNLOCK(&users);
09791       ast_log(LOG_WARNING, "Failed to load configuration file.\n");
09792       if (ucfg)
09793          ast_config_destroy(ucfg);
09794       return 0;
09795    }
09796 }

static int load_module ( void   )  [static]

Definition at line 9825 of file app_voicemail.c.

References ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_install_vm_functions(), ast_manager_register, ast_register_application, cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), load_config(), mailbox_exists_acf, manager_list_voicemail_users(), messagecount(), vm_box_exists(), vm_exec(), vm_execmain(), and vmauthenticate().

09826 {
09827    int res;
09828    my_umask = umask(0);
09829    umask(my_umask);
09830 
09831    /* compute the location of the voicemail spool directory */
09832    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
09833 
09834    if ((res = load_config(0)))
09835       return res;
09836 
09837    res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
09838    res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
09839    res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
09840    res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
09841    res |= ast_custom_function_register(&mailbox_exists_acf);
09842    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
09843    if (res)
09844       return res;
09845 
09846    ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
09847 
09848    ast_install_vm_functions(has_voicemail, inboxcount, messagecount);
09849 
09850    return res;
09851 }

static int make_dir ( char *  dest,
int  len,
const char *  context,
const char *  ext,
const char *  folder 
) [static]

Definition at line 1072 of file app_voicemail.c.

01073 {
01074    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01075 }

static void make_email_file ( FILE *  p,
char *  srcemail,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  attach,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
int  imap 
) [static]

Creates the email file to be sent to indicate a new voicemail exists for a user.

Parameters:
p The output file to generate the email contents into.
srcemail The email address to send the email to, presumably the email address for the owner of the mailbox.
vmu The voicemail user who is sending the voicemail.
msgnum The message index in the mailbox folder.
context 
mailbox The voicemail box to read the voicemail to be notified in this email.
cidnum The caller ID number.
cidname The caller ID name.
attach the name of the sound file to be attached to the email, if attach_user_voicemail == 1.
format The message sound file format. i.e. .wav
duration The time of the message content, in seconds.
attach_user_voicemail if 1, the sound file is attached to the email.
chan 
category 
imap if == 1, indicates the target folder for the email notification to be sent to will be an IMAP mailstore. This causes additional mailbox headers to be set, which would facilitate searching for the email in the destination IMAP folder.
The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.

Definition at line 3512 of file app_voicemail.c.

References ast_channel_alloc, ast_channel_free(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_localtime(), ast_log(), ast_random(), ast_safe_system(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), base_encode(), charset, check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, create_dirpath(), ast_vm_user::email, emailbody, emaildateformat, emailsubject, encode_mime_str(), ENDL, fromstring, ast_vm_user::fullname, globalflags, LOG_WARNING, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, ast_channel::name, pbx_substitute_variables_helper(), prep_email_sub_vars(), ast_channel::priority, quote(), strip_control(), VM_PBXSKIP, vmu_tm(), VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

Referenced by sendmail().

03513 {
03514    char date[256];
03515    char host[MAXHOSTNAMELEN] = "";
03516    char who[256];
03517    char bound[256];
03518    char fname[256];
03519    char dur[256];
03520    char tmpcmd[256];
03521    struct ast_tm tm;
03522    char enc_cidnum[256] = "", enc_cidname[256] = "";
03523    char *passdata = NULL, *passdata2;
03524    size_t len_passdata = 0, len_passdata2, tmplen;
03525    char *greeting_attachment;
03526 
03527 #ifdef IMAP_STORAGE
03528 #define ENDL "\r\n"
03529 #else
03530 #define ENDL "\n"
03531 #endif
03532 
03533    /* One alloca for multiple fields */
03534    len_passdata2 = strlen(vmu->fullname);
03535    if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
03536       len_passdata2 = tmplen;
03537    }
03538    if ((tmplen = strlen(fromstring)) > len_passdata2) {
03539       len_passdata2 = tmplen;
03540    }
03541    len_passdata2 = len_passdata2 * 3 + 200;
03542    passdata2 = alloca(len_passdata2);
03543 
03544    if (!ast_strlen_zero(cidnum)) {
03545       strip_control(cidnum, enc_cidnum, sizeof(enc_cidnum));
03546    }
03547    if (!ast_strlen_zero(cidname)) {
03548       strip_control(cidname, enc_cidname, sizeof(enc_cidname));
03549    }
03550    gethostname(host, sizeof(host) - 1);
03551 
03552    if (strchr(srcemail, '@'))
03553       ast_copy_string(who, srcemail, sizeof(who));
03554    else 
03555       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
03556    
03557    greeting_attachment = strrchr(ast_strdupa(attach), '/');
03558    if (greeting_attachment)
03559       *greeting_attachment++ = '\0';
03560 
03561    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
03562    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
03563    fprintf(p, "Date: %s" ENDL, date);
03564 
03565    /* Set date format for voicemail mail */
03566    ast_strftime(date, sizeof(date), emaildateformat, &tm);
03567 
03568    if (!ast_strlen_zero(fromstring)) {
03569       struct ast_channel *ast;
03570       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
03571          char *ptr;
03572          memset(passdata2, 0, len_passdata2);
03573          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category);
03574          pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
03575          len_passdata = strlen(passdata2) * 3 + 300;
03576          passdata = alloca(len_passdata);
03577          if (check_mime(passdata2)) {
03578             int first_line = 1;
03579             encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
03580             while ((ptr = strchr(passdata, ' '))) {
03581                *ptr = '\0';
03582                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
03583                first_line = 0;
03584                passdata = ptr + 1;
03585             }
03586             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
03587          } else {
03588             fprintf(p, "From: %s <%s>" ENDL, quote(passdata2, passdata, len_passdata), who);
03589          }
03590          ast_channel_free(ast);
03591       } else {
03592          ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
03593       }
03594    } else {
03595       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
03596    }
03597 
03598    if (check_mime(vmu->fullname)) {
03599       int first_line = 1;
03600       char *ptr;
03601       encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
03602       while ((ptr = strchr(passdata2, ' '))) {
03603          *ptr = '\0';
03604          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
03605          first_line = 0;
03606          passdata2 = ptr + 1;
03607       }
03608       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
03609    } else {
03610       fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
03611    }
03612    if (!ast_strlen_zero(emailsubject)) {
03613       struct ast_channel *ast;
03614       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
03615          int vmlen = strlen(emailsubject) * 3 + 200;
03616          /* Only allocate more space if the previous was not large enough */
03617          if (vmlen > len_passdata) {
03618             passdata = alloca(vmlen);
03619             len_passdata = vmlen;
03620          }
03621 
03622          memset(passdata, 0, len_passdata);
03623          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, len_passdata, category);
03624          pbx_substitute_variables_helper(ast, emailsubject, passdata, len_passdata);
03625          if (check_mime(passdata)) {
03626             int first_line = 1;
03627             char *ptr;
03628             encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
03629             while ((ptr = strchr(passdata2, ' '))) {
03630                *ptr = '\0';
03631                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
03632                first_line = 0;
03633                passdata2 = ptr + 1;
03634             }
03635             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
03636          } else {
03637             fprintf(p, "Subject: %s" ENDL, passdata);
03638          }
03639          ast_channel_free(ast);
03640       } else {
03641          ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
03642       }
03643    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
03644       fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
03645    } else {
03646       fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
03647    }
03648 
03649    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1, (unsigned int)ast_random(), mailbox, (int)getpid(), host);
03650    if (imap) {
03651       /* additional information needed for IMAP searching */
03652       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
03653       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
03654       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
03655       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
03656 #ifdef IMAP_STORAGE
03657       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
03658 #else
03659       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
03660 #endif
03661       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
03662       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
03663       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
03664       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
03665       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
03666       if (!ast_strlen_zero(category)) {
03667          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
03668       } else {
03669          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
03670       }
03671       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
03672       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
03673       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long)time(NULL));
03674    }
03675    if (!ast_strlen_zero(cidnum)) {
03676       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
03677    }
03678    if (!ast_strlen_zero(cidname)) {
03679       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
03680    }
03681    fprintf(p, "MIME-Version: 1.0" ENDL);
03682    if (attach_user_voicemail) {
03683       /* Something unique. */
03684       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox, (int)getpid(), (unsigned int)ast_random());
03685 
03686       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
03687       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
03688       fprintf(p, "--%s" ENDL, bound);
03689    }
03690    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
03691    if (emailbody) {
03692       struct ast_channel *ast;
03693       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
03694          char *passdata;
03695          int vmlen = strlen(emailbody) * 3 + 200;
03696          passdata = alloca(vmlen);
03697          memset(passdata, 0, vmlen);
03698          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category);
03699          pbx_substitute_variables_helper(ast, emailbody, passdata, vmlen);
03700          fprintf(p, "%s" ENDL, passdata);
03701          ast_channel_free(ast);
03702       } else
03703          ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
03704    } else if (msgnum > -1) {
03705       if (strcmp(vmu->mailbox, mailbox)) {
03706          /* Forwarded type */
03707          struct ast_config *msg_cfg;
03708          const char *v;
03709          int inttime;
03710          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
03711          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03712          /* Retrieve info from VM attribute file */
03713          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
03714          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
03715          if (strlen(fromfile) < sizeof(fromfile) - 5) {
03716             strcat(fromfile, ".txt");
03717          }
03718          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
03719             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
03720                ast_copy_string(origcallerid, v, sizeof(origcallerid));
03721             }
03722 
03723             /* You might be tempted to do origdate, except that a) it's in the wrong
03724              * format, and b) it's missing for IMAP recordings. */
03725             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
03726                struct timeval tv = { inttime, };
03727                struct ast_tm tm;
03728                ast_localtime(&tv, &tm, NULL);
03729                ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
03730             }
03731             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
03732                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
03733                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
03734                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
03735                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
03736                date, origcallerid, origdate);
03737             ast_config_destroy(msg_cfg);
03738          } else {
03739             goto plain_message;
03740          }
03741       } else {
03742 plain_message:
03743          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
03744             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
03745             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
03746             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
03747             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
03748       }
03749    } else {
03750       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
03751             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
03752    }
03753    if (attach_user_voicemail) {
03754       /* Eww. We want formats to tell us their own MIME type */
03755       char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
03756       char tmpdir[256], newtmp[256];
03757       int tmpfd = -1;
03758    
03759       if (vmu->volgain < -.001 || vmu->volgain > .001) {
03760          create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
03761          snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
03762          tmpfd = mkstemp(newtmp);
03763          chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
03764          ast_debug(3, "newtmp: %s\n", newtmp);
03765          if (tmpfd > -1) {
03766             int soxstatus;
03767             snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
03768             if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
03769                attach = newtmp;
03770                ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
03771             } else {
03772                ast_log(LOG_WARNING, "Sox failed to reencode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
03773                   soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
03774                ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
03775             }
03776          }
03777       }
03778       fprintf(p, "--%s" ENDL, bound);
03779       if (msgnum > -1)
03780          fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"" ENDL, ctype, format, msgnum + 1, format);
03781       else
03782          fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
03783       fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
03784       fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
03785       if (msgnum > -1)
03786          fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"" ENDL ENDL, msgnum + 1, format);
03787       else
03788          fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
03789       snprintf(fname, sizeof(fname), "%s.%s", attach, format);
03790       base_encode(fname, p);
03791       fprintf(p, ENDL "--%s--" ENDL "." ENDL, bound);
03792       if (tmpfd > -1) {
03793          unlink(fname);
03794          close(tmpfd);
03795          unlink(newtmp);
03796       }
03797    }
03798 #undef ENDL
03799 }

static int make_file ( char *  dest,
const int  len,
const char *  dir,
const int  num 
) [static]

Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.

Parameters:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The length of the path string that was written out.
The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1087 of file app_voicemail.c.

Referenced by advanced_options(), close_mailbox(), copy_message(), forward_message(), leave_voicemail(), make_email_file(), notify_new_message(), play_message(), prep_email_sub_vars(), resequence_mailbox(), save_to_folder(), vm_execmain(), and vm_forwardoptions().

01088 {
01089    return snprintf(dest, len, "%s/msg%04d", dir, num);
01090 }

static int manager_list_voicemail_users ( struct mansession s,
const struct message m 
) [static]

Manager list voicemail users command.

Definition at line 9026 of file app_voicemail.c.

References AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_ack(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::context, count_messages(), ast_vm_user::dialout, ast_vm_user::email, ast_vm_user::exit, ast_vm_user::fullname, inboxcount(), ast_vm_user::language, ast_vm_user::mailbox, ast_vm_user::mailcmd, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, ast_vm_user::saydurationm, ast_vm_user::serveremail, ast_vm_user::uniqueid, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_OPERATOR, VM_REVIEW, VM_SAYCID, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by load_module().

09027 {
09028    struct ast_vm_user *vmu = NULL;
09029    const char *id = astman_get_header(m, "ActionID");
09030    char actionid[128] = "";
09031 
09032    if (!ast_strlen_zero(id))
09033       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
09034 
09035    AST_LIST_LOCK(&users);
09036 
09037    if (AST_LIST_EMPTY(&users)) {
09038       astman_send_ack(s, m, "There are no voicemail users currently defined.");
09039       AST_LIST_UNLOCK(&users);
09040       astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
09041       return RESULT_SUCCESS;
09042    }
09043    
09044    astman_send_ack(s, m, "Voicemail user list will follow");
09045    
09046    AST_LIST_TRAVERSE(&users, vmu, list) {
09047       char dirname[256];
09048 
09049 #ifdef IMAP_STORAGE
09050       int new, old;
09051       inboxcount (vmu->mailbox, &new, &old);
09052 #endif
09053       
09054       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
09055       astman_append(s,
09056          "%s"
09057          "Event: VoicemailUserEntry\r\n"
09058          "VMContext: %s\r\n"
09059          "VoiceMailbox: %s\r\n"
09060          "Fullname: %s\r\n"
09061          "Email: %s\r\n"
09062          "Pager: %s\r\n"
09063          "ServerEmail: %s\r\n"
09064          "MailCommand: %s\r\n"
09065          "Language: %s\r\n"
09066          "TimeZone: %s\r\n"
09067          "Callback: %s\r\n"
09068          "Dialout: %s\r\n"
09069          "UniqueID: %s\r\n"
09070          "ExitContext: %s\r\n"
09071          "SayDurationMinimum: %d\r\n"
09072          "SayEnvelope: %s\r\n"
09073          "SayCID: %s\r\n"
09074          "AttachMessage: %s\r\n"
09075          "AttachmentFormat: %s\r\n"
09076          "DeleteMessage: %s\r\n"
09077          "VolumeGain: %.2f\r\n"
09078          "CanReview: %s\r\n"
09079          "CallOperator: %s\r\n"
09080          "MaxMessageCount: %d\r\n"
09081          "MaxMessageLength: %d\r\n"
09082          "NewMessageCount: %d\r\n"
09083 #ifdef IMAP_STORAGE
09084          "OldMessageCount: %d\r\n"
09085          "IMAPUser: %s\r\n"
09086 #endif
09087          "\r\n",
09088          actionid,
09089          vmu->context,
09090          vmu->mailbox,
09091          vmu->fullname,
09092          vmu->email,
09093          vmu->pager,
09094          vmu->serveremail,
09095          vmu->mailcmd,
09096          vmu->language,
09097          vmu->zonetag,
09098          vmu->callback,
09099          vmu->dialout,
09100          vmu->uniqueid,
09101          vmu->exit,
09102          vmu->saydurationm,
09103          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
09104          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
09105          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
09106          vmu->attachfmt,
09107          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
09108          vmu->volgain,
09109          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
09110          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
09111          vmu->maxmsg,
09112          vmu->maxsecs,
09113 #ifdef IMAP_STORAGE
09114          new, old, vmu->imapuser
09115 #else
09116          count_messages(vmu, dirname)
09117 #endif
09118          );
09119    }     
09120    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
09121 
09122    AST_LIST_UNLOCK(&users);
09123 
09124    return RESULT_SUCCESS;
09125 }

static void* mb_poll_thread ( void *  data  )  [static]

Definition at line 8883 of file app_voicemail.c.

References ast_cond_timedwait(), ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_tvadd(), ast_tvnow(), poll_lock, and poll_subscribed_mailboxes().

Referenced by start_poll_thread().

08884 {
08885    while (poll_thread_run) {
08886       struct timespec ts = { 0, };
08887       struct timeval tv;
08888 
08889       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
08890       ts.tv_sec = tv.tv_sec;
08891       ts.tv_nsec = tv.tv_usec * 1000;
08892 
08893       ast_mutex_lock(&poll_lock);
08894       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
08895       ast_mutex_unlock(&poll_lock);
08896 
08897       if (!poll_thread_run)
08898          break;
08899 
08900       poll_subscribed_mailboxes();
08901    }
08902 
08903    return NULL;
08904 }

static const char* mbox ( int  id  )  [static]

Definition at line 1129 of file app_voicemail.c.

Referenced by add_peer_mailboxes(), adsi_load_vmail(), copy_message(), get_folder(), and save_to_folder().

01130 {
01131    static const char *msgs[] = {
01132 #ifdef IMAP_STORAGE
01133       imapfolder,
01134 #else
01135       "INBOX",
01136 #endif
01137       "Old",
01138       "Work",
01139       "Family",
01140       "Friends",
01141       "Cust1",
01142       "Cust2",
01143       "Cust3",
01144       "Cust4",
01145       "Cust5",
01146       "Deleted",
01147       "Urgent"
01148    };
01149    return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "Unknown";
01150 }

static int messagecount ( const char *  context,
const char *  mailbox,
const char *  folder 
) [static]

Definition at line 4184 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04185    {
04186       return __has_voicemail(context, mailbox, folder, 0);
04187    }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 8906 of file app_voicemail.c.

References ast_free.

Referenced by mwi_unsub_event_cb().

08907 {
08908    ast_free(mwi_sub);
08909 }

static void mwi_sub_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 8938 of file app_voicemail.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_SUB, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), mwi_sub::entry, mwi_sub::mailbox, and mwi_sub::uniqueid.

Referenced by start_poll_thread().

08939 {
08940    const char *mailbox;
08941    const char *context;
08942    uint32_t uniqueid;
08943    unsigned int len;
08944    struct mwi_sub *mwi_sub;
08945 
08946    if (ast_event_get_type(event) != AST_EVENT_SUB)
08947       return;
08948 
08949    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
08950       return;
08951 
08952    mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
08953    context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
08954    uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
08955 
08956    len = sizeof(*mwi_sub);
08957    if (!ast_strlen_zero(mailbox))
08958       len += strlen(mailbox);
08959 
08960    if (!ast_strlen_zero(context))
08961       len += strlen(context) + 1; /* Allow for seperator */
08962 
08963    if (!(mwi_sub = ast_calloc(1, len)))
08964       return;
08965 
08966    mwi_sub->uniqueid = uniqueid;
08967    if (!ast_strlen_zero(mailbox))
08968       strcpy(mwi_sub->mailbox, mailbox);
08969 
08970    if (!ast_strlen_zero(context)) {
08971       strcat(mwi_sub->mailbox, "@");
08972       strcat(mwi_sub->mailbox, context);
08973    }
08974 
08975    AST_RWLIST_WRLOCK(&mwi_subs);
08976    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
08977    AST_RWLIST_UNLOCK(&mwi_subs);
08978 }

static void mwi_unsub_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 8911 of file app_voicemail.c.

References ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_UNSUB, AST_LIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, mwi_sub::entry, mwi_sub_destroy(), and mwi_sub::uniqueid.

Referenced by start_poll_thread().

08912 {
08913    uint32_t uniqueid;
08914    struct mwi_sub *mwi_sub;
08915 
08916    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
08917       return;
08918 
08919    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
08920       return;
08921 
08922    uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
08923 
08924    AST_RWLIST_WRLOCK(&mwi_subs);
08925    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
08926       if (mwi_sub->uniqueid == uniqueid) {
08927          AST_LIST_REMOVE_CURRENT(entry);
08928          break;
08929       }
08930    }
08931    AST_RWLIST_TRAVERSE_SAFE_END
08932    AST_RWLIST_UNLOCK(&mwi_subs);
08933 
08934    if (mwi_sub)
08935       mwi_sub_destroy(mwi_sub);
08936 }

static int notify_new_message ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  msgnum,
long  duration,
char *  fmt,
char *  cidnum,
char *  cidname 
) [static]

Definition at line 5558 of file app_voicemail.c.

References ast_app_has_voicemail(), ast_app_inboxcount(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_vm_user::attachfmt, ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::email, EVENT_FLAG_CALL, globalflags, LOG_WARNING, ast_vm_user::mailbox, make_dir(), make_file(), manager_event, ast_vm_user::pager, pbx_builtin_getvar_helper(), queue_mwi_event(), RETRIEVE, run_externnotify(), sendmail(), sendpage(), ast_vm_user::serveremail, strsep(), VM_ATTACH, and VM_DELETE.

05559    {
05560       char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
05561       int newmsgs = 0, oldmsgs = 0;
05562       const char *category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
05563       char *myserveremail = serveremail;
05564 
05565       make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
05566       make_file(fn, sizeof(fn), todir, msgnum);
05567       snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
05568 
05569       if (!ast_strlen_zero(vmu->attachfmt)) {
05570          if (strstr(fmt, vmu->attachfmt))
05571             fmt = vmu->attachfmt;
05572          else
05573             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, fmt, vmu->mailbox, vmu->context);
05574       }
05575 
05576       /* Attach only the first format */
05577       fmt = ast_strdupa(fmt);
05578       stringp = fmt;
05579       strsep(&stringp, "|");
05580 
05581       if (!ast_strlen_zero(vmu->serveremail))
05582          myserveremail = vmu->serveremail;
05583 
05584       if (!ast_strlen_zero(vmu->email)) {
05585          int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
05586          if (!attach_user_voicemail)
05587             attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
05588 
05589          if (attach_user_voicemail)
05590             RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
05591 
05592          /* XXX possible imap issue, should category be NULL XXX */
05593          sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, fmt, duration, attach_user_voicemail, chan, category);
05594 
05595          if (attach_user_voicemail)
05596             DISPOSE(todir, msgnum);
05597       }
05598 
05599       if (!ast_strlen_zero(vmu->pager)) {
05600          sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category);
05601       }
05602 
05603       if (ast_test_flag(vmu, VM_DELETE))
05604          DELETE(todir, msgnum, fn, vmu);
05605 
05606       /* Leave voicemail for someone */
05607       if (ast_app_has_voicemail(ext_context, NULL)) 
05608          ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs);
05609 
05610       queue_mwi_event(ext_context, newmsgs, oldmsgs);
05611 
05612       manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
05613       run_externnotify(vmu->context, vmu->mailbox);
05614 
05615       return 0;
05616    }

static int ochar ( struct baseio bio,
int  c,
FILE *  so 
) [static]

Definition at line 3258 of file app_voicemail.c.

References BASELINELEN, eol, and baseio::linelength.

Referenced by base_encode().

03259 {
03260    if (bio->linelength >= BASELINELEN) {
03261       if (fputs(eol, so) == EOF)
03262          return -1;
03263 
03264       bio->linelength= 0;
03265    }
03266 
03267    if (putc(((unsigned char)c), so) == EOF)
03268       return -1;
03269 
03270    bio->linelength++;
03271 
03272    return 1;
03273 }

static int open_mailbox ( struct vm_state vms,
struct ast_vm_user vmu,
int  box 
) [static]

Definition at line 6234 of file app_voicemail.c.

References ast_copy_string(), ast_log(), ast_unlock_path(), ast_vm_user::context, count_messages(), create_dirpath(), vm_state::curbox, vm_state::curdir, last_message_index(), vm_state::lastmsg, LOG_ERROR, LOG_NOTICE, resequence_mailbox(), vm_state::username, vm_lock_path(), and vm_state::vmbox.

Referenced by vm_execmain().

06235 {
06236    int res = 0;
06237    int count_msg, last_msg;
06238 
06239    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
06240    
06241    /* Rename the member vmbox HERE so that we don't try to return before
06242     * we know what's going on.
06243     */
06244    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
06245    
06246    /* Faster to make the directory than to check if it exists. */
06247    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
06248 
06249    count_msg = count_messages(vmu, vms->curdir);
06250    if (count_msg < 0)
06251       return count_msg;
06252    else
06253       vms->lastmsg = count_msg - 1;
06254 
06255    /*
06256    The following test is needed in case sequencing gets messed up.
06257    There appears to be more than one way to mess up sequence, so
06258    we will not try to find all of the root causes--just fix it when
06259    detected.
06260    */
06261 
06262    if (vm_lock_path(vms->curdir)) {
06263       ast_log(LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
06264       return -1;
06265    }
06266 
06267    last_msg = last_message_index(vmu, vms->curdir);
06268    ast_unlock_path(vms->curdir);
06269 
06270    if (last_msg < 0) 
06271       return last_msg;
06272    else if (vms->lastmsg != last_msg) {
06273       ast_log(LOG_NOTICE, "Resequencing Mailbox: %s\n", vms->curdir);
06274       res = resequence_mailbox(vmu, vms->curdir);
06275       if (res)
06276          return res;
06277    }
06278 
06279    return 0;
06280 }

static int play_greeting ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  filename,
char *  ecodes 
) [static]

Definition at line 3920 of file app_voicemail.c.

References ast_debug, ast_fileexists(), ast_streamfile(), ast_waitstream(), ast_vm_user::context, DISPOSE, ast_channel::language, ast_vm_user::mailbox, and RETRIEVE.

Referenced by invent_message(), and leave_voicemail().

03921 {
03922    int res = -2;
03923    
03924 #ifdef ODBC_STORAGE
03925    int success = 
03926 #endif
03927    RETRIEVE(filename, -1, vmu->mailbox, vmu->context);
03928    if (ast_fileexists(filename, NULL, NULL) > 0) {
03929       res = ast_streamfile(chan, filename, chan->language);
03930       if (res > -1) 
03931          res = ast_waitstream(chan, ecodes);
03932 #ifdef ODBC_STORAGE
03933       if (success == -1) {
03934          /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
03935          ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
03936          store_file(filename, vmu->mailbox, vmu->context, -1);
03937       }
03938 #endif
03939    }
03940    DISPOSE(filename, -1);
03941 
03942    return res;
03943 }

static int play_message ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms 
) [static]

Definition at line 6070 of file app_voicemail.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_log(), ast_say_number(), ast_strdupa, ast_test_flag, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::fn2, vm_state::heard, ast_channel::language, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

Referenced by vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_zh(), and vm_execmain().

06071    {
06072       int res = 0;
06073       char filename[256], *cid;
06074       const char *origtime, *context, *category, *duration;
06075       struct ast_config *msg_cfg;
06076       struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06077 
06078       vms->starting = 0; 
06079       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06080       adsi_message(chan, vms);
06081       if (!vms->curmsg)
06082          res = wait_file2(chan, vms, "vm-first");  /* "First" */
06083       else if (vms->curmsg == vms->lastmsg)
06084          res = wait_file2(chan, vms, "vm-last");      /* "last" */
06085       if (!res) {
06086          /* POLISH syntax */
06087          if (!strcasecmp(chan->language, "pl")) { 
06088             if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06089                int ten, one;
06090                char nextmsg[256];
06091                ten = (vms->curmsg + 1) / 10;
06092                one = (vms->curmsg + 1) % 10;
06093                
06094                if (vms->curmsg < 20) {
06095                   snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
06096                   res = wait_file2(chan, vms, nextmsg);
06097                } else {
06098                   snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
06099                   res = wait_file2(chan, vms, nextmsg);
06100                   if (one > 0) {
06101                      if (!res) {
06102                         snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
06103                         res = wait_file2(chan, vms, nextmsg);
06104                      }
06105                   }
06106                }
06107             }
06108             if (!res)
06109                res = wait_file2(chan, vms, "vm-message");
06110          } else {
06111             if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
06112                res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
06113             else /* DEFAULT syntax */ {
06114                res = wait_file2(chan, vms, "vm-message");
06115             }
06116             if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06117                if (!res) {
06118                   res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
06119                }
06120             }
06121          }
06122       }
06123 
06124       /* Retrieve info from VM attribute file */
06125       make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
06126       snprintf(filename, sizeof(filename), "%s.txt", vms->fn2);
06127       RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
06128       msg_cfg = ast_config_load(filename, config_flags);
06129       if (!msg_cfg) {
06130          ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06131          return 0;
06132       }
06133 
06134       if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
06135          ast_log(LOG_WARNING, "No origtime?!\n");
06136          DISPOSE(vms->curdir, vms->curmsg);
06137          ast_config_destroy(msg_cfg);
06138          return 0;
06139       }
06140 
06141       cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
06142       duration = ast_variable_retrieve(msg_cfg, "message", "duration");
06143       category = ast_variable_retrieve(msg_cfg, "message", "category");
06144 
06145       context = ast_variable_retrieve(msg_cfg, "message", "context");
06146       if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
06147          context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
06148       if (!res) {
06149          res = play_message_category(chan, category);
06150       }
06151       if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
06152          res = play_message_datetime(chan, vmu, origtime, filename);
06153       if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
06154          res = play_message_callerid(chan, vms, cid, context, 0);
06155       if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
06156          res = play_message_duration(chan, vms, duration, vmu->saydurationm);
06157       /* Allow pressing '1' to skip envelope / callerid */
06158       if (res == '1')
06159          res = 0;
06160       ast_config_destroy(msg_cfg);
06161 
06162       if (!res) {
06163          make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06164          vms->heard[vms->curmsg] = 1;
06165          if ((res = wait_file(chan, vms, vms->fn)) < 0) {
06166             ast_log(LOG_WARNING, "Playback of message %s failed\n", vms->fn);
06167             res = 0;
06168          }
06169       }
06170       DISPOSE(vms->curdir, vms->curmsg);
06171       return res;
06172    }

static int play_message_callerid ( struct ast_channel chan,
struct vm_state vms,
char *  cid,
const char *  context,
int  callback 
) [static]

Definition at line 5956 of file app_voicemail.c.

References ast_callerid_parse(), ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_say_digit_str(), ast_stream_and_wait(), ast_strlen_zero(), ast_verb, cidinternalcontexts, ast_channel::language, MAX_NUM_CID_CONTEXTS, name, and wait_file2().

Referenced by advanced_options(), and play_message().

05957    {
05958       int res = 0;
05959       int i;
05960       char *callerid, *name;
05961       char prefile[PATH_MAX] = "";
05962       
05963 
05964       /* If voicemail cid is not enabled, or we didn't get cid or context from
05965       * the attribute file, leave now.
05966       *
05967       * TODO Still need to change this so that if this function is called by the
05968       * message envelope (and someone is explicitly requesting to hear the CID),
05969       * it does not check to see if CID is enabled in the config file.
05970       */
05971       if ((cid == NULL)||(context == NULL))
05972          return res;
05973 
05974       /* Strip off caller ID number from name */
05975       ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
05976       ast_callerid_parse(cid, &name, &callerid);
05977       if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
05978          /* Check for internal contexts and only */
05979          /* say extension when the call didn't come from an internal context in the list */
05980          for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++) {
05981             ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
05982             if ((strcmp(cidinternalcontexts[i], context) == 0))
05983                break;
05984          }
05985          if (i != MAX_NUM_CID_CONTEXTS) { /* internal context? */
05986             if (!res) {
05987                snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
05988                if (!ast_strlen_zero(prefile)) {
05989                /* See if we can find a recorded name for this person instead of their extension number */
05990                   if (ast_fileexists(prefile, NULL, NULL) > 0) {
05991                      ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
05992                      if (!callback)
05993                         res = wait_file2(chan, vms, "vm-from");
05994                      res = ast_stream_and_wait(chan, prefile, "");
05995                   } else {
05996                      ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
05997                      /* Say "from extension" as one saying to sound smoother */
05998                      if (!callback)
05999                         res = wait_file2(chan, vms, "vm-from-extension");
06000                      res = ast_say_digit_str(chan, callerid, "", chan->language);
06001                   }
06002                }
06003             }
06004          } else if (!res) {
06005             ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
06006             /* Since this is all nicely figured out, why not say "from phone number" in this case? */
06007             if (!callback)
06008                res = wait_file2(chan, vms, "vm-from-phonenumber");
06009             res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
06010          }
06011       } else {
06012          /* Number unknown */
06013          ast_debug(1, "VM-CID: From an unknown number\n");
06014          /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
06015          res = wait_file2(chan, vms, "vm-unknown-caller");
06016       }
06017       return res;
06018    }

static int play_message_category ( struct ast_channel chan,
const char *  category 
) [static]

Definition at line 5868 of file app_voicemail.c.

References ast_log(), ast_play_and_wait(), ast_strlen_zero(), and LOG_WARNING.

Referenced by play_message().

05869    {
05870       int res = 0;
05871 
05872       if (!ast_strlen_zero(category))
05873          res = ast_play_and_wait(chan, category);
05874 
05875       if (res) {
05876          ast_log(LOG_WARNING, "No sound file for category '%s' was found.\n", category);
05877          res = 0;
05878       }
05879 
05880       return res;
05881    }

static int play_message_datetime ( struct ast_channel chan,
struct ast_vm_user vmu,
const char *  origtime,
const char *  filename 
) [static]

Definition at line 5883 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_get_time_t(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_say_date_with_format, ast_strlen_zero(), ast_tvnow(), ast_channel::language, LOG_WARNING, vm_zone::msg_format, vm_zone::name, pbx_builtin_setvar_helper(), vm_zone::timezone, and ast_vm_user::zonetag.

Referenced by advanced_options(), and play_message().

05884    {
05885       int res = 0;
05886       struct vm_zone *the_zone = NULL;
05887       time_t t;
05888 
05889       if (ast_get_time_t(origtime, &t, 0, NULL)) {
05890          ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
05891          return 0;
05892       }
05893 
05894       /* Does this user have a timezone specified? */
05895       if (!ast_strlen_zero(vmu->zonetag)) {
05896          /* Find the zone in the list */
05897          struct vm_zone *z;
05898          AST_LIST_LOCK(&zones);
05899          AST_LIST_TRAVERSE(&zones, z, list) {
05900             if (!strcmp(z->name, vmu->zonetag)) {
05901                the_zone = z;
05902                break;
05903             }
05904          }
05905          AST_LIST_UNLOCK(&zones);
05906       }
05907 
05908    /* No internal variable parsing for now, so we'll comment it out for the time being */
05909 #if 0
05910       /* Set the DIFF_* variables */
05911       ast_localtime(&t, &time_now, NULL);
05912       tv_now = ast_tvnow();
05913       ast_localtime(&tv_now, &time_then, NULL);
05914 
05915       /* Day difference */
05916       if (time_now.tm_year == time_then.tm_year)
05917          snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
05918       else
05919          snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
05920       pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
05921 
05922       /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
05923 #endif
05924       if (the_zone) {
05925          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
05926       }
05927       else if (!strcasecmp(chan->language,"pl"))       /* POLISH syntax */
05928          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
05929       else if (!strcasecmp(chan->language, "se"))       /* SWEDISH syntax */
05930          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
05931       else if (!strcasecmp(chan->language, "no"))       /* NORWEGIAN syntax */
05932          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
05933       else if (!strcasecmp(chan->language, "de"))       /* GERMAN syntax */
05934          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
05935       else if (!strcasecmp(chan->language, "nl"))      /* DUTCH syntax */
05936          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
05937       else if (!strcasecmp(chan->language, "it"))      /* ITALIAN syntax */
05938          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
05939       else if (!strcasecmp(chan->language, "gr"))
05940          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
05941       else if (!strcasecmp(chan->language, "pt_BR"))
05942          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
05943       else if (!strncasecmp(chan->language, "zh", 2)) /* CHINESE (Taiwan) syntax */
05944          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);     
05945       else {
05946          res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
05947       }
05948 #if 0
05949       pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
05950 #endif
05951       return res;
05952    }

static int play_message_duration ( struct ast_channel chan,
struct vm_state vms,
const char *  duration,
int  minduration 
) [static]

Definition at line 6020 of file app_voicemail.c.

References ast_debug, AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_channel::language, num, say_and_wait(), and wait_file2().

Referenced by play_message().

06021    {
06022       int res = 0;
06023       int durationm;
06024       int durations;
06025       /* Verify that we have a duration for the message */
06026       if (duration == NULL)
06027          return res;
06028 
06029       /* Convert from seconds to minutes */
06030       durations = atoi(duration);
06031       durationm = durations / 60;
06032 
06033       ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
06034 
06035       if ((!res) && (durationm >= minduration)) {
06036          res = wait_file2(chan, vms, "vm-duration");
06037 
06038          /* POLISH syntax */
06039          if (!strcasecmp(chan->language, "pl")) {
06040             div_t num = div(durationm, 10);
06041 
06042             if (durationm == 1) {
06043                res = ast_play_and_wait(chan, "digits/1z");
06044                res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
06045             } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
06046                if (num.rem == 2) {
06047                   if (!num.quot) {
06048                      res = ast_play_and_wait(chan, "digits/2-ie");
06049                   } else {
06050                      res = say_and_wait(chan, durationm - 2 , chan->language);
06051                      res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
06052                   }
06053                } else {
06054                   res = say_and_wait(chan, durationm, chan->language);
06055                }
06056                res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
06057             } else {
06058                res = say_and_wait(chan, durationm, chan->language);
06059                res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
06060             }
06061          /* DEFAULT syntax */
06062          } else {
06063             res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
06064             res = wait_file2(chan, vms, "vm-minutes");
06065          }
06066       }
06067       return res;
06068    }

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

Definition at line 10100 of file app_voicemail.c.

References ast_channel_setoption(), ast_copy_string(), AST_DIGIT_ANY, ast_filedelete(), ast_filerename(), ast_log(), AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_stream_and_wait(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, INTRO, LOG_WARNING, ast_vm_user::mailbox, STORE, vm_exec(), VM_OPERATOR, and VM_REVIEW.

10103 {
10104    /* Record message & let caller review or re-record it, or set options if applicable */
10105    int res = 0;
10106    int cmd = 0;
10107    int max_attempts = 3;
10108    int attempts = 0;
10109    int recorded = 0;
10110    int message_exists = 0;
10111    signed char zero_gain = 0;
10112    char tempfile[PATH_MAX];
10113    char *acceptdtmf = "#";
10114    char *canceldtmf = "";
10115 
10116    /* Note that urgent and private are for flagging messages as such in the future */
10117 
10118    /* barf if no pointer passed to store duration in */
10119    if (duration == NULL) {
10120       ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
10121       return -1;
10122    }
10123 
10124    if (!outsidecaller)
10125       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
10126    else
10127       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
10128 
10129    cmd = '3';  /* Want to start by recording */
10130 
10131    while ((cmd >= 0) && (cmd != 't')) {
10132       switch (cmd) {
10133       case '1':
10134          if (!message_exists) {
10135             /* In this case, 1 is to record a message */
10136             cmd = '3';
10137             break;
10138          } else {
10139             /* Otherwise 1 is to save the existing message */
10140             ast_verb(3, "Saving message as is\n");
10141             if (!outsidecaller) 
10142                ast_filerename(tempfile, recordfile, NULL);
10143             ast_stream_and_wait(chan, "vm-msgsaved", "");
10144             if (!outsidecaller) {
10145                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms);
10146                DISPOSE(recordfile, -1);
10147             }
10148             cmd = 't';
10149             return res;
10150          }
10151       case '2':
10152          /* Review */
10153          ast_verb(3, "Reviewing the message\n");
10154          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
10155          break;
10156       case '3':
10157          message_exists = 0;
10158          /* Record */
10159          if (recorded == 1) 
10160             ast_verb(3, "Re-recording the message\n");
10161          else  
10162             ast_verb(3, "Recording the message\n");
10163          
10164          if (recorded && outsidecaller) {
10165             cmd = ast_play_and_wait(chan, INTRO);
10166             cmd = ast_play_and_wait(chan, "beep");
10167          }
10168          recorded = 1;
10169          /* 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 */
10170          if (record_gain)
10171             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
10172          if (ast_test_flag(vmu, VM_OPERATOR))
10173             canceldtmf = "0";
10174          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
10175          if (record_gain)
10176             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
10177          if (cmd == -1) {
10178             /* User has hung up, no options to give */
10179             if (!outsidecaller) {
10180                /* user was recording a greeting and they hung up, so let's delete the recording. */
10181                ast_filedelete(tempfile, NULL);
10182             }     
10183             return cmd;
10184          }
10185          if (cmd == '0') {
10186             break;
10187          } else if (cmd == '*') {
10188             break;
10189 #if 0
10190          } else if (vmu->review && (*duration < 5)) {
10191             /* Message is too short */
10192             ast_verb(3, "Message too short\n");
10193             cmd = ast_play_and_wait(chan, "vm-tooshort");
10194             cmd = ast_filedelete(tempfile, NULL);
10195             break;
10196          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
10197             /* Message is all silence */
10198             ast_verb(3, "Nothing recorded\n");
10199             cmd = ast_filedelete(tempfile, NULL);
10200             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
10201             if (!cmd)
10202                cmd = ast_play_and_wait(chan, "vm-speakup");
10203             break;
10204 #endif
10205          } else {
10206             /* If all is well, a message exists */
10207             message_exists = 1;
10208             cmd = 0;
10209          }
10210          break;
10211       case '4':
10212       case '5':
10213       case '6':
10214       case '7':
10215       case '8':
10216       case '9':
10217       case '*':
10218       case '#':
10219          cmd = ast_play_and_wait(chan, "vm-sorry");
10220          break;
10221 #if 0 
10222 /*  XXX Commented out for the moment because of the dangers of deleting
10223     a message while recording (can put the message numbers out of sync) */
10224       case '*':
10225          /* Cancel recording, delete message, offer to take another message*/
10226          cmd = ast_play_and_wait(chan, "vm-deleted");
10227          cmd = ast_filedelete(tempfile, NULL);
10228          if (outsidecaller) {
10229             res = vm_exec(chan, NULL);
10230             return res;
10231          }
10232          else
10233             return 1;
10234 #endif
10235       case '0':
10236          if (!ast_test_flag(vmu, VM_OPERATOR)) {
10237             cmd = ast_play_and_wait(chan, "vm-sorry");
10238             break;
10239          }
10240          if (message_exists || recorded) {
10241             cmd = ast_play_and_wait(chan, "vm-saveoper");
10242             if (!cmd)
10243                cmd = ast_waitfordigit(chan, 3000);
10244             if (cmd == '1') {
10245                ast_play_and_wait(chan, "vm-msgsaved");
10246                cmd = '0';
10247             } else {
10248                ast_play_and_wait(chan, "vm-deleted");
10249                DELETE(recordfile, -1, recordfile, vmu);
10250                cmd = '0';
10251             }
10252          }
10253          return cmd;
10254       default:
10255          /* If the caller is an ouside caller, and the review option is enabled,
10256             allow them to review the message, but let the owner of the box review
10257             their OGM's */
10258          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
10259             return cmd;
10260          if (message_exists) {
10261             cmd = ast_play_and_wait(chan, "vm-review");
10262          } else {
10263             cmd = ast_play_and_wait(chan, "vm-torerecord");
10264             if (!cmd)
10265                cmd = ast_waitfordigit(chan, 600);
10266          }
10267          
10268          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
10269             cmd = ast_play_and_wait(chan, "vm-reachoper");
10270             if (!cmd)
10271                cmd = ast_waitfordigit(chan, 600);
10272          }
10273 #if 0
10274          if (!cmd)
10275             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
10276 #endif
10277          if (!cmd)
10278             cmd = ast_waitfordigit(chan, 6000);
10279          if (!cmd) {
10280             attempts++;
10281          }
10282          if (attempts > max_attempts) {
10283             cmd = 't';
10284          }
10285       }
10286    }
10287    if (outsidecaller)
10288       ast_play_and_wait(chan, "vm-goodbye");
10289    if (cmd == 't')
10290       cmd = 0;
10291    return cmd;
10292 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 8861 of file app_voicemail.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), mwi_sub::entry, inboxcount(), mwi_sub::mailbox, mwi_sub::old_new, mwi_sub::old_old, and queue_mwi_event().

Referenced by mb_poll_thread().

08862 {
08863    struct mwi_sub *mwi_sub;
08864 
08865    AST_RWLIST_RDLOCK(&mwi_subs);
08866    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
08867       int new = 0, old = 0;
08868 
08869       if (ast_strlen_zero(mwi_sub->mailbox))
08870          continue;
08871 
08872       inboxcount(mwi_sub->mailbox, &new, &old);
08873 
08874       if (new != mwi_sub->old_new || old != mwi_sub->old_old) {
08875          mwi_sub->old_new = new;
08876          mwi_sub->old_old = old;
08877          queue_mwi_event(mwi_sub->mailbox, new, old);
08878       }
08879    }
08880    AST_RWLIST_UNLOCK(&mwi_subs);
08881 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

static void prep_email_sub_vars ( struct ast_channel ast,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  dur,
char *  date,
char *  passdata,
size_t  passdatasize,
const char *  category 
) [static]

Definition at line 3334 of file app_voicemail.c.

References ast_callerid_merge(), ast_callerid_split(), ast_config_destroy(), ast_config_load, ast_localtime(), ast_log(), ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, emaildateformat, ast_vm_user::fullname, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, and pbx_builtin_setvar_helper().

03335 {
03336    char callerid[256];
03337    char fromdir[256], fromfile[256];
03338    struct ast_config *msg_cfg;
03339    const char *origcallerid, *origtime;
03340    char origcidname[80], origcidnum[80], origdate[80];
03341    int inttime;
03342    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03343 
03344    /* Prepare variables for substitution in email body and subject */
03345    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
03346    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
03347    snprintf(passdata, passdatasize, "%d", msgnum);
03348    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
03349    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
03350    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
03351    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
03352       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
03353    pbx_builtin_setvar_helper(ast, "VM_CIDNAME"