Fri Jul 24 00:41:15 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 "asterisk/taskprocessor.h"

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_sub_task
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 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 MINPASSWORD   0
#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, j)
#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_FWDURGAUTO   (1 << 18)
#define VM_MESSAGEWRAP   (1 << 17)
#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 VMSTATE_MAX_MSG_ARRAY   256
#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), OPT_MESSAGE_Urgent = (1 << 8),
  OPT_MESSAGE_PRIORITY = (1 << 9)
}
enum  { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
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 int add_email_attachment (FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
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)
 The advanced options within a message.
static int append_mailbox (const char *context, const char *box, const char *data)
static void apply_option (struct ast_vm_user *vmu, const char *var, const char *value)
 Sets a a specific property value.
static void apply_options (struct ast_vm_user *vmu, const char *options)
 Destructively Parse options and apply.
static void apply_options_full (struct ast_vm_user *retval, struct ast_variable *var)
 Loads the options specific to a voicemail user.
static int base_encode (char *filename, FILE *so)
 Performs a base 64 encode algorithm on the contents of a File.
static int change_password_realtime (struct ast_vm_user *vmu, const char *password)
 Performs a change of the voicemail passowrd in the realtime engine.
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 check_password (struct ast_vm_user *vmu, char *password)
 Check that password meets minimum required length.
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)
 Utility function to copy a file.
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, const char *flag)
 Copies a message from one mailbox to another.
static void copy_plain_file (char *frompath, char *topath)
 Copies a voicemail information (envelope) file.
static int count_messages (struct ast_vm_user *vmu, char *dir)
 Find all .txt files - even if they are not in sequence from 0000.
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 *box)
static struct ast_vm_userfind_user (struct ast_vm_user *ivm, const char *context, const char *mailbox)
 Finds a voicemail user from the users file or the realtime engine.
static struct ast_vm_userfind_user_realtime (struct ast_vm_user *ivm, const char *context, const char *mailbox)
 Finds a voicemail user from the realtime engine.
static int forward_message (struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int is_new_message, signed char record_gain, int urgent)
 Sends a voicemail message to a mailbox recipient.
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)
 Gets the current date and time, as formatted string.
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)
 plays a prompt and waits for a keypress.
static int handle_subscribe (void *datap)
static int handle_unsubscribe (void *datap)
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)
 Determines if the given folder has messages.
static int inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
static int inboxcount2 (const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static int inbuf (struct baseio *bio, FILE *fi)
 utility used by inchar(), for base_encode()
static int inchar (struct baseio *bio, FILE *fi)
 utility used by base_encode()
static int invent_message (struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
static int is_valid_dtmf (const char *key)
 Determines if a DTMF key entered is valid.
static int last_message_index (struct ast_vm_user *vmu, char *dir)
 Determines the highest message number in use for a given user and mailbox folder.
static int leave_voicemail (struct ast_channel *chan, char *ext, struct leave_vm_options *options)
 Prompts the user and records a voicemail to a mailbox.
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)
 Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.
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 *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag)
 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, const char *flag)
 Sends email notification that a user has a new voicemail waiting for them.
static int ochar (struct baseio *bio, int c, FILE *so)
 utility used by base_encode()
static int open_mailbox (struct vm_state *vms, struct ast_vm_user *vmu, int box)
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, char *flag)
static void poll_subscribed_mailboxes (void)
static void populate_defaults (struct ast_vm_user *vmu)
 Sets default voicemail system options to a voicemail user.
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, const char *flag)
static void queue_mwi_event (const char *box, int urgent, int new, int old)
static char * quote (const char *from, char *to, size_t len)
 Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
static int reload (void)
static void rename_file (char *sfn, char *dfn)
 Renames a message in a mailbox folder.
static int reset_user_pw (const char *context, const char *mailbox, const char *newpass)
 Resets a user password to a specified password.
static void run_externnotify (char *context, char *extension, const char *flag)
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 sayname (struct ast_channel *chan, const char *mailbox, const char *context)
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 *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
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, const char *flag)
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 max_logins, 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)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Spanish syntax for 'You have N messages' greeting.
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (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)
 Italian syntax for 'You have N messages' greeting.
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Portuguese syntax for 'You have N messages' greeting.
static int vm_browse_messages_tw (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Chinese (Taiwan)syntax for 'You have N messages' greeting.
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
 The handler for the change password option.
static void vm_change_password_shell (struct ast_vm_user *vmu, char *newpassword)
static char * vm_check_password_shell (char *command, char *buf, size_t len)
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 *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
 presents the option to prepend to an existing message when forwarding it.
static int vm_instructions (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_en (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_tw (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
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_he (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_tw (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 *box)
static int vm_play_folder_name_pl (struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua (struct ast_channel *chan, char *box)
static int vm_tempgreeting (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
 The handler for 'record a temporary greeting'.
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 struct ast_module_infoast_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_check_cmd [128]
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 int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
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_RECURSIVE_MUTEX_INITIALIZER_NP )
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 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }}
enum { ... }  vm_box
static char vm_invalid_password [80] = "vm-invalid-password"
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_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 183 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 206 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 207 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 180 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 176 of file app_voicemail.c.

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

Definition at line 469 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 188 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 190 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 191 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 189 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 192 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 606 of file app_voicemail.c.

Referenced by load_config().

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

Definition at line 470 of file app_voicemail.c.

Referenced by notify_new_message(), play_record_review(), and vm_tempgreeting().

#define DISPOSE ( a,
 ) 

Definition at line 465 of file app_voicemail.c.

Referenced by advanced_options(), forward_message(), invent_message(), leave_voicemail(), notify_new_message(), play_message(), play_record_review(), sayname(), vm_intro(), vm_options(), and vm_tempgreeting().

#define ENDL   "\n"

Referenced by add_email_attachment(), and make_email_file().

#define eol   "\r\n"

Definition at line 208 of file app_voicemail.c.

Referenced by base_encode(), and ochar().

#define ERROR_LOCK_PATH   -100

Definition at line 232 of file app_voicemail.c.

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

Definition at line 467 of file app_voicemail.c.

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

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

Referenced by handle_voicemail_show_users().

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

Referenced by handle_voicemail_show_zones().

#define INTRO   "vm-intro"

Definition at line 199 of file app_voicemail.c.

Referenced by leave_voicemail(), play_record_review(), and vm_forwardoptions().

#define MAX_DATETIME_FORMAT   512

Definition at line 210 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 211 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 201 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

Definition at line 202 of file app_voicemail.c.

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

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 204 of file app_voicemail.c.

Referenced by load_config().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 482 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 481 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 468 of file app_voicemail.c.

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

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 464 of file app_voicemail.c.

Referenced by advanced_options(), forward_message(), invent_message(), leave_voicemail(), notify_new_message(), play_message(), sayname(), vm_intro(), vm_options(), and vm_tempgreeting().

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

Definition at line 197 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 174 of file app_voicemail.c.

Referenced by run_externnotify().

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

Definition at line 466 of file app_voicemail.c.

Referenced by copy_message(), forward_message(), leave_voicemail(), and play_record_review().

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 491 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 193 of file app_voicemail.c.

Referenced by is_valid_dtmf().

#define VM_ALLOCED   (1 << 13)

Structure was malloc'ed, instead of placed in a return (usually static) buffer

Definition at line 226 of file app_voicemail.c.

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

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 224 of file app_voicemail.c.

Referenced by apply_option(), forward_message(), load_config(), manager_list_voicemail_users(), notify_new_message(), and sendmail().

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 225 of file app_voicemail.c.

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

#define VM_DIRECFORWARD   (1 << 10)

Permit caller to use the Directory app for selecting to which mailbox to forward a VM

Definition at line 223 of file app_voicemail.c.

Referenced by forward_message(), and load_config().

#define VM_ENVELOPE   (1 << 4)

Play the envelope information (who-from, time received, etc.)

Definition at line 217 of file app_voicemail.c.

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

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 221 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 220 of file app_voicemail.c.

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

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 231 of file app_voicemail.c.

Referenced by forward_message(), and load_config().

#define VM_MESSAGEWRAP   (1 << 17)

Wrap around from the last message to the first, and vice-versa

Definition at line 230 of file app_voicemail.c.

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

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 229 of file app_voicemail.c.

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

#define VM_OPERATOR   (1 << 1)

Allow 0 to be pressed to go to 'o' extension

Definition at line 214 of file app_voicemail.c.

Referenced by apply_option(), leave_voicemail(), load_config(), manager_list_voicemail_users(), and play_record_review().

#define VM_PBXSKIP   (1 << 9)

Skip the [PBX] preamble in the Subject line of emails

Definition at line 222 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

#define VM_REVIEW   (1 << 0)

After recording, permit the caller to review the recording before saving

Definition at line 213 of file app_voicemail.c.

Referenced by apply_option(), load_config(), manager_list_voicemail_users(), and play_record_review().

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 215 of file app_voicemail.c.

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

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 218 of file app_voicemail.c.

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

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 227 of file app_voicemail.c.

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

#define VM_SKIPAFTERCMD   (1 << 6)

After deletion, assume caller wants to go to the next message

Definition at line 219 of file app_voicemail.c.

Referenced by load_config(), and vm_execmain().

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 216 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 228 of file app_voicemail.c.

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

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 409 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 182 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 178 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 179 of file app_voicemail.c.

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


Enumeration Type Documentation

anonymous enum

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 235 of file app_voicemail.c.

00235      {
00236    NEW_FOLDER,
00237    OLD_FOLDER,
00238    WORK_FOLDER,
00239    FAMILY_FOLDER,
00240    FRIENDS_FOLDER,
00241    GREETINGS_FOLDER
00242 } vm_box;

anonymous enum

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 

Definition at line 244 of file app_voicemail.c.

00244      {
00245    OPT_SILENT =           (1 << 0),
00246    OPT_BUSY_GREETING =    (1 << 1),
00247    OPT_UNAVAIL_GREETING = (1 << 2),
00248    OPT_RECORDGAIN =       (1 << 3),
00249    OPT_PREPEND_MAILBOX =  (1 << 4),
00250    OPT_AUTOPLAY =         (1 << 6),
00251    OPT_DTMFEXIT =         (1 << 7),
00252    OPT_MESSAGE_Urgent =   (1 << 8),
00253    OPT_MESSAGE_PRIORITY = (1 << 9)
00254 } vm_option_flags;

anonymous enum

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 256 of file app_voicemail.c.

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


Function Documentation

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

Definition at line 4674 of file app_voicemail.c.

References ast_strlen_zero().

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

04675 {
04676    DIR *dir;
04677    struct dirent *de;
04678    char fn[256];
04679    int ret = 0;
04680 
04681    /* If no mailbox, return immediately */
04682    if (ast_strlen_zero(mailbox))
04683       return 0;
04684 
04685    if (ast_strlen_zero(folder))
04686       folder = "INBOX";
04687    if (ast_strlen_zero(context))
04688       context = "default";
04689 
04690    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
04691 
04692    if (!(dir = opendir(fn)))
04693       return 0;
04694 
04695    while ((de = readdir(dir))) {
04696       if (!strncasecmp(de->d_name, "msg", 3)) {
04697          if (shortcircuit) {
04698             ret = 1;
04699             break;
04700          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
04701             if (shortcircuit) return 1;
04702             ret++;
04703          }
04704       }
04705    }
04706 
04707    closedir(dir);
04708 
04709    /* If we are checking INBOX, we should check Urgent as well */
04710    if (strcmp(folder, "INBOX") == 0) {
04711       return (ret + __has_voicemail(context, mailbox, "Urgent", shortcircuit));
04712    } else {
04713       return ret;
04714    }
04715 }

static void __reg_module ( void   )  [static]

Definition at line 11463 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

Definition at line 11463 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 9636 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(), LOG_ERROR, and mbox().

09637 {
09638    struct ast_vm_user svm;
09639    AST_DECLARE_APP_ARGS(arg,
09640       AST_APP_ARG(mbox);
09641       AST_APP_ARG(context);
09642    );
09643 
09644    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
09645 
09646    if (ast_strlen_zero(arg.mbox)) {
09647       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
09648       return -1;
09649    }
09650 
09651    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
09652    return 0;
09653 }

static int add_email_attachment ( FILE *  p,
struct ast_vm_user vmu,
char *  format,
char *  attach,
char *  greeting_attachment,
char *  mailbox,
char *  bound,
char *  filename,
int  last,
int  msgnum 
) [static]

Definition at line 4173 of file app_voicemail.c.

References ast_debug, ast_log(), ast_safe_system(), base_encode(), ast_vm_user::context, create_dirpath(), ENDL, LOG_WARNING, ast_vm_user::mailbox, VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

Referenced by make_email_file().

04174 {
04175    char tmpdir[256], newtmp[256];
04176    char fname[256];
04177    char tmpcmd[256];
04178    int tmpfd = -1;
04179 
04180    /* Eww. We want formats to tell us their own MIME type */
04181    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04182 
04183    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04184       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04185       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04186       tmpfd = mkstemp(newtmp);
04187       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04188       ast_debug(3, "newtmp: %s\n", newtmp);
04189       if (tmpfd > -1) {
04190          int soxstatus;
04191          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04192          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04193             attach = newtmp;
04194             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04195          } else {
04196             ast_log(LOG_WARNING, "Sox failed to reencode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04197                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04198             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04199          }
04200       }
04201    }
04202    fprintf(p, "--%s" ENDL, bound);
04203    if (msgnum > -1)
04204       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04205    else
04206       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, attach, format);
04207    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04208    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04209    if (msgnum > -1)
04210       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04211    else
04212       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, attach, format);
04213    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04214    base_encode(fname, p);
04215    if (last)
04216       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04217    if (tmpfd > -1) {
04218       unlink(fname);
04219       close(tmpfd);
04220       unlink(newtmp);
04221    }
04222    return 0;
04223 }

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

Definition at line 5583 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

05584 {
05585    int x;
05586    if (!ast_adsi_available(chan))
05587       return;
05588    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05589    if (x < 0)
05590       return;
05591    if (!x) {
05592       if (adsi_load_vmail(chan, useadsi)) {
05593          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
05594          return;
05595       }
05596    } else
05597       *useadsi = 1;
05598 }

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

Definition at line 5772 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available, chan, and vm_state::curmsg.

Referenced by vm_execmain().

05773 {
05774    int bytes=0;
05775    unsigned char buf[256];
05776    unsigned char keys[8];
05777 
05778    int x;
05779 
05780    if (!ast_adsi_available(chan))
05781       return;
05782 
05783    /* New meaning for keys */
05784    for (x=0;x<5;x++)
05785       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05786 
05787    keys[6] = 0x0;
05788    keys[7] = 0x0;
05789 
05790    if (!vms->curmsg) {
05791       /* No prev key, provide "Folder" instead */
05792       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05793    }
05794    if (vms->curmsg >= vms->lastmsg) {
05795       /* If last message ... */
05796       if (vms->curmsg) {
05797          /* but not only message, provide "Folder" instead */
05798          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05799       } else {
05800          /* Otherwise if only message, leave blank */
05801          keys[3] = 1;
05802       }
05803    }
05804 
05805    /* If deleted, show "undeleted" */
05806    if (vms->deleted[vms->curmsg]) 
05807       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05808 
05809    /* Except "Exit" */
05810    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05811    bytes += ast_adsi_set_keys(buf + bytes, keys);
05812    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05813 
05814    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05815 }

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

Definition at line 5648 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, ast_adsi_voice_mode, and chan.

Referenced by vm_execmain().

05649 {
05650    unsigned char buf[256];
05651    int bytes=0;
05652    unsigned char keys[8];
05653    int x,y;
05654 
05655    if (!ast_adsi_available(chan))
05656       return;
05657 
05658    for (x=0;x<5;x++) {
05659       y = ADSI_KEY_APPS + 12 + start + x;
05660       if (y > ADSI_KEY_APPS + 12 + 4)
05661          y = 0;
05662       keys[x] = ADSI_KEY_SKT | y;
05663    }
05664    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05665    keys[6] = 0;
05666    keys[7] = 0;
05667 
05668    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05669    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05670    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05671    bytes += ast_adsi_set_keys(buf + bytes, keys);
05672    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05673 
05674    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05675 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 5920 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, ast_adsi_voice_mode, and chan.

Referenced by vm_execmain().

05921 {
05922    unsigned char buf[256];
05923    int bytes=0;
05924 
05925    if (!ast_adsi_available(chan))
05926       return;
05927    bytes += adsi_logo(buf + bytes);
05928    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
05929    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
05930    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05931    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05932 
05933    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05934 }

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

Definition at line 5454 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, chan, mbox(), and num.

Referenced by adsi_begin().

05455 {
05456    unsigned char buf[256];
05457    int bytes=0;
05458    int x;
05459    char num[5];
05460 
05461    *useadsi = 0;
05462    bytes += ast_adsi_data_mode(buf + bytes);
05463    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05464 
05465    bytes = 0;
05466    bytes += adsi_logo(buf);
05467    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05468 #ifdef DISPLAY
05469    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
05470 #endif
05471    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05472    bytes += ast_adsi_data_mode(buf + bytes);
05473    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05474 
05475    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
05476       bytes = 0;
05477       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
05478       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05479       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05480       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05481       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05482       return 0;
05483    }
05484 
05485 #ifdef DISPLAY
05486    /* Add a dot */
05487    bytes = 0;
05488    bytes += ast_adsi_logo(buf);
05489    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05490    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
05491    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05492    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05493 #endif
05494    bytes = 0;
05495    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
05496    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
05497    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
05498    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
05499    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
05500    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
05501    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05502 
05503 #ifdef DISPLAY
05504    /* Add another dot */
05505    bytes = 0;
05506    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
05507    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05508 
05509    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05510    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05511 #endif
05512 
05513    bytes = 0;
05514    /* These buttons we load but don't use yet */
05515    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
05516    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
05517    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
05518    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
05519    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
05520    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
05521    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05522 
05523 #ifdef DISPLAY
05524    /* Add another dot */
05525    bytes = 0;
05526    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
05527    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05528    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05529 #endif
05530 
05531    bytes = 0;
05532    for (x=0;x<5;x++) {
05533       snprintf(num, sizeof(num), "%d", x);
05534       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
05535    }
05536    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
05537    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05538 
05539 #ifdef DISPLAY
05540    /* Add another dot */
05541    bytes = 0;
05542    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
05543    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05544    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05545 #endif
05546 
05547    if (ast_adsi_end_download(chan)) {
05548       bytes = 0;
05549       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
05550       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05551       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05552       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05553       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05554       return 0;
05555    }
05556    bytes = 0;
05557    bytes += ast_adsi_download_disconnect(buf + bytes);
05558    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05559    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05560 
05561    ast_debug(1, "Done downloading scripts...\n");
05562 
05563 #ifdef DISPLAY
05564    /* Add last dot */
05565    bytes = 0;
05566    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
05567    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05568 #endif
05569    ast_debug(1, "Restarting session...\n");
05570 
05571    bytes = 0;
05572    /* Load the session now */
05573    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
05574       *useadsi = 1;
05575       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
05576    } else
05577       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
05578 
05579    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05580    return 0;
05581 }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 5600 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, ast_adsi_voice_mode, and chan.

Referenced by vm_authenticate().

05601 {
05602    unsigned char buf[256];
05603    int bytes=0;
05604    unsigned char keys[8];
05605    int x;
05606    if (!ast_adsi_available(chan))
05607       return;
05608 
05609    for (x=0;x<8;x++)
05610       keys[x] = 0;
05611    /* Set one key for next */
05612    keys[3] = ADSI_KEY_APPS + 3;
05613 
05614    bytes += adsi_logo(buf + bytes);
05615    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05616    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
05617    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05618    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
05619    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05620    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05621    bytes += ast_adsi_set_keys(buf + bytes, keys);
05622    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05623    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05624 }

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

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

05447 {
05448    int bytes = 0;
05449    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
05450    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
05451    return bytes;
05452 }

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

Definition at line 5677 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available, ast_copy_string(), ast_strlen_zero(), chan, vm_state::curmsg, vm_state::fn, num, and strsep().

Referenced by play_message(), and vm_execmain().

05678 {
05679    int bytes=0;
05680    unsigned char buf[256]; 
05681    char buf1[256], buf2[256];
05682    char fn2[PATH_MAX];
05683 
05684    char cid[256]="";
05685    char *val;
05686    char *name, *num;
05687    char datetime[21]="";
05688    FILE *f;
05689 
05690    unsigned char keys[8];
05691 
05692    int x;
05693 
05694    if (!ast_adsi_available(chan))
05695       return;
05696 
05697    /* Retrieve important info */
05698    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
05699    f = fopen(fn2, "r");
05700    if (f) {
05701       while (!feof(f)) {   
05702          if (!fgets((char *)buf, sizeof(buf), f)) {
05703             continue;
05704          }
05705          if (!feof(f)) {
05706             char *stringp=NULL;
05707             stringp = (char *)buf;
05708             strsep(&stringp, "=");
05709             val = strsep(&stringp, "=");
05710             if (!ast_strlen_zero(val)) {
05711                if (!strcmp((char *)buf, "callerid"))
05712                   ast_copy_string(cid, val, sizeof(cid));
05713                if (!strcmp((char *)buf, "origdate"))
05714                   ast_copy_string(datetime, val, sizeof(datetime));
05715             }
05716          }
05717       }
05718       fclose(f);
05719    }
05720    /* New meaning for keys */
05721    for (x=0;x<5;x++)
05722       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05723    keys[6] = 0x0;
05724    keys[7] = 0x0;
05725 
05726    if (!vms->curmsg) {
05727       /* No prev key, provide "Folder" instead */
05728       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05729    }
05730    if (vms->curmsg >= vms->lastmsg) {
05731       /* If last message ... */
05732       if (vms->curmsg) {
05733          /* but not only message, provide "Folder" instead */
05734          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05735          bytes += ast_adsi_voice_mode(buf + bytes, 0);
05736 
05737       } else {
05738          /* Otherwise if only message, leave blank */
05739          keys[3] = 1;
05740       }
05741    }
05742 
05743    if (!ast_strlen_zero(cid)) {
05744       ast_callerid_parse(cid, &name, &num);
05745       if (!name)
05746          name = num;
05747    } else
05748       name = "Unknown Caller";
05749 
05750    /* If deleted, show "undeleted" */
05751 
05752    if (vms->deleted[vms->curmsg])
05753       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05754 
05755    /* Except "Exit" */
05756    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05757    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
05758       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
05759    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
05760 
05761    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05762    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05763    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
05764    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
05765    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05766    bytes += ast_adsi_set_keys(buf + bytes, keys);
05767    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05768 
05769    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05770 }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 5626 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, ast_adsi_voice_mode, and chan.

Referenced by vm_authenticate().

05627 {
05628    unsigned char buf[256];
05629    int bytes=0;
05630    unsigned char keys[8];
05631    int x;
05632    if (!ast_adsi_available(chan))
05633       return;
05634 
05635    for (x=0;x<8;x++)
05636       keys[x] = 0;
05637    /* Set one key for next */
05638    keys[3] = ADSI_KEY_APPS + 3;
05639 
05640    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05641    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05642    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05643    bytes += ast_adsi_set_keys(buf + bytes, keys);
05644    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05645    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05646 }

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

Definition at line 5817 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, chan, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_execmain().

05818 {
05819    unsigned char buf[256] = "";
05820    char buf1[256] = "", buf2[256] = "";
05821    int bytes=0;
05822    unsigned char keys[8];
05823    int x;
05824 
05825    char *newm = (vms->newmessages == 1) ? "message" : "messages";
05826    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
05827    if (!ast_adsi_available(chan))
05828       return;
05829    if (vms->newmessages) {
05830       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
05831       if (vms->oldmessages) {
05832          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
05833          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
05834       } else {
05835          snprintf(buf2, sizeof(buf2), "%s.", newm);
05836       }
05837    } else if (vms->oldmessages) {
05838       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
05839       snprintf(buf2, sizeof(buf2), "%s.", oldm);
05840    } else {
05841       strcpy(buf1, "You have no messages.");
05842       buf2[0] = ' ';
05843       buf2[1] = '\0';
05844    }
05845    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05846    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05847    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05848 
05849    for (x=0;x<6;x++)
05850       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05851    keys[6] = 0;
05852    keys[7] = 0;
05853 
05854    /* Don't let them listen if there are none */
05855    if (vms->lastmsg < 0)
05856       keys[0] = 1;
05857    bytes += ast_adsi_set_keys(buf + bytes, keys);
05858 
05859    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05860 
05861    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05862 }

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

Definition at line 5864 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, chan, vm_state::curbox, and vm_state::lastmsg.

Referenced by vm_execmain().

05865 {
05866    unsigned char buf[256] = "";
05867    char buf1[256] = "", buf2[256] = "";
05868    int bytes=0;
05869    unsigned char keys[8];
05870    int x;
05871 
05872    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
05873 
05874    if (!ast_adsi_available(chan))
05875       return;
05876 
05877    /* Original command keys */
05878    for (x=0;x<6;x++)
05879       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05880 
05881    keys[6] = 0;
05882    keys[7] = 0;
05883 
05884    if ((vms->lastmsg + 1) < 1)
05885       keys[0] = 0;
05886 
05887    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
05888       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
05889 
05890    if (vms->lastmsg + 1)
05891       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
05892    else
05893       strcpy(buf2, "no messages.");
05894    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05895    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05896    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
05897    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05898    bytes += ast_adsi_set_keys(buf + bytes, keys);
05899 
05900    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05901 
05902    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05903    
05904 }

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]

The advanced options within a message.

Parameters:
chan 
vmu 
vms 
msg 
option 
record_gain Provides handling for the play message envelope, call the person back, or reply to message.
Returns:
zero on success, -1 on error.

Definition at line 11037 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, chan, CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), num, play_message_callerid(), play_message_datetime(), RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

11038 {
11039    int res = 0;
11040    char filename[PATH_MAX];
11041    struct ast_config *msg_cfg = NULL;
11042    const char *origtime, *context;
11043    char *name, *num;
11044    int retries = 0;
11045    char *cid;
11046    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
11047 
11048    vms->starting = 0; 
11049 
11050    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11051 
11052    /* Retrieve info from VM attribute file */
11053    snprintf(filename,sizeof(filename), "%s.txt", vms->fn);
11054    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
11055    msg_cfg = ast_config_load(filename, config_flags);
11056    DISPOSE(vms->curdir, vms->curmsg);
11057    if (!msg_cfg) {
11058       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
11059       return 0;
11060    }
11061 
11062    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
11063       ast_config_destroy(msg_cfg);
11064       return 0;
11065    }
11066 
11067    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
11068 
11069    context = ast_variable_retrieve(msg_cfg, "message", "context");
11070    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
11071       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
11072    switch (option) {
11073    case 3: /* Play message envelope */
11074       if (!res)
11075          res = play_message_datetime(chan, vmu, origtime, filename);
11076       if (!res)
11077          res = play_message_callerid(chan, vms, cid, context, 0);
11078 
11079       res = 't';
11080       break;
11081 
11082    case 2:  /* Call back */
11083 
11084       if (ast_strlen_zero(cid))
11085          break;
11086 
11087       ast_callerid_parse(cid, &name, &num);
11088       while ((res > -1) && (res != 't')) {
11089          switch (res) {
11090          case '1':
11091             if (num) {
11092                /* Dial the CID number */
11093                res = dialout(chan, vmu, num, vmu->callback);
11094                if (res) {
11095                   ast_config_destroy(msg_cfg);
11096                   return 9;
11097                }
11098             } else {
11099                res = '2';
11100             }
11101             break;
11102 
11103          case '2':
11104             /* Want to enter a different number, can only do this if there's a dialout context for this user */
11105             if (!ast_strlen_zero(vmu->dialout)) {
11106                res = dialout(chan, vmu, NULL, vmu->dialout);
11107                if (res) {
11108                   ast_config_destroy(msg_cfg);
11109                   return 9;
11110                }
11111             } else {
11112                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
11113                res = ast_play_and_wait(chan, "vm-sorry");
11114             }
11115             ast_config_destroy(msg_cfg);
11116             return res;
11117          case '*':
11118             res = 't';
11119             break;
11120          case '3':
11121          case '4':
11122          case '5':
11123          case '6':
11124          case '7':
11125          case '8':
11126          case '9':
11127          case '0':
11128 
11129             res = ast_play_and_wait(chan, "vm-sorry");
11130             retries++;
11131             break;
11132          default:
11133             if (num) {
11134                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
11135                res = ast_play_and_wait(chan, "vm-num-i-have");
11136                if (!res)
11137                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
11138                if (!res)
11139                   res = ast_play_and_wait(chan, "vm-tocallnum");
11140                /* Only prompt for a caller-specified number if there is a dialout context specified */
11141                if (!ast_strlen_zero(vmu->dialout)) {
11142                   if (!res)
11143                      res = ast_play_and_wait(chan, "vm-calldiffnum");
11144                }
11145             } else {
11146                res = ast_play_and_wait(chan, "vm-nonumber");
11147                if (!ast_strlen_zero(vmu->dialout)) {
11148                   if (!res)
11149                      res = ast_play_and_wait(chan, "vm-toenternumber");
11150                }
11151             }
11152             if (!res)
11153                res = ast_play_and_wait(chan, "vm-star-cancel");
11154             if (!res)
11155                res = ast_waitfordigit(chan, 6000);
11156             if (!res) {
11157                retries++;
11158                if (retries > 3)
11159                   res = 't';
11160             }
11161             break; 
11162             
11163          }
11164          if (res == 't')
11165             res = 0;
11166          else if (res == '*')
11167             res = -1;
11168       }
11169       break;
11170       
11171    case 1:  /* Reply */
11172       /* Send reply directly to sender */
11173       if (ast_strlen_zero(cid))
11174          break;
11175 
11176       ast_callerid_parse(cid, &name, &num);
11177       if (!num) {
11178          ast_verb(3, "No CID number available, no reply sent\n");
11179          if (!res)
11180             res = ast_play_and_wait(chan, "vm-nonumber");
11181          ast_config_destroy(msg_cfg);
11182          return res;
11183       } else {
11184          struct ast_vm_user vmu2;
11185          if (find_user(&vmu2, vmu->context, num)) {
11186             struct leave_vm_options leave_options;
11187             char mailbox[AST_MAX_EXTENSION * 2 + 2];
11188             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
11189 
11190             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
11191             
11192             memset(&leave_options, 0, sizeof(leave_options));
11193             leave_options.record_gain = record_gain;
11194             res = leave_voicemail(chan, mailbox, &leave_options);
11195             if (!res)
11196                res = 't';
11197             ast_config_destroy(msg_cfg);
11198             return res;
11199          } else {
11200             /* Sender has no mailbox, can't reply */
11201             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
11202             ast_play_and_wait(chan, "vm-nobox");
11203             res = 't';
11204             ast_config_destroy(msg_cfg);
11205             return res;
11206          }
11207       } 
11208       res = 0;
11209 
11210       break;
11211    }
11212 
11213 #ifndef IMAP_STORAGE
11214    ast_config_destroy(msg_cfg);
11215 
11216    if (!res) {
11217       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11218       vms->heard[msg] = 1;
11219       res = wait_file(chan, vms, vms->fn);
11220    }
11221 #endif
11222    return res;
11223 }

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

Definition at line 9556 of file app_voicemail.c.

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

Referenced by load_config().

09557 {
09558    /* Assumes lock is already held */
09559    char *tmp;
09560    char *stringp;
09561    char *s;
09562    struct ast_vm_user *vmu;
09563    char *mailbox_full;
09564    int new = 0, old = 0, urgent = 0;
09565 
09566    tmp = ast_strdupa(data);
09567 
09568    if (!(vmu = find_or_create(context, box)))
09569       return -1;
09570    
09571    populate_defaults(vmu);
09572 
09573    stringp = tmp;
09574    if ((s = strsep(&stringp, ","))) 
09575       ast_copy_string(vmu->password, s, sizeof(vmu->password));
09576    if (stringp && (s = strsep(&stringp, ","))) 
09577       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
09578    if (stringp && (s = strsep(&stringp, ","))) 
09579       ast_copy_string(vmu->email, s, sizeof(vmu->email));
09580    if (stringp && (s = strsep(&stringp, ","))) 
09581       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
09582    if (stringp && (s = strsep(&stringp, ","))) 
09583       apply_options(vmu, s);
09584 
09585    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
09586    strcpy(mailbox_full, box);
09587    strcat(mailbox_full, "@");
09588    strcat(mailbox_full, context);
09589 
09590    inboxcount2(mailbox_full, &urgent, &new, &old);
09591    queue_mwi_event(mailbox_full, urgent, new, old);
09592 
09593    return 0;
09594 }

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

Sets a a specific property value.

Parameters:
vmu The voicemail user object to work with.
var The name of the property to be set.
value The value to be set to the property.
The property name must be one of the understood properties. See the source for details.

Definition at line 757 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_log(), AST_LOG_WARNING, 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, 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_MESSAGEWRAP, 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().

00758 {
00759    int x;
00760    if (!strcasecmp(var, "attach")) {
00761       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00762    } else if (!strcasecmp(var, "attachfmt")) {
00763       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00764    } else if (!strcasecmp(var, "serveremail")) {
00765       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00766    } else if (!strcasecmp(var, "language")) {
00767       ast_copy_string(vmu->language, value, sizeof(vmu->language));
00768    } else if (!strcasecmp(var, "tz")) {
00769       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00770 #ifdef IMAP_STORAGE
00771    } else if (!strcasecmp(var, "imapuser")) {
00772       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00773    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
00774       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00775    } else if (!strcasecmp(var, "imapvmshareid")) {
00776       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
00777 #endif
00778    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00779       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
00780    } else if (!strcasecmp(var, "saycid")){
00781       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
00782    } else if (!strcasecmp(var,"sendvoicemail")){
00783       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
00784    } else if (!strcasecmp(var, "review")){
00785       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00786    } else if (!strcasecmp(var, "tempgreetwarn")){
00787       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
00788    } else if (!strcasecmp(var, "messagewrap")){
00789       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
00790    } else if (!strcasecmp(var, "operator")) {
00791       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
00792    } else if (!strcasecmp(var, "envelope")){
00793       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
00794    } else if (!strcasecmp(var, "moveheard")){
00795       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
00796    } else if (!strcasecmp(var, "sayduration")){
00797       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
00798    } else if (!strcasecmp(var, "saydurationm")){
00799       if (sscanf(value, "%d", &x) == 1) {
00800          vmu->saydurationm = x;
00801       } else {
00802          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
00803       }
00804    } else if (!strcasecmp(var, "forcename")){
00805       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
00806    } else if (!strcasecmp(var, "forcegreetings")){
00807       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
00808    } else if (!strcasecmp(var, "callback")) {
00809       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00810    } else if (!strcasecmp(var, "dialout")) {
00811       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00812    } else if (!strcasecmp(var, "exitcontext")) {
00813       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00814    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
00815       if (vmu->maxsecs <= 0) {
00816          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
00817          vmu->maxsecs = vmmaxsecs;
00818       } else {
00819          vmu->maxsecs = atoi(value);
00820       }
00821       if (!strcasecmp(var, "maxmessage"))
00822          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
00823    } else if (!strcasecmp(var, "maxmsg")) {
00824       vmu->maxmsg = atoi(value);
00825       if (vmu->maxmsg <= 0) {
00826          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
00827          vmu->maxmsg = MAXMSG;
00828       } else if (vmu->maxmsg > MAXMSGLIMIT) {
00829          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00830          vmu->maxmsg = MAXMSGLIMIT;
00831       }
00832    } else if (!strcasecmp(var, "backupdeleted")) {
00833       if (sscanf(value, "%d", &x) == 1)
00834          vmu->maxdeletedmsg = x;
00835       else if (ast_true(value))
00836          vmu->maxdeletedmsg = MAXMSG;
00837       else
00838          vmu->maxdeletedmsg = 0;
00839 
00840       if (vmu->maxdeletedmsg < 0) {
00841          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
00842          vmu->maxdeletedmsg = MAXMSG;
00843       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
00844          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
00845          vmu->maxdeletedmsg = MAXMSGLIMIT;
00846       }
00847    } else if (!strcasecmp(var, "volgain")) {
00848       sscanf(value, "%lf", &vmu->volgain);
00849    } else if (!strcasecmp(var, "options")) {
00850       apply_options(vmu, value);
00851    }
00852 }

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

Destructively Parse options and apply.

Definition at line 967 of file app_voicemail.c.

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

Referenced by append_mailbox(), and apply_option().

00968 {  
00969    char *stringp;
00970    char *s;
00971    char *var, *value;
00972    stringp = ast_strdupa(options);
00973    while ((s = strsep(&stringp, "|"))) {
00974       value = s;
00975       if ((var = strsep(&value, "=")) && value) {
00976          apply_option(vmu, var, value);
00977       }
00978    }  
00979 }

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

Loads the options specific to a voicemail user.

This is called when a vm_user structure is being set up, such as from load_options.

Definition at line 986 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, ast_variable::value, and var.

Referenced by find_user_realtime(), and load_config().

00987 {
00988    struct ast_variable *tmp;
00989    tmp = var;
00990    while (tmp) {
00991       if (!strcasecmp(tmp->name, "vmsecret")) {
00992          ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00993       } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) { /* don't overwrite vmsecret if it exists */
00994          if (ast_strlen_zero(retval->password))
00995             ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00996       } else if (!strcasecmp(tmp->name, "uniqueid")) {
00997          ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
00998       } else if (!strcasecmp(tmp->name, "pager")) {
00999          ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
01000       } else if (!strcasecmp(tmp->name, "email")) {
01001          ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
01002       } else if (!strcasecmp(tmp->name, "fullname")) {
01003          ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
01004       } else if (!strcasecmp(tmp->name, "context")) {
01005          ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
01006 #ifdef IMAP_STORAGE
01007       } else if (!strcasecmp(tmp->name, "imapuser")) {
01008          ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
01009       } else if (!strcasecmp(tmp->name, "imappassword") || !strcasecmp(tmp->name, "imapsecret")) {
01010          ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
01011       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01012          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01013 #endif
01014       } else
01015          apply_option(retval, tmp->name, tmp->value);
01016       tmp = tmp->next;
01017    } 
01018 }

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

Performs a base 64 encode algorithm on the contents of a File.

Parameters:
filename The path to the file to be encoded. Must be readable, file is opened in read mode.
so A FILE handle to the output file to receive the base 64 encoded contents of the input file, identified by filename.
TODO: shouldn't this (and the above 3 support functions) be put into some kind of external utility location, such as funcs/func_base64.c ?

Returns:
zero on success, -1 on error.

Definition at line 3661 of file app_voicemail.c.

References ast_log(), BASEMAXINLINE, eol, errno, inchar(), and ochar().

03662 {
03663    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
03664       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
03665       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
03666       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
03667    int i,hiteof= 0;
03668    FILE *fi;
03669    struct baseio bio;
03670 
03671    memset(&bio, 0, sizeof(bio));
03672    bio.iocp = BASEMAXINLINE;
03673 
03674    if (!(fi = fopen(filename, "rb"))) {
03675       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
03676       return -1;
03677    }
03678 
03679    while (!hiteof){
03680       unsigned char igroup[3], ogroup[4];
03681       int c,n;
03682 
03683       igroup[0]= igroup[1]= igroup[2]= 0;
03684 
03685       for (n= 0;n<3;n++) {
03686          if ((c = inchar(&bio, fi)) == EOF) {
03687             hiteof= 1;
03688             break;
03689          }
03690 
03691          igroup[n]= (unsigned char)c;
03692       }
03693 
03694       if (n> 0) {
03695          ogroup[0]= dtable[igroup[0]>>2];
03696          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
03697          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
03698          ogroup[3]= dtable[igroup[2]&0x3F];
03699 
03700          if (n<3) {
03701             ogroup[3]= '=';
03702 
03703             if (n<2)
03704                ogroup[2]= '=';
03705          }
03706 
03707          for (i= 0;i<4;i++)
03708             ochar(&bio, ogroup[i], so);
03709       }
03710    }
03711 
03712    fclose(fi);
03713    
03714    if (fputs(eol,so)==EOF)
03715       return 0;
03716 
03717    return 1;
03718 }

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

Performs a change of the voicemail passowrd in the realtime engine.

Parameters:
vmu The voicemail user to change the password for.
password The new value to be set to the password for this user.
This only works if the voicemail user has a unique id, and if there is a realtime engine configured. This is called from the (top level) vm_change_password.

Returns:
zero on success, -1 on error.

Definition at line 945 of file app_voicemail.c.

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

Referenced by vm_change_password().

00946 {
00947    int res;
00948    if (!ast_strlen_zero(vmu->uniqueid)) {
00949       if (strlen(password) > 10) {
00950          ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
00951       }
00952       res = ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, SENTINEL);
00953       if (res > 0) {
00954          ast_copy_string(vmu->password, password, sizeof(vmu->password));
00955          res = 0;
00956       } else if (!res) {
00957          res = -1;
00958       }
00959       return res;
00960    }
00961    return -1;
00962 }

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 3826 of file app_voicemail.c.

Referenced by make_email_file().

03827 {
03828    for (; *str; str++) {
03829       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
03830          return 1;
03831       }
03832    }
03833    return 0;
03834 }

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

Check that password meets minimum required length.

Parameters:
vmu The voicemail user to change the password for.
password The password string to check
Returns:
zero on ok, 1 on not ok.

Definition at line 907 of file app_voicemail.c.

References ast_debug, ast_log(), AST_LOG_DEBUG, AST_LOG_NOTICE, AST_LOG_WARNING, ast_strlen_zero(), buf, ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, and vm_check_password_shell().

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

00908 {
00909    /* check minimum length */
00910    if (strlen(password) < minpassword)
00911       return 1;
00912    if (!ast_strlen_zero(ext_pass_check_cmd)) {
00913       char cmd[255], buf[255];
00914 
00915       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
00916 
00917       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
00918       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
00919          ast_debug(5, "Result: %s\n", buf);
00920          if (!strncasecmp(buf, "VALID", 5)) {
00921             ast_debug(3, "Passed password check: '%s'\n", buf);
00922             return 0;
00923          } else if (!strncasecmp(buf, "FAILURE", 7)) {
00924             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
00925             return 0;
00926          } else {
00927             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
00928             return 1;
00929          }
00930       }
00931    }
00932    return 0;
00933 }

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

Definition at line 6973 of file app_voicemail.c.

References ast_log(), ast_test_flag, ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, vm_state::deleted, ERROR_LOCK_PATH, EXISTS, vm_state::fn, vm_state::heard, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by vm_execmain().

06974 {
06975    int x = 0;
06976 #ifndef IMAP_STORAGE
06977    int res = 0, nummsg;
06978    char fn2[PATH_MAX];
06979 #endif
06980 
06981    if (vms->lastmsg <= -1)
06982       goto done;
06983 
06984    vms->curmsg = -1; 
06985 #ifndef IMAP_STORAGE
06986    /* Get the deleted messages fixed */ 
06987    if (vm_lock_path(vms->curdir))
06988       return ERROR_LOCK_PATH;
06989 
06990    for (x = 0; x < vmu->maxmsg; x++) { 
06991       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) { 
06992          /* Save this message.  It's not in INBOX or hasn't been heard */ 
06993          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
06994          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
06995             break;
06996          vms->curmsg++; 
06997          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg); 
06998          if (strcmp(vms->fn, fn2)) { 
06999             RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07000          } 
07001       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { 
07002          /* Move to old folder before deleting */ 
07003          res = save_to_folder(vmu, vms, x, 1);
07004          if (res == ERROR_LOCK_PATH) {
07005             /* If save failed do not delete the message */
07006             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07007             vms->deleted[x] = 0;
07008             vms->heard[x] = 0;
07009             --x;
07010          }
07011       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07012          /* Move to deleted folder */ 
07013          res = save_to_folder(vmu, vms, x, 10);
07014          if (res == ERROR_LOCK_PATH) {
07015             /* If save failed do not delete the message */
07016             vms->deleted[x] = 0;
07017             vms->heard[x] = 0;
07018             --x;
07019          }
07020       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07021          /* If realtime storage enabled - we should explicitly delete this message,
07022          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07023          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07024          if (EXISTS(vms->curdir, x, vms->fn, NULL))
07025             DELETE(vms->curdir, x, vms->fn, vmu);
07026       }
07027    } 
07028 
07029    /* Delete ALL remaining messages */
07030    nummsg = x - 1;
07031    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07032       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07033       if (EXISTS(vms->curdir, x, vms->fn, NULL))
07034          DELETE(vms->curdir, x, vms->fn, vmu);
07035    }
07036    ast_unlock_path(vms->curdir);
07037 #else
07038    if (vms->deleted) {
07039       for (x=0;x < vmu->maxmsg;x++) { 
07040          if (vms->deleted[x]) { 
07041             ast_debug(3,"IMAP delete of %d\n",x);
07042             DELETE(vms->curdir, x, vms->fn, vmu);
07043          }
07044       }
07045    }
07046 #endif
07047 
07048 done:
07049    if (vms->deleted)
07050       memset(vms->deleted, 0, vmu->maxmsg * sizeof(int)); 
07051    if (vms->heard)
07052       memset(vms->heard, 0, vmu->maxmsg * sizeof(int)); 
07053 
07054    return 0;
07055 }

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

Definition at line 9740 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, ast_vm_user::context, and ast_vm_user::list.

Referenced by handle_voicemail_show_users().

09741 {
09742    int which = 0;
09743    int wordlen;
09744    struct ast_vm_user *vmu;
09745    const char *context = "";
09746 
09747    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
09748    if (pos > 4)
09749       return NULL;
09750    if (pos == 3)
09751       return (state == 0) ? ast_strdup("for") : NULL;
09752    wordlen = strlen(word);
09753    AST_LIST_TRAVERSE(&users, vmu, list) {
09754       if (!strncasecmp(word, vmu->context, wordlen)) {
09755          if (context && strcmp(context, vmu->context) && ++which > state)
09756             return ast_strdup(vmu->context);
09757          /* ignore repeated contexts ? */
09758          context = vmu->context;
09759       }
09760    }
09761    return NULL;
09762 }

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

Utility function to copy a file.

Parameters:
infile The path to the file to be copied. The file must be readable, it is opened in read only mode.
outfile The path for which to copy the file to. The directory permissions must allow the creation (or truncation) of the file, and allow for opening the file in write only mode.
When the compiler option HARDLINK_WHEN_POSSIBLE is set, the copy operation will attempt to use the hard link facility instead of copy the file (to save disk space). If the link operation fails, it falls back to the copy operation. The copy operation copies up to 4096 bytes at once.

Returns:
zero on success, -1 on error.

Definition at line 3467 of file app_voicemail.c.

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

03468 {
03469    int ifd;
03470    int ofd;
03471    int res;
03472    int len;
03473    char buf[4096];
03474 
03475 #ifdef HARDLINK_WHEN_POSSIBLE
03476    /* Hard link if possible; saves disk space & is faster */
03477    if (link(infile, outfile)) {
03478 #endif
03479       if ((ifd = open(infile, O_RDONLY)) < 0) {
03480          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03481          return -1;
03482       }
03483       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03484          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03485          close(ifd);
03486          return -1;
03487       }
03488       do {
03489          len = read(ifd, buf, sizeof(buf));
03490          if (len < 0) {
03491             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03492             close(ifd);
03493             close(ofd);
03494             unlink(outfile);
03495          }
03496          if (len) {
03497             res = write(ofd, buf, len);
03498             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03499                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03500                close(ifd);
03501                close(ofd);
03502                unlink(outfile);
03503             }
03504          }
03505       } while (len);
03506       close(ifd);
03507       close(ofd);
03508       return 0;
03509 #ifdef HARDLINK_WHEN_POSSIBLE
03510    } else {
03511       /* Hard link succeeded */
03512       return 0;
03513    }
03514 #endif
03515 }

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,
const char *  flag 
) [static]

Copies a message from one mailbox to another.

Parameters:
chan 
vmu 
imbox 
msgnum 
duration 
recip 
fmt 
dir This is only used by file storage based mailboxes.
Returns:
zero on success, -1 on error.

Definition at line 4618 of file app_voicemail.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_channel::language, last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), mbox(), notify_new_message(), S_OR, STORE, vm_delete(), and vm_lock_path().

Referenced by forward_message(), and leave_voicemail().

04619 {
04620    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
04621    const char *frombox = mbox(imbox);
04622    int recipmsgnum;
04623 
04624    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
04625 
04626    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
04627       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
04628    } else {
04629       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04630    }
04631    
04632    if (!dir)
04633       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
04634    else
04635       ast_copy_string(fromdir, dir, sizeof(fromdir));
04636 
04637    make_file(frompath, sizeof(frompath), fromdir, msgnum);
04638    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04639 
04640    if (vm_lock_path(todir))
04641       return ERROR_LOCK_PATH;
04642 
04643    recipmsgnum = last_message_index(recip, todir) + 1;
04644    if (recipmsgnum < recip->maxmsg) {
04645       make_file(topath, sizeof(topath), todir, recipmsgnum);
04646       if (EXISTS(fromdir, msgnum, frompath, chan->language)) {
04647          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
04648       } else {
04649          /* For ODBC storage, if the file we want to copy isn't yet in the database, then the SQL
04650           * copy will fail. Instead, we need to create a local copy, store it, and delete the local
04651           * copy. We don't have to #ifdef this because if file storage reaches this point, there's a
04652           * much worse problem happening and IMAP storage doesn't call this function
04653           */
04654          copy_plain_file(frompath, topath);
04655          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
04656          vm_delete(topath);
04657       }
04658    } else {
04659       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
04660    }
04661    ast_unlock_path(todir);
04662    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
04663    
04664    return 0;
04665 }

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

Copies a voicemail information (envelope) file.

Parameters:
frompath 
topath 
Every voicemail has the data (.wav) file, and the information file. This function performs the file system copying of the information file for a voicemail, handling the internal fields and their values. This is used by the COPY macro when not using IMAP storage.

Definition at line 3526 of file app_voicemail.c.

References ast_check_realtime(), ast_filecopy(), ast_load_realtime(), exten, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.

Referenced by copy_message().

03527 {
03528    char frompath2[PATH_MAX], topath2[PATH_MAX];
03529    struct ast_variable *tmp,*var = NULL;
03530    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
03531    ast_filecopy(frompath, topath, NULL);
03532    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
03533    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
03534    if (ast_check_realtime("voicemail_data")) {
03535       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
03536       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
03537       for (tmp = var; tmp; tmp = tmp->next) {
03538          if (!strcasecmp(tmp->name, "origmailbox")) {
03539             origmailbox = tmp->value;
03540          } else if (!strcasecmp(tmp->name, "context")) {
03541             context = tmp->value;
03542          } else if (!strcasecmp(tmp->name, "macrocontext")) {
03543             macrocontext = tmp->value;
03544          } else if (!strcasecmp(tmp->name, "exten")) {
03545             exten = tmp->value;
03546          } else if (!strcasecmp(tmp->name, "priority")) {
03547             priority = tmp->value;
03548          } else if (!strcasecmp(tmp->name, "callerchan")) {
03549             callerchan = tmp->value;
03550          } else if (!strcasecmp(tmp->name, "callerid")) {
03551             callerid = tmp->value;
03552          } else if (!strcasecmp(tmp->name, "origdate")) {
03553             origdate = tmp->value;
03554          } else if (!strcasecmp(tmp->name, "origtime")) {
03555             origtime = tmp->value;
03556          } else if (!strcasecmp(tmp->name, "category")) {
03557             category = tmp->value;
03558          } else if (!strcasecmp(tmp->name, "duration")) {
03559             duration = tmp->value;
03560          }
03561       }
03562       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, SENTINEL);
03563    }
03564    copy(frompath2, topath2);
03565    ast_variables_destroy(var);
03566 }

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

Find all .txt files - even if they are not in sequence from 0000.

Parameters:
vmu 
dir This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP).
Returns:
the count of messages, zero or more.

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

03374 {
03375 
03376    int vmcount = 0;
03377    DIR *vmdir = NULL;
03378    struct dirent *vment = NULL;
03379 
03380    if (vm_lock_path(dir))
03381       return ERROR_LOCK_PATH;
03382 
03383    if ((vmdir = opendir(dir))) {
03384       while ((vment = readdir(vmdir))) {
03385          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03386             vmcount++;
03387          }
03388       }
03389       closedir(vmdir);
03390    }
03391    ast_unlock_path(dir);
03392    
03393    return vmcount;
03394 }

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 1288 of file app_voicemail.c.

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

01289 {
01290    mode_t   mode = VOICEMAIL_DIR_MODE;
01291    int res;
01292 
01293    make_dir(dest, len, context, ext, folder);
01294    if ((res = ast_mkdir(dest, mode))) {
01295       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01296       return -1;
01297    }
01298    return 0;
01299 }

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

Definition at line 10965 of file app_voicemail.c.

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

Referenced by advanced_options(), and vm_execmain().

10966 {
10967    int cmd = 0;
10968    char destination[80] = "";
10969    int retries = 0;
10970 
10971    if (!num) {
10972       ast_verb(3, "Destination number will be entered manually\n");
10973       while (retries < 3 && cmd != 't') {
10974          destination[1] = '\0';
10975          destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
10976          if (!cmd)
10977             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
10978          if (!cmd)
10979             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
10980          if (!cmd) {
10981             cmd = ast_waitfordigit(chan, 6000);
10982             if (cmd)
10983                destination[0] = cmd;
10984          }
10985          if (!cmd) {
10986             retries++;
10987          } else {
10988 
10989             if (cmd < 0)
10990                return 0;
10991             if (cmd == '*') {
10992                ast_verb(3, "User hit '*' to cancel outgoing call\n");
10993                return 0;
10994             }
10995             if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0) 
10996                retries++;
10997             else
10998                cmd = 't';
10999          }
11000       }
11001       if (retries >= 3) {
11002          return 0;
11003       }
11004       
11005    } else {
11006       if (option_verbose > 2)
11007          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
11008       ast_copy_string(destination, num, sizeof(destination));
11009    }
11010 
11011    if (!ast_strlen_zero(destination)) {
11012       if (destination[strlen(destination) -1 ] == '*')
11013          return 0; 
11014       if (option_verbose > 2)
11015          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
11016       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
11017       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
11018       chan->priority = 0;
11019       return 9;
11020    }
11021    return 0;
11022 }

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 3852 of file app_voicemail.c.

References charset.

Referenced by make_email_file().

03853 {
03854    char tmp[80];
03855    int first_section = 1;
03856    size_t endlen = 0, tmplen = 0;
03857    *end = '\0';
03858 
03859    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03860    for (; *start; start++) {
03861       int need_encoding = 0;
03862       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
03863          need_encoding = 1;
03864       }
03865       if ((first_section && need_encoding && preamble + tmplen > 70) ||
03866          (first_section && !need_encoding && preamble + tmplen > 72) ||
03867          (!first_section && need_encoding && tmplen > 70) ||
03868          (!first_section && !need_encoding && tmplen > 72)) {
03869          /* Start new line */
03870          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
03871          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03872          first_section = 0;
03873       }
03874       if (need_encoding && *start == ' ') {
03875          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
03876       } else if (need_encoding) {
03877          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
03878       } else {
03879          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
03880       }
03881    }
03882    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
03883    return end;
03884 }

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

Definition at line 9524 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, ast_vm_user::list, LOG_WARNING, ast_vm_user::mailbox, and VM_SEARCH.

Referenced by append_mailbox(), and load_config().

09525 {
09526    struct ast_vm_user *vmu;
09527 
09528    AST_LIST_TRAVERSE(&users, vmu, list) {
09529       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
09530          if (strcasecmp(vmu->context, context)) {
09531             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
09532                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
09533                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
09534                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
09535          }
09536          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
09537          return NULL;
09538       }
09539       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
09540          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
09541          return NULL;
09542       }
09543    }
09544    
09545    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
09546       return NULL;
09547    
09548    ast_copy_string(vmu->context, context, sizeof(vmu->context));
09549    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
09550 
09551    AST_LIST_INSERT_TAIL(&users, vmu, list);
09552    
09553    return vmu;
09554 }

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

Finds a voicemail user from the users file or the realtime engine.

Parameters:
ivm 
context 
mailbox 
Returns:
The ast_vm_user structure for the user that was found.

Definition at line 1089 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, ast_vm_user::list, VM_ALLOCED, and VM_SEARCH.

01090 {
01091    /* This function could be made to generate one from a database, too */
01092    struct ast_vm_user *vmu=NULL, *cur;
01093    AST_LIST_LOCK(&users);
01094 
01095    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01096       context = "default";
01097 
01098    AST_LIST_TRAVERSE(&users, cur, list) {
01099       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01100          break;
01101       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01102          break;
01103    }
01104    if (cur) {
01105       /* Make a copy, so that on a reload, we have no race */
01106       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01107          memcpy(vmu, cur, sizeof(*vmu));
01108          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01109          AST_LIST_NEXT(vmu, list) = NULL;
01110       }
01111    } else
01112       vmu = find_user_realtime(ivm, context, mailbox);
01113    AST_LIST_UNLOCK(&users);
01114    return vmu;
01115 }

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

Finds a voicemail user from the realtime engine.

Parameters:
ivm 
context 
mailbox This is called as a fall through case when the normal find_user() was not able to find a user. That is, the default it so look in the usual voicemail users file first.
Returns:
The ast_vm_user structure for the user that was found.

Definition at line 1052 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, populate_defaults(), SENTINEL, var, VM_ALLOCED, and VM_SEARCH.

01053 {
01054    struct ast_variable *var;
01055    struct ast_vm_user *retval;
01056 
01057    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01058       if (!ivm)
01059          ast_set_flag(retval, VM_ALLOCED);   
01060       else
01061          memset(retval, 0, sizeof(*retval));
01062       if (mailbox) 
01063          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01064       populate_defaults(retval);
01065       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01066          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01067       else
01068          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01069       if (var) {
01070          apply_options_full(retval, var);
01071          ast_variables_destroy(var);
01072       } else { 
01073          if (!ivm) 
01074             ast_free(retval);
01075          retval = NULL;
01076       }  
01077    } 
01078    return retval;
01079 }

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

Sends a voicemail message to a mailbox recipient.

Parameters:
ast_channel 
context 
vms 
sender 
fmt 
is_new_message Used to indicate the mode for which this method was invoked. Will be 0 when called to forward an existing message (option 8) Will be 1 when called to leave a message (option 3->5)
record_gain 
Reads the destination mailbox(es) from keypad input for CID, or if use_directory feature is enabled, the Directory.

When in the leave message mode (is_new_message == 1):

When in the forward message mode (is_new_message == 0):

Returns:
zero on success, -1 on error.

Definition at line 6274 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_LOG_ERROR, 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(), chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), free_user(), globalflags, ast_channel::language, leave_voicemail(), ast_app::list, LOG_NOTICE, ast_vm_user::mailbox, pbx_exec(), pbx_findapp(), ast_channel::priority, RETRIEVE, run_externnotify(), s, S_OR, sendmail(), STORE, strsep(), vm_state::username, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

06275 {
06276 #ifdef IMAP_STORAGE
06277    int todircount=0;
06278    struct vm_state *dstvms;
06279 #endif
06280    char username[70]="";
06281    char fn[PATH_MAX]; /* for playback of name greeting */
06282    char ecodes[16] = "#";
06283    int res = 0, cmd = 0;
06284    struct ast_vm_user *receiver = NULL, *vmtmp;
06285    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06286    char *stringp;
06287    const char *s;
06288    int saved_messages = 0, found = 0;
06289    int valid_extensions = 0;
06290    char *dir;
06291    int curmsg;
06292    char urgent_str[7] = "";
06293    char tmptxtfile[PATH_MAX];
06294 
06295    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
06296       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
06297    }
06298 
06299    if (vms == NULL) return -1;
06300    dir = vms->curdir;
06301    curmsg = vms->curmsg;
06302 
06303    tmptxtfile[0] = '\0';
06304    while (!res && !valid_extensions) {
06305       int use_directory = 0;
06306       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
06307          int done = 0;
06308          int retries = 0;
06309          cmd=0;
06310          while ((cmd >= 0) && !done ){
06311             if (cmd)
06312                retries = 0;
06313             switch (cmd) {
06314             case '1': 
06315                use_directory = 0;
06316                done = 1;
06317                break;
06318             case '2': 
06319                use_directory = 1;
06320                done=1;
06321                break;
06322             case '*': 
06323                cmd = 't';
06324                done = 1;
06325                break;
06326             default: 
06327                /* Press 1 to enter an extension press 2 to use the directory */
06328                cmd = ast_play_and_wait(chan,"vm-forward");
06329                if (!cmd)
06330                   cmd = ast_waitfordigit(chan,3000);
06331                if (!cmd)
06332                   retries++;
06333                if (retries > 3) {
06334                   cmd = 't';
06335                   done = 1;
06336                }
06337                
06338             }
06339          }
06340          if (cmd < 0 || cmd == 't')
06341             break;
06342       }
06343       
06344       if (use_directory) {
06345          /* use app_directory */
06346          
06347          char old_context[sizeof(chan->context)];
06348          char old_exten[sizeof(chan->exten)];
06349          int old_priority;
06350          struct ast_app* directory_app;
06351 
06352          directory_app = pbx_findapp("Directory");
06353          if (directory_app) {
06354             char vmcontext[256];
06355             /* make backup copies */
06356             memcpy(old_context, chan->context, sizeof(chan->context));
06357             memcpy(old_exten, chan->exten, sizeof(chan->exten));
06358             old_priority = chan->priority;
06359             
06360             /* call the the Directory, changes the channel */
06361             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
06362             res = pbx_exec(chan, directory_app, vmcontext);
06363             
06364             ast_copy_string(username, chan->exten, sizeof(username));
06365             
06366             /* restore the old context, exten, and priority */
06367             memcpy(chan->context, old_context, sizeof(chan->context));
06368             memcpy(chan->exten, old_exten, sizeof(chan->exten));
06369             chan->priority = old_priority;
06370          } else {
06371             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
06372             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
06373          }
06374       } else {
06375          /* Ask for an extension */
06376          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
06377          if (res)
06378             break;
06379          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
06380             break;
06381       }
06382       
06383       /* start all over if no username */
06384       if (ast_strlen_zero(username))
06385          continue;
06386       stringp = username;
06387       s = strsep(&stringp, "*");
06388       /* start optimistic */
06389       valid_extensions = 1;
06390       while (s) {
06391          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
06392             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
06393             found++;
06394          } else {
06395             /* XXX Optimization for the future.  When we encounter a single bad extension,
06396              * bailing out on all of the extensions may not be the way to go.  We should
06397              * probably just bail on that single extension, then allow the user to enter
06398              * several more. XXX
06399              */
06400             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
06401                free_user(receiver);
06402             }
06403             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
06404             valid_extensions = 0;
06405             break;
06406          }
06407 
06408          /* play name if available, else play extension number */
06409          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
06410          RETRIEVE(fn, -1, s, receiver->context);
06411          if (ast_fileexists(fn, NULL, NULL) > 0) {
06412             res = ast_stream_and_wait(chan, fn, ecodes);
06413             if (res) {
06414                DISPOSE(fn, -1);
06415                return res;
06416             }
06417          } else {
06418             res = ast_say_digit_str(chan, s, ecodes, chan->language);
06419          }
06420          DISPOSE(fn, -1);
06421 
06422          s = strsep(&stringp, "*");
06423       }
06424       /* break from the loop of reading the extensions */
06425       if (valid_extensions)
06426          break;
06427       /* "I am sorry, that's not a valid extension.  Please try again." */
06428       res = ast_play_and_wait(chan, "pbx-invalid");
06429    }
06430    /* check if we're clear to proceed */
06431    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
06432       return res;
06433    if (is_new_message == 1) {
06434       struct leave_vm_options leave_options;
06435       char mailbox[AST_MAX_EXTENSION * 2 + 2];
06436       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
06437 
06438       /* Send VoiceMail */
06439       memset(&leave_options, 0, sizeof(leave_options));
06440       leave_options.record_gain = record_gain;
06441       cmd = leave_voicemail(chan, mailbox, &leave_options);
06442    } else {
06443       /* Forward VoiceMail */
06444       long duration = 0;
06445       struct vm_state vmstmp;
06446       memcpy(&vmstmp, vms, sizeof(vmstmp));
06447 
06448       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
06449 
06450       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
06451       if (!cmd) {
06452          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
06453 #ifdef IMAP_STORAGE
06454             int attach_user_voicemail;
06455             char *myserveremail = serveremail;
06456             
06457             /* get destination mailbox */
06458             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
06459             if (!dstvms) {
06460                dstvms = create_vm_state_from_user(vmtmp);
06461             }
06462             if (dstvms) {
06463                init_mailstream(dstvms, 0);
06464                if (!dstvms->mailstream) {
06465                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
06466                } else {
06467                   STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
06468                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
06469                }
06470             } else {
06471                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
06472             }
06473             if (!ast_strlen_zero(vmtmp->serveremail))
06474                myserveremail = vmtmp->serveremail;
06475             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
06476             /* NULL category for IMAP storage */
06477             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, dstvms->curbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, NULL, urgent_str);
06478 #else
06479             copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
06480 #endif
06481             saved_messages++;
06482             AST_LIST_REMOVE_CURRENT(list);
06483             free_user(vmtmp);
06484             if (res)
06485                break;
06486          }
06487          AST_LIST_TRAVERSE_SAFE_END;
06488          if (saved_messages > 0) {
06489             /* give confirmation that the message was saved */
06490             /* commented out since we can't forward batches yet
06491             if (saved_messages == 1)
06492                res = ast_play_and_wait(chan, "vm-message");
06493             else
06494                res = ast_play_and_wait(chan, "vm-messages");
06495             if (!res)
06496                res = ast_play_and_wait(chan, "vm-saved"); */
06497 #ifdef IMAP_STORAGE
06498             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
06499             if (ast_strlen_zero(vmstmp.introfn))
06500 #endif
06501             res = ast_play_and_wait(chan, "vm-msgsaved");
06502          }  
06503       }
06504       DISPOSE(dir, curmsg);
06505    }
06506 
06507    /* If anything failed above, we still have this list to free */
06508    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
06509       free_user(vmtmp);
06510    return res ? res : cmd;
06511 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1324 of file app_voicemail.c.

References ast_free, ast_test_flag, and VM_ALLOCED.

01325 {
01326    if (ast_test_flag(vmu, VM_ALLOCED))
01327       ast_free(vmu);
01328 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 10192 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10193 {
10194    struct ast_vm_user *current;
10195    AST_LIST_LOCK(&users);
10196    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
10197       ast_set_flag(current, VM_ALLOCED);
10198       free_user(current);
10199    }
10200    AST_LIST_UNLOCK(&users);
10201 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 10204 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10205 {
10206    struct vm_zone *zcur;
10207    AST_LIST_LOCK(&zones);
10208    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
10209       free_zone(zcur);
10210    AST_LIST_UNLOCK(&zones);
10211 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4393 of file app_voicemail.c.

References ast_free.

04394 {
04395    ast_free(z);
04396 }

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

Gets the current date and time, as formatted string.

Parameters:
s The buffer to hold the output formatted date.
len the length of the buffer. Used to prevent buffer overflow in ast_strftime.
The date format string used is "%a %b %e %r UTC %Y".

Returns:
zero on success, -1 on error.

Definition at line 4349 of file app_voicemail.c.

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

04350 {
04351    struct ast_tm tm;
04352    struct timeval t = ast_tvnow();
04353    
04354    ast_localtime(&t, &tm, "UTC");
04355 
04356    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04357 }

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 5940 of file app_voicemail.c.

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

Referenced by get_folder2().

05941 {
05942    int x;
05943    int d;
05944    char fn[PATH_MAX];
05945    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
05946    if (d)
05947       return d;
05948    for (x = start; x< 5; x++) {  /* For all folders */
05949       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
05950          return d;
05951       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
05952       if (d)
05953          return d;
05954       snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
05955       d = vm_play_folder_name(chan, fn);
05956       if (d)
05957          return d;
05958       d = ast_waitfordigit(chan, 500);
05959       if (d)
05960          return d;
05961    }
05962    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
05963    if (d)
05964       return d;
05965    d = ast_waitfordigit(chan, 4000);
05966    return d;
05967 }

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

plays a prompt and waits for a keypress.

Parameters:
chan 
fn the name of the voice prompt file to be played. For example, 'vm-changeto', 'vm-savefolder'
start Does not appear to be used at this time.
This is used by the main menu option to move a message to a folder or to save a message into a folder. After playing the message identified by the fn parameter value, it calls get_folder(), which plays the prompting for the number inputs that correspond to the available folders.

Returns:
zero on success, or -1 on error.

Definition at line 5981 of file app_voicemail.c.

References ast_play_and_wait(), chan, and get_folder().

Referenced by vm_execmain().

05982 {
05983    int res = 0;
05984    res = ast_play_and_wait(chan, fn);  /* Folder name */
05985    while (((res < '0') || (res > '9')) &&
05986          (res != '#') && (res >= 0)) {
05987       res = get_folder(chan, 0);
05988    }
05989    return res;
05990 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 9976 of file app_voicemail.c.

References ast_calloc, ast_free, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), mwi_sub_task::context, mwi_sub::mailbox, mwi_sub_task::mailbox, mwi_sub_task::uniqueid, and mwi_sub::uniqueid.

Referenced by mwi_sub_event_cb().

09977 {
09978    unsigned int len;
09979    struct mwi_sub *mwi_sub;
09980    struct mwi_sub_task *p = datap;
09981 
09982    len = sizeof(*mwi_sub);
09983    if (!ast_strlen_zero(p->mailbox))
09984       len += strlen(p->mailbox);
09985 
09986    if (!ast_strlen_zero(p->context))
09987       len += strlen(p->context) + 1; /* Allow for seperator */
09988 
09989    if (!(mwi_sub = ast_calloc(1, len)))
09990       return -1;
09991 
09992    mwi_sub->uniqueid = p->uniqueid;
09993    if (!ast_strlen_zero(p->mailbox))
09994       strcpy(mwi_sub->mailbox, p->mailbox);
09995 
09996    if (!ast_strlen_zero(p->context)) {
09997       strcat(mwi_sub->mailbox, "@");
09998       strcat(mwi_sub->mailbox, p->context);
09999    }
10000 
10001    AST_RWLIST_WRLOCK(&mwi_subs);
10002    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
10003    AST_RWLIST_UNLOCK(&mwi_subs);
10004    ast_free((void *) p->mailbox);
10005    ast_free((void *) p->context);
10006    ast_free(p);   
10007    return 0;
10008 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 9954 of file app_voicemail.c.

References ast_free, 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 mwi_unsub_event_cb().

09955 {
09956    struct mwi_sub *mwi_sub;
09957    uint32_t *uniqueid = datap;
09958    
09959    AST_RWLIST_WRLOCK(&mwi_subs);
09960    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
09961       if (mwi_sub->uniqueid == *uniqueid) {
09962          AST_LIST_REMOVE_CURRENT(entry);
09963          break;
09964       }
09965    }
09966    AST_RWLIST_TRAVERSE_SAFE_END
09967    AST_RWLIST_UNLOCK(&mwi_subs);
09968 
09969    if (mwi_sub)
09970       mwi_sub_destroy(mwi_sub);
09971 
09972    ast_free(uniqueid);  
09973    return 0;
09974 }

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 9875 of file app_voicemail.c.

References ast_cli_args::argc, 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.

09876 {
09877    switch (cmd) {
09878    case CLI_INIT:
09879       e->command = "voicemail reload";
09880       e->usage =
09881          "Usage: voicemail reload\n"
09882          "       Reload voicemail configuration\n";
09883       return NULL;
09884    case CLI_GENERATE:
09885       return NULL;
09886    }
09887 
09888    if (a->argc != 2)
09889       return CLI_SHOWUSAGE;
09890 
09891    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
09892    load_config(1);
09893    
09894    return CLI_SUCCESS;
09895 }

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 9765 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::list, 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.

09766 {
09767    struct ast_vm_user *vmu;
09768 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
09769    const char *context = NULL;
09770    int users_counter = 0;
09771 
09772    switch (cmd) {
09773    case CLI_INIT:
09774       e->command = "voicemail show users";
09775       e->usage =
09776          "Usage: voicemail show users [for <context>]\n"
09777          "       Lists all mailboxes currently set up\n";
09778       return NULL;
09779    case CLI_GENERATE:
09780       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
09781    }  
09782 
09783    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
09784       return CLI_SHOWUSAGE;
09785    if (a->argc == 5) {
09786       if (strcmp(a->argv[3],"for"))
09787          return CLI_SHOWUSAGE;
09788       context = a->argv[4];
09789    }
09790 
09791    if (ast_check_realtime("voicemail")) {
09792       if (!context) {
09793          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
09794          return CLI_SHOWUSAGE;
09795       }
09796       return show_users_realtime(a->fd, context);
09797    }
09798 
09799    AST_LIST_LOCK(&users);
09800    if (AST_LIST_EMPTY(&users)) {
09801       ast_cli(a->fd, "There are no voicemail users currently defined\n");
09802       AST_LIST_UNLOCK(&users);
09803       return CLI_FAILURE;
09804    }
09805    if (a->argc == 3)
09806       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
09807    else {
09808       int count = 0;
09809       AST_LIST_TRAVERSE(&users, vmu, list) {
09810          if (!strcmp(context, vmu->context))
09811             count++;
09812       }
09813       if (count) {
09814          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
09815       } else {
09816          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
09817          AST_LIST_UNLOCK(&users);
09818          return CLI_FAILURE;
09819       }
09820    }
09821    AST_LIST_TRAVERSE(&users, vmu, list) {
09822       int newmsgs = 0, oldmsgs = 0;
09823       char count[12], tmp[256] = "";
09824 
09825       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
09826          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
09827          inboxcount(tmp, &newmsgs, &oldmsgs);
09828          snprintf(count, sizeof(count), "%d", newmsgs);
09829          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
09830          users_counter++;
09831       }
09832    }
09833    AST_LIST_UNLOCK(&users);
09834    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
09835    return CLI_SUCCESS;
09836 }

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 9839 of file app_voicemail.c.

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

09840 {
09841    struct vm_zone *zone;
09842 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
09843    char *res = CLI_SUCCESS;
09844 
09845    switch (cmd) {
09846    case CLI_INIT:
09847       e->command = "voicemail show zones";
09848       e->usage =
09849          "Usage: voicemail show zones\n"
09850          "       Lists zone message formats\n";
09851       return NULL;
09852    case CLI_GENERATE:
09853       return NULL;
09854    }
09855 
09856    if (a->argc != 3)
09857       return CLI_SHOWUSAGE;
09858 
09859    AST_LIST_LOCK(&zones);
09860    if (!AST_LIST_EMPTY(&zones)) {
09861       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
09862       AST_LIST_TRAVERSE(&zones, zone, list) {
09863          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
09864       }
09865    } else {
09866       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
09867       res = CLI_FAILURE;
09868    }
09869    AST_LIST_UNLOCK(&zones);
09870 
09871    return res;
09872 }

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

Determines if the given folder has messages.

Parameters:
mailbox The @ delimited string for user. If no context is found, uses 'default' for the context.
folder the folder to look in
This function is used when the mailbox is stored in a filesystem back end. This invokes the messagecount(). Here we are interested in the presence of messages (> 0) only, not the actual count.
Returns:
1 if the folder has one or more messages. zero otherwise.

Definition at line 4726 of file app_voicemail.c.

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

04727 {
04728    char tmp[256], *tmp2 = tmp, *box, *context;
04729    ast_copy_string(tmp, mailbox, sizeof(tmp));
04730    while ((box = strsep(&tmp2, ","))) {
04731       if ((context = strchr(box, '@')))
04732          *context++ = '\0';
04733       else
04734          context = "default";
04735       if (__has_voicemail(context, box, folder, 1))
04736          return 1;
04737    }
04738    return 0;
04739 }

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

Definition at line 4798 of file app_voicemail.c.

References inboxcount2().

Referenced by handle_voicemail_show_users(), leave_voicemail(), load_module(), and manager_list_voicemail_users().

04799 {
04800    return inboxcount2(mailbox, NULL, newmsgs, oldmsgs);
04801 }

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

Definition at line 4742 of file app_voicemail.c.

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

Referenced by append_mailbox(), inboxcount(), load_module(), poll_subscribed_mailboxes(), and run_externnotify().

04743 {
04744    char tmp[256];
04745    char *context;
04746 
04747    /* If no mailbox, return immediately */
04748    if (ast_strlen_zero(mailbox))
04749       return 0;
04750 
04751    if (newmsgs)
04752       *newmsgs = 0;
04753    if (oldmsgs)
04754       *oldmsgs = 0;
04755    if (urgentmsgs)
04756       *urgentmsgs = 0;
04757 
04758    if (strchr(mailbox, ',')) {
04759       int tmpnew, tmpold, tmpurgent;
04760       char *mb, *cur;
04761 
04762       ast_copy_string(tmp, mailbox, sizeof(tmp));
04763       mb = tmp;
04764       while ((cur = strsep(&mb, ", "))) {
04765          if (!ast_strlen_zero(cur)) {
04766             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
04767                return -1;
04768             else {
04769                if (newmsgs)
04770                   *newmsgs += tmpnew; 
04771                if (oldmsgs)
04772                   *oldmsgs += tmpold;
04773                if (urgentmsgs)
04774                   *urgentmsgs += tmpurgent;
04775             }
04776          }
04777       }
04778       return 0;
04779    }
04780 
04781    ast_copy_string(tmp, mailbox, sizeof(tmp));
04782    
04783    if ((context = strchr(tmp, '@')))
04784       *context++ = '\0';
04785    else
04786       context = "default";
04787 
04788    if (newmsgs)
04789       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
04790    if (oldmsgs)
04791       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
04792    if (urgentmsgs)
04793       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
04794 
04795    return 0;
04796 }

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

utility used by inchar(), for base_encode()

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

03599 {
03600    int l;
03601 
03602    if (bio->ateof)
03603       return 0;
03604 
03605    if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
03606       if (ferror(fi))
03607          return -1;
03608 
03609       bio->ateof = 1;
03610       return 0;
03611    }
03612 
03613    bio->iolen= l;
03614    bio->iocp= 0;
03615 
03616    return 1;
03617 }

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

utility used by base_encode()

Definition at line 3622 of file app_voicemail.c.

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

Referenced by base_encode().

03623 {
03624    if (bio->iocp>=bio->iolen) {
03625       if (!inbuf(bio, fi))
03626          return EOF;
03627    }
03628 
03629    return bio->iobuf[bio->iocp++];
03630 }

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

Definition at line 4359 of file app_voicemail.c.

References ast_fileexists(), ast_log(), ast_say_digit_str(), ast_stream_and_wait(), chan, create_dirpath(), DISPOSE, ast_channel::language, and RETRIEVE.

04360 {
04361    int res;
04362    char fn[PATH_MAX];
04363    char dest[PATH_MAX];
04364 
04365    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04366 
04367    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04368       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04369       return -1;
04370    }
04371 
04372    RETRIEVE(fn, -1, ext, context);
04373    if (ast_fileexists(fn, NULL, NULL) > 0) {
04374       res = ast_stream_and_wait(chan, fn, ecodes);
04375       if (res) {
04376          DISPOSE(fn, -1);
04377          return res;
04378       }
04379    } else {
04380       /* Dispose just in case */
04381       DISPOSE(fn, -1);
04382       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04383       if (res)
04384          return res;
04385       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04386       if (res)
04387          return res;
04388    }
04389    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04390    return res;
04391 }

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

Determines if a DTMF key entered is valid.

Parameters:
key The character to be compared. expects a single character. Though is capable of handling a string, this is internally copies using ast_strdupa.
Tests the character entered against the set of valid DTMF characters.
Returns:
1 if the character entered is a valid DTMF digit, 0 if the character is invalid.

Definition at line 1027 of file app_voicemail.c.

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

Referenced by load_config().

01028 {
01029    int i;
01030    char *local_key = ast_strdupa(key);
01031 
01032    for (i = 0; i < strlen(key); ++i) {
01033       if (!strchr(VALID_DTMF, *local_key)) {
01034          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01035          return 0;
01036       }
01037       local_key++;
01038    }
01039    return 1;
01040 }

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

Determines the highest message number in use for a given user and mailbox folder.

Parameters:
vmu 
dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.
This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP). Typical use to set the msgnum would be to take the value returned from this method and add one to it.

Note:
Should always be called with a lock already set on dir.
Returns:
the value of zero or greaterto indicate the last message index in use, -1 to indicate none.

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

03428 {
03429    int x;
03430    unsigned char map[MAXMSGLIMIT] = "";
03431    DIR *msgdir;
03432    struct dirent *msgdirent;
03433    int msgdirint;
03434 
03435    /* Reading the entire directory into a file map scales better than
03436     * doing a stat repeatedly on a predicted sequence.  I suspect this
03437     * is partially due to stat(2) internally doing a readdir(2) itself to
03438     * find each file. */
03439    msgdir = opendir(dir);
03440    while ((msgdirent = readdir(msgdir))) {
03441       if (sscanf(msgdirent->d_name, "msg%d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03442          map[msgdirint] = 1;
03443    }
03444    closedir(msgdir);
03445 
03446    for (x = 0; x < vmu->maxmsg; x++) {
03447       if (map[x] == 0)
03448          break;
03449    }
03450 
03451    return x - 1;
03452 }

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

Prompts the user and records a voicemail to a mailbox.

Parameters:
chan 
ext 
options OPT_BUSY_GREETING, OPT_UNAVAIL_GREETING
Returns:
zero on success, -1 on error.

Definition at line 4868 of file app_voicemail.c.

References ast_callerid_merge(), ast_canmatch_extension(), ast_channel_lock, ast_channel_unlock, ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_mutex_lock(), ast_mutex_unlock(), ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verbose, ast_waitstream(), chan, 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(), 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_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, RENAME, RETRIEVE, S_OR, SENTINEL, STORE, strsep(), transfer, VERBOSE_PREFIX_3, vm_lock_path(), VM_OPERATOR, and VOICEMAIL_FILE_MODE.

04869 {
04870 #ifdef IMAP_STORAGE
04871    int newmsgs, oldmsgs;
04872 #else
04873    char urgdir[PATH_MAX];
04874 #endif
04875    char txtfile[PATH_MAX];
04876    char tmptxtfile[PATH_MAX];
04877    struct vm_state *vms = NULL;
04878    char callerid[256];
04879    FILE *txt;
04880    char date[256];
04881    int txtdes;
04882    int res = 0;
04883    int msgnum;
04884    int duration = 0;
04885    int ausemacro = 0;
04886    int ousemacro = 0;
04887    int ouseexten = 0;
04888    int rtmsgid = 0;
04889    char tmpid[16];
04890    char tmpdur[16];
04891    char priority[16];
04892    char origtime[16];
04893    char dir[PATH_MAX];
04894    char tmpdir[PATH_MAX];
04895    char fn[PATH_MAX];
04896    char prefile[PATH_MAX] = "";
04897    char tempfile[PATH_MAX] = "";
04898    char ext_context[256] = "";
04899    char fmt[80];
04900    char *context;
04901    char ecodes[17] = "#";
04902    char tmp[1024] = "";
04903    char *tmpptr;
04904    struct ast_vm_user *vmu;
04905    struct ast_vm_user svm;
04906    const char *category = NULL;
04907    const char *code;
04908    const char *alldtmf = "0123456789ABCD*#";
04909    char flag[80];
04910 
04911    ast_copy_string(tmp, ext, sizeof(tmp));
04912    ext = tmp;
04913    if ((context = strchr(tmp, '@'))) {
04914       *context++ = '\0';
04915       tmpptr = strchr(context, '&');
04916    } else {
04917       tmpptr = strchr(ext, '&');
04918    }
04919 
04920    if (tmpptr)
04921       *tmpptr++ = '\0';
04922 
04923    ast_channel_lock(chan);
04924    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
04925       category = ast_strdupa(category);
04926    }
04927    ast_channel_unlock(chan);
04928 
04929    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
04930       ast_copy_string(flag, "Urgent", sizeof(flag));
04931    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
04932       ast_copy_string(flag, "PRIORITY", sizeof(flag));
04933    } else {
04934       flag[0] = '\0';
04935    }
04936 
04937    ast_debug(3, "Before find_user\n");
04938    if (!(vmu = find_user(&svm, context, ext))) {
04939       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
04940       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
04941       return res;
04942    }
04943    /* Setup pre-file if appropriate */
04944    if (strcmp(vmu->context, "default"))
04945       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
04946    else
04947       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
04948 
04949    /* Set the path to the prefile. Will be one of 
04950       VM_SPOOL_DIRcontext/ext/busy
04951       VM_SPOOL_DIRcontext/ext/unavail
04952       Depending on the flag set in options.
04953    */
04954    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
04955       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
04956    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
04957       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
04958    }
04959    /* Set the path to the tmpfile as
04960       VM_SPOOL_DIR/context/ext/temp
04961       and attempt to create the folder structure.
04962    */
04963    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
04964    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
04965       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
04966       return -1;
04967    }
04968    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
04969    if (ast_fileexists(tempfile, NULL, NULL) > 0)
04970       ast_copy_string(prefile, tempfile, sizeof(prefile));
04971 
04972    DISPOSE(tempfile, -1);
04973    /* It's easier just to try to make it than to check for its existence */
04974    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
04975 
04976    /* Check current or macro-calling context for special extensions */
04977    if (ast_test_flag(vmu, VM_OPERATOR)) {
04978       if (!ast_strlen_zero(vmu->exit)) {
04979          if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
04980             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
04981             ouseexten = 1;
04982          }
04983       } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
04984          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
04985          ouseexten = 1;
04986       } else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
04987          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
04988          ousemacro = 1;
04989       }
04990    }
04991 
04992    if (!ast_strlen_zero(vmu->exit)) {
04993       if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
04994          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
04995    } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
04996       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
04997    else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
04998       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
04999       ausemacro = 1;
05000    }
05001 
05002    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05003       for (code = alldtmf; *code; code++) {
05004          char e[2] = "";
05005          e[0] = *code;
05006          if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num))
05007             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05008       }
05009    }
05010 
05011    /* Play the beginning intro if desired */
05012    if (!ast_strlen_zero(prefile)) {
05013 #ifdef ODBC_STORAGE
05014       int success = 
05015 #endif
05016          RETRIEVE(prefile, -1, ext, context);
05017       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05018          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05019             res = ast_waitstream(chan, ecodes);
05020 #ifdef ODBC_STORAGE
05021          if (success == -1) {
05022             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05023             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05024             store_file(prefile, vmu->mailbox, vmu->context, -1);
05025          }
05026 #endif
05027       } else {
05028          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05029          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05030       }
05031       DISPOSE(prefile, -1);
05032       if (res < 0) {
05033          ast_debug(1, "Hang up during prefile playback\n");
05034          free_user(vmu);
05035          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05036          return -1;
05037       }
05038    }
05039    if (res == '#') {
05040       /* On a '#' we skip the instructions */
05041       ast_set_flag(options, OPT_SILENT);
05042       res = 0;
05043    }
05044    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05045       res = ast_stream_and_wait(chan, INTRO, ecodes);
05046       if (res == '#') {
05047          ast_set_flag(options, OPT_SILENT);
05048          res = 0;
05049       }
05050    }
05051    if (res > 0)
05052       ast_stopstream(chan);
05053    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05054     other than the operator -- an automated attendant or mailbox login for example */
05055    if (res == '*') {
05056       chan->exten[0] = 'a';
05057       chan->exten[1] = '\0';
05058       if (!ast_strlen_zero(vmu->exit)) {
05059          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05060       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05061          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05062       }
05063       chan->priority = 0;
05064       free_user(vmu);
05065       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05066       return 0;
05067    }
05068 
05069    /* Check for a '0' here */
05070    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05071    transfer:
05072       if (ouseexten || ousemacro) {
05073          chan->exten[0] = 'o';
05074          chan->exten[1] = '\0';
05075          if (!ast_strlen_zero(vmu->exit)) {
05076             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05077          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05078             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05079          }
05080          ast_play_and_wait(chan, "transfer");
05081          chan->priority = 0;
05082          free_user(vmu);
05083          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05084       }
05085       return 0;
05086    }
05087 
05088    /* Allow all other digits to exit Voicemail and return to the dialplan */
05089    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05090       if (!ast_strlen_zero(options->exitcontext))
05091          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05092       free_user(vmu);
05093       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05094       return res;
05095    }
05096 
05097    if (res < 0) {
05098       free_user(vmu);
05099       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05100       return -1;
05101    }
05102    /* The meat of recording the message...  All the announcements and beeps have been played*/
05103    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05104    if (!ast_strlen_zero(fmt)) {
05105       msgnum = 0;
05106 
05107 #ifdef IMAP_STORAGE
05108       /* Is ext a mailbox? */
05109       /* must open stream for this user to get info! */
05110       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05111       if (res < 0) {
05112          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05113          return -1;
05114       }
05115       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05116       /* It is possible under certain circumstances that inboxcount did not
05117        * create a vm_state when it was needed. This is a catchall which will
05118        * rarely be used.
05119        */
05120          if (!(vms = create_vm_state_from_user(vmu))) {
05121             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05122             return -1;
05123          }
05124       }
05125       vms->newmessages++;
05126       
05127       /* here is a big difference! We add one to it later */
05128       msgnum = newmsgs + oldmsgs;
05129       ast_debug(3, "Messagecount set to %d\n",msgnum);
05130       snprintf(fn, sizeof(fn), "%s/imap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05131       /* set variable for compatibility */
05132       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05133 
05134       /* Check if mailbox is full */
05135       check_quota(vms, imapfolder);
05136       if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
05137          ast_debug(1, "*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
05138          ast_play_and_wait(chan, "vm-mailboxfull");
05139          return -1;
05140       }
05141       
05142       /* Check if we have exceeded maxmsg */
05143       if (msgnum >= vmu->maxmsg) {
05144          ast_log(AST_LOG_WARNING, "Unable to leave message since we will exceed the maximum number of messages allowed (%u > %u)\n", msgnum, vmu->maxmsg);
05145          ast_play_and_wait(chan, "vm-mailboxfull");
05146          return -1;
05147       }
05148 #else
05149       if (count_messages(vmu, dir) >= vmu->maxmsg) {
05150          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05151          if (!res)
05152             res = ast_waitstream(chan, "");
05153          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05154          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05155          goto leave_vm_out;
05156       }
05157 
05158 #endif
05159       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05160       txtdes = mkstemp(tmptxtfile);
05161       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05162       if (txtdes < 0) {
05163          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05164          if (!res)
05165             res = ast_waitstream(chan, "");
05166          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05167          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05168          goto leave_vm_out;
05169       }
05170 
05171       /* Now play the beep once we have the message number for our next message. */
05172       if (res >= 0) {
05173          /* Unless we're *really* silent, try to send the beep */
05174          res = ast_stream_and_wait(chan, "beep", "");
05175       }
05176             
05177       /* Store information in real-time storage */
05178       if (ast_check_realtime("voicemail_data")) {
05179          snprintf(priority, sizeof(priority), "%d", chan->priority);
05180          snprintf(origtime, sizeof(origtime), "%ld", (long)time(NULL));
05181          get_date(date, sizeof(date));
05182          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", S_OR(category,""), SENTINEL);
05183       }
05184 
05185       /* Store information */
05186       txt = fdopen(txtdes, "w+");
05187       if (txt) {
05188          get_date(date, sizeof(date));
05189          fprintf(txt, 
05190             ";\n"
05191             "; Message Information file\n"
05192             ";\n"
05193             "[message]\n"
05194             "origmailbox=%s\n"
05195             "context=%s\n"
05196             "macrocontext=%s\n"
05197             "exten=%s\n"
05198             "priority=%d\n"
05199             "callerchan=%s\n"
05200             "callerid=%s\n"
05201             "origdate=%s\n"
05202             "origtime=%ld\n"
05203             "category=%s\n",
05204             ext,
05205             chan->context,
05206             chan->macrocontext, 
05207             chan->exten,
05208             chan->priority,
05209             chan->name,
05210             ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
05211             date, (long)time(NULL),
05212             category ? category : "");
05213       } else
05214          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
05215       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms, flag);
05216 
05217       if (txt) {
05218          fprintf(txt, "flag=%s\n", flag);
05219          if (duration < vmminsecs) {
05220             fclose(txt);
05221             if (option_verbose > 2) 
05222                ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminsecs);
05223             ast_filedelete(tmptxtfile, NULL);
05224             unlink(tmptxtfile);
05225             if (ast_check_realtime("voicemail_data")) {
05226                snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
05227                ast_destroy_realtime("voicemail_data", "id", tmpid, SENTINEL);
05228             }
05229          } else {
05230             fprintf(txt, "duration=%d\n", duration);
05231             fclose(txt);
05232             if (vm_lock_path(dir)) {
05233                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
05234                /* Delete files */
05235                ast_filedelete(tmptxtfile, NULL);
05236                unlink(tmptxtfile);
05237             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
05238                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
05239                unlink(tmptxtfile);
05240                ast_unlock_path(dir);
05241                if (ast_check_realtime("voicemail_data")) {
05242                   snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
05243                   ast_destroy_realtime("voicemail_data", "id", tmpid, SENTINEL);
05244                }
05245             } else {
05246 #ifndef IMAP_STORAGE
05247                msgnum = last_message_index(vmu, dir) + 1;
05248 #endif
05249                make_file(fn, sizeof(fn), dir, msgnum);
05250 
05251                /* assign a variable with the name of the voicemail file */ 
05252 #ifndef IMAP_STORAGE
05253                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
05254 #else
05255                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05256 #endif
05257 
05258                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
05259                ast_filerename(tmptxtfile, fn, NULL);
05260                rename(tmptxtfile, txtfile);
05261 
05262                /* Properly set permissions on voicemail text descriptor file.
05263                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
05264                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
05265                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
05266 
05267                ast_unlock_path(dir);
05268                if (ast_check_realtime("voicemail_data")) {
05269                   snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
05270                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
05271                   ast_update_realtime("voicemail_data", "id", tmpid, "filename", fn, "duration", tmpdur, SENTINEL);
05272                }
05273                /* We must store the file first, before copying the message, because
05274                 * ODBC storage does the entire copy with SQL.
05275                 */
05276                if (ast_fileexists(fn, NULL, NULL) > 0) {
05277                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
05278                }
05279 
05280                /* Are there to be more recipients of this message? */
05281                while (tmpptr) {
05282                   struct ast_vm_user recipu, *recip;
05283                   char *exten, *cntx;
05284                
05285                   exten = strsep(&tmpptr, "&");
05286                   cntx = strchr(exten, '@');
05287                   if (cntx) {
05288                      *cntx = '\0';
05289                      cntx++;
05290                   }
05291                   if ((recip = find_user(&recipu, cntx, exten))) {
05292                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
05293                      free_user(recip);
05294                   }
05295                }
05296 #ifndef IMAP_STORAGE
05297                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
05298                   /* Move the message from INBOX to Urgent folder if this is urgent! */
05299                   char sfn[PATH_MAX];
05300                   char dfn[PATH_MAX];
05301                   int x;
05302                   /* It's easier just to try to make it than to check for its existence */
05303                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
05304                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n",sfn,dfn);
05305                   x = last_message_index(vmu, urgdir) + 1;
05306                   make_file(sfn, sizeof(sfn), dir, msgnum);
05307                   make_file(dfn, sizeof(dfn), urgdir, x);
05308                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
05309                }
05310 #endif
05311                /* Notification needs to happen after the copy, though. */
05312                if (ast_fileexists(fn, NULL, NULL)) {
05313 #ifdef IMAP_STORAGE
05314                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
05315 #else
05316                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
05317 #endif
05318                }
05319 
05320                /* Disposal needs to happen after the optional move and copy */
05321                if (ast_fileexists(fn, NULL, NULL)) {
05322                   DISPOSE(dir, msgnum);
05323                }
05324             }
05325          }
05326       }
05327       if (res == '0') {
05328          goto transfer;
05329       } else if (res > 0)
05330          res = 0;
05331 
05332       if (duration < vmminsecs)
05333          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
05334          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05335       else
05336          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05337    } else
05338       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
05339 leave_vm_out:
05340    free_user(vmu);
05341 
05342 #ifdef IMAP_STORAGE
05343    /* expunge message - use UID Expunge if supported on IMAP server*/
05344    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n",expungeonhangup);
05345    if (expungeonhangup == 1) {
05346       ast_mutex_lock(&vms->lock);
05347 #ifdef HAVE_IMAP_TK2006
05348       if (LEVELUIDPLUS (vms->mailstream)) {
05349          mail_expunge_full(vms->mailstream,NIL,EX_UID);
05350       } else 
05351 #endif
05352          mail_expunge(vms->mailstream);
05353       ast_mutex_unlock(&vms->lock);
05354    }
05355 #endif
05356    
05357    return res;
05358 }

static int load_config ( int  reload  )  [static]

Definition at line 10258 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_dsp_get_threshold_from_settings(), ast_false(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_unload_realtime(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, 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(), vm_zone::list, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, pagerbody, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, saydurationminfo, SENDMAIL, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, var, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, and VOICEMAIL_CONFIG.

10259 {
10260    struct ast_vm_user *current;
10261    struct ast_config *cfg, *ucfg;
10262    char *cat;
10263    struct ast_variable *var;
10264    const char *val;
10265    char *q, *stringp;
10266    int x;
10267    int tmpadsi[4];
10268    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10269 
10270    ast_unload_realtime("voicemail");
10271    ast_unload_realtime("voicemail_data");
10272 
10273    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
10274       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
10275          return 0;
10276       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
10277       cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
10278    } else {
10279       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
10280       ucfg = ast_config_load("users.conf", config_flags);
10281    }
10282 #ifdef IMAP_STORAGE
10283    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
10284 #endif
10285    /* set audio control prompts */
10286    strcpy(listen_control_forward_key,DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
10287    strcpy(listen_control_reverse_key,DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
10288    strcpy(listen_control_pause_key,DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
10289    strcpy(listen_control_restart_key,DEFAULT_LISTEN_CONTROL_RESTART_KEY);
10290    strcpy(listen_control_stop_key,DEFAULT_LISTEN_CONTROL_STOP_KEY);
10291 
10292    /* Free all the users structure */  
10293    free_vm_users();
10294 
10295    /* Free all the zones structure */
10296    free_vm_zones();
10297 
10298    AST_LIST_LOCK(&users);  
10299 
10300    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
10301    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
10302 
10303    if (cfg) {
10304       /* General settings */
10305 
10306       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
10307          val = "default";
10308       ast_copy_string(userscontext, val, sizeof(userscontext));
10309       /* Attach voice message to mail message ? */
10310       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
10311          val = "yes";
10312       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
10313 
10314       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
10315          val = "no";
10316       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
10317 
10318       volgain = 0.0;
10319       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
10320          sscanf(val, "%lf", &volgain);
10321 
10322 #ifdef ODBC_STORAGE
10323       strcpy(odbc_database, "asterisk");
10324       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
10325          ast_copy_string(odbc_database, val, sizeof(odbc_database));
10326       }
10327       strcpy(odbc_table, "voicemessages");
10328       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
10329          ast_copy_string(odbc_table, val, sizeof(odbc_table));
10330       }
10331 #endif      
10332       /* Mail command */
10333       strcpy(mailcmd, SENDMAIL);
10334       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
10335          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
10336 
10337       maxsilence = 0;
10338       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
10339          maxsilence = atoi(val);
10340          if (maxsilence > 0)
10341             maxsilence *= 1000;
10342       }
10343       
10344       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
10345          maxmsg = MAXMSG;
10346       } else {
10347          maxmsg = atoi(val);
10348          if (maxmsg <= 0) {
10349             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
10350             maxmsg = MAXMSG;
10351          } else if (maxmsg > MAXMSGLIMIT) {
10352             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
10353             maxmsg = MAXMSGLIMIT;
10354          }
10355       }
10356 
10357       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
10358          maxdeletedmsg = 0;
10359       } else {
10360          if (sscanf(val, "%d", &x) == 1)
10361             maxdeletedmsg = x;
10362          else if (ast_true(val))
10363             maxdeletedmsg = MAXMSG;
10364          else
10365             maxdeletedmsg = 0;
10366 
10367          if (maxdeletedmsg < 0) {
10368             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
10369             maxdeletedmsg = MAXMSG;
10370          } else if (maxdeletedmsg > MAXMSGLIMIT) {
10371             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
10372             maxdeletedmsg = MAXMSGLIMIT;
10373          }
10374       }
10375 
10376       /* Load date format config for voicemail mail */
10377       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
10378          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
10379       }
10380 
10381       /* External password changing command */
10382       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
10383          ast_copy_string(ext_pass_cmd,val,sizeof(ext_pass_cmd));
10384          pwdchange = PWDCHANGE_EXTERNAL;
10385       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
10386          ast_copy_string(ext_pass_cmd,val,sizeof(ext_pass_cmd));
10387          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
10388       }
10389  
10390       /* External password validation command */
10391       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
10392          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
10393          ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
10394       }
10395 
10396 #ifdef IMAP_STORAGE
10397       /* IMAP server address */
10398       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
10399          ast_copy_string(imapserver, val, sizeof(imapserver));
10400       } else {
10401          ast_copy_string(imapserver,"localhost", sizeof(imapserver));
10402       }
10403       /* IMAP server port */
10404       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
10405          ast_copy_string(imapport, val, sizeof(imapport));
10406       } else {
10407          ast_copy_string(imapport,"143", sizeof(imapport));
10408       }
10409       /* IMAP server flags */
10410       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
10411          ast_copy_string(imapflags, val, sizeof(imapflags));
10412       }
10413       /* IMAP server master username */
10414       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
10415          ast_copy_string(authuser, val, sizeof(authuser));
10416       }
10417       /* IMAP server master password */
10418       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
10419          ast_copy_string(authpassword, val, sizeof(authpassword));
10420       }
10421       /* Expunge on exit */
10422       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
10423          if (ast_false(val))
10424             expungeonhangup = 0;
10425          else
10426             expungeonhangup = 1;
10427       } else {
10428          expungeonhangup = 1;
10429       }
10430       /* IMAP voicemail folder */
10431       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
10432          ast_copy_string(imapfolder, val, sizeof(imapfolder));
10433       } else {
10434          ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder));
10435       }
10436       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
10437          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
10438       }
10439       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
10440          imapgreetings = ast_true(val);
10441       } else {
10442          imapgreetings = 0;
10443       }
10444       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
10445          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
10446       } else {
10447          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
10448       }
10449 
10450       /* There is some very unorthodox casting done here. This is due
10451        * to the way c-client handles the argument passed in. It expects a 
10452        * void pointer and casts the pointer directly to a long without
10453        * first dereferencing it. */
10454       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
10455          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
10456       } else {
10457          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
10458       }
10459 
10460       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
10461          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
10462       } else {
10463          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
10464       }
10465 
10466       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
10467          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
10468       } else {
10469          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
10470       }
10471 
10472       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
10473          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
10474       } else {
10475          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
10476       }
10477 
10478 #endif
10479       /* External voicemail notify application */
10480       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
10481          ast_copy_string(externnotify, val, sizeof(externnotify));
10482          ast_debug(1, "found externnotify: %s\n", externnotify);
10483       } else {
10484          externnotify[0] = '\0';
10485       }
10486 
10487       /* SMDI voicemail notification */
10488       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
10489          ast_debug(1, "Enabled SMDI voicemail notification\n");
10490          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
10491             smdi_iface = ast_smdi_interface_find(val);
10492          } else {
10493             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
10494             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
10495          }
10496          if (!smdi_iface) {
10497             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
10498          } 
10499       }
10500 
10501       /* Silence treshold */
10502       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
10503       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
10504          silencethreshold = atoi(val);
10505       
10506       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
10507          val = ASTERISK_USERNAME;
10508       ast_copy_string(serveremail, val, sizeof(serveremail));
10509       
10510       vmmaxsecs = 0;
10511       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
10512          if (sscanf(val, "%d", &x) == 1) {
10513             vmmaxsecs = x;
10514          } else {
10515             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
10516          }
10517       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
10518          static int maxmessage_deprecate = 0;
10519          if (maxmessage_deprecate == 0) {
10520             maxmessage_deprecate = 1;
10521             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
10522          }
10523          if (sscanf(val, "%d", &x) == 1) {
10524             vmmaxsecs = x;
10525          } else {
10526             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
10527          }
10528       }
10529 
10530       vmminsecs = 0;
10531       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
10532          if (sscanf(val, "%d", &x) == 1) {
10533             vmminsecs = x;
10534             if (maxsilence <= vmminsecs)
10535                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
10536          } else {
10537             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
10538          }
10539       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
10540          static int maxmessage_deprecate = 0;
10541          if (maxmessage_deprecate == 0) {
10542             maxmessage_deprecate = 1;
10543             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
10544          }
10545          if (sscanf(val, "%d", &x) == 1) {
10546             vmminsecs = x;
10547             if (maxsilence <= vmminsecs)
10548                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
10549          } else {
10550             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
10551          }
10552       }
10553 
10554       val = ast_variable_retrieve(cfg, "general", "format");
10555       if (!val)
10556          val = "wav";   
10557       ast_copy_string(vmfmts, val, sizeof(vmfmts));
10558 
10559       skipms = 3000;
10560       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
10561          if (sscanf(val, "%d", &x) == 1) {
10562             maxgreet = x;
10563          } else {
10564             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
10565          }
10566       }
10567 
10568       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
10569          if (sscanf(val, "%d", &x) == 1) {
10570             skipms = x;
10571          } else {
10572             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
10573          }
10574       }
10575 
10576       maxlogins = 3;
10577       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
10578          if (sscanf(val, "%d", &x) == 1) {
10579             maxlogins = x;
10580          } else {
10581             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
10582          }
10583       }
10584 
10585       minpassword = MINPASSWORD;
10586       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
10587          if (sscanf(val, "%d", &x) == 1) {
10588             minpassword = x;
10589          } else {
10590             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
10591          }
10592       }
10593 
10594       /* Force new user to record name ? */
10595       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
10596          val = "no";
10597       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
10598 
10599       /* Force new user to record greetings ? */
10600       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
10601          val = "no";
10602       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
10603 
10604       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
10605          ast_debug(1, "VM_CID Internal context string: %s\n", val);
10606          stringp = ast_strdupa(val);
10607          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
10608             if (!ast_strlen_zero(stringp)) {
10609                q = strsep(&stringp, ",");
10610                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
10611                   q++;
10612                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
10613                ast_debug(1,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
10614             } else {
10615                cidinternalcontexts[x][0] = '\0';
10616             }
10617          }
10618       }
10619       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
10620          ast_debug(1,"VM Review Option disabled globally\n");
10621          val = "no";
10622       }
10623       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
10624 
10625       /* Temporary greeting reminder */
10626       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
10627          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
10628          val = "no";
10629       } else {
10630          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
10631       }
10632       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
10633       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
10634          ast_debug(1, "VM next message wrap disabled globally\n");
10635          val = "no";
10636       }
10637       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);  
10638 
10639       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
10640          ast_debug(1,"VM Operator break disabled globally\n");
10641          val = "no";
10642       }
10643       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
10644 
10645       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
10646          ast_debug(1,"VM CID Info before msg disabled globally\n");
10647          val = "no";
10648       } 
10649       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
10650 
10651       if (!(val = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
10652          ast_debug(1,"Send Voicemail msg disabled globally\n");
10653          val = "no";
10654       }
10655       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
10656    
10657       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
10658          ast_debug(1,"ENVELOPE before msg enabled globally\n");
10659          val = "yes";
10660       }
10661       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
10662 
10663       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
10664          ast_debug(1,"Move Heard enabled globally\n");
10665          val = "yes";
10666       }
10667       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
10668 
10669       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
10670          ast_debug(1,"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
10671          val = "no";
10672       }
10673       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);   
10674 
10675       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
10676          ast_debug(1,"Duration info before msg enabled globally\n");
10677          val = "yes";
10678       }
10679       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
10680 
10681       saydurationminfo = 2;
10682       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
10683          if (sscanf(val, "%d", &x) == 1) {
10684             saydurationminfo = x;
10685          } else {
10686             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
10687          }
10688       }
10689 
10690       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
10691          ast_debug(1,"We are not going to skip to the next msg after save/delete\n");
10692          val = "no";
10693       }
10694       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
10695 
10696       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
10697          ast_copy_string(dialcontext, val, sizeof(dialcontext));
10698          ast_debug(1, "found dialout context: %s\n", dialcontext);
10699       } else {
10700          dialcontext[0] = '\0';  
10701       }
10702       
10703       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
10704          ast_copy_string(callcontext, val, sizeof(callcontext));
10705          ast_debug(1, "found callback context: %s\n", callcontext);
10706       } else {
10707          callcontext[0] = '\0';
10708       }
10709 
10710       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
10711          ast_copy_string(exitcontext, val, sizeof(exitcontext));
10712          ast_debug(1, "found operator context: %s\n", exitcontext);
10713       } else {
10714          exitcontext[0] = '\0';
10715       }
10716       
10717       /* load password sounds configuration */
10718       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
10719          ast_copy_string(vm_password, val, sizeof(vm_password));
10720       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
10721          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
10722       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
10723          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
10724       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
10725          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
10726       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
10727          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
10728       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
10729          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
10730       /* load configurable audio prompts */
10731       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
10732          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
10733       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
10734          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
10735       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
10736          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
10737       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
10738          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
10739       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
10740          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
10741 
10742       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
10743          val = "no";
10744       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
10745 
10746       poll_freq = DEFAULT_POLL_FREQ;
10747       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
10748          if (sscanf(val, "%u", &poll_freq) != 1) {
10749             poll_freq = DEFAULT_POLL_FREQ;
10750             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
10751          }
10752       }
10753 
10754       poll_mailboxes = 0;
10755       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
10756          poll_mailboxes = ast_true(val);
10757 
10758       if (ucfg) { 
10759          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
10760             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
10761                continue;
10762             if ((current = find_or_create(userscontext, cat))) {
10763                populate_defaults(current);
10764                apply_options_full(current, ast_variable_browse(ucfg, cat));
10765                ast_copy_string(current->context, userscontext, sizeof(current->context));
10766             }
10767          }
10768          ast_config_destroy(ucfg);
10769       }
10770       cat = ast_category_browse(cfg, NULL);
10771       while (cat) {
10772          if (strcasecmp(cat, "general")) {
10773             var = ast_variable_browse(cfg, cat);
10774             if (strcasecmp(cat, "zonemessages")) {
10775                /* Process mailboxes in this context */
10776                while (var) {
10777                   append_mailbox(cat, var->name, var->value);
10778                   var = var->next;
10779                }
10780             } else {
10781                /* Timezones in this context */
10782                while (var) {
10783                   struct vm_zone *z;
10784                   if ((z = ast_malloc(sizeof(*z)))) {
10785                      char *msg_format, *tzone;
10786                      msg_format = ast_strdupa(var->value);
10787                      tzone = strsep(&msg_format, "|");
10788                      if (msg_format) {
10789                         ast_copy_string(z->name, var->name, sizeof(z->name));
10790                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
10791                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
10792                         AST_LIST_LOCK(&zones);
10793                         AST_LIST_INSERT_HEAD(&zones, z, list);
10794                         AST_LIST_UNLOCK(&zones);
10795                      } else {
10796                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
10797                         ast_free(z);
10798                      }
10799                   } else {
10800                      AST_LIST_UNLOCK(&users);
10801                      ast_config_destroy(cfg);
10802                      return -1;
10803                   }
10804                   var = var->next;
10805                }
10806             }
10807          }
10808          cat = ast_category_browse(cfg, cat);
10809       }
10810       memset(fromstring, 0, sizeof(fromstring));
10811       memset(pagerfromstring, 0, sizeof(pagerfromstring));
10812       strcpy(charset, "ISO-8859-1");
10813       if (emailbody) {
10814          ast_free(emailbody);
10815          emailbody = NULL;
10816       }
10817       if (emailsubject) {
10818          ast_free(emailsubject);
10819          emailsubject = NULL;
10820       }
10821       if (pagerbody) {
10822          ast_free(pagerbody);
10823          pagerbody = NULL;
10824       }
10825       if (pagersubject) {
10826          ast_free(pagersubject);
10827          pagersubject = NULL;
10828       }
10829       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
10830          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
10831       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
10832          ast_copy_string(fromstring, val, sizeof(fromstring));
10833       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
10834          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
10835       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
10836          ast_copy_string(charset, val, sizeof(charset));
10837       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
10838          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
10839          for (x = 0; x < 4; x++) {
10840             memcpy(&adsifdn[x], &tmpadsi[x], 1);
10841          }
10842       }
10843       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
10844          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
10845          for (x = 0; x < 4; x++) {
10846             memcpy(&adsisec[x], &tmpadsi[x], 1);
10847          }
10848       }
10849       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
10850          if (atoi(val)) {
10851             adsiver = atoi(val);
10852          }
10853       }
10854       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
10855          ast_copy_string(zonetag, val, sizeof(zonetag));
10856       }
10857       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
10858          emailsubject = ast_strdup(val);
10859       }
10860       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
10861          emailbody = substitute_escapes(val);
10862       }
10863       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
10864          pagersubject = ast_strdup(val);
10865       }
10866       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
10867          pagerbody = substitute_escapes(val);
10868       }
10869       AST_LIST_UNLOCK(&users);
10870       ast_config_destroy(cfg);
10871 
10872       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
10873          start_poll_thread();
10874       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
10875          stop_poll_thread();;
10876 
10877       return 0;
10878    } else {
10879       AST_LIST_UNLOCK(&users);
10880       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
10881       if (ucfg)
10882          ast_config_destroy(ucfg);
10883       return 0;
10884    }
10885 }

static int load_module ( void   )  [static]

Definition at line 10931 of file app_voicemail.c.

References ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_install_vm_functions(), ast_log(), ast_manager_register, ast_realtime_require_field(), ast_register_application, ast_taskprocessor_get(), cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), load_config(), mailbox_exists_acf, manager_list_voicemail_users(), messagecount(), mwi_subscription_tps, RQ_CHAR, RQ_UINTEGER3, sayname(), SENTINEL, vm_box_exists(), vm_exec(), vm_execmain(), and vmauthenticate().

10932 {
10933    int res;
10934    my_umask = umask(0);
10935    umask(my_umask);
10936 
10937    /* compute the location of the voicemail spool directory */
10938    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
10939    
10940    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
10941       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
10942    }
10943 
10944    if ((res = load_config(0)))
10945       return res;
10946 
10947    res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
10948    res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
10949    res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
10950    res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
10951    res |= ast_custom_function_register(&mailbox_exists_acf);
10952    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
10953    if (res)
10954       return res;
10955 
10956    ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
10957 
10958    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
10959    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
10960    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
10961 
10962    return res;
10963 }

static int make_dir ( char *  dest,
int  len,
const char *  context,
const char *  ext,
const char *  folder 
) [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 1244 of file app_voicemail.c.

01245 {
01246    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01247 }

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 *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
int  imap,
const char *  flag 
) [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 3906 of file app_voicemail.c.

References add_email_attachment(), ast_channel_alloc(), ast_channel_free(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_localtime(), ast_log(), ast_random(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), chan, charset, check_mime(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, ast_vm_user::email, emailbody, emaildateformat, emailsubject, encode_mime_str(), ENDL, fromstring, ast_vm_user::fullname, globalflags, 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, and vmu_tm().

Referenced by sendmail().

03907 {
03908    char date[256];
03909    char host[MAXHOSTNAMELEN] = "";
03910    char who[256];
03911    char bound[256];
03912    char dur[256];
03913    struct ast_tm tm;
03914    char enc_cidnum[256] = "", enc_cidname[256] = "";
03915    char *passdata = NULL, *passdata2;
03916    size_t len_passdata = 0, len_passdata2, tmplen;
03917    char *greeting_attachment; 
03918    char filename[256];
03919 
03920 #ifdef IMAP_STORAGE
03921 #define ENDL "\r\n"
03922 #else
03923 #define ENDL "\n"
03924 #endif
03925 
03926    /* One alloca for multiple fields */
03927    len_passdata2 = strlen(vmu->fullname);
03928    if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
03929       len_passdata2 = tmplen;
03930    }
03931    if ((tmplen = strlen(fromstring)) > len_passdata2) {
03932       len_passdata2 = tmplen;
03933    }
03934    len_passdata2 = len_passdata2 * 3 + 200;
03935    passdata2 = alloca(len_passdata2);
03936 
03937    if (cidnum) {
03938       strip_control(cidnum, enc_cidnum, sizeof(enc_cidnum));
03939    }
03940    if (cidname) {
03941       strip_control(cidname, enc_cidname, sizeof(enc_cidname));
03942    }
03943    gethostname(host, sizeof(host) - 1);
03944 
03945    if (strchr(srcemail, '@'))
03946       ast_copy_string(who, srcemail, sizeof(who));
03947    else 
03948       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
03949    
03950    greeting_attachment = strrchr(ast_strdupa(attach), '/');
03951    if (greeting_attachment)
03952       *greeting_attachment++ = '\0';
03953 
03954    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
03955    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
03956    fprintf(p, "Date: %s" ENDL, date);
03957 
03958    /* Set date format for voicemail mail */
03959    ast_strftime(date, sizeof(date), emaildateformat, &tm);
03960 
03961    if (!ast_strlen_zero(fromstring)) {
03962       struct ast_channel *ast;
03963       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
03964          char *ptr;
03965          memset(passdata2, 0, len_passdata2);
03966          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category, flag);
03967          pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
03968          len_passdata = strlen(passdata2) * 3 + 300;
03969          passdata = alloca(len_passdata);
03970          if (check_mime(passdata2)) {
03971             int first_line = 1;
03972             encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
03973             while ((ptr = strchr(passdata, ' '))) {
03974                *ptr = '\0';
03975                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
03976                first_line = 0;
03977                passdata = ptr + 1;
03978             }
03979             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
03980          } else {
03981             fprintf(p, "From: %s <%s>" ENDL, quote(passdata2, passdata, len_passdata), who);
03982          }
03983          ast_channel_free(ast);
03984       } else {
03985          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
03986       }
03987    } else {
03988       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
03989    }
03990 
03991    if (check_mime(vmu->fullname)) {
03992       int first_line = 1;
03993       char *ptr;
03994       encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
03995       while ((ptr = strchr(passdata2, ' '))) {
03996          *ptr = '\0';
03997          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
03998          first_line = 0;
03999          passdata2 = ptr + 1;
04000       }
04001       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
04002    } else {
04003       fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
04004    }
04005    if (!ast_strlen_zero(emailsubject)) {
04006       struct ast_channel *ast;
04007       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04008          int vmlen = strlen(emailsubject) * 3 + 200;
04009          /* Only allocate more space if the previous was not large enough */
04010          if (vmlen > len_passdata) {
04011             passdata = alloca(vmlen);
04012             len_passdata = vmlen;
04013          }
04014 
04015          memset(passdata, 0, len_passdata);
04016          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, len_passdata, category, flag);
04017          pbx_substitute_variables_helper(ast, emailsubject, passdata, len_passdata);
04018          if (check_mime(passdata)) {
04019             int first_line = 1;
04020             char *ptr;
04021             encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
04022             while ((ptr = strchr(passdata2, ' '))) {
04023                *ptr = '\0';
04024                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
04025                first_line = 0;
04026                passdata2 = ptr + 1;
04027             }
04028             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
04029          } else {
04030             fprintf(p, "Subject: %s" ENDL, passdata);
04031          }
04032          ast_channel_free(ast);
04033       } else {
04034          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04035       }
04036    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04037       if (ast_strlen_zero(flag)) {
04038          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04039       } else {
04040          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04041       }
04042    } else {
04043       if (ast_strlen_zero(flag)) {
04044          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04045       } else {
04046          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04047       }
04048    }
04049 
04050    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1, (unsigned int)ast_random(), mailbox, (int)getpid(), host);
04051    if (imap) {
04052       /* additional information needed for IMAP searching */
04053       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04054       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04055       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04056       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04057 #ifdef IMAP_STORAGE
04058       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04059 #else
04060       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04061 #endif
04062       /* flag added for Urgent */
04063       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04064       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04065       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04066       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04067       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04068       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04069       if (!ast_strlen_zero(category)) {
04070          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04071       } else {
04072          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04073       }
04074       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04075       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04076       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long)time(NULL));
04077    }
04078    if (!ast_strlen_zero(cidnum)) {
04079       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04080    }
04081    if (!ast_strlen_zero(cidname)) {
04082       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04083    }
04084    fprintf(p, "MIME-Version: 1.0" ENDL);
04085    if (attach_user_voicemail) {
04086       /* Something unique. */
04087       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox, (int)getpid(), (unsigned int)ast_random());
04088 
04089       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04090       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04091       fprintf(p, "--%s" ENDL, bound);
04092    }
04093    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04094    if (emailbody) {
04095       struct ast_channel *ast;
04096       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04097          char *passdata;
04098          int vmlen = strlen(emailbody)*3 + 200;
04099          passdata = alloca(vmlen);
04100          memset(passdata, 0, vmlen);
04101          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04102          pbx_substitute_variables_helper(ast, emailbody, passdata, vmlen);
04103          fprintf(p, "%s" ENDL, passdata);
04104          ast_channel_free(ast);
04105       } else
04106          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04107    } else if (msgnum > -1) {
04108       if (strcmp(vmu->mailbox, mailbox)) {
04109          /* Forwarded type */
04110          struct ast_config *msg_cfg;
04111          const char *v;
04112          int inttime;
04113          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04114          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04115          /* Retrieve info from VM attribute file */
04116          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04117          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04118          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04119             strcat(fromfile, ".txt");
04120          }
04121          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04122             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04123                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04124             }
04125 
04126             /* You might be tempted to do origdate, except that a) it's in the wrong
04127              * format, and b) it's missing for IMAP recordings. */
04128             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%d", &inttime) == 1) {
04129                struct timeval tv = { inttime, };
04130                struct ast_tm tm;
04131                ast_localtime(&tv, &tm, NULL);
04132                ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
04133             }
04134             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04135                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04136                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04137                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04138                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04139                date, origcallerid, origdate);
04140             ast_config_destroy(msg_cfg);
04141          } else {
04142             goto plain_message;
04143          }
04144       } else {
04145 plain_message:
04146          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04147             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04148             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04149             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04150             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04151       }
04152    } else {
04153       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04154             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04155    }
04156 
04157    if (imap || attach_user_voicemail) {
04158       if (!ast_strlen_zero(attach2)) {
04159          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04160          ast_debug(5, "creating second attachment filename %s\n", filename);
04161          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04162          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04163          ast_debug(5, "creating attachment filename %s\n", filename);
04164          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04165       } else {
04166          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04167          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04168          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04169       }
04170    }
04171 }

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 1259 of file app_voicemail.c.

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

01260 {
01261    return snprintf(dest, len, "%s/msg%04d", dir, num);
01262 }

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

Manager list voicemail users command.

Definition at line 10091 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::list, ast_vm_user::mailbox, ast_vm_user::mailcmd, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, s, 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().

10092 {
10093    struct ast_vm_user *vmu = NULL;
10094    const char *id = astman_get_header(m, "ActionID");
10095    char actionid[128] = "";
10096 
10097    if (!ast_strlen_zero(id))
10098       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
10099 
10100    AST_LIST_LOCK(&users);
10101 
10102    if (AST_LIST_EMPTY(&users)) {
10103       astman_send_ack(s, m, "There are no voicemail users currently defined.");
10104       AST_LIST_UNLOCK(&users);
10105       return RESULT_SUCCESS;
10106    }
10107    
10108    astman_send_ack(s, m, "Voicemail user list will follow");
10109    
10110    AST_LIST_TRAVERSE(&users, vmu, list) {
10111       char dirname[256];
10112 
10113 #ifdef IMAP_STORAGE
10114       int new, old;
10115       inboxcount(vmu->mailbox, &new, &old);
10116 #endif
10117       
10118       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
10119       astman_append(s,
10120          "%s"
10121          "Event: VoicemailUserEntry\r\n"
10122          "VMContext: %s\r\n"
10123          "VoiceMailbox: %s\r\n"
10124          "Fullname: %s\r\n"
10125          "Email: %s\r\n"
10126          "Pager: %s\r\n"
10127          "ServerEmail: %s\r\n"
10128          "MailCommand: %s\r\n"
10129          "Language: %s\r\n"
10130          "TimeZone: %s\r\n"
10131          "Callback: %s\r\n"
10132          "Dialout: %s\r\n"
10133          "UniqueID: %s\r\n"
10134          "ExitContext: %s\r\n"
10135          "SayDurationMinimum: %d\r\n"
10136          "SayEnvelope: %s\r\n"
10137          "SayCID: %s\r\n"
10138          "AttachMessage: %s\r\n"
10139          "AttachmentFormat: %s\r\n"
10140          "DeleteMessage: %s\r\n"
10141          "VolumeGain: %.2f\r\n"
10142          "CanReview: %s\r\n"
10143          "CallOperator: %s\r\n"
10144          "MaxMessageCount: %d\r\n"
10145          "MaxMessageLength: %d\r\n"
10146          "NewMessageCount: %d\r\n"
10147 #ifdef IMAP_STORAGE
10148          "OldMessageCount: %d\r\n"
10149          "IMAPUser: %s\r\n"
10150 #endif
10151          "\r\n",
10152          actionid,
10153          vmu->context,
10154          vmu->mailbox,
10155          vmu->fullname,
10156          vmu->email,
10157          vmu->pager,
10158          vmu->serveremail,
10159          vmu->mailcmd,
10160          vmu->language,
10161          vmu->zonetag,
10162          vmu->callback,
10163          vmu->dialout,
10164          vmu->uniqueid,
10165          vmu->exit,
10166          vmu->saydurationm,
10167          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
10168          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
10169          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
10170          vmu->attachfmt,
10171          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
10172          vmu->volgain,
10173          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
10174          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
10175          vmu->maxmsg,
10176          vmu->maxsecs,
10177 #ifdef IMAP_STORAGE
10178          new, old, vmu->imapuser
10179 #else
10180          count_messages(vmu, dirname)
10181 #endif
10182          );
10183    }     
10184    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
10185 
10186    AST_LIST_UNLOCK(&users);
10187 
10188    return RESULT_SUCCESS;
10189 }

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

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

09927 {
09928    while (poll_thread_run) {
09929       struct timespec ts = { 0, };
09930       struct timeval wait;
09931 
09932       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
09933       ts.tv_sec = wait.tv_sec;
09934       ts.tv_nsec = wait.tv_usec * 1000;
09935 
09936       ast_mutex_lock(&poll_lock);
09937       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
09938       ast_mutex_unlock(&poll_lock);
09939 
09940       if (!poll_thread_run)
09941          break;
09942 
09943       poll_subscribed_mailboxes();
09944    }
09945 
09946    return NULL;
09947 }

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

Definition at line 1301 of file app_voicemail.c.

Referenced by acf_mailbox_exists(), add_peer_mailboxes(), adsi_load_vmail(), build_gateway(), copy_message(), get_folder(), has_voicemail(), notify_new_message(), open_mailbox(), save_to_folder(), vm_box_exists(), and vm_execmain().

01302 {
01303    static const char *msgs[] = {
01304 #ifdef IMAP_STORAGE
01305       imapfolder,
01306 #else
01307       "INBOX",
01308 #endif
01309       "Old",
01310       "Work",
01311       "Family",
01312       "Friends",
01313       "Cust1",
01314       "Cust2",
01315       "Cust3",
01316       "Cust4",
01317       "Cust5",
01318       "Deleted",
01319       "Urgent"
01320    };
01321    return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "Unknown";
01322 }

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

Definition at line 4669 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04670 {
04671    return __has_voicemail(context, mailbox, folder, 0);
04672 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 9949 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

09950 {
09951    ast_free(mwi_sub);
09952 }

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

Definition at line 10026 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_free, ast_log(), ast_strdup, ast_taskprocessor_push(), handle_subscribe(), LOG_ERROR, and mwi_subscription_tps.

Referenced by start_poll_thread().

10027 {
10028    struct mwi_sub_task *mwist;
10029    
10030    if (ast_event_get_type(event) != AST_EVENT_SUB)
10031       return;
10032 
10033    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10034       return;
10035 
10036    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
10037       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
10038       return;
10039    }
10040    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
10041    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
10042    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10043    
10044    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
10045       ast_free(mwist);
10046    }
10047 }

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

Definition at line 10010 of file app_voicemail.c.

References ast_calloc, ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_UNSUB, ast_free, ast_taskprocessor_push(), handle_unsubscribe(), mwi_subscription_tps, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

10011 {
10012    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
10013    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
10014       return;
10015 
10016    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10017       return;
10018 
10019    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10020    *uniqueid = u;
10021    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
10022       ast_free(uniqueid);
10023    }
10024 }

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,
const char *  flag 
) [static]

Sends email notification that a user has a new voicemail waiting for them.

Parameters:
chan 
vmu 
vms 
msgnum 
duration 
fmt 
cidnum The Caller ID phone number value.
cidname The Caller ID name value.
Returns:
zero on success, -1 on error.

Definition at line 6174 of file app_voicemail.c.

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_unlock, ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_vm_user::attachfmt, chan, ast_vm_user::context, vm_state::curmsg, DELETE, DISPOSE, ast_vm_user::email, EVENT_FLAG_CALL, globalflags, ast_vm_user::mailbox, make_dir(), make_file(), manager_event, mbox(), vm_state::newmessages, ast_vm_user::pager, pbx_builtin_getvar_helper(), queue_mwi_event(), RETRIEVE, run_externnotify(), sendmail(), sendpage(), ast_vm_user::serveremail, strsep(), VM_ATTACH, vm_delete(), and VM_DELETE.

06175 {
06176    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06177    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06178    const char *category;
06179    char *myserveremail = serveremail;
06180 
06181    ast_channel_lock(chan);
06182    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06183       category = ast_strdupa(category);
06184    }
06185    ast_channel_unlock(chan);
06186 
06187    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
06188    make_file(fn, sizeof(fn), todir, msgnum);
06189    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06190 
06191    if (!ast_strlen_zero(vmu->attachfmt)) {
06192       if (strstr(fmt, vmu->attachfmt))
06193          fmt = vmu->attachfmt;
06194       else
06195          ast_log(AST_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);
06196    }
06197 
06198    /* Attach only the first format */
06199    fmt = ast_strdupa(fmt);
06200    stringp = fmt;
06201    strsep(&stringp, "|");
06202 
06203    if (!ast_strlen_zero(vmu->serveremail))
06204       myserveremail = vmu->serveremail;
06205 
06206    if (!ast_strlen_zero(vmu->email)) {
06207       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06208       if (!attach_user_voicemail)
06209          attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
06210 
06211       if (attach_user_voicemail)
06212          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06213 
06214       /* XXX possible imap issue, should category be NULL XXX */
06215       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06216 
06217       if (attach_user_voicemail)
06218          DISPOSE(todir, msgnum);
06219    }
06220 
06221    if (!ast_strlen_zero(vmu->pager)) {
06222       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
06223    }
06224 
06225    if (ast_test_flag(vmu, VM_DELETE))
06226       DELETE(todir, msgnum, fn, vmu);
06227 
06228    /* Leave voicemail for someone */
06229    if (ast_app_has_voicemail(ext_context, NULL)) 
06230       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06231 
06232    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06233 
06234    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);
06235    run_externnotify(vmu->context, vmu->mailbox, flag);
06236 
06237 #ifdef IMAP_STORAGE
06238    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06239    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06240       vm_imap_delete(vms->curmsg, vmu);
06241       vms->newmessages--;  /* Fix new message count */
06242    }
06243 #endif
06244 
06245    return 0;
06246 }

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

utility used by base_encode()

Definition at line 3635 of file app_voicemail.c.

References BASELINELEN, eol, and baseio::linelength.

Referenced by base_encode().

03636 {
03637    if (bio->linelength >= BASELINELEN) {
03638       if (fputs(eol,so) == EOF)
03639          return -1;
03640 
03641       bio->linelength= 0;
03642    }
03643 
03644    if (putc(((unsigned char)c),so) == EOF)
03645       return -1;
03646 
03647    bio->linelength++;
03648 
03649    return 1;
03650 }

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

Definition at line 6930 of file app_voicemail.c.

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

Referenced by vm_execmain().

06931 {
06932    int count_msg, last_msg;
06933 
06934    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
06935    
06936    /* Rename the member vmbox HERE so that we don't try to return before
06937     * we know what's going on.
06938     */
06939    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
06940    
06941    /* Faster to make the directory than to check if it exists. */
06942    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
06943 
06944    count_msg = count_messages(vmu, vms->curdir);
06945    if (count_msg < 0)
06946       return count_msg;
06947    else
06948       vms->lastmsg = count_msg - 1;
06949 
06950    /*
06951    The following test is needed in case sequencing gets messed up.
06952    There appears to be more than one way to mess up sequence, so
06953    we will not try to find all of the root causes--just fix it when
06954    detected.
06955    */
06956 
06957    if (vm_lock_path(vms->curdir)) {
06958       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
06959       return -1;
06960    }
06961 
06962    last_msg = last_message_index(vmu, vms->curdir);
06963    ast_unlock_path(vms->curdir);
06964 
06965    if (last_msg < 0) 
06966       return last_msg;
06967 
06968    return 0;
06969 }

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

Definition at line 6728 of file app_voicemail.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), chan, CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, 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_he(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_tw(), and vm_execmain().

06729 {
06730    int res = 0;
06731    char filename[256], *cid;
06732    const char *origtime, *context, *category, *duration, *flag;
06733    struct ast_config *msg_cfg;
06734    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06735 
06736    vms->starting = 0; 
06737    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06738    adsi_message(chan, vms);
06739    if (!vms->curmsg)
06740       res = wait_file2(chan, vms, "vm-first");  /* "First" */
06741    else if (vms->curmsg == vms->lastmsg)
06742       res = wait_file2(chan, vms, "vm-last");      /* "last" */
06743 
06744    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
06745    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
06746    msg_cfg = ast_config_load(filename, config_flags);
06747    if (!msg_cfg) {
06748       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06749       return 0;
06750    }
06751    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
06752 
06753    /* Play the word urgent if we are listening to urgent messages */
06754    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
06755       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
06756    }
06757 
06758    if (!res) {
06759       /* POLISH syntax */
06760       if (!strcasecmp(chan->language, "pl")) { 
06761          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06762             int ten, one;
06763             char nextmsg[256];
06764             ten = (vms->curmsg + 1) / 10;
06765             one = (vms->curmsg + 1) % 10;
06766             
06767             if (vms->curmsg < 20) {
06768                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
06769                res = wait_file2(chan, vms, nextmsg);
06770             } else {
06771                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
06772                res = wait_file2(chan, vms, nextmsg);
06773                if (one > 0) {
06774                   if (!res) {
06775                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
06776                      res = wait_file2(chan, vms, nextmsg);
06777                   }
06778                }
06779             }
06780          }
06781          if (!res)
06782             res = wait_file2(chan, vms, "vm-message");
06783       /* HEBREW syntax */
06784       } else if (!strcasecmp(chan->language, "he")) {
06785          if (!vms->curmsg) {
06786             res = wait_file2(chan, vms, "vm-message");
06787             res = wait_file2(chan, vms, "vm-first");
06788          } else if (vms->curmsg == vms->lastmsg) {
06789             res = wait_file2(chan, vms, "vm-message");
06790             res = wait_file2(chan, vms, "vm-last");
06791          } else {
06792             res = wait_file2(chan, vms, "vm-message");
06793             res = wait_file2(chan, vms, "vm-number");
06794             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
06795          }
06796       } else {
06797          if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
06798             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
06799          else /* DEFAULT syntax */ {
06800             res = wait_file2(chan, vms, "vm-message");
06801          }
06802          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06803             if (!res) {
06804                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
06805             }
06806          }
06807       }
06808    }
06809 
06810    if (!msg_cfg) {
06811       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06812       return 0;
06813    }
06814 
06815    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
06816       ast_log(AST_LOG_WARNING, "No origtime?!\n");
06817       DISPOSE(vms->curdir, vms->curmsg);
06818       ast_config_destroy(msg_cfg);
06819       return 0;
06820    }
06821 
06822    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
06823    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
06824    category = ast_variable_retrieve(msg_cfg, "message", "category");
06825 
06826    context = ast_variable_retrieve(msg_cfg, "message", "context");
06827    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
06828       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
06829    if (!res) {
06830       res = play_message_category(chan, category);
06831    }
06832    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
06833       res = play_message_datetime(chan, vmu, origtime, filename);
06834    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
06835       res = play_message_callerid(chan, vms, cid, context, 0);
06836    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
06837       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
06838    /* Allow pressing '1' to skip envelope / callerid */
06839    if (res == '1')
06840       res = 0;
06841    ast_config_destroy(msg_cfg);
06842 
06843    if (!res) {
06844       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06845       vms->heard[vms->curmsg] = 1;
06846 #ifdef IMAP_STORAGE
06847       /*IMAP storage stores any prepended message from a forward
06848        * as a separate file from the rest of the message
06849        */
06850       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
06851          wait_file(chan, vms, vms->introfn);
06852       }
06853 #endif
06854       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
06855          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
06856          res = 0;
06857       }
06858    }
06859    DISPOSE(vms->curdir, vms->curmsg);
06860    return res;
06861 }

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

Definition at line 6614 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, chan, cidinternalcontexts, ast_channel::language, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

06615 {
06616    int res = 0;
06617    int i;
06618    char *callerid, *name;
06619    char prefile[PATH_MAX] = "";
06620    
06621 
06622    /* If voicemail cid is not enabled, or we didn't get cid or context from
06623     * the attribute file, leave now.
06624     *
06625     * TODO Still need to change this so that if this function is called by the
06626     * message envelope (and someone is explicitly requesting to hear the CID),
06627     * it does not check to see if CID is enabled in the config file.
06628     */
06629    if ((cid == NULL)||(context == NULL))
06630       return res;
06631 
06632    /* Strip off caller ID number from name */
06633    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
06634    ast_callerid_parse(cid, &name, &callerid);
06635    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
06636       /* Check for internal contexts and only */
06637       /* say extension when the call didn't come from an internal context in the list */
06638       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
06639          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
06640          if ((strcmp(cidinternalcontexts[i], context) == 0))
06641             break;
06642       }
06643       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
06644          if (!res) {
06645             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
06646             if (!ast_strlen_zero(prefile)) {
06647             /* See if we can find a recorded name for this person instead of their extension number */
06648                if (ast_fileexists(prefile, NULL, NULL) > 0) {
06649                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
06650                   if (!callback)
06651                      res = wait_file2(chan, vms, "vm-from");
06652                   res = ast_stream_and_wait(chan, prefile, "");
06653                } else {
06654                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
06655                   /* Say "from extension" as one saying to sound smoother */
06656                   if (!callback)
06657                      res = wait_file2(chan, vms, "vm-from-extension");
06658                   res = ast_say_digit_str(chan, callerid, "", chan->language);
06659                }
06660             }
06661          }
06662       } else if (!res) {
06663          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
06664          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
06665          if (!callback)
06666             res = wait_file2(chan, vms, "vm-from-phonenumber");
06667          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
06668       }
06669    } else {
06670       /* Number unknown */
06671       ast_debug(1, "VM-CID: From an unknown number\n");
06672       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
06673       res = wait_file2(chan, vms, "vm-unknown-caller");
06674    }
06675    return res;
06676 }

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

Definition at line 6526 of file app_voicemail.c.

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

Referenced by play_message().

06527 {
06528    int res = 0;
06529 
06530    if (!ast_strlen_zero(category))
06531       res = ast_play_and_wait(chan, category);
06532 
06533    if (res) {
06534       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
06535       res = 0;
06536    }
06537 
06538    return res;
06539 }

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

Definition at line 6541 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(), chan, ast_channel::language, vm_zone::list, 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().

06542 {
06543    int res = 0;
06544    struct vm_zone *the_zone = NULL;
06545    time_t t;
06546 
06547    if (ast_get_time_t(origtime, &t, 0, NULL)) {
06548       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
06549       return 0;
06550    }
06551 
06552    /* Does this user have a timezone specified? */
06553    if (!ast_strlen_zero(vmu->zonetag)) {
06554       /* Find the zone in the list */
06555       struct vm_zone *z;
06556       AST_LIST_LOCK(&zones);
06557       AST_LIST_TRAVERSE(&zones, z, list) {
06558          if (!strcmp(z->name, vmu->zonetag)) {
06559             the_zone = z;
06560             break;
06561          }
06562       }
06563       AST_LIST_UNLOCK(&zones);
06564    }
06565 
06566 /* No internal variable parsing for now, so we'll comment it out for the time being */
06567 #if 0
06568    /* Set the DIFF_* variables */
06569    ast_localtime(&t, &time_now, NULL);
06570    tv_now = ast_tvnow();
06571    ast_localtime(&tv_now, &time_then, NULL);
06572 
06573    /* Day difference */
06574    if (time_now.tm_year == time_then.tm_year)
06575       snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
06576    else
06577       snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
06578    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
06579 
06580    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
06581 #endif
06582    if (the_zone) {
06583       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
06584    }
06585    else if (!strcasecmp(chan->language,"pl"))       /* POLISH syntax */
06586       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
06587    else if (!strcasecmp(chan->language,"se"))       /* SWEDISH syntax */
06588       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
06589    else if (!strcasecmp(chan->language,"no"))       /* NORWEGIAN syntax */
06590       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06591    else if (!strcasecmp(chan->language,"de"))       /* GERMAN syntax */
06592       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06593    else if (!strcasecmp(chan->language,"nl"))      /* DUTCH syntax */
06594       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
06595    else if (!strcasecmp(chan->language,"it"))      /* ITALIAN syntax */
06596       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);
06597    else if (!strcasecmp(chan->language,"gr"))
06598       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
06599    else if (!strcasecmp(chan->language,"pt_BR"))
06600       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);
06601    else if (!strcasecmp(chan->language,"tw"))      /* CHINESE (Taiwan) syntax */
06602       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);     
06603    else {
06604       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
06605    }
06606 #if 0
06607    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
06608 #endif
06609    return res;
06610 }

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

Definition at line 6678 of file app_voicemail.c.

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

Referenced by play_message().

06679 {
06680    int res = 0;
06681    int durationm;
06682    int durations;
06683    /* Verify that we have a duration for the message */
06684    if (duration == NULL)
06685       return res;
06686 
06687    /* Convert from seconds to minutes */
06688    durations=atoi(duration);
06689    durationm=(durations / 60);
06690 
06691    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
06692 
06693    if ((!res) && (durationm >= minduration)) {
06694       res = wait_file2(chan, vms, "vm-duration");
06695 
06696       /* POLISH syntax */
06697       if (!strcasecmp(chan->language, "pl")) {
06698          div_t num = div(durationm, 10);
06699 
06700          if (durationm == 1) {
06701             res = ast_play_and_wait(chan, "digits/1z");
06702             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
06703          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
06704             if (num.rem == 2) {
06705                if (!num.quot) {
06706                   res = ast_play_and_wait(chan, "digits/2-ie");
06707                } else {
06708                   res = say_and_wait(chan, durationm - 2 , chan->language);
06709                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
06710                }
06711             } else {
06712                res = say_and_wait(chan, durationm, chan->language);
06713             }
06714             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
06715          } else {
06716             res = say_and_wait(chan, durationm, chan->language);
06717             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
06718          }
06719       /* DEFAULT syntax */
06720       } else {
06721          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
06722          res = wait_file2(chan, vms, "vm-minutes");
06723       }
06724    }
06725    return res;
06726 }

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,
char *  flag 
) [static]

Definition at line 11225 of file app_voicemail.c.

References acceptdtmf, ast_channel_setoption(), ast_copy_string(), ast_debug, 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_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, ast_waitfordigit(), chan, ast_vm_user::context, DELETE, DISPOSE, INTRO, ast_vm_user::mailbox, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

11228 {
11229    /* Record message & let caller review or re-record it, or set options if applicable */
11230    int res = 0;
11231    int cmd = 0;
11232    int max_attempts = 3;
11233    int attempts = 0;
11234    int recorded = 0;
11235    int msg_exists = 0;
11236    signed char zero_gain = 0;
11237    char tempfile[PATH_MAX];
11238    char *acceptdtmf = "#";
11239    char *canceldtmf = "";
11240 
11241    /* Note that urgent and private are for flagging messages as such in the future */
11242 
11243    /* barf if no pointer passed to store duration in */
11244    if (duration == NULL) {
11245       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
11246       return -1;
11247    }
11248 
11249    if (!outsidecaller)
11250       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
11251    else
11252       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
11253 
11254    cmd = '3';  /* Want to start by recording */
11255 
11256    while ((cmd >= 0) && (cmd != 't')) {
11257       switch (cmd) {
11258       case '1':
11259          if (!msg_exists) {
11260             /* In this case, 1 is to record a message */
11261             cmd = '3';
11262             break;
11263          } else {
11264             /* Otherwise 1 is to save the existing message */
11265             ast_verb(3, "Saving message as is\n");
11266             if (!outsidecaller) 
11267                ast_filerename(tempfile, recordfile, NULL);
11268             ast_stream_and_wait(chan, "vm-msgsaved", "");
11269             if (!outsidecaller) {
11270                /* Saves to IMAP server - but SHOULD save to filesystem ONLY if recording greetings! */
11271 #ifndef IMAP_STORAGE
11272                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
11273                DISPOSE(recordfile, -1);
11274 #endif
11275             }
11276             cmd = 't';
11277             return res;
11278          }
11279       case '2':
11280          /* Review */
11281          ast_verb(3, "Reviewing the message\n");
11282          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
11283          break;
11284       case '3':
11285          msg_exists = 0;
11286          /* Record */
11287          if (recorded == 1) 
11288             ast_verb(3, "Re-recording the message\n");
11289          else  
11290             ast_verb(3, "Recording the message\n");
11291          
11292          if (recorded && outsidecaller) {
11293             cmd = ast_play_and_wait(chan, INTRO);
11294             cmd = ast_play_and_wait(chan, "beep");
11295          }
11296          recorded = 1;
11297          /* 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 */
11298          if (record_gain)
11299             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
11300          if (ast_test_flag(vmu, VM_OPERATOR))
11301             canceldtmf = "0";
11302          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
11303          if (record_gain)
11304             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
11305          if (cmd == -1) {
11306             /* User has hung up, no options to give */
11307             if (!outsidecaller) {
11308                /* user was recording a greeting and they hung up, so let's delete the recording. */
11309                ast_filedelete(tempfile, NULL);
11310             }     
11311             return cmd;
11312          }
11313          if (cmd == '0') {
11314             break;
11315          } else if (cmd == '*') {
11316             break;
11317 #if 0
11318          } else if (vmu->review && (*duration < 5)) {
11319             /* Message is too short */
11320             ast_verb(3, "Message too short\n");
11321             cmd = ast_play_and_wait(chan, "vm-tooshort");
11322             cmd = ast_filedelete(tempfile, NULL);
11323             break;
11324          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
11325             /* Message is all silence */
11326             ast_verb(3, "Nothing recorded\n");
11327             cmd = ast_filedelete(tempfile, NULL);
11328             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
11329             if (!cmd)
11330                cmd = ast_play_and_wait(chan, "vm-speakup");
11331             break;
11332 #endif
11333          } else {
11334             /* If all is well, a message exists */
11335             msg_exists = 1;
11336             cmd = 0;
11337          }
11338          break;
11339       case '4':
11340          if (outsidecaller) {  /* only mark vm messages */
11341             /* Mark Urgent */
11342             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11343                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
11344                ast_debug(1000, "This message is too urgent!\n");
11345                res = ast_play_and_wait(chan, "vm-marked-urgent");
11346                strcpy(flag, "Urgent");
11347             } else if (flag) {
11348                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
11349                res = ast_play_and_wait(chan, "vm-urgent-removed");
11350                strcpy(flag, "");
11351             } else {
11352                ast_play_and_wait(chan, "vm-sorry");
11353             }
11354             cmd = 0;
11355          } else {
11356             cmd = ast_play_and_wait(chan, "vm-sorry");
11357          }
11358          break;
11359       case '5':
11360       case '6':
11361       case '7':
11362       case '8':
11363       case '9':
11364       case '*':
11365       case '#':
11366          cmd = ast_play_and_wait(chan, "vm-sorry");
11367          break;
11368 #if 0 
11369 /*  XXX Commented out for the moment because of the dangers of deleting
11370     a message while recording (can put the message numbers out of sync) */
11371       case '*':
11372          /* Cancel recording, delete message, offer to take another message*/
11373          cmd = ast_play_and_wait(chan, "vm-deleted");
11374          cmd = ast_filedelete(tempfile, NULL);
11375          if (outsidecaller) {
11376             res = vm_exec(chan, NULL);
11377             return res;
11378          }
11379          else
11380             return 1;
11381 #endif
11382       case '0':
11383          if (!ast_test_flag(vmu, VM_OPERATOR)) {
11384             cmd = ast_play_and_wait(chan, "vm-sorry");
11385             break;
11386          }
11387          if (msg_exists || recorded) {
11388             cmd = ast_play_and_wait(chan, "vm-saveoper");
11389             if (!cmd)
11390                cmd = ast_waitfordigit(chan, 3000);
11391             if (cmd == '1') {
11392                ast_play_and_wait(chan, "vm-msgsaved");
11393                cmd = '0';
11394             } else if (cmd == '4') {
11395                if (flag) {
11396                   ast_play_and_wait(chan, "vm-marked-urgent");
11397                   strcpy(flag, "Urgent");
11398                }
11399                ast_play_and_wait(chan, "vm-msgsaved");
11400                cmd = '0';
11401             } else {
11402                ast_play_and_wait(chan, "vm-deleted");
11403                DELETE(recordfile, -1, recordfile, vmu);
11404                cmd = '0';
11405             }
11406          }
11407          return cmd;
11408       default:
11409          /* If the caller is an ouside caller, and the review option is enabled,
11410             allow them to review the message, but let the owner of the box review
11411             their OGM's */
11412          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
11413             return cmd;
11414          if (msg_exists) {
11415             cmd = ast_play_and_wait(chan, "vm-review");
11416             if (!cmd && outsidecaller) {
11417                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11418                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
11419                } else if (flag) {
11420                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
11421                }
11422             }
11423          } else {
11424             cmd = ast_play_and_wait(chan, "vm-torerecord");
11425             if (!cmd)
11426                cmd = ast_waitfordigit(chan, 600);
11427          }
11428          
11429          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
11430             cmd = ast_play_and_wait(chan, "vm-reachoper");
11431             if (!cmd)
11432                cmd = ast_waitfordigit(chan, 600);
11433          }
11434 #if 0
11435          if (!cmd)
11436             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
11437 #endif
11438          if (!cmd)
11439             cmd = ast_waitfordigit(chan, 6000);
11440          if (!cmd) {
11441             attempts++;
11442          }
11443          if (attempts > max_attempts) {
11444             cmd = 't';
11445          }
11446       }
11447    }
11448    if (outsidecaller)
11449       ast_play_and_wait(chan, "vm-goodbye");
11450    if (cmd == 't')
11451       cmd = 0;
11452    return cmd;
11453 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 9903 of file app_voicemail.c.

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

Referenced by mb_poll_thread().

09904 {
09905    struct mwi_sub *mwi_sub;
09906 
09907    AST_RWLIST_RDLOCK(&mwi_subs);
09908    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
09909       int new = 0, old = 0, urgent = 0;
09910 
09911       if (ast_strlen_zero(mwi_sub->mailbox))
09912          continue;
09913 
09914       inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
09915 
09916       if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
09917          mwi_sub->old_urgent = urgent;
09918          mwi_sub->old_new = new;
09919          mwi_sub->old_old = old;
09920          queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
09921       }
09922    }
09923    AST_RWLIST_UNLOCK(&mwi_subs);
09924 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

This applies select global settings to a newly created (dynamic) instance of a voicemail user.

Definition at line 731 of file app_voicemail.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_vm_user::callback, callcontext, dialcontext, ast_vm_user::dialout, ast_vm_user::exit, exitcontext, globalflags, ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::saydurationm, saydurationminfo, ast_vm_user::volgain, and ast_vm_user::zonetag.

00732 {
00733    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00734    if (saydurationminfo)
00735       vmu->saydurationm = saydurationminfo;
00736    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00737    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00738    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00739    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00740    if (vmmaxsecs)
00741       vmu->maxsecs = vmmaxsecs;
00742    if (maxmsg)
00743       vmu->maxmsg = maxmsg;
00744    if (maxdeletedmsg)
00745       vmu->maxdeletedmsg = maxdeletedmsg;
00746    vmu->volgain = volgain;
00747 }

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,
const char *  flag 
) [static]

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

03721 {
03722    char callerid[256];
03723    char fromdir[256], fromfile[256];
03724    struct ast_config *msg_cfg;
03725    const char *origcallerid, *origtime;
03726    char origcidname[80], origcidnum[80], origdate[80];
03727    int inttime;
03728    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03729 
03730    /* Prepare variables for substitution in email body and subject */
03731    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
03732    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
03733    snprintf(passdata, passdatasize, "%d", msgnum);
03734    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
03735    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
03736    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
03737    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
03738       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
03739    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
03740    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
03741    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
03742    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
03743    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
03744 
03745    /* Retrieve info from VM attribute file */
03746    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
03747    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
03748    if (strlen(fromfile) < sizeof(fromfile) - 5) {
03749       strcat(fromfile, ".txt");
03750    }
03751    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
03752       if (option_debug > 0) {
03753          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
03754       }
03755       return;
03756    }
03757 
03758    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
03759       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
03760       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
03761       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
03762       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
03763    }
03764 
03765    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%d", &inttime) == 1) {
03766       struct timeval tv = { inttime, };
03767       struct ast_tm tm;
03768       ast_localtime(&tv, &tm, NULL);
03769       ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
03770       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
03771    }
03772    ast_config_destroy(msg_cfg);
03773 }

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

Definition at line 6138 of file app_voicemail.c.

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

Referenced by append_mailbox(), notify_new_message(), poll_subscribed_mailboxes(), and vm_execmain().

06139 {
06140    struct ast_event *event;
06141    char *mailbox, *context;
06142 
06143    /* Strip off @default */
06144    context = mailbox = ast_strdupa(box);
06145    strsep(&context, "@");
06146    if (ast_strlen_zero(context))
06147       context = "default";
06148 
06149    if (!(event = ast_event_new(AST_EVENT_MWI,
06150          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06151          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06152          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06153          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06154          AST_EVENT_IE_END))) {
06155       return;
06156    }
06157 
06158    ast_event_queue_and_cache(event);
06159 }

static char* quote ( const char *  from,
char *  to,
size_t  len 
) [static]

Wraps a character sequence in double quotes, escaping occurences of quotes within the string.

Parameters:
from The string to work with.
to The string to write the modified quoted string. This buffer should be sufficiently larger than the from string, so as to allow it to be expanded by the surrounding quotes and escaping of internal quotes.
Returns:
The destination string with quotes wrapped on it (the to field).

Definition at line 3782 of file app_voicemail.c.

03783 {
03784    char *ptr = to;
03785    *ptr++ = '"';
03786    for (; ptr < to + len - 1; from++) {
03787       if (*from == '"')
03788          *ptr++ = '\\';
03789       else if (*from == '\0')
03790          break;
03791       *ptr++ = *from;
03792    }
03793    if (ptr < to + len - 1)
03794       *ptr++ = '"';
03795    *ptr = '\0';
03796    return to;
03797 }

static int reload ( void   )  [static]

Definition at line 10901 of file app_voicemail.c.

References load_config().

10902 {
10903    return load_config(1);
10904 }

static void rename_file ( char *  sfn,
char *  dfn 
) [static]

Renames a message in a mailbox folder.

Parameters:
sfn The path to the mailbox information and data file to be renamed.
dfn The path for where the message data and information files will be renamed to.
This method is used by the RENAME macro when mailboxes are stored on the filesystem. (not ODBC and not IMAP).

Definition at line 3403 of file app_voicemail.c.

References ast_check_realtime(), ast_filerename(), ast_update_realtime(), and SENTINEL.

03404 {
03405    char stxt[PATH_MAX];
03406    char dtxt[PATH_MAX];
03407    ast_filerename(sfn,dfn,NULL);
03408    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03409    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03410    if (ast_check_realtime("voicemail_data")) {
03411       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03412    }
03413    rename(stxt, dtxt);
03414 }

static int reset_user_pw ( const char *  context,
const char *  mailbox,
const char *  newpass 
) [static]

Resets a user password to a specified password.

Parameters:
context 
mailbox 
newpass This does the actual change password work, called by the vm_change_password() function.
Returns:
zero on success, -1 on error.

Definition at line 1127 of file app_voicemail.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::context, ast_vm_user::list, ast_vm_user::mailbox, and ast_vm_user::password.

Referenced by vm_change_password(), and vm_change_password_shell().

01128 {
01129    /* This function could be made to generate one from a database, too */
01130    struct ast_vm_user *cur;
01131    int res = -1;
01132    AST_LIST_LOCK(&users);
01133    AST_LIST_TRAVERSE(&users, cur, list) {
01134       if ((!context || !strcasecmp(context, cur->context)) &&
01135          (!strcasecmp(mailbox, cur->mailbox)))
01136             break;
01137    }
01138    if (cur) {
01139       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01140       res = 0;
01141    }
01142    AST_LIST_UNLOCK(&users);
01143    return res;
01144 }

static void run_externnotify ( char *  context,
char *  extension,
const char *  flag 
) [static]

Definition at line 4805 of file app_voicemail.c.

References ast_app_has_voicemail(), ast_copy_string(), ast_debug, ast_log(), AST_LOG_ERROR, ast_safe_system(), ast_smdi_mwi_message_destroy(), ast_smdi_mwi_message_wait_station(), ast_smdi_mwi_set(), ast_smdi_mwi_unset(), ast_strlen_zero(), ASTOBJ_UNREF, ast_smdi_mwi_message::cause, ast_smdi_mwi_message::fwd_st, inboxcount2(), smdi_iface, and SMDI_MWI_WAIT_TIMEOUT.

04806 {
04807    char arguments[255];
04808    char ext_context[256] = "";
04809    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
04810    struct ast_smdi_mwi_message *mwi_msg;
04811 
04812    if (!ast_strlen_zero(context))
04813       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
04814    else
04815       ast_copy_string(ext_context, extension, sizeof(ext_context));
04816 
04817    if (smdi_iface) {
04818       if (ast_app_has_voicemail(ext_context, NULL)) 
04819          ast_smdi_mwi_set(smdi_iface, extension);
04820       else
04821          ast_smdi_mwi_unset(smdi_iface, extension);
04822 
04823       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
04824          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
04825          if (!strncmp(mwi_msg->cause, "INV", 3))
04826             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
04827          else if (!strncmp(mwi_msg->cause, "BLK", 3))
04828             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
04829          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
04830          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
04831       } else {
04832          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
04833       }
04834    }
04835 
04836    if (!ast_strlen_zero(externnotify)) {
04837       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
04838          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
04839       } else {
04840          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
04841          ast_debug(1, "Executing %s\n", arguments);
04842          ast_safe_system(arguments);
04843       }
04844    }
04845 }

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

Definition at line 5367 of file app_voicemail.c.

References ast_debug, ast_log(), AST_LOG_NOTICE, ast_mutex_lock(), ast_mutex_unlock(), ast_unlock_path(), ast_vm_user::context, COPY, create_dirpath(), vm_state::curbox, vm_state::curdir, ERROR_LOCK_PATH, EXISTS, last_message_index(), ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, RENAME, vm_state::username, and vm_lock_path().

Referenced by close_mailbox(), and vm_execmain().

05368 {
05369 #ifdef IMAP_STORAGE
05370    /* we must use mbox(x) folder names, and copy the message there */
05371    /* simple. huh? */
05372    char sequence[10];
05373    char mailbox[256];
05374    int res;
05375 
05376    /* get the real IMAP message number for this message */
05377    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
05378    
05379    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
05380    ast_mutex_lock(&vms->lock);
05381    /* if save to Old folder, put in INBOX as read */
05382    if (box == OLD_FOLDER) {
05383       mail_setflag(vms->mailstream, sequence, "\\Seen");
05384       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
05385    } else if (box == NEW_FOLDER) {
05386       mail_setflag(vms->mailstream, sequence, "\\Unseen");
05387       mail_clearflag(vms->mailstream, sequence, "\\Seen");
05388    }
05389    if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
05390       ast_mutex_unlock(&vms->lock);
05391       return 0;
05392    }
05393    /* Create the folder if it don't exist */
05394    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
05395    ast_debug(5, "Checking if folder exists: %s\n",mailbox);
05396    if (mail_create(vms->mailstream, mailbox) == NIL) 
05397       ast_debug(5, "Folder exists.\n");
05398    else
05399       ast_log(AST_LOG_NOTICE, "Folder %s created!\n",mbox(box));
05400    res = !mail_copy(vms->mailstream, sequence, (char *)mbox(box));
05401    ast_mutex_unlock(&vms->lock);
05402    return res;
05403 #else
05404    char *dir = vms->curdir;
05405    char *username = vms->username;
05406    char *context = vmu->context;
05407    char sfn[PATH_MAX];
05408    char dfn[PATH_MAX];
05409    char ddir[PATH_MAX];
05410    const char *dbox = mbox(box);
05411    int x, i;
05412    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
05413 
05414    if (vm_lock_path(ddir))
05415       return ERROR_LOCK_PATH;
05416 
05417    x = last_message_index(vmu, ddir) + 1;
05418 
05419    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
05420       x--;
05421       for (i = 1; i <= x; i++) {
05422          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
05423          make_file(sfn, sizeof(sfn), ddir, i);
05424          make_file(dfn, sizeof(dfn), ddir, i - 1);
05425          if (EXISTS(ddir, i, sfn, NULL)) {
05426             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
05427          } else
05428             break;
05429       }
05430    } else {
05431       if (x >= vmu->maxmsg) {
05432          ast_unlock_path(ddir);
05433          return -1;
05434       }
05435    }
05436    make_file(sfn, sizeof(sfn), dir, msg);
05437    make_file(dfn, sizeof(dfn), ddir, x);
05438    if (strcmp(sfn, dfn)) {
05439       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
05440    }
05441    ast_unlock_path(ddir);
05442 #endif
05443    return 0;
05444 }

static int say_and_wait ( struct ast_channel chan,
int  num,
const char *  language 
) [static]

Definition at line 5360 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_say_number(), and chan.

Referenced by play_message_duration(), vm_execmain(), vm_intro_cz(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_it(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_se(), and vm_intro_tw().

05361 {
05362    int d;
05363    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
05364    return d;
05365 }

static int sayname ( struct ast_channel chan,
const char *  mailbox,
const char *  context 
) [static]

Definition at line 10887 of file app_voicemail.c.

References ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_stream_and_wait(), chan, DISPOSE, and RETRIEVE.

Referenced by load_module().

10888 {
10889    int res = -1;
10890    char dir[PATH_MAX];
10891    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
10892    ast_debug(2, "About to try retrieving name file %s\n", dir);
10893    RETRIEVE(dir, -1, mailbox, context);
10894    if (ast_fileexists(dir, NULL, NULL)) {
10895       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
10896    }
10897    DISPOSE(dir, -1);
10898    return res;
10899 }

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 *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
const char *  flag 
) [static]

Definition at line 4226 of file app_voicemail.c.

References ast_debug, ast_log(), ast_safe_system(), ast_strlen_zero(), ast_test_flag, chan, ast_vm_user::email, globalflags, ast_vm_user::mailbox, make_email_file(), VM_ATTACH, and vm_mkftemp().

04227 {
04228    FILE *p=NULL;
04229    char tmp[80] = "/tmp/astmail-XXXXXX";
04230    char tmp2[256];
04231 
04232    if (vmu && ast_strlen_zero(vmu->email)) {
04233       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04234       return(0);
04235    }
04236    if (!strcmp(format, "wav49"))
04237       format = "WAV";
04238    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04239    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04240       command hangs */
04241    if ((p = vm_mkftemp(tmp)) == NULL) {
04242       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04243       return -1;
04244    } else {
04245       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04246       fclose(p);
04247       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04248       ast_safe_system(tmp2);
04249       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04250    }
04251    return 0;
04252 }

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,
const char *  flag 
) [static]

Definition at line 4254 of file app_voicemail.c.

References ast_channel_alloc(), ast_channel_free(), ast_copy_string(), ast_debug, ast_log(), ast_safe_system(), AST_STATE_DOWN, ast_strftime(), ast_strlen_zero(), fromstring, MAXHOSTNAMELEN, pagerbody, pagerfromstring, pagersubject, pbx_substitute_variables_helper(), prep_email_sub_vars(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

04255 {
04256    char date[256];
04257    char host[MAXHOSTNAMELEN] = "";
04258    char who[256];
04259    char dur[PATH_MAX];
04260    char tmp[80] = "/tmp/astmail-XXXXXX";
04261    char tmp2[PATH_MAX];
04262    struct ast_tm tm;
04263    FILE *p;
04264 
04265    if ((p = vm_mkftemp(tmp)) == NULL) {
04266       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04267       return -1;
04268    }
04269    gethostname(host, sizeof(host)-1);
04270    if (strchr(srcemail, '@'))
04271       ast_copy_string(who, srcemail, sizeof(who));
04272    else 
04273       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04274    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04275    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04276    fprintf(p, "Date: %s\n", date);
04277 
04278    if (*pagerfromstring) {
04279       struct ast_channel *ast;
04280       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04281          char *passdata;
04282          int vmlen = strlen(fromstring)*3 + 200;
04283          passdata = alloca(vmlen);
04284          memset(passdata, 0, vmlen);
04285          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04286          pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
04287          fprintf(p, "From: %s <%s>\n", passdata, who);
04288          ast_channel_free(ast);
04289       } else 
04290          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04291    } else
04292       fprintf(p, "From: Asterisk PBX <%s>\n", who);
04293    fprintf(p, "To: %s\n", pager);
04294    if (pagersubject) {
04295       struct ast_channel *ast;
04296       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04297          char *passdata;
04298          int vmlen = strlen(pagersubject) * 3 + 200;
04299          passdata = alloca(vmlen);
04300          memset(passdata, 0, vmlen);
04301          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04302          pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
04303          fprintf(p, "Subject: %s\n\n", passdata);
04304          ast_channel_free(ast);
04305       } else
04306          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04307    } else {
04308       if (ast_strlen_zero(flag)) {
04309          fprintf(p, "Subject: New VM\n\n");
04310       } else {
04311          fprintf(p, "Subject: New %s VM\n\n", flag);
04312       }
04313    }
04314 
04315    ast_strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
04316    if (pagerbody) {
04317       struct ast_channel *ast;
04318       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04319          char *passdata;
04320          int vmlen = strlen(pagerbody) * 3 + 200;
04321          passdata = alloca(vmlen);
04322          memset(passdata, 0, vmlen);
04323          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04324          pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
04325          fprintf(p, "%s\n", passdata);
04326          ast_channel_free(ast);
04327       } else
04328          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04329    } else {
04330       fprintf(p, "New %s long %s msg in box %s\n"
04331             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04332    }
04333    fclose(p);
04334    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04335    ast_safe_system(tmp2);
04336    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04337    return 0;
04338 }

static char* show_users_realtime ( int  fd,
const char *  context 
) [static]

Definition at line 9701 of file app_voicemail.c.

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, SENTINEL, and var.

Referenced by handle_voicemail_show_users().

09702 {
09703    struct ast_config *cfg;
09704    const char *cat = NULL;
09705 
09706    if (!(cfg = ast_load_realtime_multientry("voicemail", 
09707       "context", context, SENTINEL))) {
09708       return CLI_FAILURE;
09709    }
09710 
09711    ast_cli(fd,
09712       "\n"
09713       "=============================================================\n"
09714       "=== Configured Voicemail Users ==============================\n"
09715       "=============================================================\n"
09716       "===\n");
09717 
09718    while ((cat = ast_category_browse(cfg, cat))) {
09719       struct ast_variable *var = NULL;
09720       ast_cli(fd,
09721          "=== Mailbox ...\n"
09722          "===\n");
09723       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
09724          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
09725       ast_cli(fd,
09726          "===\n"
09727          "=== ---------------------------------------------------------\n"
09728          "===\n");
09729    }
09730 
09731    ast_cli(fd,
09732       "=============================================================\n"
09733       "\n");
09734 
09735    ast_config_destroy(cfg);
09736 
09737    return CLI_SUCCESS;
09738 }

static void start_poll_thread ( void   )  [static]

Definition at line 10049 of file app_voicemail.c.

References AST_EVENT_IE_END, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_report_subs(), AST_EVENT_SUB, ast_event_subscribe(), AST_EVENT_UNSUB, ast_pthread_create, mb_poll_thread(), mwi_sub_event_cb(), mwi_sub_sub, mwi_unsub_event_cb(), and mwi_unsub_sub.

Referenced by load_config().

static void stop_poll_thread ( void   )  [static]

Definition at line 10067 of file app_voicemail.c.

References ast_cond_signal(), ast_event_unsubscribe(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, mwi_sub_sub, mwi_unsub_sub, and poll_lock.

Referenced by load_config(), and unload_module().

10068 {
10069    poll_thread_run = 0;
10070 
10071    if (mwi_sub_sub) {
10072       ast_event_unsubscribe(mwi_sub_sub);
10073       mwi_sub_sub = NULL;
10074    }
10075 
10076    if (mwi_unsub_sub) {
10077       ast_event_unsubscribe(mwi_unsub_sub);
10078       mwi_unsub_sub = NULL;
10079    }
10080 
10081    ast_mutex_lock(&poll_lock);
10082    ast_cond_signal(&poll_cond);
10083    ast_mutex_unlock(&poll_lock);
10084 
10085    pthread_join(poll_thread, NULL);
10086 
10087    poll_thread = AST_PTHREADT_NULL;
10088 }

static char* strip_control ( const char *  input,
char *  buf,
size_t  buflen 
) [static]

Definition at line 702 of file app_voicemail.c.

Referenced by make_email_file().

00703 {
00704    char *bufptr = buf;
00705    for (; *input; input++) {
00706       if (*input < 32) {
00707          continue;
00708       }
00709       *bufptr++ = *input;
00710       if (bufptr == buf + buflen - 1) {
00711          break;
00712       }
00713    }
00714    *bufptr = '\0';
00715    return buf;
00716 }

static char* substitute_escapes ( const char *  value  )  [static]

Definition at line 10213 of file app_voicemail.c.

References ast_log(), AST_LOG_NOTICE, ast_str_append(), ast_str_create(), and str.

Referenced by load_config().

10214 {
10215    char *current, *result;
10216 
10217    /* Add 16 for fudge factor */
10218    struct ast_str *str = ast_str_create(strlen(value) + 16);
10219 
10220    /* Substitute strings \r, \n, and \t into the appropriate characters */
10221    for (current = (char *) value; *current; current++) {
10222       if (*current == '\\') {
10223          current++;
10224          if (!*current) {
10225             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
10226             break;
10227          }
10228          switch (*current) {
10229          case 'r':
10230             ast_str_append(&str, 0, "\r");
10231             break;
10232          case 'n':
10233 #ifdef IMAP_STORAGE
10234             if (!str->used || str->str[str->used - 1] != '\r') {
10235                ast_str_append(&str, 0, "\r");
10236             }
10237 #endif
10238             ast_str_append(&str, 0, "\n");
10239             break;
10240          case 't':
10241             ast_str_append(&str, 0, "\t");
10242             break;
10243          default:
10244             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
10245             break;
10246          }
10247       } else {
10248          ast_str_append(&str, 0, "%c", *current);
10249       }
10250    }
10251 
10252    result = ast_strdup(str->str);
10253    ast_free(str);
10254 
10255    return result;
10256 }

static int unload_module ( void   )  [static]

Definition at line 10906 of file app_voicemail.c.

References ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), ast_uninstall_vm_functions(), ast_unload_realtime(), ast_unregister_application(), cli_voicemail, free_vm_users(), free_vm_zones(), mailbox_exists_acf, mwi_subscription_tps, and stop_poll_thread().

10907 {
10908    int res;
10909 
10910    res = ast_unregister_application(app);
10911    res |= ast_unregister_application(app2);
10912    res |= ast_unregister_application(app3);
10913    res |= ast_unregister_application(app4);
10914    res |= ast_custom_function_unregister(&mailbox_exists_acf);
10915    res |= ast_manager_unregister("VoicemailUsersList");
10916    ast_cli_unregister_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
10917    ast_uninstall_vm_functions();
10918 
10919    if (poll_thread != AST_PTHREADT_NULL)
10920       stop_poll_thread();
10921 
10922    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
10923    ast_unload_realtime("voicemail");
10924    ast_unload_realtime("voicemail_data");
10925 
10926    free_vm_users();
10927    free_vm_zones();
10928    return res;
10929 }

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  max_logins,
int  silent 
) [static]

Definition at line 8659 of file app_voicemail.c.

References adsi_begin(), adsi_login(), adsi_password(), ast_copy_string(), ast_debug, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitstream(), chan, find_user(), ast_vm_user::password, and vm_password.

Referenced by vm_execmain(), and vmauthenticate().

08662 {
08663    int useadsi=0, valid=0, logretries=0;
08664    char password[AST_MAX_EXTENSION]="", *passptr;
08665    struct ast_vm_user vmus, *vmu = NULL;
08666 
08667    /* If ADSI is supported, setup login screen */
08668    adsi_begin(chan, &useadsi);
08669    if (!skipuser && useadsi)
08670       adsi_login(chan);
08671    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
08672       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
08673       return -1;
08674    }
08675    
08676    /* Authenticate them and get their mailbox/password */
08677    
08678    while (!valid && (logretries < max_logins)) {
08679       /* Prompt for, and read in the username */
08680       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
08681          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
08682          return -1;
08683       }
08684       if (ast_strlen_zero(mailbox)) {
08685          if (chan->cid.cid_num) {
08686             ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
08687          } else {
08688             ast_verb(3,"Username not entered\n");  
08689             return -1;
08690          }
08691       }
08692       if (useadsi)
08693          adsi_password(chan);
08694 
08695       if (!ast_strlen_zero(prefix)) {
08696          char fullusername[80] = "";
08697          ast_copy_string(fullusername, prefix, sizeof(fullusername));
08698          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
08699          ast_copy_string(mailbox, fullusername, mailbox_size);
08700       }
08701 
08702       ast_debug(1, "Before find user for mailbox %s\n",mailbox);
08703       vmu = find_user(&vmus, context, mailbox);
08704       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
08705          /* saved password is blank, so don't bother asking */
08706          password[0] = '\0';
08707       } else {
08708          if (ast_streamfile(chan, vm_password, chan->language)) {
08709             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
08710             return -1;
08711          }
08712          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
08713             ast_log(AST_LOG_WARNING, "Unable to read password\n");
08714             return -1;
08715          }
08716       }
08717 
08718       if (vmu) {
08719          passptr = vmu->password;
08720          if (passptr[0] == '-') passptr++;
08721       }
08722       if (vmu && !strcmp(passptr, password))
08723          valid++;
08724       else {
08725          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
08726          if (!ast_strlen_zero(prefix))
08727             mailbox[0] = '\0';
08728       }
08729       logretries++;
08730       if (!valid) {
08731          if (skipuser || logretries >= max_logins) {
08732             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
08733                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
08734                return -1;
08735             }
08736          } else {
08737             if (useadsi)
08738                adsi_login(chan);
08739             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
08740                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
08741                return -1;
08742             }
08743          }
08744          if (ast_waitstream(chan, "")) /* Channel is hung up */
08745             return -1;
08746       }
08747    }
08748    if (!valid && (logretries >= max_logins)) {
08749       ast_stopstream(chan);
08750       ast_play_and_wait(chan, "vm-goodbye");
08751       return -1;
08752    }
08753    if (vmu && !skipuser) {
08754       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
08755    }
08756    return 0;
08757 }

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

Definition at line 9596 of file app_voicemail.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), chan, find_user(), mbox(), and pbx_builtin_setvar_helper().

Referenced by load_module().

09597 {
09598    struct ast_vm_user svm;
09599    char *context, *box;
09600    AST_DECLARE_APP_ARGS(args,
09601       AST_APP_ARG(mbox);
09602       AST_APP_ARG(options);
09603    );
09604    static int dep_warning = 0;
09605 
09606    if (ast_strlen_zero(data)) {
09607       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
09608       return -1;
09609    }
09610 
09611    if (!dep_warning) {
09612       dep_warning = 1;
09613       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
09614    }
09615 
09616    box = ast_strdupa(data);
09617 
09618    AST_STANDARD_APP_ARGS(args, box);
09619 
09620    if (args.options) {
09621    }
09622 
09623    if ((context = strchr(args.mbox, '@'))) {
09624       *context = '\0';
09625       context++;
09626    }
09627 
09628    if (find_user(&svm, context, args.mbox)) {
09629       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
09630    } else
09631       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
09632 
09633    return 0;
09634 }

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

Top level method to invoke the language variant vm_browse_messages_XX function.

Parameters:
chan The channel for the current user. We read the language property from this.
vms passed into the language-specific vm_browse_messages function.
vmu passed into the language-specific vm_browse_messages function.
The method to be invoked is determined by the value of language code property in the user's channel. The default (when unable to match) is to use english.

Returns:
zero on success, -1 on error.

Definition at line 8640 of file app_voicemail.c.

References chan, ast_channel::language, vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_pt(), and vm_browse_messages_tw().

Referenced by vm_execmain().

08641 {
08642    if (!strcasecmp(chan->language, "es")) {  /* SPANISH */
08643       return vm_browse_messages_es(chan, vms, vmu);
08644    } else if (!strcasecmp(chan->language, "it")) { /* ITALIAN */
08645       return vm_browse_messages_it(chan, vms, vmu);
08646    } else if (!strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {   /* PORTUGUESE */
08647       return vm_browse_messages_pt(chan, vms, vmu);
08648    } else if (!strcasecmp(chan->language, "gr")){
08649       return vm_browse_messages_gr(chan, vms, vmu);   /* GREEK */
08650    } else if (!strcasecmp(chan->language, "tw")){
08651       return vm_browse_messages_tw(chan, vms, vmu);   /* CHINESE (Taiwan) */
08652    } else if (!strcasecmp(chan->language, "he")) {
08653       return vm_browse_messages_he(chan, vms, vmu);   /* HEBREW */
08654    } else { /* Default to English syntax */
08655       return vm_browse_messages_en(chan, vms, vmu);
08656    }
08657 }

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

Default English syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 8503 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::curbox, vm_state::fn, vm_state::lastmsg, and play_message().

Referenced by vm_browse_messages().

08504 {
08505    int cmd=0;
08506 
08507    if (vms->lastmsg > -1) {
08508       cmd = play_message(chan, vmu, vms);
08509    } else {
08510       cmd = ast_play_and_wait(chan, "vm-youhave");
08511       if (!cmd) 
08512          cmd = ast_play_and_wait(chan, "vm-no");
08513       if (!cmd) {
08514          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08515          cmd = ast_play_and_wait(chan, vms->fn);
08516       }
08517       if (!cmd)
08518          cmd = ast_play_and_wait(chan, "vm-messages");
08519    }
08520    return cmd;
08521 }

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

Spanish syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 8557 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::curbox, vm_state::fn, vm_state::lastmsg, and play_message().

Referenced by vm_browse_messages().

08558 {
08559    int cmd=0;
08560 
08561    if (vms->lastmsg > -1) {
08562       cmd = play_message(chan, vmu, vms);
08563    } else {
08564       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08565       if (!cmd)
08566          cmd = ast_play_and_wait(chan, "vm-messages");
08567       if (!cmd) {
08568          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08569          cmd = ast_play_and_wait(chan, vms->fn);
08570       }
08571    }
08572    return cmd;
08573 }

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

Greek syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 8451 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::curbox, vm_state::fn, vm_state::lastmsg, play_message(), and vm_state::vmbox.

Referenced by vm_browse_messages().

08452 {
08453    int cmd=0;
08454 
08455    if (vms->lastmsg > -1) {
08456       cmd = play_message(chan, vmu, vms);
08457    } else {
08458       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08459       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
08460          if (!cmd) {
08461             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
08462             cmd = ast_play_and_wait(chan, vms->fn);
08463          }
08464          if (!cmd)
08465             cmd = ast_play_and_wait(chan, "vm-messages");
08466       } else {
08467          if (!cmd)
08468             cmd = ast_play_and_wait(chan, "vm-messages");
08469          if (!cmd) {
08470             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08471             cmd = ast_play_and_wait(chan, vms->fn);
08472          }
08473       }
08474    } 
08475    return cmd;
08476 }

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

Definition at line 8479 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::fn, vm_state::lastmsg, and play_message().

Referenced by vm_browse_messages().

08480 {
08481    int cmd = 0;
08482 
08483    if (vms->lastmsg > -1) {
08484       cmd = play_message(chan, vmu, vms);
08485    } else {
08486       if (!strcasecmp(vms->fn, "INBOX")) {
08487          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
08488       } else {
08489          cmd = ast_play_and_wait(chan, "vm-nomessages");
08490       }
08491    }
08492    return cmd;
08493 }

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

Italian syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 8531 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::curbox, vm_state::fn, vm_state::lastmsg, and play_message().

Referenced by vm_browse_messages().

08532 {
08533    int cmd=0;
08534 
08535    if (vms->lastmsg > -1) {
08536       cmd = play_message(chan, vmu, vms);
08537    } else {
08538       cmd = ast_play_and_wait(chan, "vm-no");
08539       if (!cmd)
08540          cmd = ast_play_and_wait(chan, "vm-message");
08541       if (!cmd) {
08542          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08543          cmd = ast_play_and_wait(chan, vms->fn);
08544       }
08545    }
08546    return cmd;
08547 }

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

Portuguese syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 8583 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::curbox, vm_state::fn, vm_state::lastmsg, and play_message().

Referenced by vm_browse_messages().

08584 {
08585    int cmd=0;
08586 
08587    if (vms->lastmsg > -1) {
08588       cmd = play_message(chan, vmu, vms);
08589    } else {
08590       cmd = ast_play_and_wait(chan, "vm-no");
08591       if (!cmd) {
08592          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08593          cmd = ast_play_and_wait(chan, vms->fn);
08594       }
08595       if (!cmd)
08596          cmd = ast_play_and_wait(chan, "vm-messages");
08597    }
08598    return cmd;
08599 }

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

Chinese (Taiwan)syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 8609 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::curbox, vm_state::fn, vm_state::lastmsg, and play_message().

Referenced by vm_browse_messages().

08610 {
08611    int cmd=0;
08612 
08613    if (vms->lastmsg > -1) {
08614       cmd = play_message(chan, vmu, vms);
08615    } else {
08616       cmd = ast_play_and_wait(chan, "vm-you");
08617       if (!cmd) 
08618          cmd = ast_play_and_wait(chan, "vm-haveno");
08619       if (!cmd)
08620          cmd = ast_play_and_wait(chan, "vm-messages");
08621       if (!cmd) {
08622          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08623          cmd = ast_play_and_wait(chan, vms->fn);
08624       }
08625    }
08626    return cmd;
08627 }

static void vm_change_password ( struct ast_vm_user vmu,
const char *  newpassword 
) [static]

The handler for the change password option.

Parameters:
vmu The voicemail user to work with.
newpassword The new password (that has been gathered from the appropriate prompting). This is called when a new user logs in for the first time and the option to force them to change their password is set. It is also called when the user wants to change their password from menu option '5' on the mailbox options menu.

Definition at line 1153 of file app_voicemail.c.

References ast_category_browse(), ast_category_get(), ast_config_load, ast_copy_string(), ast_debug, ast_log(), AST_LOG_WARNING, ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, config_flags, config_text_file_save(), ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, reset_user_pw(), var, and VOICEMAIL_CONFIG.

Referenced by vm_newuser(), and vm_options().

01154 {
01155    struct ast_config   *cfg=NULL;
01156    struct ast_variable *var=NULL;
01157    struct ast_category *cat=NULL;
01158    char *category=NULL, *value=NULL, *new=NULL;
01159    const char *tmp=NULL;
01160    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01161    if (!change_password_realtime(vmu, newpassword))
01162       return;
01163 
01164    /* check voicemail.conf */
01165    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags))) {
01166       while ((category = ast_category_browse(cfg, category))) {
01167          if (!strcasecmp(category, vmu->context)) {
01168             if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01169                ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01170                break;
01171             }
01172             value = strstr(tmp,",");
01173             if (!value) {
01174                ast_log(AST_LOG_WARNING, "variable has bad format.\n");
01175                break;
01176             }
01177             new = alloca((strlen(value)+strlen(newpassword)+1));
01178             sprintf(new,"%s%s", newpassword, value);
01179             if (!(cat = ast_category_get(cfg, category))) {
01180                ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01181                break;
01182             }
01183             ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01184          }
01185       }
01186       /* save the results */
01187       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01188       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01189       config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01190    }
01191    category = NULL;
01192    var = NULL;
01193    /* check users.conf and update the password stored for the mailbox*/
01194    /* if no vmsecret entry exists create one. */
01195    if ((cfg = ast_config_load("users.conf", config_flags))) {
01196       ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01197       while ((category = ast_category_browse(cfg, category))) {
01198          ast_debug(4, "users.conf: %s\n", category);
01199          if (!strcasecmp(category, vmu->mailbox)) {
01200             if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01201                ast_debug(3, "looks like we need to make vmsecret!\n");
01202                var = ast_variable_new("vmsecret", newpassword, "");
01203             } 
01204             new = alloca(strlen(newpassword)+1);
01205             sprintf(new, "%s", newpassword);
01206             if (!(cat = ast_category_get(cfg, category))) {
01207                ast_debug(4, "failed to get category!\n");
01208                break;
01209             }
01210             if (!var)      
01211                ast_variable_update(cat, "vmsecret", new, NULL, 0);
01212             else
01213                ast_variable_append(cat, var);
01214          }
01215       }
01216       /* save the results and clean things up */
01217       reset_user_pw(vmu->context, vmu->mailbox, newpassword);  
01218       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01219       config_text_file_save("users.conf", cfg, "AppVoicemail");
01220    }
01221 }

static void vm_change_password_shell ( struct ast_vm_user vmu,
char *  newpassword 
) [static]

Definition at line 1223 of file app_voicemail.c.

References ast_copy_string(), ast_safe_system(), buf, ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, and reset_user_pw().

Referenced by vm_newuser(), and vm_options().

01224 {
01225    char buf[255];
01226    snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
01227    if (!ast_safe_system(buf)) {
01228       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01229       /* Reset the password in memory, too */
01230       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01231    }
01232 }

static char* vm_check_password_shell ( char *  command,
char *  buf,
size_t  len 
) [static]

Definition at line 854 of file app_voicemail.c.

References AST_APP_ARG, ast_close_fds_above_n(), AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_safe_fork(), ast_strdupa, errno, and LOG_WARNING.

Referenced by check_password().

00855 {
00856    int fds[2], pid = 0;
00857 
00858    memset(buf, 0, len);
00859 
00860    if (pipe(fds)) {
00861       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
00862    } else {
00863       /* good to go*/
00864       pid = ast_safe_fork(0);
00865 
00866       if (pid < 0) {
00867          /* ok maybe not */
00868          close(fds[0]);
00869          close(fds[1]);
00870          snprintf(buf, len, "FAILURE: Fork failed");
00871       } else if (pid) {
00872          /* parent */
00873          close(fds[1]);
00874          if (read(fds[0], buf, len) < 0) {
00875             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
00876          }
00877          close(fds[0]);
00878       } else {
00879          /*  child */
00880          AST_DECLARE_APP_ARGS(arg,
00881             AST_APP_ARG(v)[20];
00882          );
00883          char *mycmd = ast_strdupa(command);
00884 
00885          close(fds[0]);
00886          dup2(fds[1], STDOUT_FILENO);
00887          close(fds[1]);
00888          ast_close_fds_above_n(STDOUT_FILENO);
00889 
00890          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
00891 
00892          execv(arg.v[0], arg.v); 
00893          printf("FAILURE: %s", strerror(errno));
00894          _exit(0);
00895       }
00896    }
00897    return buf;
00898 }

static int vm_delete ( char *  file  )  [static]

Removes the voicemail sound and information file.

Parameters:
file The path to the sound file. This will be the the folder and message index, without the extension.
This is used by the DELETE macro when voicemails are stored on the file system.

Returns:
zero on success, -1 on error.

Definition at line 3577 of file app_voicemail.c.

References ast_check_realtime(), ast_destroy_realtime(), ast_filedelete(), and SENTINEL.

03578 {
03579    char *txt;
03580    int txtsize = 0;
03581 
03582    txtsize = (strlen(file) + 5)*sizeof(char);
03583    txt = alloca(txtsize);
03584    /* Sprintf here would safe because we alloca'd exactly the right length,
03585     * but trying to eliminate all sprintf's anyhow
03586     */
03587    if (ast_check_realtime("voicemail_data")) {
03588       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
03589    }
03590    snprintf(txt, txtsize, "%s.txt", file);
03591    unlink(txt);
03592    return ast_filedelete(file, NULL);
03593 }

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

Definition at line 9464 of file app_voicemail.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), ast_copy_flags, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, chan, ERROR_LOCK_PATH, ast_flags::flags, leave_voicemail(), OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and vm_app_options.

Referenced by load_module(), and play_record_review().

09465 {
09466    int res = 0;
09467    char *tmp;
09468    struct leave_vm_options leave_options;
09469    struct ast_flags flags = { 0 };
09470    char *opts[OPT_ARG_ARRAY_SIZE];
09471    AST_DECLARE_APP_ARGS(args,
09472       AST_APP_ARG(argv0);
09473       AST_APP_ARG(argv1);
09474    );
09475    
09476    memset(&leave_options, 0, sizeof(leave_options));
09477 
09478    if (chan->_state != AST_STATE_UP)
09479       ast_answer(chan);
09480 
09481    if (!ast_strlen_zero(data)) {
09482       tmp = ast_strdupa(data);
09483       AST_STANDARD_APP_ARGS(args, tmp);
09484       if (args.argc == 2) {
09485          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09486             return -1;
09487          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
09488          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09489             int gain;
09490 
09491             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
09492                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09493                return -1;
09494             } else {
09495                leave_options.record_gain = (signed char) gain;
09496             }
09497          }
09498          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
09499             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
09500                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
09501          }
09502       }
09503    } else {
09504       char temp[256];
09505       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
09506       if (res < 0)
09507          return res;
09508       if (ast_strlen_zero(temp))
09509          return 0;
09510       args.argv0 = ast_strdupa(temp);
09511    }
09512 
09513    res = leave_voicemail(chan, args.argv0, &leave_options);
09514 
09515    if (res == ERROR_LOCK_PATH) {
09516       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
09517       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
09518       res = 0;
09519    }
09520 
09521    return res;
09522 }

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

Definition at line 8759 of file app_voicemail.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), ast_adsi_unload_session, ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_log(), AST_LOG_ERROR, ast_mutex_lock(), ast_mutex_unlock(), ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_vm_user::callback, chan, close_mailbox(), ast_vm_user::context, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), ast_flags::flags, forward_message(), free_user(), get_folder2(), globalflags, has_voicemail(), language, ast_vm_user::language, ast_vm_user::mailbox, make_file(), manager_event, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, open_mailbox(), OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), run_externnotify(), save_to_folder(), say_and_wait(), vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, and VM_SVMAIL.

Referenced by load_module().

08760 {
08761    /* XXX This is, admittedly, some pretty horrendous code.  For some
08762       reason it just seemed a lot easier to do with GOTO's.  I feel
08763       like I'm back in my GWBASIC days. XXX */
08764    int res=-1;
08765    int cmd=0;
08766    int valid = 0;
08767    char prefixstr[80] ="";
08768    char ext_context[256]="";
08769    int box;
08770    int useadsi = 0;
08771    int skipuser = 0;
08772    struct vm_state vms;
08773    struct ast_vm_user *vmu = NULL, vmus;
08774    char *context=NULL;
08775    int silentexit = 0;
08776    struct ast_flags flags = { 0 };
08777    signed char record_gain = 0;
08778    int play_auto = 0;
08779    int play_folder = 0;
08780    int in_urgent = 0;
08781 #ifdef IMAP_STORAGE
08782    int deleted = 0;
08783 #endif
08784 
08785    /* Add the vm_state to the active list and keep it active */
08786    memset(&vms, 0, sizeof(vms));
08787 
08788    vms.lastmsg = -1;
08789 
08790    memset(&vmus, 0, sizeof(vmus));
08791 
08792    if (chan->_state != AST_STATE_UP) {
08793       ast_debug(1, "Before ast_answer\n");
08794       ast_answer(chan);
08795    }
08796 
08797    if (!ast_strlen_zero(data)) {
08798       char *opts[OPT_ARG_ARRAY_SIZE];
08799       char *parse;
08800       AST_DECLARE_APP_ARGS(args,
08801          AST_APP_ARG(argv0);
08802          AST_APP_ARG(argv1);
08803       );
08804 
08805       parse = ast_strdupa(data);
08806 
08807       AST_STANDARD_APP_ARGS(args, parse);
08808 
08809       if (args.argc == 2) {
08810          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
08811             return -1;
08812          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
08813             int gain;
08814             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
08815                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
08816                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
08817                   return -1;
08818                } else {
08819                   record_gain = (signed char) gain;
08820                }
08821             } else {
08822                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
08823             }
08824          }
08825          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
08826             play_auto = 1;
08827             if (opts[OPT_ARG_PLAYFOLDER]) {
08828                if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%d", &play_folder) != 1) {
08829                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for folder autoplay option\n", opts[OPT_ARG_PLAYFOLDER]);
08830                }
08831             } else {
08832                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
08833             }  
08834             if ( play_folder > 9 || play_folder < 0) {
08835                ast_log(AST_LOG_WARNING, "Invalid value '%d' provided for folder autoplay option\n", play_folder);
08836                play_folder = 0;
08837             }
08838          }
08839       } else {
08840          /* old style options parsing */
08841          while (*(args.argv0)) {
08842             if (*(args.argv0) == 's')
08843                ast_set_flag(&flags, OPT_SILENT);
08844             else if (*(args.argv0) == 'p')
08845                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
08846             else 
08847                break;
08848             (args.argv0)++;
08849          }
08850 
08851       }
08852 
08853       valid = ast_test_flag(&flags, OPT_SILENT);
08854 
08855       if ((context = strchr(args.argv0, '@')))
08856          *context++ = '\0';
08857 
08858       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
08859          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
08860       else
08861          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
08862 
08863       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
08864          skipuser++;
08865       else
08866          valid = 0;
08867    }
08868 
08869    if (!valid)
08870       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
08871 
08872    ast_debug(1, "After vm_authenticate\n");
08873    if (!res) {
08874       valid = 1;
08875       if (!skipuser)
08876          vmu = &vmus;
08877    } else {
08878       res = 0;
08879    }
08880 
08881    /* If ADSI is supported, setup login screen */
08882    adsi_begin(chan, &useadsi);
08883 
08884 #ifdef IMAP_STORAGE
08885    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
08886    pthread_setspecific(ts_vmstate.key, &vms);
08887 
08888    vms.interactive = 1;
08889    vms.updated = 1;
08890    if (vmu)
08891       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
08892    vmstate_insert(&vms);
08893    init_vm_state(&vms);
08894 #endif
08895    if (!valid)
08896       goto out;
08897 
08898    if (!(vms.deleted = ast_calloc(vmu->maxmsg, sizeof(int)))) {
08899       ast_log(AST_LOG_ERROR, "Could not allocate memory for deleted message storage!\n");
08900       cmd = ast_play_and_wait(chan, "an-error-has-occured");
08901       return -1;
08902    }
08903    if (!(vms.heard = ast_calloc(vmu->maxmsg, sizeof(int)))) {
08904       ast_log(AST_LOG_ERROR, "Could not allocate memory for heard message storage!\n");
08905       cmd = ast_play_and_wait(chan, "an-error-has-occured");
08906       return -1;
08907    }
08908    
08909    /* Set language from config to override channel language */
08910    if (!ast_strlen_zero(vmu->language))
08911       ast_string_field_set(chan, language, vmu->language);
08912 
08913    /* Retrieve urgent, old and new message counts */
08914    ast_debug(1, "Before open_mailbox\n");
08915    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
08916    if (res == ERROR_LOCK_PATH)
08917       goto out;
08918    vms.oldmessages = vms.lastmsg + 1;
08919    ast_debug(1, "Number of old messages: %d\n",vms.oldmessages);
08920    /* check INBOX */
08921    res = open_mailbox(&vms, vmu, NEW_FOLDER);
08922    if (res == ERROR_LOCK_PATH)
08923       goto out;
08924    vms.newmessages = vms.lastmsg + 1;
08925    ast_debug(1, "Number of new messages: %d\n",vms.newmessages);
08926    /* Start in Urgent */
08927    in_urgent = 1;
08928    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
08929    if (res == ERROR_LOCK_PATH)
08930       goto out;
08931    vms.urgentmessages = vms.lastmsg + 1;
08932    ast_debug(1, "Number of urgent messages: %d\n",vms.urgentmessages);
08933 
08934    /* Select proper mailbox FIRST!! */
08935    if (play_auto) {
08936       if (vms.urgentmessages) {
08937          in_urgent = 1;
08938          res = open_mailbox(&vms, vmu, 11);
08939       } else {
08940          in_urgent = 0;
08941          res = open_mailbox(&vms, vmu, play_folder);
08942       }
08943       if (res == ERROR_LOCK_PATH)
08944          goto out;
08945 
08946       /* If there are no new messages, inform the user and hangup */
08947       if (vms.lastmsg == -1) {
08948          in_urgent = 0;
08949          cmd = vm_browse_messages(chan, &vms, vmu);
08950          res = 0;
08951          goto out;
08952       }
08953    } else {
08954       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
08955          /* If we only have old messages start here */
08956          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
08957          in_urgent = 0;
08958          play_folder = 1;
08959          if (res == ERROR_LOCK_PATH)
08960             goto out;
08961       } else if (!vms.urgentmessages && vms.newmessages) {
08962          /* If we have new messages but none are urgent */
08963          in_urgent = 0;
08964          res = open_mailbox(&vms, vmu, NEW_FOLDER);
08965          if (res == ERROR_LOCK_PATH)
08966             goto out;
08967       }
08968    }
08969 
08970    if (useadsi)
08971       adsi_status(chan, &vms);
08972    res = 0;
08973 
08974    /* Check to see if this is a new user */
08975    if (!strcasecmp(vmu->mailbox, vmu->password) && 
08976       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
08977       if (ast_play_and_wait(chan, "vm-newuser") == -1)
08978          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
08979       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
08980       if ((cmd == 't') || (cmd == '#')) {
08981          /* Timeout */
08982          res = 0;
08983          goto out;
08984       } else if (cmd < 0) {
08985          /* Hangup */
08986          res = -1;
08987          goto out;
08988       }
08989    }
08990 #ifdef IMAP_STORAGE
08991       ast_debug(3, "Checking quotas: comparing %u to %u\n",vms.quota_usage,vms.quota_limit);
08992       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
08993          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
08994          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
08995       }
08996       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n",(vms.newmessages + vms.oldmessages),vmu->maxmsg);
08997       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
08998          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
08999          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09000       }
09001 #endif
09002    if (play_auto) {
09003       cmd = '1';
09004    } else {
09005       cmd = vm_intro(chan, vmu, &vms);
09006    }
09007 
09008    vms.repeats = 0;
09009    vms.starting = 1;
09010    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09011       /* Run main menu */
09012       switch (cmd) {
09013       case '1': /* First message */
09014          vms.curmsg = 0;
09015          /* Fall through */
09016       case '5': /* Play current message */
09017          cmd = vm_browse_messages(chan, &vms, vmu);
09018          break;
09019       case '2': /* Change folders */
09020          if (useadsi)
09021             adsi_folders(chan, 0, "Change to folder...");
09022          cmd = get_folder2(chan, "vm-changeto", 0);
09023          if (cmd == '#') {
09024             cmd = 0;
09025          } else if (cmd > 0) {
09026             cmd = cmd - '0';
09027             res = close_mailbox(&vms, vmu);
09028             if (res == ERROR_LOCK_PATH)
09029                goto out;
09030             /* If folder is not urgent, set in_urgent to zero! */
09031             if (cmd != 11) in_urgent = 0;
09032             res = open_mailbox(&vms, vmu, cmd);
09033             if (res == ERROR_LOCK_PATH)
09034                goto out;
09035             play_folder = cmd;
09036             cmd = 0;
09037          }
09038          if (useadsi)
09039             adsi_status2(chan, &vms);
09040             
09041          if (!cmd)
09042             cmd = vm_play_folder_name(chan, vms.vmbox);
09043 
09044          vms.starting = 1;
09045          break;
09046       case '3': /* Advanced options */
09047          cmd = 0;
09048          vms.repeats = 0;
09049          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09050             switch (cmd) {
09051             case '1': /* Reply */
09052                if (vms.lastmsg > -1 && !vms.starting) {
09053                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
09054                   if (cmd == ERROR_LOCK_PATH) {
09055                      res = cmd;
09056                      goto out;
09057                   }
09058                } else
09059                   cmd = ast_play_and_wait(chan, "vm-sorry");
09060                cmd = 't';
09061                break;
09062             case '2': /* Callback */
09063                if (!vms.starting)
09064                   ast_verb(3, "Callback Requested\n");
09065                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
09066                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
09067                   if (cmd == 9) {
09068                      silentexit = 1;
09069                      goto out;
09070                   } else if (cmd == ERROR_LOCK_PATH) {
09071                      res = cmd;
09072                      goto out;
09073                   }
09074                } else 
09075                   cmd = ast_play_and_wait(chan, "vm-sorry");
09076                cmd = 't';
09077                break;
09078             case '3': /* Envelope */
09079                if (vms.lastmsg > -1 && !vms.starting) {
09080                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
09081                   if (cmd == ERROR_LOCK_PATH) {
09082                      res = cmd;
09083                      goto out;
09084                   }
09085                } else
09086                   cmd = ast_play_and_wait(chan, "vm-sorry");
09087                cmd = 't';
09088                break;
09089             case '4': /* Dialout */
09090                if (!ast_strlen_zero(vmu->dialout)) {
09091                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
09092                   if (cmd == 9) {
09093                      silentexit = 1;
09094                      goto out;
09095                   }
09096                } else 
09097                   cmd = ast_play_and_wait(chan, "vm-sorry");
09098                cmd = 't';
09099                break;
09100 
09101             case '5': /* Leave VoiceMail */
09102                if (ast_test_flag(vmu, VM_SVMAIL)) {
09103                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
09104                   if (cmd == ERROR_LOCK_PATH) {
09105                      res = cmd;
09106                      ast_log(AST_LOG_WARNING, "forward_message failed to lock path.\n");
09107                      goto out;
09108                   }
09109                } else
09110                   cmd = ast_play_and_wait(chan,"vm-sorry");
09111                cmd='t';
09112                break;
09113                
09114             case '*': /* Return to main menu */
09115                cmd = 't';
09116                break;
09117 
09118             default:
09119                cmd = 0;
09120                if (!vms.starting) {
09121                   cmd = ast_play_and_wait(chan, "vm-toreply");
09122                }
09123                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
09124                   cmd = ast_play_and_wait(chan, "vm-tocallback");
09125                }
09126                if (!cmd && !vms.starting) {
09127                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
09128                }
09129                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
09130                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
09131                }
09132                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
09133                   cmd=ast_play_and_wait(chan, "vm-leavemsg");
09134                if (!cmd)
09135                   cmd = ast_play_and_wait(chan, "vm-starmain");
09136                if (!cmd)
09137                   cmd = ast_waitfordigit(chan,6000);
09138                if (!cmd)
09139                   vms.repeats++;
09140                if (vms.repeats > 3)
09141                   cmd = 't';
09142             }
09143          }
09144          if (cmd == 't') {
09145             cmd = 0;
09146             vms.repeats = 0;
09147          }
09148          break;
09149       case '4': /* Go to the previous message */
09150          if (vms.curmsg > 0) {
09151             vms.curmsg--;
09152             cmd = play_message(chan, vmu, &vms);
09153          } else {
09154             /* Check if we were listening to new
09155                messages.  If so, go to Urgent messages
09156                instead of saying "no more messages"
09157             */
09158             if (in_urgent == 0 && vms.urgentmessages > 0) {
09159                /* Check for Urgent messages */
09160                in_urgent = 1;
09161                res = close_mailbox(&vms, vmu);
09162                if (res == ERROR_LOCK_PATH)
09163                   goto out;
09164                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
09165                if (res == ERROR_LOCK_PATH)
09166                   goto out;
09167                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n",vms.lastmsg + 1);
09168                vms.curmsg = vms.lastmsg;
09169                if (vms.lastmsg < 0)
09170                   cmd = ast_play_and_wait(chan, "vm-nomore");
09171             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09172                vms.curmsg = vms.lastmsg;
09173                cmd = play_message(chan, vmu, &vms);
09174             } else {
09175                cmd = ast_play_and_wait(chan, "vm-nomore");
09176             }
09177          }
09178          break;
09179       case '6': /* Go to the next message */
09180          if (vms.curmsg < vms.lastmsg) {
09181             vms.curmsg++;
09182             cmd = play_message(chan, vmu, &vms);
09183          } else {
09184             if (in_urgent && vms.newmessages > 0) {
09185                /* Check if we were listening to urgent
09186                 * messages.  If so, go to regular new messages
09187                 * instead of saying "no more messages"
09188                 */
09189                in_urgent = 0;
09190                res = close_mailbox(&vms, vmu);
09191                if (res == ERROR_LOCK_PATH)
09192                   goto out;
09193                res = open_mailbox(&vms, vmu, NEW_FOLDER);
09194                if (res == ERROR_LOCK_PATH)
09195                   goto out;
09196                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09197                vms.curmsg = -1;
09198                if (vms.lastmsg < 0) {
09199                   cmd = ast_play_and_wait(chan, "vm-nomore");
09200                }
09201             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09202                vms.curmsg = 0;
09203                cmd = play_message(chan, vmu, &vms);
09204             } else {
09205                cmd = ast_play_and_wait(chan, "vm-nomore");
09206             }
09207          }
09208          break;
09209       case '7': /* Delete the current message */
09210          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
09211             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
09212             if (useadsi)
09213                adsi_delete(chan, &vms);
09214             if (vms.deleted[vms.curmsg]) {
09215                if (play_folder == 0) {
09216                   if (in_urgent) {
09217                      vms.urgentmessages--;
09218                   } else {
09219                      vms.newmessages--;
09220                   }
09221                }
09222                else if (play_folder == 1)
09223                   vms.oldmessages--;
09224                cmd = ast_play_and_wait(chan, "vm-deleted");
09225             } else {
09226                if (play_folder == 0) {
09227                   if (in_urgent) {
09228                      vms.urgentmessages++;
09229                   } else {
09230                      vms.newmessages++;
09231                   }
09232                }
09233                else if (play_folder == 1)
09234                   vms.oldmessages++;
09235                cmd = ast_play_and_wait(chan, "vm-undeleted");
09236             }
09237             if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
09238                if (vms.curmsg < vms.lastmsg) {
09239                   vms.curmsg++;
09240                   cmd = play_message(chan, vmu, &vms);
09241                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09242                   vms.curmsg = 0;
09243                   cmd = play_message(chan, vmu, &vms);
09244                } else {
09245                   /* Check if we were listening to urgent
09246                      messages.  If so, go to regular new messages
09247                      instead of saying "no more messages"
09248                   */
09249                   if (in_urgent == 1) {
09250                      /* Check for new messages */
09251                      in_urgent = 0;
09252                      res = close_mailbox(&vms, vmu);
09253                      if (res == ERROR_LOCK_PATH)
09254                         goto out;
09255                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
09256                      if (res == ERROR_LOCK_PATH)
09257                         goto out;
09258                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09259                      vms.curmsg = -1;
09260                      if (vms.lastmsg < 0)
09261                         cmd = ast_play_and_wait(chan, "vm-nomore");
09262                   } else {
09263                      cmd = ast_play_and_wait(chan, "vm-nomore");
09264                   }
09265                }
09266             }
09267          } else /* Delete not valid if we haven't selected a message */
09268             cmd = 0;
09269 #ifdef IMAP_STORAGE
09270          deleted = 1;
09271 #endif
09272          break;
09273    
09274       case '8': /* Forward the current messgae */
09275          if (vms.lastmsg > -1) {
09276             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
09277             if (cmd == ERROR_LOCK_PATH) {
09278                res = cmd;
09279                goto out;
09280             }
09281          } else {
09282             /* Check if we were listening to urgent
09283                messages.  If so, go to regular new messages
09284                instead of saying "no more messages"
09285             */
09286             if (in_urgent == 1 && vms.newmessages > 0) {
09287                /* Check for new messages */
09288                in_urgent = 0;
09289                res = close_mailbox(&vms, vmu);
09290                if (res == ERROR_LOCK_PATH)
09291                   goto out;
09292                res = open_mailbox(&vms, vmu, NEW_FOLDER);
09293                if (res == ERROR_LOCK_PATH)
09294                   goto out;
09295                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09296                vms.curmsg = -1;
09297                if (vms.lastmsg < 0)
09298                   cmd = ast_play_and_wait(chan, "vm-nomore");
09299             } else {
09300                cmd = ast_play_and_wait(chan, "vm-nomore");
09301             }
09302          }
09303          break;
09304       case '9': /* Save message to folder */
09305          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
09306             /* No message selected */
09307             cmd = 0;
09308             break;
09309          }
09310          if (useadsi)
09311             adsi_folders(chan, 1, "Save to folder...");
09312          cmd = get_folder2(chan, "vm-savefolder", 1);
09313          box = 0; /* Shut up compiler */
09314          if (cmd == '#') {
09315             cmd = 0;
09316             break;
09317          } else if (cmd > 0) {
09318             box = cmd = cmd - '0';
09319             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
09320             if (cmd == ERROR_LOCK_PATH) {
09321                res = cmd;
09322                goto out;
09323 #ifndef IMAP_STORAGE
09324             } else if (!cmd) {
09325                vms.deleted[vms.curmsg] = 1;
09326 #endif
09327             } else {
09328                vms.deleted[vms.curmsg] = 0;
09329                vms.heard[vms.curmsg] = 0;
09330             }
09331          }
09332          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
09333          if (useadsi)
09334             adsi_message(chan, &vms);
09335          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box));
09336          if (!cmd) {
09337             cmd = ast_play_and_wait(chan, "vm-message");
09338             if (!cmd) 
09339                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
09340             if (!cmd)
09341                cmd = ast_play_and_wait(chan, "vm-savedto");
09342             if (!cmd)
09343                cmd = vm_play_folder_name(chan, vms.fn);
09344          } else {
09345             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09346          }
09347          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
09348             if (vms.curmsg < vms.lastmsg) {
09349                vms.curmsg++;
09350                cmd = play_message(chan, vmu, &vms);
09351             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09352                vms.curmsg = 0;
09353                cmd = play_message(chan, vmu, &vms);
09354             } else {
09355                /* Check if we were listening to urgent
09356                   messages.  If so, go to regular new messages
09357                   instead of saying "no more messages"
09358                */
09359                if (in_urgent == 1 && vms.newmessages > 0) {
09360                   /* Check for new messages */
09361                   in_urgent = 0;
09362                   res = close_mailbox(&vms, vmu);
09363                   if (res == ERROR_LOCK_PATH)
09364                      goto out;
09365                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
09366                   if (res == ERROR_LOCK_PATH)
09367                      goto out;
09368                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09369                   vms.curmsg = -1;
09370                   if (vms.lastmsg < 0)
09371                      cmd = ast_play_and_wait(chan, "vm-nomore");
09372                } else {
09373                   cmd = ast_play_and_wait(chan, "vm-nomore");
09374                }
09375             }
09376          }
09377          break;
09378       case '*': /* Help */
09379          if (!vms.starting) {
09380             cmd = ast_play_and_wait(chan, "vm-onefor");
09381             if (!cmd)
09382                cmd = vm_play_folder_name(chan, vms.vmbox);
09383             if (!cmd)
09384                cmd = ast_play_and_wait(chan, "vm-opts");
09385             if (!cmd)
09386                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
09387          } else
09388             cmd = 0;
09389          break;
09390       case '0': /* Mailbox options */
09391          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
09392          if (useadsi)
09393             adsi_status(chan, &vms);
09394          break;
09395       default: /* Nothing */
09396          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
09397          break;
09398       }
09399    }
09400    if ((cmd == 't') || (cmd == '#')) {
09401       /* Timeout */
09402       res = 0;
09403    } else {
09404       /* Hangup */
09405       res = -1;
09406    }
09407 
09408 out:
09409    if (res > -1) {
09410       ast_stopstream(chan);
09411       adsi_goodbye(chan);
09412       if (valid) {
09413          if (silentexit)
09414             res = ast_play_and_wait(chan, "vm-dialout");
09415          else 
09416             res = ast_play_and_wait(chan, "vm-goodbye");
09417          if (res > 0)
09418             res = 0;
09419       }
09420       if (useadsi)
09421          ast_adsi_unload_session(chan);
09422    }
09423    if (vmu)
09424       close_mailbox(&vms, vmu);
09425    if (valid) {
09426       int new = 0, old = 0, urgent = 0;
09427       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
09428       manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
09429       /* Urgent flag not passwd to externnotify here */
09430       run_externnotify(vmu->context, vmu->mailbox, NULL);
09431       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
09432       queue_mwi_event(ext_context, urgent, new, old);
09433    }
09434 #ifdef IMAP_STORAGE
09435    /* expunge message - use UID Expunge if supported on IMAP server*/
09436    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n",deleted,expungeonhangup);
09437    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
09438       ast_mutex_lock(&vms.lock);
09439 #ifdef HAVE_IMAP_TK2006
09440       if (LEVELUIDPLUS (vms.mailstream)) {
09441          mail_expunge_full(vms.mailstream,NIL,EX_UID);
09442       } else 
09443 #endif
09444          mail_expunge(vms.mailstream);
09445       ast_mutex_unlock(&vms.lock);
09446    }
09447    /*  before we delete the state, we should copy pertinent info
09448     *  back to the persistent model */
09449    vmstate_delete(&vms);
09450 #endif
09451    if (vmu)
09452       free_user(vmu);
09453    if (vms.deleted)
09454       ast_free(vms.deleted);
09455    if (vms.heard)
09456       ast_free(vms.heard);
09457 
09458 #ifdef IMAP_STORAGE
09459    pthread_setspecific(ts_vmstate.key, NULL);
09460 #endif
09461    return res;
09462 }

static int vm_forwardoptions ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  curdir,
int  curmsg,
char *  vm_fmts,
char *  context,
signed char  record_gain,
long *  duration,
struct vm_state vms,
char *  flag 
) [static]

presents the option to prepend to an existing message when forwarding it.

Parameters:
chan 
vmu 
curdir 
curmsg 
vmfmts 
context 
record_gain 
duration 
vms Presents a prompt for 1 to prepend the current message, 2 to forward the message without prepending, or * to return to the main menu.
This is invoked from forward_message() when performing a forward operation (option 8 from main menu).
Returns:
zero on success, -1 on error.

Definition at line 6009 of file app_voicemail.c.

References ast_category_get(), ast_channel_setoption(), ast_config_destroy(), ast_config_load, ast_filecopy(), ast_filedelete(), AST_OPTION_RXGAIN, ast_play_and_prepend(), ast_play_and_wait(), ast_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), chan, CONFIG_FLAG_NOCACHE, config_flags, config_text_file_save(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

Referenced by forward_message().

06011 {
06012 #ifdef IMAP_STORAGE
06013    int res;
06014 #endif
06015    int cmd = 0;
06016    int retries = 0, prepend_duration = 0, already_recorded = 0;
06017    char msgfile[PATH_MAX], backup[PATH_MAX];
06018    char textfile[PATH_MAX];
06019    struct ast_config *msg_cfg;
06020    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06021 #ifndef IMAP_STORAGE
06022    signed char zero_gain = 0;
06023 #endif
06024    const char *duration_str;
06025 
06026    /* Must always populate duration correctly */
06027    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06028    strcpy(textfile, msgfile);
06029    strcpy(backup, msgfile);
06030    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06031    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06032 
06033    if ((msg_cfg = ast_config_load(textfile, config_flags)) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06034       *duration = atoi(duration_str);
06035    } else {
06036       *duration = 0;
06037    }
06038 
06039    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06040       if (cmd)
06041          retries = 0;
06042       switch (cmd) {
06043       case '1': 
06044 
06045 #ifdef IMAP_STORAGE
06046          /* Record new intro file */
06047          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06048          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06049          res = ast_play_and_wait(chan, INTRO);
06050          res = ast_play_and_wait(chan, "beep");
06051          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *)duration, NULL, record_gain, vms, flag);
06052          cmd = 't';
06053 #else
06054 
06055          /* prepend a message to the current message, update the metadata and return */
06056 
06057          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06058          strcpy(textfile, msgfile);
06059          strncat(textfile, ".txt", sizeof(textfile) - 1);
06060          *duration = 0;
06061 
06062          /* if we can't read the message metadata, stop now */
06063          if (!msg_cfg) {
06064             cmd = 0;
06065             break;
06066          }
06067          
06068          /* Back up the original file, so we can retry the prepend */
06069          if (already_recorded)
06070             ast_filecopy(backup, msgfile, NULL);
06071          else
06072             ast_filecopy(msgfile, backup, NULL);
06073          already_recorded = 1;
06074 
06075          if (record_gain)
06076             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06077 
06078          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06079          if (record_gain)
06080             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06081 
06082          
06083          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06084             *duration = atoi(duration_str);
06085 
06086          if (prepend_duration) {
06087             struct ast_category *msg_cat;
06088             /* need enough space for a maximum-length message duration */
06089             char duration_buf[12];
06090 
06091             *duration += prepend_duration;
06092             msg_cat = ast_category_get(msg_cfg, "message");
06093             snprintf(duration_buf, 11, "%ld", *duration);
06094             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06095                config_text_file_save(textfile, msg_cfg, "app_voicemail");
06096             }
06097          }
06098 
06099 #endif
06100          break;
06101       case '2': 
06102          /* NULL out introfile so we know there is no intro! */
06103 #ifdef IMAP_STORAGE
06104          *vms->introfn = '\0';
06105 #endif
06106          cmd = 't';
06107          break;
06108       case '*':
06109          cmd = '*';
06110          break;
06111       default: 
06112          cmd = ast_play_and_wait(chan,"vm-forwardoptions");
06113             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06114          if (!cmd)
06115             cmd = ast_play_and_wait(chan,"vm-starmain");
06116             /* "press star to return to the main menu" */
06117          if (!cmd)
06118             cmd = ast_waitfordigit(chan,6000);
06119          if (!cmd)
06120             retries++;
06121          if (retries > 3)
06122             cmd = 't';
06123       }
06124    }
06125 
06126    if (msg_cfg)
06127       ast_config_destroy(msg_cfg);
06128    if (already_recorded)
06129       ast_filedelete(backup, NULL);
06130    if (prepend_duration)
06131       *duration = prepend_duration;
06132 
06133    if (cmd == 't' || cmd == 'S')
06134       cmd = 0;
06135    return cmd;
06136 }

static int vm_instructions ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 8152 of file app_voicemail.c.

References chan, ast_channel::language, vm_state::starting, vm_instructions_en(), and vm_instructions_tw().

Referenced by vm_execmain().

08153 {
08154    if (vms->starting && !strcasecmp(chan->language, "tw")) { /* CHINESE (Taiwan) syntax */
08155       return vm_instructions_tw(chan, vmu, vms, skipadvanced, in_urgent);
08156    } else {             /* Default to ENGLISH */
08157       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08158    }
08159 }

static int vm_instructions_en ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 8048 of file app_voicemail.c.

References ast_play_and_wait(), ast_test_flag, ast_waitfordigit(), chan, vm_state::curmsg, vm_state::deleted, vm_state::lastmsg, vm_state::newmessages, vm_state::repeats, vm_state::starting, vm_state::urgentmessages, VM_MESSAGEWRAP, vm_play_folder_name(), and vm_state::vmbox.

Referenced by vm_instructions(), and vm_instructions_tw().

08049 {
08050    int res = 0;
08051    /* Play instructions and wait for new command */
08052    while (!res) {
08053       if (vms->starting) {
08054          if (vms->lastmsg > -1) {
08055             if (skipadvanced)
08056                res = ast_play_and_wait(chan, "vm-onefor-full");
08057             else
08058                res = ast_play_and_wait(chan, "vm-onefor");
08059             if (!res)
08060                res = vm_play_folder_name(chan, vms->vmbox);
08061          }
08062          if (!res) {
08063             if (skipadvanced)
08064                res = ast_play_and_wait(chan, "vm-opts-full");
08065             else
08066                res = ast_play_and_wait(chan, "vm-opts");
08067          }
08068       } else {
08069          /* Added for additional help */
08070          if (skipadvanced) {
08071             res = ast_play_and_wait(chan, "vm-onefor-full");
08072             if (!res)
08073                res = vm_play_folder_name(chan, vms->vmbox);
08074             res = ast_play_and_wait(chan, "vm-opts-full");
08075          }
08076          /* Logic:
08077           * If the current message is not the first OR
08078           * if we're listening to the first new message and there are
08079           * also urgent messages, then prompt for navigation to the
08080           * previous message
08081           */
08082          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08083             res = ast_play_and_wait(chan, "vm-prev");
08084          }
08085          if (!res && !skipadvanced)
08086             res = ast_play_and_wait(chan, "vm-advopts");
08087          if (!res)
08088             res = ast_play_and_wait(chan, "vm-repeat");
08089          /* Logic:
08090           * If we're not listening to the last message OR
08091           * we're listening to the last urgent message and there are
08092           * also new non-urgent messages, then prompt for navigation
08093           * to the next message
08094           */
08095          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08096             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08097             res = ast_play_and_wait(chan, "vm-next");
08098          }
08099          if (!res) {
08100             if (!vms->deleted[vms->curmsg])
08101                res = ast_play_and_wait(chan, "vm-delete");
08102             else
08103                res = ast_play_and_wait(chan, "vm-undelete");
08104             if (!res)
08105                res = ast_play_and_wait(chan, "vm-toforward");
08106             if (!res)
08107                res = ast_play_and_wait(chan, "vm-savemessage");
08108          }
08109       }
08110       if (!res) {
08111          if (skipadvanced)
08112             res = ast_play_and_wait(chan, "vm-helpexit-full");
08113          else
08114             res = ast_play_and_wait(chan, "vm-helpexit");
08115       }
08116       if (!res)
08117          res = ast_waitfordigit(chan, 6000);
08118       if (!res) {
08119          vms->repeats++;
08120          if (vms->repeats > 2) {
08121             res = 't';
08122          }
08123       }
08124    }
08125    return res;
08126 }

static int vm_instructions_tw ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 8128 of file app_voicemail.c.

References ast_play_and_wait(), chan, vm_state::lastmsg, vm_state::starting, vm_instructions_en(), vm_play_folder_name(), and vm_state::vmbox.

Referenced by vm_instructions().

08129 {
08130    int res = 0;
08131    /* Play instructions and wait for new command */
08132    while (!res) {
08133       if (vms->lastmsg > -1) {
08134          res = ast_play_and_wait(chan, "vm-listen");
08135          if (!res)
08136             res = vm_play_folder_name(chan, vms->vmbox);
08137          if (!res)
08138             res = ast_play_and_wait(chan, "press");
08139          if (!res)
08140             res = ast_play_and_wait(chan, "digits/1");
08141       }
08142       if (!res)
08143          res = ast_play_and_wait(chan, "vm-opts");
08144       if (!res) {
08145          vms->starting = 0;
08146          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08147       }
08148    }
08149    return res;
08150 }

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

Definition at line 7996 of file app_voicemail.c.

References ast_fileexists(), ast_play_and_wait(), ast_test_flag, chan, ast_vm_user::context, DISPOSE, ast_channel::language, ast_vm_user::mailbox, RETRIEVE, vm_state::username, vm_intro_cz(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_he(), vm_intro_it(), vm_intro_multilang(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_pt(), vm_intro_pt_BR(), vm_intro_se(), vm_intro_tw(), and VM_TEMPGREETWARN.

Referenced by vm_execmain().

07997 {
07998    char prefile[256];
07999    
08000    /* Notify the user that the temp greeting is set and give them the option to remove it */
08001    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08002    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08003       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08004       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08005          ast_play_and_wait(chan, "vm-tempgreetactive");
08006       }
08007       DISPOSE(prefile, -1);
08008    }
08009 
08010    /* Play voicemail intro - syntax is different for different languages */
08011    if (!strcasecmp(chan->language, "de")) {  /* GERMAN syntax */
08012       return vm_intro_de(chan, vms);
08013    } else if (!strcasecmp(chan->language, "es")) { /* SPANISH syntax */
08014       return vm_intro_es(chan, vms);
08015    } else if (!strcasecmp(chan->language, "it")) { /* ITALIAN syntax */
08016       return vm_intro_it(chan, vms);
08017    } else if (!strcasecmp(chan->language, "fr")) { /* FRENCH syntax */
08018       return vm_intro_fr(chan, vms);
08019    } else if (!strcasecmp(chan->language, "nl")) { /* DUTCH syntax */
08020       return vm_intro_nl(chan, vms);
08021    } else if (!strcasecmp(chan->language, "pt")) { /* PORTUGUESE syntax */
08022       return vm_intro_pt(chan, vms);
08023    } else if (!strcasecmp(chan->language, "pt_BR")) { /* BRAZILIAN PORTUGUESE syntax */
08024       return vm_intro_pt_BR(chan, vms);
08025    } else if (!strcasecmp(chan->language, "cz")) { /* CZECH syntax */
08026       return vm_intro_cz(chan, vms);
08027    } else if (!strcasecmp(chan->language, "gr")) { /* GREEK syntax */
08028       return vm_intro_gr(chan, vms);
08029    } else if (!strcasecmp(chan->language, "pl")) { /* POLISH syntax */
08030       return vm_intro_pl(chan, vms);
08031    } else if (!strcasecmp(chan->language, "se")) { /* SWEDISH syntax */
08032       return vm_intro_se(chan, vms);
08033    } else if (!strcasecmp(chan->language, "no")) { /* NORWEGIAN syntax */
08034       return vm_intro_no(chan, vms);
08035    } else if (!strcasecmp(chan->language, "ru")) { /* RUSSIAN syntax */
08036       return vm_intro_multilang(chan, vms, "n");
08037    } else if (!strcasecmp(chan->language, "tw")) { /* CHINESE (Taiwan) syntax */
08038       return vm_intro_tw(chan, vms);
08039    } else if (!strcasecmp(chan->language, "ua")) { /* UKRAINIAN syntax */
08040       return vm_intro_multilang(chan, vms, "n");
08041    } else if (!strcasecmp(chan->language, "he")) { /* HEBREW syntax */
08042        return vm_intro_he(chan, vms);
08043    } else {             /* Default to ENGLISH */
08044       return vm_intro_en(chan, vms);
08045    }
08046 }

static int vm_intro_cz ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7897 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07898 {
07899    int res;
07900    res = ast_play_and_wait(chan, "vm-youhave");
07901    if (!res) {
07902       if (vms->newmessages) {
07903          if (vms->newmessages == 1) {
07904             res = ast_play_and_wait(chan, "digits/jednu");
07905          } else {
07906             res = say_and_wait(chan, vms->newmessages, chan->language);
07907          }
07908          if (!res) {
07909             if ((vms->newmessages == 1))
07910                res = ast_play_and_wait(chan, "vm-novou");
07911             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
07912                res = ast_play_and_wait(chan, "vm-nove");
07913             if (vms->newmessages > 4)
07914                res = ast_play_and_wait(chan, "vm-novych");
07915          }
07916          if (vms->oldmessages && !res)
07917             res = ast_play_and_wait(chan, "vm-and");
07918          else if (!res) {
07919             if ((vms->newmessages == 1))
07920                res = ast_play_and_wait(chan, "vm-zpravu");
07921             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
07922                res = ast_play_and_wait(chan, "vm-zpravy");
07923             if (vms->newmessages > 4)
07924                res = ast_play_and_wait(chan, "vm-zprav");
07925          }
07926       }
07927       if (!res && vms->oldmessages) {
07928          res = say_and_wait(chan, vms->oldmessages, chan->language);
07929          if (!res) {
07930             if ((vms->oldmessages == 1))
07931                res = ast_play_and_wait(chan, "vm-starou");
07932             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
07933                res = ast_play_and_wait(chan, "vm-stare");
07934             if (vms->oldmessages > 4)
07935                res = ast_play_and_wait(chan, "vm-starych");
07936          }
07937          if (!res) {
07938             if ((vms->oldmessages == 1))
07939                res = ast_play_and_wait(chan, "vm-zpravu");
07940             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
07941                res = ast_play_and_wait(chan, "vm-zpravy");
07942             if (vms->oldmessages > 4)
07943                res = ast_play_and_wait(chan, "vm-zprav");
07944          }
07945       }
07946       if (!res) {
07947          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07948             res = ast_play_and_wait(chan, "vm-no");
07949             if (!res)
07950                res = ast_play_and_wait(chan, "vm-zpravy");
07951          }
07952       }
07953    }
07954    return res;
07955 }

static int vm_intro_de ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7593 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07594 {
07595    /* Introduce messages they have */
07596    int res;
07597    res = ast_play_and_wait(chan, "vm-youhave");
07598    if (!res) {
07599       if (vms->newmessages) {
07600          if ((vms->newmessages == 1))
07601             res = ast_play_and_wait(chan, "digits/1F");
07602          else
07603             res = say_and_wait(chan, vms->newmessages, chan->language);
07604          if (!res)
07605             res = ast_play_and_wait(chan, "vm-INBOX");
07606          if (vms->oldmessages && !res)
07607             res = ast_play_and_wait(chan, "vm-and");
07608          else if (!res) {
07609             if ((vms->newmessages == 1))
07610                res = ast_play_and_wait(chan, "vm-message");
07611             else
07612                res = ast_play_and_wait(chan, "vm-messages");
07613          }
07614             
07615       }
07616       if (!res && vms->oldmessages) {
07617          if (vms->oldmessages == 1)
07618             res = ast_play_and_wait(chan, "digits/1F");
07619          else
07620             res = say_and_wait(chan, vms->oldmessages, chan->language);
07621          if (!res)
07622             res = ast_play_and_wait(chan, "vm-Old");
07623          if (!res) {
07624             if (vms->oldmessages == 1)
07625                res = ast_play_and_wait(chan, "vm-message");
07626             else
07627                res = ast_play_and_wait(chan, "vm-messages");
07628          }
07629       }
07630       if (!res) {
07631          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07632             res = ast_play_and_wait(chan, "vm-no");
07633             if (!res)
07634                res = ast_play_and_wait(chan, "vm-messages");
07635          }
07636       }
07637    }
07638    return res;
07639 }

static int vm_intro_en ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7342 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07343 {
07344    int res;
07345 
07346    /* Introduce messages they have */
07347    res = ast_play_and_wait(chan, "vm-youhave");
07348    if (!res) {
07349       if (vms->urgentmessages) {
07350          res = say_and_wait(chan, vms->urgentmessages, chan->language);
07351          if (!res)
07352             res = ast_play_and_wait(chan, "vm-Urgent");
07353          if ((vms->oldmessages || vms->newmessages) && !res) {
07354             res = ast_play_and_wait(chan, "vm-and");
07355          } else if (!res) {
07356             if ((vms->urgentmessages == 1))
07357                res = ast_play_and_wait(chan, "vm-message");
07358             else
07359                res = ast_play_and_wait(chan, "vm-messages");
07360          }
07361       }
07362       if (vms->newmessages) {
07363          res = say_and_wait(chan, vms->newmessages, chan->language);
07364          if (!res)
07365             res = ast_play_and_wait(chan, "vm-INBOX");
07366          if (vms->oldmessages && !res)
07367             res = ast_play_and_wait(chan, "vm-and");
07368          else if (!res) {
07369             if ((vms->newmessages == 1))
07370                res = ast_play_and_wait(chan, "vm-message");
07371             else
07372                res = ast_play_and_wait(chan, "vm-messages");
07373          }
07374             
07375       }
07376       if (!res && vms->oldmessages) {
07377          res = say_and_wait(chan, vms->oldmessages, chan->language);
07378          if (!res)
07379             res = ast_play_and_wait(chan, "vm-Old");
07380          if (!res) {
07381             if (vms->oldmessages == 1)
07382                res = ast_play_and_wait(chan, "vm-message");
07383             else
07384                res = ast_play_and_wait(chan, "vm-messages");
07385          }
07386       }
07387       if (!res) {
07388          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
07389             res = ast_play_and_wait(chan, "vm-no");
07390             if (!res)
07391                res = ast_play_and_wait(chan, "vm-messages");
07392          }
07393       }
07394    }
07395    return res;
07396 }

static int vm_intro_es ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7642 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07643 {
07644    /* Introduce messages they have */
07645    int res;
07646    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07647       res = ast_play_and_wait(chan, "vm-youhaveno");
07648       if (!res)
07649          res = ast_play_and_wait(chan, "vm-messages");
07650    } else {
07651       res = ast_play_and_wait(chan, "vm-youhave");
07652    }
07653    if (!res) {
07654       if (vms->newmessages) {
07655          if (!res) {
07656             if ((vms->newmessages == 1)) {
07657                res = ast_play_and_wait(chan, "digits/1M");
07658                if (!res)
07659                   res = ast_play_and_wait(chan, "vm-message");
07660                if (!res)
07661                   res = ast_play_and_wait(chan, "vm-INBOXs");
07662             } else {
07663                res = say_and_wait(chan, vms->newmessages, chan->language);
07664                if (!res)
07665                   res = ast_play_and_wait(chan, "vm-messages");
07666                if (!res)
07667                   res = ast_play_and_wait(chan, "vm-INBOX");
07668             }
07669          }
07670          if (vms->oldmessages && !res)
07671             res = ast_play_and_wait(chan, "vm-and");
07672       }
07673       if (vms->oldmessages) {
07674          if (!res) {
07675             if (vms->oldmessages == 1) {
07676                res = ast_play_and_wait(chan, "digits/1M");
07677                if (!res)
07678                   res = ast_play_and_wait(chan, "vm-message");
07679                if (!res)
07680                   res = ast_play_and_wait(chan, "vm-Olds");
07681             } else {
07682                res = say_and_wait(chan, vms->oldmessages, chan->language);
07683                if (!res)
07684                   res = ast_play_and_wait(chan, "vm-messages");
07685                if (!res)
07686                   res = ast_play_and_wait(chan, "vm-Old");
07687             }
07688          }
07689       }
07690    }
07691 return res;
07692 }

static int vm_intro_fr ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7740 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07741 {
07742    /* Introduce messages they have */
07743    int res;
07744    res = ast_play_and_wait(chan, "vm-youhave");
07745    if (!res) {
07746       if (vms->newmessages) {
07747          res = say_and_wait(chan, vms->newmessages, chan->language);
07748          if (!res)
07749             res = ast_play_and_wait(chan, "vm-INBOX");
07750          if (vms->oldmessages && !res)
07751             res = ast_play_and_wait(chan, "vm-and");
07752          else if (!res) {
07753             if ((vms->newmessages == 1))
07754                res = ast_play_and_wait(chan, "vm-message");
07755             else
07756                res = ast_play_and_wait(chan, "vm-messages");
07757          }
07758             
07759       }
07760       if (!res && vms->oldmessages) {
07761          res = say_and_wait(chan, vms->oldmessages, chan->language);
07762          if (!res)
07763             res = ast_play_and_wait(chan, "vm-Old");
07764          if (!res) {
07765             if (vms->oldmessages == 1)
07766                res = ast_play_and_wait(chan, "vm-message");
07767             else
07768                res = ast_play_and_wait(chan, "vm-messages");
07769          }
07770       }
07771       if (!res) {
07772          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07773             res = ast_play_and_wait(chan, "vm-no");
07774             if (!res)
07775                res = ast_play_and_wait(chan, "vm-messages");
07776          }
07777       }
07778    }
07779    return res;
07780 }

static int vm_intro_gr ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7141 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), chan, ast_channel::language, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_intro().

07142 {
07143    int res = 0;
07144 
07145    if (vms->newmessages) {
07146       res = ast_play_and_wait(chan, "vm-youhave");
07147       if (!res) 
07148          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07149       if (!res) {
07150          if ((vms->newmessages == 1)) {
07151             res = ast_play_and_wait(chan, "vm-INBOX");
07152             if (!res)
07153                res = ast_play_and_wait(chan, "vm-message");
07154          } else {
07155             res = ast_play_and_wait(chan, "vm-INBOXs");
07156             if (!res)
07157                res = ast_play_and_wait(chan, "vm-messages");
07158          }
07159       }
07160    } else if (vms->oldmessages){
07161       res = ast_play_and_wait(chan, "vm-youhave");
07162       if (!res)
07163          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07164       if ((vms->oldmessages == 1)){
07165          res = ast_play_and_wait(chan, "vm-Old");
07166          if (!res)
07167             res = ast_play_and_wait(chan, "vm-message");
07168       } else {
07169          res = ast_play_and_wait(chan, "vm-Olds");
07170          if (!res)
07171             res = ast_play_and_wait(chan, "vm-messages");
07172       }
07173    } else if (!vms->oldmessages && !vms->newmessages) 
07174       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07175    return res;
07176 }

static int vm_intro_he ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7275 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), chan, ast_channel::language, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_intro().

07276 {
07277    int res = 0;
07278 
07279    /* Introduce messages they have */
07280    if (!res) {
07281       if ((vms->newmessages) || (vms->oldmessages)) {
07282          res = ast_play_and_wait(chan, "vm-youhave");
07283       }
07284       /*
07285        * The word "shtei" refers to the number 2 in hebrew when performing a count
07286        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
07287        * an element, this is one of them.
07288        */
07289       if (vms->newmessages) {
07290          if (!res) {
07291             if (vms->newmessages == 1) {
07292                res = ast_play_and_wait(chan, "vm-INBOX1");
07293             } else {
07294                if (vms->newmessages == 2) {
07295                   res = ast_play_and_wait(chan, "vm-shtei");
07296                } else {
07297                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07298                }
07299                res = ast_play_and_wait(chan, "vm-INBOX");
07300             }
07301          }
07302          if (vms->oldmessages && !res) {
07303             res = ast_play_and_wait(chan, "vm-and");
07304             if (vms->oldmessages == 1) {
07305                res = ast_play_and_wait(chan, "vm-Old1");
07306             } else {
07307                if (vms->oldmessages == 2) {
07308                   res = ast_play_and_wait(chan, "vm-shtei");
07309                } else {
07310                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07311                }
07312                res = ast_play_and_wait(chan, "vm-Old");
07313             }
07314          }
07315       }
07316       if (!res && vms->oldmessages && !vms->newmessages) {
07317          if (!res) {
07318             if (vms->oldmessages == 1) {
07319                res = ast_play_and_wait(chan, "vm-Old1");
07320             } else {
07321                if (vms->oldmessages == 2) {
07322                   res = ast_play_and_wait(chan, "vm-shtei");
07323                } else {
07324                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
07325                }
07326                res = ast_play_and_wait(chan, "vm-Old");
07327             }
07328          }
07329       }
07330       if (!res) {
07331          if (!vms->oldmessages && !vms->newmessages) {
07332             if (!res) {
07333                res = ast_play_and_wait(chan, "vm-nomessages");
07334             }
07335          }
07336       }
07337    }
07338    return res;
07339 }

static int vm_intro_it ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7399 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07400 {
07401    /* Introduce messages they have */
07402    int res;
07403    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
07404       res = ast_play_and_wait(chan, "vm-no") ||
07405          ast_play_and_wait(chan, "vm-message");
07406    else
07407       res = ast_play_and_wait(chan, "vm-youhave");
07408    if (!res && vms->newmessages) {
07409       res = (vms->newmessages == 1) ?
07410          ast_play_and_wait(chan, "digits/un") ||
07411          ast_play_and_wait(chan, "vm-nuovo") ||
07412          ast_play_and_wait(chan, "vm-message") :
07413          /* 2 or more new messages */
07414          say_and_wait(chan, vms->newmessages, chan->language) ||
07415          ast_play_and_wait(chan, "vm-nuovi") ||
07416          ast_play_and_wait(chan, "vm-messages");
07417       if (!res && vms->oldmessages)
07418          res = ast_play_and_wait(chan, "vm-and");
07419    }
07420    if (!res && vms->oldmessages) {
07421       res = (vms->oldmessages == 1) ?
07422          ast_play_and_wait(chan, "digits/un") ||
07423          ast_play_and_wait(chan, "vm-vecchio") ||
07424          ast_play_and_wait(chan, "vm-message") :
07425          /* 2 or more old messages */
07426          say_and_wait(chan, vms->oldmessages, chan->language) ||
07427          ast_play_and_wait(chan, "vm-vecchi") ||
07428          ast_play_and_wait(chan, "vm-messages");
07429    }
07430    return res;
07431 }

static int vm_intro_multilang ( struct ast_channel chan,
struct vm_state vms,
const char  message_gender[] 
) [static]

Definition at line 7235 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_counted_adjective(), ast_say_counted_noun(), ast_say_number(), chan, ast_channel::language, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_intro().

07236 {
07237    int res;
07238    int lastnum = 0;
07239 
07240    res = ast_play_and_wait(chan, "vm-youhave");
07241 
07242    if (!res && vms->newmessages) {
07243       lastnum = vms->newmessages;
07244 
07245       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07246          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
07247       }
07248 
07249       if (!res && vms->oldmessages) {
07250          res = ast_play_and_wait(chan, "vm-and");
07251       }
07252    }
07253 
07254    if (!res && vms->oldmessages) {
07255       lastnum = vms->oldmessages;
07256 
07257       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07258          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
07259       }
07260    }
07261 
07262    if (!res) {
07263       if (lastnum == 0) {
07264          res = ast_play_and_wait(chan, "vm-no");
07265       }
07266       if (!res) {
07267          res = ast_say_counted_noun(chan, lastnum, "vm-message");
07268       }
07269    }
07270 
07271    return res;
07272 }

static int vm_intro_nl ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7783 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07784 {
07785    /* Introduce messages they have */
07786    int res;
07787    res = ast_play_and_wait(chan, "vm-youhave");
07788    if (!res) {
07789       if (vms->newmessages) {
07790          res = say_and_wait(chan, vms->newmessages, chan->language);
07791          if (!res) {
07792             if (vms->newmessages == 1)
07793                res = ast_play_and_wait(chan, "vm-INBOXs");
07794             else
07795                res = ast_play_and_wait(chan, "vm-INBOX");
07796          }
07797          if (vms->oldmessages && !res)
07798             res = ast_play_and_wait(chan, "vm-and");
07799          else if (!res) {
07800             if ((vms->newmessages == 1))
07801                res = ast_play_and_wait(chan, "vm-message");
07802             else
07803                res = ast_play_and_wait(chan, "vm-messages");
07804          }
07805             
07806       }
07807       if (!res && vms->oldmessages) {
07808          res = say_and_wait(chan, vms->oldmessages, chan->language);
07809          if (!res) {
07810             if (vms->oldmessages == 1)
07811                res = ast_play_and_wait(chan, "vm-Olds");
07812             else
07813                res = ast_play_and_wait(chan, "vm-Old");
07814          }
07815          if (!res) {
07816             if (vms->oldmessages == 1)
07817                res = ast_play_and_wait(chan, "vm-message");
07818             else
07819                res = ast_play_and_wait(chan, "vm-messages");
07820          }
07821       }
07822       if (!res) {
07823          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07824             res = ast_play_and_wait(chan, "vm-no");
07825             if (!res)
07826                res = ast_play_and_wait(chan, "vm-messages");
07827          }
07828       }
07829    }
07830    return res;
07831 }

static int vm_intro_no ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7549 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07550 {
07551    /* Introduce messages they have */
07552    int res;
07553 
07554    res = ast_play_and_wait(chan, "vm-youhave");
07555    if (res)
07556       return res;
07557 
07558    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07559       res = ast_play_and_wait(chan, "vm-no");
07560       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07561       return res;
07562    }
07563 
07564    if (vms->newmessages) {
07565       if ((vms->newmessages == 1)) {
07566          res = ast_play_and_wait(chan, "digits/1");
07567          res = res ? res : ast_play_and_wait(chan, "vm-ny");
07568          res = res ? res : ast_play_and_wait(chan, "vm-message");
07569       } else {
07570          res = say_and_wait(chan, vms->newmessages, chan->language);
07571          res = res ? res : ast_play_and_wait(chan, "vm-nye");
07572          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07573       }
07574       if (!res && vms->oldmessages)
07575          res = ast_play_and_wait(chan, "vm-and");
07576    }
07577    if (!res && vms->oldmessages) {
07578       if (vms->oldmessages == 1) {
07579          res = ast_play_and_wait(chan, "digits/1");
07580          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
07581          res = res ? res : ast_play_and_wait(chan, "vm-message");
07582       } else {
07583          res = say_and_wait(chan, vms->oldmessages, chan->language);
07584          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
07585          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07586       }
07587    }
07588 
07589    return res;
07590 }

static int vm_intro_pl ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7434 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, num, vm_state::oldmessages, and say_and_wait().

Referenced by vm_intro().

07435 {
07436    /* Introduce messages they have */
07437    int res;
07438    div_t num;
07439 
07440    if (!vms->oldmessages && !vms->newmessages) {
07441       res = ast_play_and_wait(chan, "vm-no");
07442       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07443       return res;
07444    } else {
07445       res = ast_play_and_wait(chan, "vm-youhave");
07446    }
07447 
07448    if (vms->newmessages) {
07449       num = div(vms->newmessages, 10);
07450       if (vms->newmessages == 1) {
07451          res = ast_play_and_wait(chan, "digits/1-a");
07452          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
07453          res = res ? res : ast_play_and_wait(chan, "vm-message");
07454       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07455          if (num.rem == 2) {
07456             if (!num.quot) {
07457                res = ast_play_and_wait(chan, "digits/2-ie");
07458             } else {
07459                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
07460                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07461             }
07462          } else {
07463             res = say_and_wait(chan, vms->newmessages, chan->language);
07464          }
07465          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
07466          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07467       } else {
07468          res = say_and_wait(chan, vms->newmessages, chan->language);
07469          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
07470          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07471       }
07472       if (!res && vms->oldmessages)
07473          res = ast_play_and_wait(chan, "vm-and");
07474    }
07475    if (!res && vms->oldmessages) {
07476       num = div(vms->oldmessages, 10);
07477       if (vms->oldmessages == 1) {
07478          res = ast_play_and_wait(chan, "digits/1-a");
07479          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
07480          res = res ? res : ast_play_and_wait(chan, "vm-message");
07481       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07482          if (num.rem == 2) {
07483             if (!num.quot) {
07484                res = ast_play_and_wait(chan, "digits/2-ie");
07485             } else {
07486                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
07487                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07488             }
07489          } else {
07490             res = say_and_wait(chan, vms->oldmessages, chan->language);
07491          }
07492          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
07493          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07494       } else {
07495          res = say_and_wait(chan, vms->oldmessages, chan->language);
07496          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
07497          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07498       }
07499    }
07500 
07501    return res;
07502 }

static int vm_intro_pt ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7834 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, and vm_state::urgentmessages.

Referenced by vm_intro().

07835 {
07836    /* Introduce messages they have */
07837    int res;
07838    res = ast_play_and_wait(chan, "vm-youhave");
07839    if (!res) {
07840       if (vms->newmessages) {
07841          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07842          if (!res) {
07843             if ((vms->newmessages == 1)) {
07844                res = ast_play_and_wait(chan, "vm-message");
07845                if (!res)
07846                   res = ast_play_and_wait(chan, "vm-INBOXs");
07847             } else {
07848                res = ast_play_and_wait(chan, "vm-messages");
07849                if (!res)
07850                   res = ast_play_and_wait(chan, "vm-INBOX");
07851             }
07852          }
07853          if (vms->oldmessages && !res)
07854             res = ast_play_and_wait(chan, "vm-and");
07855       }
07856       if (!res && vms->oldmessages) {
07857          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07858          if (!res) {
07859             if (vms->oldmessages == 1) {
07860                res = ast_play_and_wait(chan, "vm-message");
07861                if (!res)
07862                   res = ast_play_and_wait(chan, "vm-Olds");
07863             } else {
07864                res = ast_play_and_wait(chan, "vm-messages");
07865                if (!res)
07866                   res = ast_play_and_wait(chan, "vm-Old");
07867             }
07868          }
07869       }
07870       if (!res) {
07871          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07872             res = ast_play_and_wait(chan, "vm-no");
07873             if (!res)
07874                res = ast_play_and_wait(chan, "vm-messages");
07875          }
07876       }
07877    }
07878    return res;
07879 }

static int vm_intro_pt_BR ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7695 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, and vm_state::urgentmessages.

Referenced by vm_intro().

07695                                                                          {
07696    /* Introduce messages they have */
07697    int res;
07698    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07699       res = ast_play_and_wait(chan, "vm-nomessages");
07700       return res;
07701    } else {
07702       res = ast_play_and_wait(chan, "vm-youhave");
07703    }
07704    if (vms->newmessages) {
07705       if (!res)
07706          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07707       if ((vms->newmessages == 1)) {
07708          if (!res)
07709             res = ast_play_and_wait(chan, "vm-message");
07710          if (!res)
07711             res = ast_play_and_wait(chan, "vm-INBOXs");
07712       } else {
07713          if (!res)
07714             res = ast_play_and_wait(chan, "vm-messages");
07715          if (!res)
07716             res = ast_play_and_wait(chan, "vm-INBOX");
07717       }
07718       if (vms->oldmessages && !res)
07719          res = ast_play_and_wait(chan, "vm-and");
07720    }
07721    if (vms->oldmessages) {
07722       if (!res)
07723          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07724       if (vms->oldmessages == 1) {
07725          if (!res)
07726             res = ast_play_and_wait(chan, "vm-message");
07727          if (!res)
07728             res = ast_play_and_wait(chan, "vm-Olds");
07729       } else {
07730          if (!res)
07731             res = ast_play_and_wait(chan, "vm-messages");
07732          if (!res)
07733             res = ast_play_and_wait(chan, "vm-Old");
07734       }
07735    }
07736    return res;
07737 }

static int vm_intro_se ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7505 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

07506 {
07507    /* Introduce messages they have */
07508    int res;
07509 
07510    res = ast_play_and_wait(chan, "vm-youhave");
07511    if (res)
07512       return res;
07513 
07514    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07515       res = ast_play_and_wait(chan, "vm-no");
07516       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07517       return res;
07518    }
07519 
07520    if (vms->newmessages) {
07521       if ((vms->newmessages == 1)) {
07522          res = ast_play_and_wait(chan, "digits/ett");
07523          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
07524          res = res ? res : ast_play_and_wait(chan, "vm-message");
07525       } else {
07526          res = say_and_wait(chan, vms->newmessages, chan->language);
07527          res = res ? res : ast_play_and_wait(chan, "vm-nya");
07528          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07529       }
07530       if (!res && vms->oldmessages)
07531          res = ast_play_and_wait(chan, "vm-and");
07532    }
07533    if (!res && vms->oldmessages) {
07534       if (vms->oldmessages == 1) {
07535          res = ast_play_and_wait(chan, "digits/ett");
07536          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
07537          res = res ? res : ast_play_and_wait(chan, "vm-message");
07538       } else {
07539          res = say_and_wait(chan, vms->oldmessages, chan->language);
07540          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
07541          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07542       }
07543    }
07544 
07545    return res;
07546 }

static int vm_intro_tw ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 7958 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_state::newmessages, vm_state::oldmessages, and say_and_wait().

Referenced by vm_intro().

07959 {
07960    int res;
07961    /* Introduce messages they have */
07962    res = ast_play_and_wait(chan, "vm-you");
07963 
07964    if (!res && vms->newmessages) {
07965       res = ast_play_and_wait(chan, "vm-have");
07966       if (!res)
07967          res = say_and_wait(chan, vms->newmessages, chan->language);
07968       if (!res)
07969          res = ast_play_and_wait(chan, "vm-tong");
07970       if (!res)
07971          res = ast_play_and_wait(chan, "vm-INBOX");
07972       if (vms->oldmessages && !res)
07973          res = ast_play_and_wait(chan, "vm-and");
07974       else if (!res) 
07975          res = ast_play_and_wait(chan, "vm-messages");
07976    }
07977    if (!res && vms->oldmessages) {
07978       res = ast_play_and_wait(chan, "vm-have");
07979       if (!res)
07980          res = say_and_wait(chan, vms->oldmessages, chan->language);
07981       if (!res)
07982          res = ast_play_and_wait(chan, "vm-tong");
07983       if (!res)
07984          res = ast_play_and_wait(chan, "vm-Old");
07985       if (!res)
07986          res = ast_play_and_wait(chan, "vm-messages");
07987    }
07988    if (!res && !vms->oldmessages && !vms->newmessages) {
07989       res = ast_play_and_wait(chan, "vm-haveno");
07990       if (!res)
07991          res = ast_play_and_wait(chan, "vm-messages");
07992    }
07993    return res;
07994 }

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

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

Definition at line 2715 of file app_voicemail.c.

References ast_lock_path(), and AST_LOCK_TIMEOUT.

02716 {
02717    switch (ast_lock_path(path)) {
02718    case AST_LOCK_TIMEOUT:
02719       return -1;
02720    default:
02721       return 0;
02722    }
02723 }

static FILE* vm_mkftemp ( char *  template  )  [static]

Definition at line 1265 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01266 {
01267    FILE *p = NULL;
01268    int pfd = mkstemp(template);
01269    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01270    if (pfd > -1) {
01271       p = fdopen(pfd, "w+");
01272       if (!p) {
01273          close(pfd);
01274          pfd = -1;
01275       }
01276    }
01277    return p;
01278 }

static int vm_newuser ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
) [static]

Definition at line 8162 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_flag, chan, check_password(), play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, VM_FORCENAME, vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, and vm_reenterpassword.

Referenced by vm_execmain().

08163 {
08164    int cmd = 0;
08165    int duration = 0;
08166    int tries = 0;
08167    char newpassword[80] = "";
08168    char newpassword2[80] = "";
08169    char prefile[PATH_MAX] = "";
08170    unsigned char buf[256];
08171    int bytes=0;
08172 
08173    if (ast_adsi_available(chan)) {
08174       bytes += adsi_logo(buf + bytes);
08175       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08176       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08177       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08178       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08179       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08180    }
08181 
08182    /* First, have the user change their password 
08183       so they won't get here again */
08184    for (;;) {
08185       newpassword[1] = '\0';
08186       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08187       if (cmd == '#')
08188          newpassword[0] = '\0';
08189       if (cmd < 0 || cmd == 't' || cmd == '#')
08190          return cmd;
08191       cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
08192       if (cmd < 0 || cmd == 't' || cmd == '#')
08193          return cmd;
08194       cmd = check_password(vmu, newpassword); /* perform password validation */
08195       if (cmd != 0) {
08196          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08197          cmd = ast_play_and_wait(chan, vm_invalid_password);
08198       } else {
08199          newpassword2[1] = '\0';
08200          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08201          if (cmd == '#')
08202             newpassword2[0] = '\0';
08203          if (cmd < 0 || cmd == 't' || cmd == '#')
08204             return cmd;
08205          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
08206          if (cmd < 0 || cmd == 't' || cmd == '#')
08207             return cmd;
08208          if (!strcmp(newpassword, newpassword2))
08209             break;
08210          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08211          cmd = ast_play_and_wait(chan, vm_mismatch);
08212       }
08213       if (++tries == 3)
08214          return -1;
08215    }
08216    if (pwdchange & PWDCHANGE_INTERNAL)
08217       vm_change_password(vmu, newpassword);
08218    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08219       vm_change_password_shell(vmu, newpassword);
08220 
08221    ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08222    cmd = ast_play_and_wait(chan, vm_passchanged);
08223 
08224    /* If forcename is set, have the user record their name */  
08225    if (ast_test_flag(vmu, VM_FORCENAME)) {
08226       snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08227       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08228          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08229          if (cmd < 0 || cmd == 't' || cmd == '#')
08230             return cmd;
08231       }
08232    }
08233 
08234    /* If forcegreetings is set, have the user record their greetings */
08235    if (ast_test_flag(vmu, VM_FORCEGREET)) {
08236       snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08237       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08238          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08239          if (cmd < 0 || cmd == 't' || cmd == '#')
08240             return cmd;
08241       }
08242 
08243       snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08244       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08245          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08246          if (cmd < 0 || cmd == 't' || cmd == '#')
08247             return cmd;
08248       }
08249    }
08250 
08251    return cmd;
08252 }

static int vm_options ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
) [static]

Definition at line 8254 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_waitfordigit(), chan, check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::password, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_reenterpassword, and vm_tempgreeting().

Referenced by vm_execmain().

08255 {
08256    int cmd = 0;
08257    int retries = 0;
08258    int duration = 0;
08259    char newpassword[80] = "";
08260    char newpassword2[80] = "";
08261    char prefile[PATH_MAX] = "";
08262    unsigned char buf[256];
08263    int bytes=0;
08264 
08265    if (ast_adsi_available(chan)) {
08266       bytes += adsi_logo(buf + bytes);
08267       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
08268       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08269       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08270       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08271       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08272    }
08273    while ((cmd >= 0) && (cmd != 't')) {
08274       if (cmd)
08275          retries = 0;
08276       switch (cmd) {
08277       case '1': /* Record your unavailable message */
08278          snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08279          cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08280          break;
08281       case '2':  /* Record your busy message */
08282          snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08283          cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08284          break;
08285       case '3': /* Record greeting */
08286          snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08287          cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08288          break;
08289       case '4':  /* manage the temporary greeting */
08290          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
08291          break;
08292       case '5': /* change password */
08293          if (vmu->password[0] == '-') {
08294             cmd = ast_play_and_wait(chan, "vm-no");
08295             break;
08296          }
08297          newpassword[1] = '\0';
08298          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08299          if (cmd == '#')
08300             newpassword[0] = '\0';
08301          else {
08302             if (cmd < 0)
08303                break;
08304             if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
08305                break;
08306             }
08307          }
08308          cmd = check_password(vmu, newpassword); /* perform password validation */
08309          if (cmd != 0) {
08310             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08311             cmd = ast_play_and_wait(chan, vm_invalid_password);
08312             break;
08313          }
08314          newpassword2[1] = '\0';
08315          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08316          if (cmd == '#')
08317             newpassword2[0] = '\0';
08318          else {
08319             if (cmd < 0)
08320                break;
08321 
08322             if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#")) < 0) {
08323                break;
08324             }
08325          }
08326          if (strcmp(newpassword, newpassword2)) {
08327             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08328             cmd = ast_play_and_wait(chan, vm_mismatch);
08329             break;
08330          }
08331          if (pwdchange & PWDCHANGE_INTERNAL)
08332             vm_change_password(vmu, newpassword);
08333          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08334             vm_change_password_shell(vmu, newpassword);
08335 
08336          ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08337          cmd = ast_play_and_wait(chan, vm_passchanged);
08338          break;
08339       case '*': 
08340          cmd = 't';
08341          break;
08342       default: 
08343          cmd = 0;
08344          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08345          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08346          if (ast_fileexists(prefile, NULL, NULL)) {
08347             cmd = ast_play_and_wait(chan, "vm-tmpexists");
08348          }
08349          DISPOSE(prefile, -1);
08350          if (!cmd) {
08351             cmd = ast_play_and_wait(chan, "vm-options");
08352          }
08353          if (!cmd) {
08354             cmd = ast_waitfordigit(chan,6000);
08355          }
08356          if (!cmd) {
08357             retries++;
08358          }
08359          if (retries > 3) {
08360             cmd = 't';
08361          }
08362       }
08363    }
08364    if (cmd == 't')
08365       cmd = 0;
08366    return cmd;
08367 }

static int vm_play_folder_name ( struct ast_channel chan,
char *  mbox 
) [static]

Definition at line 7110 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, vm_play_folder_name_gr(), vm_play_folder_name_pl(), and vm_play_folder_name_ua().

Referenced by get_folder(), vm_execmain(), vm_instructions_en(), and vm_instructions_tw().

07111 {
07112    int cmd;
07113 
07114    if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) { /* Italian, Spanish, French or Portuguese syntax */
07115       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07116       return cmd ? cmd : ast_play_and_wait(chan, box);
07117    } else if (!strcasecmp(chan->language, "gr")){
07118       return vm_play_folder_name_gr(chan, box);
07119    } else if (!strcasecmp(chan->language, "pl")){
07120       return vm_play_folder_name_pl(chan, box);
07121    } else if (!strcasecmp(chan->language, "ua")){  /* Ukrainian syntax */
07122       return vm_play_folder_name_ua(chan, box);
07123    } else {  /* Default English */
07124       cmd = ast_play_and_wait(chan, box);
07125       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07126    }
07127 }

static int vm_play_folder_name_gr ( struct ast_channel chan,
char *  box 
) [static]

Definition at line 7063 of file app_voicemail.c.

References ast_play_and_wait(), and chan.

Referenced by vm_play_folder_name().

07064 {
07065    int cmd;
07066    char *buf;
07067 
07068    buf = alloca(strlen(box)+2); 
07069    strcpy(buf, box);
07070    strcat(buf,"s");
07071 
07072    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07073       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07074       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07075    } else {
07076       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07077       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07078    }
07079 }

static int vm_play_folder_name_pl ( struct ast_channel chan,
char *  box 
) [static]

Definition at line 7081 of file app_voicemail.c.

References ast_play_and_wait(), and chan.

Referenced by vm_play_folder_name().

07082 {
07083    int cmd;
07084 
07085    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07086       if (!strcasecmp(box, "vm-INBOX"))
07087          cmd = ast_play_and_wait(chan, "vm-new-e");
07088       else
07089          cmd = ast_play_and_wait(chan, "vm-old-e");
07090       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07091    } else {
07092       cmd = ast_play_and_wait(chan, "vm-messages");
07093       return cmd ? cmd : ast_play_and_wait(chan, box);
07094    }
07095 }

static int vm_play_folder_name_ua ( struct ast_channel chan,
char *  box 
) [static]

Definition at line 7097 of file app_voicemail.c.

References ast_play_and_wait(), and chan.

Referenced by vm_play_folder_name().

07098 {
07099    int cmd;
07100 
07101    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07102       cmd = ast_play_and_wait(chan, "vm-messages");
07103       return cmd ? cmd : ast_play_and_wait(chan, box);
07104    } else {
07105       cmd = ast_play_and_wait(chan, box);
07106       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07107    }
07108 }

static int vm_tempgreeting ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
) [static]

The handler for 'record a temporary greeting'.

Parameters:
chan 
vmu 
vms 
fmtc 
record_gain This is option 4 from the mailbox options menu. This function manages the following promptings: 1: play / record / review the temporary greeting. : invokes play_record_review(). 2: remove (delete) the temporary greeting. *: return to the main menu.
Returns:
zero on success, -1 on error.

Definition at line 8385 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available, ast_adsi_display, ast_adsi_set_line, ast_adsi_transmit_message, ast_adsi_voice_mode, ast_fileexists(), ast_play_and_wait(), ast_waitfordigit(), chan, ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

08386 {
08387    int cmd = 0;
08388    int retries = 0;
08389    int duration = 0;
08390    char prefile[PATH_MAX] = "";
08391    unsigned char buf[256];
08392    int bytes = 0;
08393 
08394    if (ast_adsi_available(chan)) {
08395       bytes += adsi_logo(buf + bytes);
08396       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
08397       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08398       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08399       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08400       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08401    }
08402 
08403    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08404    while ((cmd >= 0) && (cmd != 't')) {
08405       if (cmd)
08406          retries = 0;
08407       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08408       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
08409          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08410          cmd = 't';  
08411       } else {
08412          switch (cmd) {
08413          case '1':
08414             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08415             break;
08416          case '2':
08417             DELETE(prefile, -1, prefile, vmu);
08418             ast_play_and_wait(chan, "vm-tempremoved");
08419             cmd = 't';  
08420             break;
08421          case '*': 
08422             cmd = 't';
08423             break;
08424          default:
08425             cmd = ast_play_and_wait(chan,
08426                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
08427                   "vm-tempgreeting2" : "vm-tempgreeting");
08428             if (!cmd)
08429                cmd = ast_waitfordigit(chan,6000);
08430             if (!cmd)
08431                retries++;
08432             if (retries > 3)
08433                cmd = 't';
08434          }
08435       }
08436       DISPOSE(prefile, -1);
08437    }
08438    if (cmd == 't')
08439       cmd = 0;
08440    return cmd;
08441 }

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

Definition at line 9665 of file app_voicemail.c.

References ast_copy_string(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), chan, ast_vm_user::context, pbx_builtin_setvar_helper(), s, strsep(), and vm_authenticate().

Referenced by load_module().

09666 {
09667    char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
09668    struct ast_vm_user vmus;
09669    char *options = NULL;
09670    int silent = 0, skipuser = 0;
09671    int res = -1;
09672    
09673    if (s) {
09674       s = ast_strdupa(s);
09675       user = strsep(&s, ",");
09676       options = strsep(&s, ",");
09677       if (user) {
09678          s = user;
09679          user = strsep(&s, "@");
09680          context = strsep(&s, "");
09681          if (!ast_strlen_zero(user))
09682             skipuser++;
09683          ast_copy_string(mailbox, user, sizeof(mailbox));
09684       }
09685    }
09686 
09687    if (options) {
09688       silent = (strchr(options, 's')) != NULL;
09689    }
09690 
09691    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
09692       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
09693       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
09694       ast_play_and_wait(chan, "auth-thankyou");
09695       res = 0;
09696    }
09697 
09698    return res;
09699 }

static struct ast_tm* vmu_tm ( const struct ast_vm_user vmu,
struct ast_tm tm 
) [static]

fill in *tm for current time according to the proper timezone, if any. Return tm so it can be used as a function argument.

Definition at line 3803 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_strlen_zero(), ast_tvnow(), vm_zone::name, vm_zone::timezone, and ast_vm_user::zonetag.

Referenced by make_email_file(), and sendpage().

03804 {
03805    const struct vm_zone *z = NULL;
03806    struct timeval t = ast_tvnow();
03807 
03808    /* Does this user have a timezone specified? */
03809    if (!ast_strlen_zero(vmu->zonetag)) {
03810       /* Find the zone in the list */
03811       AST_LIST_LOCK(&zones);
03812       AST_LIST_TRAVERSE(&zones, z, list) {
03813          if (!strcmp(z->name, vmu->zonetag))
03814             break;
03815       }
03816       AST_LIST_UNLOCK(&zones);
03817    }
03818    ast_localtime(&t, tm, z ? z->timezone : NULL);
03819    return tm;
03820 }

static int wait_file ( struct ast_channel chan,
struct vm_state vms,
char *  file 
) [static]

Definition at line 6521 of file app_voicemail.c.

References ast_control_streamfile(), chan, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, and listen_control_stop_key.

static int wait_file2 ( struct ast_channel chan,
struct vm_state vms,
char *  file 
) [static]

Definition at line 6513 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_log(), ast_stream_and_wait(), and chan.

Referenced by play_message(), play_message_callerid(), and play_message_duration().

06514 {
06515    int res;
06516    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
06517       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
06518    return res;
06519 }


Variable Documentation

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

Definition at line 11463 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 497 of file app_voicemail.c.

unsigned char adsifdn[4] = "\x00\x00\x00\x0F" [static]

Definition at line 678 of file app_voicemail.c.

Referenced by adsi_begin(), adsi_load_vmail(), and load_config().

unsigned char adsisec[4] = "\x9B\xDB\xF7\xAC" [static]

Definition at line 679 of file app_voicemail.c.

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 680 of file app_voicemail.c.

Referenced by adsi_begin(), adsi_load_vmail(), and load_config().

char* app = "VoiceMail" [static]

Definition at line 571 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 574 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 576 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 577 of file app_voicemail.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 11463 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 664 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char charset[32] = "ISO-8859-1" [static]

Definition at line 676 of file app_voicemail.c.

Referenced by encode_mime_str(), load_config(), make_email_file(), and tds_load_module().

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 667 of file app_voicemail.c.

Referenced by load_config(), and play_message_callerid().

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

 {
   { .handler =  handle_voicemail_show_users , .summary =  "List defined voicemail boxes" ,__VA_ARGS__ },
   { .handler =  handle_voicemail_show_zones , .summary =  "List zone message formats" ,__VA_ARGS__ },
   { .handler =  handle_voicemail_reload , .summary =  "Reload voicemail configuration" ,__VA_ARGS__ },
}

Definition at line 9897 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* descrip_vm [static]

Definition at line 501 of file app_voicemail.c.

char* descrip_vm_box_exists [static]

Definition at line 548 of file app_voicemail.c.

char* descrip_vmain [static]

Definition at line 530 of file app_voicemail.c.

char* descrip_vmauthenticate [static]

Definition at line 560 of file app_voicemail.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 663 of file app_voicemail.c.

Referenced by dial_exec_full(), directory_exec(), load_config(), populate_defaults(), ring_entry(), and wait_for_answer().

char* emailbody = NULL [static]

Definition at line 670 of file app_voicemail.c.

Referenced by load_config(), make_email_file(), and message_template_parse_emailbody().

char emaildateformat[32] = "%A, %B %d, %Y at %r" [static]

Definition at line 681 of file app_voicemail.c.

Referenced by load_config(), make_email_file(), and prep_email_sub_vars().

char* emailsubject = NULL [static]

Definition at line 671 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 665 of file app_voicemail.c.

Referenced by common_exec(), conf_run(), load_config(), and populate_defaults().

char ext_pass_check_cmd[128] [static]

Definition at line 477 of file app_voicemail.c.

char ext_pass_cmd[128] [static]

Definition at line 476 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 588 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 674 of file app_voicemail.c.

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

struct ast_flags globalflags = {0} [static]

Definition at line 659 of file app_voicemail.c.

char listen_control_forward_key[12] [static]

Definition at line 645 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 647 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 648 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 646 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 649 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

struct ast_custom_function mailbox_exists_acf [static]

Definition at line 9655 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char mailcmd[160] [static]

Definition at line 587 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 584 of file app_voicemail.c.

int maxgreet [static]

Definition at line 594 of file app_voicemail.c.

int maxlogins [static]

Definition at line 596 of file app_voicemail.c.

int maxmsg [static]

Definition at line 583 of file app_voicemail.c.

int maxsilence [static]

Definition at line 582 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 597 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 614 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

struct ast_taskprocessor* mwi_subscription_tps [static]

Definition at line 640 of file app_voicemail.c.

Referenced by load_module(), mwi_sub_event_cb(), mwi_unsub_event_cb(), and unload_module().

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 616 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

int my_umask [static]

Definition at line 479 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 672 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 675 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 673 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 609 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 604 of file app_voicemail.c.

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

Definition at line 608 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

unsigned int poll_mailboxes [static]

Poll mailboxes for changes since there is something external to app_voicemail that may change them.

Definition at line 601 of file app_voicemail.c.

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 610 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 611 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 483 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 661 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char serveremail[80] [static]

Definition at line 586 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 585 of file app_voicemail.c.

int skipms [static]

Definition at line 595 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 589 of file app_voicemail.c.

Referenced by load_config(), and run_externnotify().

char* synopsis_vm = "Leave a Voicemail message" [static]

Definition at line 499 of file app_voicemail.c.

char* synopsis_vm_box_exists [static]

Initial value:

"Check to see if Voicemail mailbox exists"

Definition at line 545 of file app_voicemail.c.

char* synopsis_vmain = "Check Voicemail messages" [static]

Definition at line 528 of file app_voicemail.c.

char* synopsis_vmauthenticate = "Authenticate with Voicemail passwords" [static]

Definition at line 558 of file app_voicemail.c.

char userscontext[AST_MAX_EXTENSION] = "default" [static]

Definition at line 495 of file app_voicemail.c.

Referenced by pbx_load_users().

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 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }} [static]

Definition at line 274 of file app_voicemail.c.

Referenced by vm_exec(), and vm_execmain().

enum { ... } vm_box

char vm_invalid_password[80] = "vm-invalid-password" [static]

Definition at line 657 of file app_voicemail.c.

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

char vm_mismatch[80] = "vm-mismatch" [static]

Definition at line 656 of file app_voicemail.c.

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

char vm_newpassword[80] = "vm-newpassword" [static]

Definition at line 653 of file app_voicemail.c.

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

enum { ... } vm_option_args

enum { ... } vm_option_flags

char vm_passchanged[80] = "vm-passchanged" [static]

Definition at line 654 of file app_voicemail.c.

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

char vm_password[80] = "vm-password" [static]

Definition at line 652 of file app_voicemail.c.

Referenced by load_config(), and vm_authenticate().

char vm_reenterpassword[80] = "vm-reenterpassword" [static]

Definition at line 655 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 474 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 590 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 593 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 592 of file app_voicemail.c.

double volgain [static]

Definition at line 591 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 581 of file app_voicemail.c.

Referenced by build_peer().


Generated on Fri Jul 24 00:41:16 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7