Wed Mar 3 22:44:07 2010

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"
Include dependency graph for app_voicemail.c:

Go to the source code of this file.

Data Structures

struct  ast_vm_user
struct  baseio
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  mwi_sub
 An MWI subscription. More...
struct  mwi_sub_task
struct  mwi_subs
struct  users
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_zh (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_zh (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_zh (struct ast_channel *chan, struct vm_state *vms)
static int vm_lock_path (const char *path)
 Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.
static FILE * vm_mkftemp (char *template)
static int vm_newuser (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_play_folder_name (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_gr (struct ast_channel *chan, char *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 = "DAHDI Telephony w/PRI & SS7" , .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 190 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 213 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 214 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 187 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 183 of file app_voicemail.c.

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

Definition at line 476 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 195 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 197 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 198 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 196 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 199 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 613 of file app_voicemail.c.

Referenced by load_config().

#define DELETE ( a,
b,
c,
 )     (vm_delete(c))
#define DISPOSE ( a,
 ) 
#define ENDL   "\n"
#define eol   "\r\n"

Definition at line 215 of file app_voicemail.c.

Referenced by base_encode(), and ochar().

#define ERROR_LOCK_PATH   -100

Definition at line 239 of file app_voicemail.c.

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

Definition at line 474 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"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"

Definition at line 206 of file app_voicemail.c.

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

#define MAX_DATETIME_FORMAT   512

Definition at line 217 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 218 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 208 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

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

Referenced by load_config().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 489 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

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

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

#define RETRIEVE ( a,
b,
c,
 ) 
#define SENDMAIL   "/usr/sbin/sendmail -t"

Definition at line 204 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 181 of file app_voicemail.c.

Referenced by run_externnotify().

#define STORE ( a,
b,
c,
d,
e,
f,
g,
h,
i,
 ) 
#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 498 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 200 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 233 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 231 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 232 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 230 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 224 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 228 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 227 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 238 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 237 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 236 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 221 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 229 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 220 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 222 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 225 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 234 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 226 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 223 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 235 of file app_voicemail.c.

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

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 416 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 189 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 185 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

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

00242      {
00243    NEW_FOLDER,
00244    OLD_FOLDER,
00245    WORK_FOLDER,
00246    FAMILY_FOLDER,
00247    FRIENDS_FOLDER,
00248    GREETINGS_FOLDER
00249 } 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 251 of file app_voicemail.c.

00251      {
00252    OPT_SILENT =           (1 << 0),
00253    OPT_BUSY_GREETING =    (1 << 1),
00254    OPT_UNAVAIL_GREETING = (1 << 2),
00255    OPT_RECORDGAIN =       (1 << 3),
00256    OPT_PREPEND_MAILBOX =  (1 << 4),
00257    OPT_AUTOPLAY =         (1 << 6),
00258    OPT_DTMFEXIT =         (1 << 7),
00259    OPT_MESSAGE_Urgent =   (1 << 8),
00260    OPT_MESSAGE_PRIORITY = (1 << 9)
00261 } vm_option_flags;

anonymous enum
Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 263 of file app_voicemail.c.

00263      {
00264    OPT_ARG_RECORDGAIN = 0,
00265    OPT_ARG_PLAYFOLDER = 1,
00266    OPT_ARG_DTMFEXIT   = 2,
00267    /* This *must* be the last value in this enum! */
00268    OPT_ARG_ARRAY_SIZE = 3,
00269 } vm_option_args;


Function Documentation

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

Definition at line 4685 of file app_voicemail.c.

References ast_strlen_zero().

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

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

static void __reg_module ( void   )  [static]

Definition at line 11488 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

09660 {
09661    struct ast_vm_user svm;
09662    AST_DECLARE_APP_ARGS(arg,
09663       AST_APP_ARG(mbox);
09664       AST_APP_ARG(context);
09665    );
09666 
09667    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
09668 
09669    if (ast_strlen_zero(arg.mbox)) {
09670       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
09671       return -1;
09672    }
09673 
09674    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
09675    return 0;
09676 }

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 4184 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().

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

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

Definition at line 5606 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

05607 {
05608    int x;
05609    if (!ast_adsi_available(chan))
05610       return;
05611    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05612    if (x < 0)
05613       return;
05614    if (!x) {
05615       if (adsi_load_vmail(chan, useadsi)) {
05616          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
05617          return;
05618       }
05619    } else
05620       *useadsi = 1;
05621 }

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

Definition at line 5795 of file app_voicemail.c.

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

Referenced by vm_execmain().

05796 {
05797    int bytes=0;
05798    unsigned char buf[256];
05799    unsigned char keys[8];
05800 
05801    int x;
05802 
05803    if (!ast_adsi_available(chan))
05804       return;
05805 
05806    /* New meaning for keys */
05807    for (x=0;x<5;x++)
05808       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05809 
05810    keys[6] = 0x0;
05811    keys[7] = 0x0;
05812 
05813    if (!vms->curmsg) {
05814       /* No prev key, provide "Folder" instead */
05815       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05816    }
05817    if (vms->curmsg >= vms->lastmsg) {
05818       /* If last message ... */
05819       if (vms->curmsg) {
05820          /* but not only message, provide "Folder" instead */
05821          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05822       } else {
05823          /* Otherwise if only message, leave blank */
05824          keys[3] = 1;
05825       }
05826    }
05827 
05828    /* If deleted, show "undeleted" */
05829    if (vms->deleted[vms->curmsg]) 
05830       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05831 
05832    /* Except "Exit" */
05833    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05834    bytes += ast_adsi_set_keys(buf + bytes, keys);
05835    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05836 
05837    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05838 }

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

Definition at line 5671 of file app_voicemail.c.

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

Referenced by vm_execmain().

05672 {
05673    unsigned char buf[256];
05674    int bytes=0;
05675    unsigned char keys[8];
05676    int x,y;
05677 
05678    if (!ast_adsi_available(chan))
05679       return;
05680 
05681    for (x=0;x<5;x++) {
05682       y = ADSI_KEY_APPS + 12 + start + x;
05683       if (y > ADSI_KEY_APPS + 12 + 4)
05684          y = 0;
05685       keys[x] = ADSI_KEY_SKT | y;
05686    }
05687    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05688    keys[6] = 0;
05689    keys[7] = 0;
05690 
05691    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05692    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05693    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05694    bytes += ast_adsi_set_keys(buf + bytes, keys);
05695    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05696 
05697    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05698 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 5943 of file app_voicemail.c.

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

Referenced by vm_execmain().

05944 {
05945    unsigned char buf[256];
05946    int bytes=0;
05947 
05948    if (!ast_adsi_available(chan))
05949       return;
05950    bytes += adsi_logo(buf + bytes);
05951    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
05952    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
05953    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05954    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05955 
05956    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05957 }

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

Definition at line 5477 of file app_voicemail.c.

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

Referenced by adsi_begin().

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

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 5623 of file app_voicemail.c.

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

Referenced by vm_authenticate().

05624 {
05625    unsigned char buf[256];
05626    int bytes=0;
05627    unsigned char keys[8];
05628    int x;
05629    if (!ast_adsi_available(chan))
05630       return;
05631 
05632    for (x=0;x<8;x++)
05633       keys[x] = 0;
05634    /* Set one key for next */
05635    keys[3] = ADSI_KEY_APPS + 3;
05636 
05637    bytes += adsi_logo(buf + bytes);
05638    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05639    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
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, "Mailbox: ******", "");
05642    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05643    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05644    bytes += ast_adsi_set_keys(buf + bytes, keys);
05645    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05646    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05647 }

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

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

05470 {
05471    int bytes = 0;
05472    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
05473    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
05474    return bytes;
05475 }

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

Definition at line 5700 of file app_voicemail.c.

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

Referenced by play_message(), and vm_execmain().

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

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 5649 of file app_voicemail.c.

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

Referenced by vm_authenticate().

05650 {
05651    unsigned char buf[256];
05652    int bytes=0;
05653    unsigned char keys[8];
05654    int x;
05655    if (!ast_adsi_available(chan))
05656       return;
05657 
05658    for (x=0;x<8;x++)
05659       keys[x] = 0;
05660    /* Set one key for next */
05661    keys[3] = ADSI_KEY_APPS + 3;
05662 
05663    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05664    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05665    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05666    bytes += ast_adsi_set_keys(buf + bytes, keys);
05667    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05668    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05669 }

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

Definition at line 5840 of file app_voicemail.c.

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

Referenced by vm_execmain().

05841 {
05842    unsigned char buf[256] = "";
05843    char buf1[256] = "", buf2[256] = "";
05844    int bytes=0;
05845    unsigned char keys[8];
05846    int x;
05847 
05848    char *newm = (vms->newmessages == 1) ? "message" : "messages";
05849    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
05850    if (!ast_adsi_available(chan))
05851       return;
05852    if (vms->newmessages) {
05853       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
05854       if (vms->oldmessages) {
05855          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
05856          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
05857       } else {
05858          snprintf(buf2, sizeof(buf2), "%s.", newm);
05859       }
05860    } else if (vms->oldmessages) {
05861       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
05862       snprintf(buf2, sizeof(buf2), "%s.", oldm);
05863    } else {
05864       strcpy(buf1, "You have no messages.");
05865       buf2[0] = ' ';
05866       buf2[1] = '\0';
05867    }
05868    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05869    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05870    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05871 
05872    for (x=0;x<6;x++)
05873       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05874    keys[6] = 0;
05875    keys[7] = 0;
05876 
05877    /* Don't let them listen if there are none */
05878    if (vms->lastmsg < 0)
05879       keys[0] = 1;
05880    bytes += ast_adsi_set_keys(buf + bytes, keys);
05881 
05882    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05883 
05884    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05885 }

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

Definition at line 5887 of file app_voicemail.c.

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

Referenced by vm_execmain().

05888 {
05889    unsigned char buf[256] = "";
05890    char buf1[256] = "", buf2[256] = "";
05891    int bytes=0;
05892    unsigned char keys[8];
05893    int x;
05894 
05895    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
05896 
05897    if (!ast_adsi_available(chan))
05898       return;
05899 
05900    /* Original command keys */
05901    for (x=0;x<6;x++)
05902       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05903 
05904    keys[6] = 0;
05905    keys[7] = 0;
05906 
05907    if ((vms->lastmsg + 1) < 1)
05908       keys[0] = 0;
05909 
05910    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
05911       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
05912 
05913    if (vms->lastmsg + 1)
05914       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
05915    else
05916       strcpy(buf2, "no messages.");
05917    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05918    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05919    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
05920    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05921    bytes += ast_adsi_set_keys(buf + bytes, keys);
05922 
05923    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05924 
05925    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05926    
05927 }

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

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

Referenced by vm_execmain().

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

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

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

09580 {
09581    /* Assumes lock is already held */
09582    char *tmp;
09583    char *stringp;
09584    char *s;
09585    struct ast_vm_user *vmu;
09586    char *mailbox_full;
09587    int new = 0, old = 0, urgent = 0;
09588 
09589    tmp = ast_strdupa(data);
09590 
09591    if (!(vmu = find_or_create(context, box)))
09592       return -1;
09593    
09594    populate_defaults(vmu);
09595 
09596    stringp = tmp;
09597    if ((s = strsep(&stringp, ","))) 
09598       ast_copy_string(vmu->password, s, sizeof(vmu->password));
09599    if (stringp && (s = strsep(&stringp, ","))) 
09600       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
09601    if (stringp && (s = strsep(&stringp, ","))) 
09602       ast_copy_string(vmu->email, s, sizeof(vmu->email));
09603    if (stringp && (s = strsep(&stringp, ","))) 
09604       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
09605    if (stringp && (s = strsep(&stringp, ","))) 
09606       apply_options(vmu, s);
09607 
09608    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
09609    strcpy(mailbox_full, box);
09610    strcat(mailbox_full, "@");
09611    strcat(mailbox_full, context);
09612 
09613    inboxcount2(mailbox_full, &urgent, &new, &old);
09614    queue_mwi_event(mailbox_full, urgent, new, old);
09615 
09616    return 0;
09617 }

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 764 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().

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

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

Destructively Parse options and apply.

Definition at line 974 of file app_voicemail.c.

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

Referenced by append_mailbox(), and apply_option().

00975 {  
00976    char *stringp;
00977    char *s;
00978    char *var, *value;
00979    stringp = ast_strdupa(options);
00980    while ((s = strsep(&stringp, "|"))) {
00981       value = s;
00982       if ((var = strsep(&value, "=")) && value) {
00983          apply_option(vmu, var, value);
00984       }
00985    }  
00986 }

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

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

Referenced by find_user_realtime(), and load_config().

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

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

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

Referenced by add_email_attachment().

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

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 952 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().

00953 {
00954    int res;
00955    if (!ast_strlen_zero(vmu->uniqueid)) {
00956       if (strlen(password) > 10) {
00957          ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
00958       }
00959       res = ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, SENTINEL);
00960       if (res > 0) {
00961          ast_copy_string(vmu->password, password, sizeof(vmu->password));
00962          res = 0;
00963       } else if (!res) {
00964          res = -1;
00965       }
00966       return res;
00967    }
00968    return -1;
00969 }

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

Referenced by make_email_file().

03838 {
03839    for (; *str; str++) {
03840       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
03841          return 1;
03842       }
03843    }
03844    return 0;
03845 }

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 914 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 vm_newuser(), and vm_options().

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

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

Definition at line 6996 of file app_voicemail.c.

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

Referenced by vm_execmain().

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

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

Definition at line 9763 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

09764 {
09765    int which = 0;
09766    int wordlen;
09767    struct ast_vm_user *vmu;
09768    const char *context = "";
09769 
09770    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
09771    if (pos > 4)
09772       return NULL;
09773    if (pos == 3)
09774       return (state == 0) ? ast_strdup("for") : NULL;
09775    wordlen = strlen(word);
09776    AST_LIST_TRAVERSE(&users, vmu, list) {
09777       if (!strncasecmp(word, vmu->context, wordlen)) {
09778          if (context && strcmp(context, vmu->context) && ++which > state)
09779             return ast_strdup(vmu->context);
09780          /* ignore repeated contexts ? */
09781          context = vmu->context;
09782       }
09783    }
09784    return NULL;
09785 }

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

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

Referenced by copy_plain_file().

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

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

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), 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, 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().

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

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

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

Referenced by copy_message().

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

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 3384 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().

03385 {
03386 
03387    int vmcount = 0;
03388    DIR *vmdir = NULL;
03389    struct dirent *vment = NULL;
03390 
03391    if (vm_lock_path(dir))
03392       return ERROR_LOCK_PATH;
03393 
03394    if ((vmdir = opendir(dir))) {
03395       while ((vment = readdir(vmdir))) {
03396          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03397             vmcount++;
03398          }
03399       }
03400       closedir(vmdir);
03401    }
03402    ast_unlock_path(dir);
03403    
03404    return vmcount;
03405 }

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

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

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

01296 {
01297    mode_t   mode = VOICEMAIL_DIR_MODE;
01298    int res;
01299 
01300    make_dir(dest, len, context, ext, folder);
01301    if ((res = ast_mkdir(dest, mode))) {
01302       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01303       return -1;
01304    }
01305    return 0;
01306 }

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

Definition at line 10990 of file app_voicemail.c.

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

Referenced by advanced_options(), and vm_execmain().

10991 {
10992    int cmd = 0;
10993    char destination[80] = "";
10994    int retries = 0;
10995 
10996    if (!num) {
10997       ast_verb(3, "Destination number will be entered manually\n");
10998       while (retries < 3 && cmd != 't') {
10999          destination[1] = '\0';
11000          destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
11001          if (!cmd)
11002             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
11003          if (!cmd)
11004             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
11005          if (!cmd) {
11006             cmd = ast_waitfordigit(chan, 6000);
11007             if (cmd)
11008                destination[0] = cmd;
11009          }
11010          if (!cmd) {
11011             retries++;
11012          } else {
11013 
11014             if (cmd < 0)
11015                return 0;
11016             if (cmd == '*') {
11017                ast_verb(3, "User hit '*' to cancel outgoing call\n");
11018                return 0;
11019             }
11020             if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0) 
11021                retries++;
11022             else
11023                cmd = 't';
11024          }
11025       }
11026       if (retries >= 3) {
11027          return 0;
11028       }
11029       
11030    } else {
11031       if (option_verbose > 2)
11032          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
11033       ast_copy_string(destination, num, sizeof(destination));
11034    }
11035 
11036    if (!ast_strlen_zero(destination)) {
11037       if (destination[strlen(destination) -1 ] == '*')
11038          return 0; 
11039       if (option_verbose > 2)
11040          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
11041       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
11042       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
11043       chan->priority = 0;
11044       return 9;
11045    }
11046    return 0;
11047 }

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

References charset.

Referenced by make_email_file().

03864 {
03865    char tmp[80];
03866    int first_section = 1;
03867    size_t endlen = 0, tmplen = 0;
03868    *end = '\0';
03869 
03870    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03871    for (; *start; start++) {
03872       int need_encoding = 0;
03873       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
03874          need_encoding = 1;
03875       }
03876       if ((first_section && need_encoding && preamble + tmplen > 70) ||
03877          (first_section && !need_encoding && preamble + tmplen > 72) ||
03878          (!first_section && need_encoding && tmplen > 70) ||
03879          (!first_section && !need_encoding && tmplen > 72)) {
03880          /* Start new line */
03881          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
03882          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03883          first_section = 0;
03884       }
03885       if (need_encoding && *start == ' ') {
03886          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
03887       } else if (need_encoding) {
03888          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
03889       } else {
03890          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
03891       }
03892    }
03893    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
03894    return end;
03895 }

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

Definition at line 9547 of file app_voicemail.c.

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

Referenced by append_mailbox(), and load_config().

09548 {
09549    struct ast_vm_user *vmu;
09550 
09551    AST_LIST_TRAVERSE(&users, vmu, list) {
09552       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
09553          if (strcasecmp(vmu->context, context)) {
09554             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
09555                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
09556                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
09557                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
09558          }
09559          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
09560          return NULL;
09561       }
09562       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
09563          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
09564          return NULL;
09565       }
09566    }
09567    
09568    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
09569       return NULL;
09570    
09571    ast_copy_string(vmu->context, context, sizeof(vmu->context));
09572    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
09573 
09574    AST_LIST_INSERT_TAIL(&users, vmu, list);
09575    
09576    return vmu;
09577 }

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

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

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

Referenced by acf_mailbox_exists(), advanced_options(), forward_message(), leave_voicemail(), vm_authenticate(), vm_box_exists(), and vm_execmain().

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

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

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

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

Referenced by find_user().

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

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):

  • allow the leaving of a message for ourselves. (Will not allow us to forward a message to ourselves, when is_new_message == 0).
  • attempt to determine the context and and mailbox, and then invoke leave_message() function to record and store the message.

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

  • retreives the current message to be forwarded
  • copies the original message to a temporary file, so updates to the envelope can be done.
  • determines the target mailbox and folders
  • copies the message into the target mailbox, using copy_message() or by generating the message into an email attachment if using imap folders.
Returns:
zero on success, -1 on error.

Definition at line 6297 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_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), vm_state::fn, free_user(), globalflags, leave_voicemail(), LOG_NOTICE, ast_vm_user::mailbox, pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), s, S_OR, sendmail(), STORE, strsep(), vm_state::username, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1331 of file app_voicemail.c.

References ast_free, ast_test_flag, and VM_ALLOCED.

Referenced by forward_message(), free_vm_users(), leave_voicemail(), and vm_execmain().

01332 {
01333    if (ast_test_flag(vmu, VM_ALLOCED))
01334       ast_free(vmu);
01335 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 10215 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10216 {
10217    struct ast_vm_user *current;
10218    AST_LIST_LOCK(&users);
10219    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
10220       ast_set_flag(current, VM_ALLOCED);
10221       free_user(current);
10222    }
10223    AST_LIST_UNLOCK(&users);
10224 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 10227 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10228 {
10229    struct vm_zone *zcur;
10230    AST_LIST_LOCK(&zones);
10231    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
10232       free_zone(zcur);
10233    AST_LIST_UNLOCK(&zones);
10234 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4404 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

04405 {
04406    ast_free(z);
04407 }

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

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

Referenced by leave_voicemail().

04361 {
04362    struct ast_tm tm;
04363    struct timeval t = ast_tvnow();
04364    
04365    ast_localtime(&t, &tm, "UTC");
04366 
04367    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04368 }

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

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

Referenced by get_folder2().

05964 {
05965    int x;
05966    int d;
05967    char fn[PATH_MAX];
05968    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
05969    if (d)
05970       return d;
05971    for (x = start; x< 5; x++) {  /* For all folders */
05972       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
05973          return d;
05974       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
05975       if (d)
05976          return d;
05977       snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
05978       d = vm_play_folder_name(chan, fn);
05979       if (d)
05980          return d;
05981       d = ast_waitfordigit(chan, 500);
05982       if (d)
05983          return d;
05984    }
05985    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
05986    if (d)
05987       return d;
05988    d = ast_waitfordigit(chan, 4000);
05989    return d;
05990 }

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

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

06005 {
06006    int res = 0;
06007    res = ast_play_and_wait(chan, fn);  /* Folder name */
06008    while (((res < '0') || (res > '9')) &&
06009          (res != '#') && (res >= 0)) {
06010       res = get_folder(chan, 0);
06011    }
06012    return res;
06013 }

static int handle_subscribe ( void *  datap  )  [static]

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

10000 {
10001    unsigned int len;
10002    struct mwi_sub *mwi_sub;
10003    struct mwi_sub_task *p = datap;
10004 
10005    len = sizeof(*mwi_sub);
10006    if (!ast_strlen_zero(p->mailbox))
10007       len += strlen(p->mailbox);
10008 
10009    if (!ast_strlen_zero(p->context))
10010       len += strlen(p->context) + 1; /* Allow for seperator */
10011 
10012    if (!(mwi_sub = ast_calloc(1, len)))
10013       return -1;
10014 
10015    mwi_sub->uniqueid = p->uniqueid;
10016    if (!ast_strlen_zero(p->mailbox))
10017       strcpy(mwi_sub->mailbox, p->mailbox);
10018 
10019    if (!ast_strlen_zero(p->context)) {
10020       strcat(mwi_sub->mailbox, "@");
10021       strcat(mwi_sub->mailbox, p->context);
10022    }
10023 
10024    AST_RWLIST_WRLOCK(&mwi_subs);
10025    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
10026    AST_RWLIST_UNLOCK(&mwi_subs);
10027    ast_free((void *) p->mailbox);
10028    ast_free((void *) p->context);
10029    ast_free(p);   
10030    return 0;
10031 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

09978 {
09979    struct mwi_sub *mwi_sub;
09980    uint32_t *uniqueid = datap;
09981    
09982    AST_RWLIST_WRLOCK(&mwi_subs);
09983    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
09984       if (mwi_sub->uniqueid == *uniqueid) {
09985          AST_LIST_REMOVE_CURRENT(entry);
09986          break;
09987       }
09988    }
09989    AST_RWLIST_TRAVERSE_SAFE_END
09990    AST_RWLIST_UNLOCK(&mwi_subs);
09991 
09992    if (mwi_sub)
09993       mwi_sub_destroy(mwi_sub);
09994 
09995    ast_free(uniqueid);  
09996    return 0;
09997 }

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

09899 {
09900    switch (cmd) {
09901    case CLI_INIT:
09902       e->command = "voicemail reload";
09903       e->usage =
09904          "Usage: voicemail reload\n"
09905          "       Reload voicemail configuration\n";
09906       return NULL;
09907    case CLI_GENERATE:
09908       return NULL;
09909    }
09910 
09911    if (a->argc != 2)
09912       return CLI_SHOWUSAGE;
09913 
09914    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
09915    load_config(1);
09916    
09917    return CLI_SUCCESS;
09918 }

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

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

09789 {
09790    struct ast_vm_user *vmu;
09791 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
09792    const char *context = NULL;
09793    int users_counter = 0;
09794 
09795    switch (cmd) {
09796    case CLI_INIT:
09797       e->command = "voicemail show users";
09798       e->usage =
09799          "Usage: voicemail show users [for <context>]\n"
09800          "       Lists all mailboxes currently set up\n";
09801       return NULL;
09802    case CLI_GENERATE:
09803       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
09804    }  
09805 
09806    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
09807       return CLI_SHOWUSAGE;
09808    if (a->argc == 5) {
09809       if (strcmp(a->argv[3],"for"))
09810          return CLI_SHOWUSAGE;
09811       context = a->argv[4];
09812    }
09813 
09814    if (ast_check_realtime("voicemail")) {
09815       if (!context) {
09816          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
09817          return CLI_SHOWUSAGE;
09818       }
09819       return show_users_realtime(a->fd, context);
09820    }
09821 
09822    AST_LIST_LOCK(&users);
09823    if (AST_LIST_EMPTY(&users)) {
09824       ast_cli(a->fd, "There are no voicemail users currently defined\n");
09825       AST_LIST_UNLOCK(&users);
09826       return CLI_FAILURE;
09827    }
09828    if (a->argc == 3)
09829       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
09830    else {
09831       int count = 0;
09832       AST_LIST_TRAVERSE(&users, vmu, list) {
09833          if (!strcmp(context, vmu->context))
09834             count++;
09835       }
09836       if (count) {
09837          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
09838       } else {
09839          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
09840          AST_LIST_UNLOCK(&users);
09841          return CLI_FAILURE;
09842       }
09843    }
09844    AST_LIST_TRAVERSE(&users, vmu, list) {
09845       int newmsgs = 0, oldmsgs = 0;
09846       char count[12], tmp[256] = "";
09847 
09848       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
09849          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
09850          inboxcount(tmp, &newmsgs, &oldmsgs);
09851          snprintf(count, sizeof(count), "%d", newmsgs);
09852          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
09853          users_counter++;
09854       }
09855    }
09856    AST_LIST_UNLOCK(&users);
09857    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
09858    return CLI_SUCCESS;
09859 }

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 9862 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::msg_format, vm_zone::name, vm_zone::timezone, and ast_cli_entry::usage.

09863 {
09864    struct vm_zone *zone;
09865 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
09866    char *res = CLI_SUCCESS;
09867 
09868    switch (cmd) {
09869    case CLI_INIT:
09870       e->command = "voicemail show zones";
09871       e->usage =
09872          "Usage: voicemail show zones\n"
09873          "       Lists zone message formats\n";
09874       return NULL;
09875    case CLI_GENERATE:
09876       return NULL;
09877    }
09878 
09879    if (a->argc != 3)
09880       return CLI_SHOWUSAGE;
09881 
09882    AST_LIST_LOCK(&zones);
09883    if (!AST_LIST_EMPTY(&zones)) {
09884       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
09885       AST_LIST_TRAVERSE(&zones, zone, list) {
09886          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
09887       }
09888    } else {
09889       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
09890       res = CLI_FAILURE;
09891    }
09892    AST_LIST_UNLOCK(&zones);
09893 
09894    return res;
09895 }

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

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

Referenced by load_module(), and vm_execmain().

04738 {
04739    char tmp[256], *tmp2 = tmp, *box, *context;
04740    ast_copy_string(tmp, mailbox, sizeof(tmp));
04741    while ((box = strsep(&tmp2, ","))) {
04742       if ((context = strchr(box, '@')))
04743          *context++ = '\0';
04744       else
04745          context = "default";
04746       if (__has_voicemail(context, box, folder, 1))
04747          return 1;
04748    }
04749    return 0;
04750 }

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

Definition at line 4809 of file app_voicemail.c.

References inboxcount2().

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

04810 {
04811    return inboxcount2(mailbox, NULL, newmsgs, oldmsgs);
04812 }

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

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

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

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

utility used by inchar(), for base_encode()

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

03610 {
03611    int l;
03612 
03613    if (bio->ateof)
03614       return 0;
03615 
03616    if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
03617       if (ferror(fi))
03618          return -1;
03619 
03620       bio->ateof = 1;
03621       return 0;
03622    }
03623 
03624    bio->iolen= l;
03625    bio->iocp= 0;
03626 
03627    return 1;
03628 }

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

utility used by base_encode()

Definition at line 3633 of file app_voicemail.c.

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

Referenced by base_encode().

03634 {
03635    if (bio->iocp>=bio->iolen) {
03636       if (!inbuf(bio, fi))
03637          return EOF;
03638    }
03639 
03640    return bio->iobuf[bio->iocp++];
03641 }

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

Definition at line 4370 of file app_voicemail.c.

References ast_fileexists(), ast_log(), AST_LOG_WARNING, ast_say_digit_str(), ast_stream_and_wait(), create_dirpath(), DISPOSE, and RETRIEVE.

Referenced by leave_voicemail().

04371 {
04372    int res;
04373    char fn[PATH_MAX];
04374    char dest[PATH_MAX];
04375 
04376    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04377 
04378    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04379       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04380       return -1;
04381    }
04382 
04383    RETRIEVE(fn, -1, ext, context);
04384    if (ast_fileexists(fn, NULL, NULL) > 0) {
04385       res = ast_stream_and_wait(chan, fn, ecodes);
04386       if (res) {
04387          DISPOSE(fn, -1);
04388          return res;
04389       }
04390    } else {
04391       /* Dispose just in case */
04392       DISPOSE(fn, -1);
04393       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04394       if (res)
04395          return res;
04396       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04397       if (res)
04398          return res;
04399    }
04400    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04401    return res;
04402 }

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

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

Referenced by load_config().

01035 {
01036    int i;
01037    char *local_key = ast_strdupa(key);
01038 
01039    for (i = 0; i < strlen(key); ++i) {
01040       if (!strchr(VALID_DTMF, *local_key)) {
01041          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01042          return 0;
01043       }
01044       local_key++;
01045    }
01046    return 1;
01047 }

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 3438 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().

03439 {
03440    int x;
03441    unsigned char map[MAXMSGLIMIT] = "";
03442    DIR *msgdir;
03443    struct dirent *msgdirent;
03444    int msgdirint;
03445 
03446    /* Reading the entire directory into a file map scales better than
03447     * doing a stat repeatedly on a predicted sequence.  I suspect this
03448     * is partially due to stat(2) internally doing a readdir(2) itself to
03449     * find each file. */
03450    msgdir = opendir(dir);
03451    while ((msgdirent = readdir(msgdir))) {
03452       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03453          map[msgdirint] = 1;
03454    }
03455    closedir(msgdir);
03456 
03457    for (x = 0; x < vmu->maxmsg; x++) {
03458       if (map[x] == 0)
03459          break;
03460    }
03461 
03462    return x - 1;
03463 }

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 4879 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_free, ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock(), ast_mutex_unlock(), ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer, ast_str_create(), ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verbose, ast_waitstream(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, ast_channel::exten, find_user(), free_user(), get_date(), inboxcount(), INTRO, invent_message(), last_message_index(), ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, 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.

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

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

static int load_config ( int  reload  )  [static]

Definition at line 10281 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_LOG_WARNING, 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_STATUS_FILEUNCHANGED, ast_vm_user::context, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), ast_variable::lineno, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, vm_zone::msg_format, vm_zone::name, ast_variable::name, ast_variable::next, pagerbody, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, saydurationminfo, SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, vm_zone::timezone, ast_variable::value, 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.

Referenced by handle_voicemail_reload(), load_module(), and reload().

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

static int load_module ( void   )  [static]

Definition at line 10956 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_LOG_WARNING, 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().

10957 {
10958    int res;
10959    my_umask = umask(0);
10960    umask(my_umask);
10961 
10962    /* compute the location of the voicemail spool directory */
10963    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
10964    
10965    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
10966       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
10967    }
10968 
10969    if ((res = load_config(0)))
10970       return res;
10971 
10972    res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
10973    res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
10974    res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
10975    res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
10976    res |= ast_custom_function_register(&mailbox_exists_acf);
10977    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
10978    if (res)
10979       return res;
10980 
10981    ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
10982 
10983    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
10984    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
10985    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
10986 
10987    return res;
10988 }

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

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

01252 {
01253    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01254 }

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 3917 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_LOG_WARNING, ast_random(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, 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, pbx_substitute_variables_helper(), prep_email_sub_vars(), ast_channel::priority, quote(), strip_control(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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 1266 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().

01267 {
01268    return snprintf(dest, len, "%s/msg%04d", dir, num);
01269 }

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

Manager list voicemail users command.

Definition at line 10114 of file app_voicemail.c.

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

Referenced by load_module().

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

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

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

09950 {
09951    while (poll_thread_run) {
09952       struct timespec ts = { 0, };
09953       struct timeval wait;
09954 
09955       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
09956       ts.tv_sec = wait.tv_sec;
09957       ts.tv_nsec = wait.tv_usec * 1000;
09958 
09959       ast_mutex_lock(&poll_lock);
09960       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
09961       ast_mutex_unlock(&poll_lock);
09962 
09963       if (!poll_thread_run)
09964          break;
09965 
09966       poll_subscribed_mailboxes();
09967    }
09968 
09969    return NULL;
09970 }

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

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

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

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

Definition at line 4680 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04681 {
04682    return __has_voicemail(context, mailbox, folder, 0);
04683 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 9972 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

09973 {
09974    ast_free(mwi_sub);
09975 }

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

Definition at line 10049 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(), mwi_sub_task::context, handle_subscribe(), LOG_ERROR, mwi_sub_task::mailbox, mwi_subscription_tps, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

10050 {
10051    struct mwi_sub_task *mwist;
10052    
10053    if (ast_event_get_type(event) != AST_EVENT_SUB)
10054       return;
10055 
10056    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10057       return;
10058 
10059    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
10060       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
10061       return;
10062    }
10063    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
10064    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
10065    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10066    
10067    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
10068       ast_free(mwist);
10069    }
10070 }

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

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

10034 {
10035    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
10036    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
10037       return;
10038 
10039    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10040       return;
10041 
10042    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10043    *uniqueid = u;
10044    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
10045       ast_free(uniqueid);
10046    }
10047 }

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

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_unlock, ast_log(), AST_LOG_WARNING, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_vm_user::attachfmt, 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.

Referenced by copy_message(), and leave_voicemail().

06198 {
06199    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06200    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06201    const char *category;
06202    char *myserveremail = serveremail;
06203 
06204    ast_channel_lock(chan);
06205    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06206       category = ast_strdupa(category);
06207    }
06208    ast_channel_unlock(chan);
06209 
06210    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
06211    make_file(fn, sizeof(fn), todir, msgnum);
06212    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06213 
06214    if (!ast_strlen_zero(vmu->attachfmt)) {
06215       if (strstr(fmt, vmu->attachfmt))
06216          fmt = vmu->attachfmt;
06217       else
06218          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);
06219    }
06220 
06221    /* Attach only the first format */
06222    fmt = ast_strdupa(fmt);
06223    stringp = fmt;
06224    strsep(&stringp, "|");
06225 
06226    if (!ast_strlen_zero(vmu->serveremail))
06227       myserveremail = vmu->serveremail;
06228 
06229    if (!ast_strlen_zero(vmu->email)) {
06230       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06231       if (!attach_user_voicemail)
06232          attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
06233 
06234       if (attach_user_voicemail)
06235          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06236 
06237       /* XXX possible imap issue, should category be NULL XXX */
06238       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06239 
06240       if (attach_user_voicemail)
06241          DISPOSE(todir, msgnum);
06242    }
06243 
06244    if (!ast_strlen_zero(vmu->pager)) {
06245       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
06246    }
06247 
06248    if (ast_test_flag(vmu, VM_DELETE))
06249       DELETE(todir, msgnum, fn, vmu);
06250 
06251    /* Leave voicemail for someone */
06252    if (ast_app_has_voicemail(ext_context, NULL)) 
06253       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06254 
06255    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06256 
06257    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);
06258    run_externnotify(vmu->context, vmu->mailbox, flag);
06259 
06260 #ifdef IMAP_STORAGE
06261    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06262    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06263       vm_imap_delete(vms->curmsg, vmu);
06264       vms->newmessages--;  /* Fix new message count */
06265    }
06266 #endif
06267 
06268    return 0;
06269 }

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

utility used by base_encode()

Definition at line 3646 of file app_voicemail.c.

References BASELINELEN, eol, and baseio::linelength.

Referenced by base_encode().

03647 {
03648    if (bio->linelength >= BASELINELEN) {
03649       if (fputs(eol,so) == EOF)
03650          return -1;
03651 
03652       bio->linelength= 0;
03653    }
03654 
03655    if (putc(((unsigned char)c),so) == EOF)
03656       return -1;
03657 
03658    bio->linelength++;
03659 
03660    return 1;
03661 }

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

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

06954 {
06955    int count_msg, last_msg;
06956 
06957    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
06958    
06959    /* Rename the member vmbox HERE so that we don't try to return before
06960     * we know what's going on.
06961     */
06962    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
06963    
06964    /* Faster to make the directory than to check if it exists. */
06965    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
06966 
06967    count_msg = count_messages(vmu, vms->curdir);
06968    if (count_msg < 0)
06969       return count_msg;
06970    else
06971       vms->lastmsg = count_msg - 1;
06972 
06973    /*
06974    The following test is needed in case sequencing gets messed up.
06975    There appears to be more than one way to mess up sequence, so
06976    we will not try to find all of the root causes--just fix it when
06977    detected.
06978    */
06979 
06980    if (vm_lock_path(vms->curdir)) {
06981       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
06982       return -1;
06983    }
06984 
06985    last_msg = last_message_index(vmu, vms->curdir);
06986    ast_unlock_path(vms->curdir);
06987 
06988    if (last_msg < 0) 
06989       return last_msg;
06990 
06991    return 0;
06992 }

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

Definition at line 6751 of file app_voicemail.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), AST_LOG_WARNING, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, 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_zh(), and vm_execmain().

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

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

Definition at line 6637 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

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

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

Definition at line 6549 of file app_voicemail.c.

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

Referenced by play_message().

06550 {
06551    int res = 0;
06552 
06553    if (!ast_strlen_zero(category))
06554       res = ast_play_and_wait(chan, category);
06555 
06556    if (res) {
06557       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
06558       res = 0;
06559    }
06560 
06561    return res;
06562 }

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

Definition at line 6564 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_LOG_WARNING, ast_say_date_with_format, ast_strlen_zero(), ast_tvnow(), 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().

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

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

Definition at line 6701 of file app_voicemail.c.

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

Referenced by play_message().

06702 {
06703    int res = 0;
06704    int durationm;
06705    int durations;
06706    /* Verify that we have a duration for the message */
06707    if (duration == NULL)
06708       return res;
06709 
06710    /* Convert from seconds to minutes */
06711    durations=atoi(duration);
06712    durationm=(durations / 60);
06713 
06714    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
06715 
06716    if ((!res) && (durationm >= minduration)) {
06717       res = wait_file2(chan, vms, "vm-duration");
06718 
06719       /* POLISH syntax */
06720       if (!strcasecmp(chan->language, "pl")) {
06721          div_t num = div(durationm, 10);
06722 
06723          if (durationm == 1) {
06724             res = ast_play_and_wait(chan, "digits/1z");
06725             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
06726          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
06727             if (num.rem == 2) {
06728                if (!num.quot) {
06729                   res = ast_play_and_wait(chan, "digits/2-ie");
06730                } else {
06731                   res = say_and_wait(chan, durationm - 2 , chan->language);
06732                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
06733                }
06734             } else {
06735                res = say_and_wait(chan, durationm, chan->language);
06736             }
06737             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
06738          } else {
06739             res = say_and_wait(chan, durationm, chan->language);
06740             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
06741          }
06742       /* DEFAULT syntax */
06743       } else {
06744          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
06745          res = wait_file2(chan, vms, "vm-minutes");
06746       }
06747    }
06748    return res;
06749 }

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 11250 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_LOG_WARNING, 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(), ast_vm_user::context, DELETE, DISPOSE, INTRO, ast_vm_user::mailbox, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

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

static void poll_subscribed_mailboxes ( void   )  [static]

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

09927 {
09928    struct mwi_sub *mwi_sub;
09929 
09930    AST_RWLIST_RDLOCK(&mwi_subs);
09931    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
09932       int new = 0, old = 0, urgent = 0;
09933 
09934       if (ast_strlen_zero(mwi_sub->mailbox))
09935          continue;
09936 
09937       inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
09938 
09939       if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
09940          mwi_sub->old_urgent = urgent;
09941          mwi_sub->old_new = new;
09942          mwi_sub->old_old = old;
09943          queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
09944       }
09945    }
09946    AST_RWLIST_UNLOCK(&mwi_subs);
09947 }

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.

  • all the globalflags
  • the saydurationminfo
  • the callcontext
  • the dialcontext
  • the exitcontext
  • vmmaxsecs, vmmaxmsg, maxdeletedmsg
  • volume gain.

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

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

00739 {
00740    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00741    if (saydurationminfo)
00742       vmu->saydurationm = saydurationminfo;
00743    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00744    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00745    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00746    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00747    if (vmmaxsecs)
00748       vmu->maxsecs = vmmaxsecs;
00749    if (maxmsg)
00750       vmu->maxmsg = maxmsg;
00751    if (maxdeletedmsg)
00752       vmu->maxdeletedmsg = maxdeletedmsg;
00753    vmu->volgain = volgain;
00754 }

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

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

Referenced by make_email_file(), and sendpage().

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

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

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

06162 {
06163    struct ast_event *event;
06164    char *mailbox, *context;
06165 
06166    /* Strip off @default */
06167    context = mailbox = ast_strdupa(box);
06168    strsep(&context, "@");
06169    if (ast_strlen_zero(context))
06170       context = "default";
06171 
06172    if (!(event = ast_event_new(AST_EVENT_MWI,
06173          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06174          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06175          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06176          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06177          AST_EVENT_IE_END))) {
06178       return;
06179    }
06180 
06181    ast_event_queue_and_cache(event);
06182 }

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

Referenced by make_email_file().

03794 {
03795    char *ptr = to;
03796    *ptr++ = '"';
03797    for (; ptr < to + len - 1; from++) {
03798       if (*from == '"')
03799          *ptr++ = '\\';
03800       else if (*from == '\0')
03801          break;
03802       *ptr++ = *from;
03803    }
03804    if (ptr < to + len - 1)
03805       *ptr++ = '"';
03806    *ptr = '\0';
03807    return to;
03808 }

static int reload ( void   )  [static]

Definition at line 10926 of file app_voicemail.c.

References load_config().

10927 {
10928    return load_config(1);
10929 }

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

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

03415 {
03416    char stxt[PATH_MAX];
03417    char dtxt[PATH_MAX];
03418    ast_filerename(sfn,dfn,NULL);
03419    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03420    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03421    if (ast_check_realtime("voicemail_data")) {
03422       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03423    }
03424    rename(stxt, dtxt);
03425 }

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 1134 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::mailbox, and ast_vm_user::password.

Referenced by vm_change_password(), and vm_change_password_shell().

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

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

Definition at line 4816 of file app_voicemail.c.

References ast_app_has_voicemail(), ast_copy_string(), ast_debug, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, 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(), and SMDI_MWI_WAIT_TIMEOUT.

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

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

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

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

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

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

Definition at line 10912 of file app_voicemail.c.

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

Referenced by load_module().

10913 {
10914    int res = -1;
10915    char dir[PATH_MAX];
10916    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
10917    ast_debug(2, "About to try retrieving name file %s\n", dir);
10918    RETRIEVE(dir, -1, mailbox, context);
10919    if (ast_fileexists(dir, NULL, NULL)) {
10920       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
10921    }
10922    DISPOSE(dir, -1);
10923    return res;
10924 }

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

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

Referenced by forward_message(), and notify_new_message().

04238 {
04239    FILE *p=NULL;
04240    char tmp[80] = "/tmp/astmail-XXXXXX";
04241    char tmp2[256];
04242 
04243    if (vmu && ast_strlen_zero(vmu->email)) {
04244       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04245       return(0);
04246    }
04247    if (!strcmp(format, "wav49"))
04248       format = "WAV";
04249    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));
04250    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04251       command hangs */
04252    if ((p = vm_mkftemp(tmp)) == NULL) {
04253       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04254       return -1;
04255    } else {
04256       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04257       fclose(p);
04258       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04259       ast_safe_system(tmp2);
04260       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04261    }
04262    return 0;
04263 }

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

References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, ast_log(), AST_LOG_WARNING, 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().

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

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

Definition at line 9724 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, ast_variable::name, ast_variable::next, SENTINEL, and ast_variable::value.

Referenced by handle_voicemail_show_users().

09725 {
09726    struct ast_config *cfg;
09727    const char *cat = NULL;
09728 
09729    if (!(cfg = ast_load_realtime_multientry("voicemail", 
09730       "context", context, SENTINEL))) {
09731       return CLI_FAILURE;
09732    }
09733 
09734    ast_cli(fd,
09735       "\n"
09736       "=============================================================\n"
09737       "=== Configured Voicemail Users ==============================\n"
09738       "=============================================================\n"
09739       "===\n");
09740 
09741    while ((cat = ast_category_browse(cfg, cat))) {
09742       struct ast_variable *var = NULL;
09743       ast_cli(fd,
09744          "=== Mailbox ...\n"
09745          "===\n");
09746       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
09747          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
09748       ast_cli(fd,
09749          "===\n"
09750          "=== ---------------------------------------------------------\n"
09751          "===\n");
09752    }
09753 
09754    ast_cli(fd,
09755       "=============================================================\n"
09756       "\n");
09757 
09758    ast_config_destroy(cfg);
09759 
09760    return CLI_SUCCESS;
09761 }

static void start_poll_thread ( void   )  [static]
static void stop_poll_thread ( void   )  [static]

Definition at line 10090 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10091 {
10092    poll_thread_run = 0;
10093 
10094    if (mwi_sub_sub) {
10095       ast_event_unsubscribe(mwi_sub_sub);
10096       mwi_sub_sub = NULL;
10097    }
10098 
10099    if (mwi_unsub_sub) {
10100       ast_event_unsubscribe(mwi_unsub_sub);
10101       mwi_unsub_sub = NULL;
10102    }
10103 
10104    ast_mutex_lock(&poll_lock);
10105    ast_cond_signal(&poll_cond);
10106    ast_mutex_unlock(&poll_lock);
10107 
10108    pthread_join(poll_thread, NULL);
10109 
10110    poll_thread = AST_PTHREADT_NULL;
10111 }

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

Definition at line 709 of file app_voicemail.c.

Referenced by make_email_file().

00710 {
00711    char *bufptr = buf;
00712    for (; *input; input++) {
00713       if (*input < 32) {
00714          continue;
00715       }
00716       *bufptr++ = *input;
00717       if (bufptr == buf + buflen - 1) {
00718          break;
00719       }
00720    }
00721    *bufptr = '\0';
00722    return buf;
00723 }

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

Definition at line 10236 of file app_voicemail.c.

References ast_free, ast_log(), AST_LOG_NOTICE, ast_str_append(), ast_str_create(), ast_strdup, ast_str::str, and ast_str::used.

Referenced by load_config().

10237 {
10238    char *current, *result;
10239 
10240    /* Add 16 for fudge factor */
10241    struct ast_str *str = ast_str_create(strlen(value) + 16);
10242 
10243    /* Substitute strings \r, \n, and \t into the appropriate characters */
10244    for (current = (char *) value; *current; current++) {
10245       if (*current == '\\') {
10246          current++;
10247          if (!*current) {
10248             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
10249             break;
10250          }
10251          switch (*current) {
10252          case 'r':
10253             ast_str_append(&str, 0, "\r");
10254             break;
10255          case 'n':
10256 #ifdef IMAP_STORAGE
10257             if (!str->used || str->str[str->used - 1] != '\r') {
10258                ast_str_append(&str, 0, "\r");
10259             }
10260 #endif
10261             ast_str_append(&str, 0, "\n");
10262             break;
10263          case 't':
10264             ast_str_append(&str, 0, "\t");
10265             break;
10266          default:
10267             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
10268             break;
10269          }
10270       } else {
10271          ast_str_append(&str, 0, "%c", *current);
10272       }
10273    }
10274 
10275    result = ast_strdup(str->str);
10276    ast_free(str);
10277 
10278    return result;
10279 }

static int unload_module ( void   )  [static]
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 8679 of file app_voicemail.c.

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

Referenced by vm_execmain(), and vmauthenticate().

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

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

Definition at line 9619 of file app_voicemail.c.

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

Referenced by load_module().

09620 {
09621    struct ast_vm_user svm;
09622    char *context, *box;
09623    AST_DECLARE_APP_ARGS(args,
09624       AST_APP_ARG(mbox);
09625       AST_APP_ARG(options);
09626    );
09627    static int dep_warning = 0;
09628 
09629    if (ast_strlen_zero(data)) {
09630       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
09631       return -1;
09632    }
09633 
09634    if (!dep_warning) {
09635       dep_warning = 1;
09636       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
09637    }
09638 
09639    box = ast_strdupa(data);
09640 
09641    AST_STANDARD_APP_ARGS(args, box);
09642 
09643    if (args.options) {
09644    }
09645 
09646    if ((context = strchr(args.mbox, '@'))) {
09647       *context = '\0';
09648       context++;
09649    }
09650 
09651    if (find_user(&svm, context, args.mbox)) {
09652       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
09653    } else
09654       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
09655 
09656    return 0;
09657 }

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

References 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_zh().

Referenced by vm_execmain().

08661 {
08662    if (!strcasecmp(chan->language, "es")) {  /* SPANISH */
08663       return vm_browse_messages_es(chan, vms, vmu);
08664    } else if (!strcasecmp(chan->language, "it")) { /* ITALIAN */
08665       return vm_browse_messages_it(chan, vms, vmu);
08666    } else if (!strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {   /* PORTUGUESE */
08667       return vm_browse_messages_pt(chan, vms, vmu);
08668    } else if (!strcasecmp(chan->language, "gr")){
08669       return vm_browse_messages_gr(chan, vms, vmu);   /* GREEK */
08670    } else if (!strncasecmp(chan->language, "zh", 2)) {
08671       return vm_browse_messages_zh(chan, vms, vmu);   /* CHINESE (Taiwan) */
08672    } else if (!strcasecmp(chan->language, "he")) {
08673       return vm_browse_messages_he(chan, vms, vmu);   /* HEBREW */
08674    } else { /* Default to English syntax */
08675       return vm_browse_messages_en(chan, vms, vmu);
08676    }
08677 }

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

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

Referenced by vm_browse_messages().

08524 {
08525    int cmd=0;
08526 
08527    if (vms->lastmsg > -1) {
08528       cmd = play_message(chan, vmu, vms);
08529    } else {
08530       cmd = ast_play_and_wait(chan, "vm-youhave");
08531       if (!cmd) 
08532          cmd = ast_play_and_wait(chan, "vm-no");
08533       if (!cmd) {
08534          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08535          cmd = ast_play_and_wait(chan, vms->fn);
08536       }
08537       if (!cmd)
08538          cmd = ast_play_and_wait(chan, "vm-messages");
08539    }
08540    return cmd;
08541 }

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

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

Referenced by vm_browse_messages().

08578 {
08579    int cmd=0;
08580 
08581    if (vms->lastmsg > -1) {
08582       cmd = play_message(chan, vmu, vms);
08583    } else {
08584       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08585       if (!cmd)
08586          cmd = ast_play_and_wait(chan, "vm-messages");
08587       if (!cmd) {
08588          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08589          cmd = ast_play_and_wait(chan, vms->fn);
08590       }
08591    }
08592    return cmd;
08593 }

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

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

Referenced by vm_browse_messages().

08472 {
08473    int cmd=0;
08474 
08475    if (vms->lastmsg > -1) {
08476       cmd = play_message(chan, vmu, vms);
08477    } else {
08478       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08479       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
08480          if (!cmd) {
08481             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
08482             cmd = ast_play_and_wait(chan, vms->fn);
08483          }
08484          if (!cmd)
08485             cmd = ast_play_and_wait(chan, "vm-messages");
08486       } else {
08487          if (!cmd)
08488             cmd = ast_play_and_wait(chan, "vm-messages");
08489          if (!cmd) {
08490             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08491             cmd = ast_play_and_wait(chan, vms->fn);
08492          }
08493       }
08494    } 
08495    return cmd;
08496 }

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

Definition at line 8499 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08500 {
08501    int cmd = 0;
08502 
08503    if (vms->lastmsg > -1) {
08504       cmd = play_message(chan, vmu, vms);
08505    } else {
08506       if (!strcasecmp(vms->fn, "INBOX")) {
08507          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
08508       } else {
08509          cmd = ast_play_and_wait(chan, "vm-nomessages");
08510       }
08511    }
08512    return cmd;
08513 }

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

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

Referenced by vm_browse_messages().

08552 {
08553    int cmd=0;
08554 
08555    if (vms->lastmsg > -1) {
08556       cmd = play_message(chan, vmu, vms);
08557    } else {
08558       cmd = ast_play_and_wait(chan, "vm-no");
08559       if (!cmd)
08560          cmd = ast_play_and_wait(chan, "vm-message");
08561       if (!cmd) {
08562          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08563          cmd = ast_play_and_wait(chan, vms->fn);
08564       }
08565    }
08566    return cmd;
08567 }

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

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

Referenced by vm_browse_messages().

08604 {
08605    int cmd=0;
08606 
08607    if (vms->lastmsg > -1) {
08608       cmd = play_message(chan, vmu, vms);
08609    } else {
08610       cmd = ast_play_and_wait(chan, "vm-no");
08611       if (!cmd) {
08612          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08613          cmd = ast_play_and_wait(chan, vms->fn);
08614       }
08615       if (!cmd)
08616          cmd = ast_play_and_wait(chan, "vm-messages");
08617    }
08618    return cmd;
08619 }

static int vm_browse_messages_zh ( 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 8629 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08630 {
08631    int cmd=0;
08632 
08633    if (vms->lastmsg > -1) {
08634       cmd = play_message(chan, vmu, vms);
08635    } else {
08636       cmd = ast_play_and_wait(chan, "vm-you");
08637       if (!cmd) 
08638          cmd = ast_play_and_wait(chan, "vm-haveno");
08639       if (!cmd)
08640          cmd = ast_play_and_wait(chan, "vm-messages");
08641       if (!cmd) {
08642          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08643          cmd = ast_play_and_wait(chan, vms->fn);
08644       }
08645    }
08646    return cmd;
08647 }

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

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

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

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

01231 {
01232    char buf[255];
01233    snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
01234    if (!ast_safe_system(buf)) {
01235       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01236       /* Reset the password in memory, too */
01237       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01238    }
01239 }

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

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

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

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

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

Referenced by copy_message(), and notify_new_message().

03589 {
03590    char *txt;
03591    int txtsize = 0;
03592 
03593    txtsize = (strlen(file) + 5)*sizeof(char);
03594    txt = alloca(txtsize);
03595    /* Sprintf here would safe because we alloca'd exactly the right length,
03596     * but trying to eliminate all sprintf's anyhow
03597     */
03598    if (ast_check_realtime("voicemail_data")) {
03599       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
03600    }
03601    snprintf(txt, txtsize, "%s.txt", file);
03602    unlink(txt);
03603    return ast_filedelete(file, NULL);
03604 }

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

Definition at line 9487 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_LOG_WARNING, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_vm_options::exitcontext, 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(), leave_vm_options::record_gain, and vm_app_options.

Referenced by load_module(), and play_record_review().

09488 {
09489    int res = 0;
09490    char *tmp;
09491    struct leave_vm_options leave_options;
09492    struct ast_flags flags = { 0 };
09493    char *opts[OPT_ARG_ARRAY_SIZE];
09494    AST_DECLARE_APP_ARGS(args,
09495       AST_APP_ARG(argv0);
09496       AST_APP_ARG(argv1);
09497    );
09498    
09499    memset(&leave_options, 0, sizeof(leave_options));
09500 
09501    if (chan->_state != AST_STATE_UP)
09502       ast_answer(chan);
09503 
09504    if (!ast_strlen_zero(data)) {
09505       tmp = ast_strdupa(data);
09506       AST_STANDARD_APP_ARGS(args, tmp);
09507       if (args.argc == 2) {
09508          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09509             return -1;
09510          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
09511          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09512             int gain;
09513 
09514             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09515                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09516                return -1;
09517             } else {
09518                leave_options.record_gain = (signed char) gain;
09519             }
09520          }
09521          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
09522             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
09523                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
09524          }
09525       }
09526    } else {
09527       char temp[256];
09528       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
09529       if (res < 0)
09530          return res;
09531       if (ast_strlen_zero(temp))
09532          return 0;
09533       args.argv0 = ast_strdupa(temp);
09534    }
09535 
09536    res = leave_voicemail(chan, args.argv0, &leave_options);
09537 
09538    if (res == ERROR_LOCK_PATH) {
09539       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
09540       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
09541       res = 0;
09542    }
09543 
09544    return res;
09545 }

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

Definition at line 8779 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_LOG_WARNING, 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, close_mailbox(), ast_vm_user::context, vm_state::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), vm_state::fn, forward_message(), free_user(), get_folder2(), globalflags, has_voicemail(), vm_state::heard, language, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), manager_event, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, OLD_FOLDER, vm_state::oldmessages, 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(), vm_state::repeats, run_externnotify(), save_to_folder(), say_and_wait(), vm_state::starting, vm_state::urgentmessages, vm_state::username, 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, VM_SVMAIL, and vm_state::vmbox.

Referenced by load_module().

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

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 6032 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(), CONFIG_FLAG_NOCACHE, config_text_file_save(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

Referenced by forward_message().

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

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

References vm_state::starting, vm_instructions_en(), and vm_instructions_zh().

Referenced by vm_execmain().

08173 {
08174    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08175       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08176    } else {             /* Default to ENGLISH */
08177       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08178    }
08179 }

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

References ast_play_and_wait(), ast_test_flag, ast_waitfordigit(), 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_zh().

08072 {
08073    int res = 0;
08074    /* Play instructions and wait for new command */
08075    while (!res) {
08076       if (vms->starting) {
08077          if (vms->lastmsg > -1) {
08078             if (skipadvanced)
08079                res = ast_play_and_wait(chan, "vm-onefor-full");
08080             else
08081                res = ast_play_and_wait(chan, "vm-onefor");
08082             if (!res)
08083                res = vm_play_folder_name(chan, vms->vmbox);
08084          }
08085          if (!res) {
08086             if (skipadvanced)
08087                res = ast_play_and_wait(chan, "vm-opts-full");
08088             else
08089                res = ast_play_and_wait(chan, "vm-opts");
08090          }
08091       } else {
08092          /* Added for additional help */
08093          if (skipadvanced) {
08094             res = ast_play_and_wait(chan, "vm-onefor-full");
08095             if (!res)
08096                res = vm_play_folder_name(chan, vms->vmbox);
08097             res = ast_play_and_wait(chan, "vm-opts-full");
08098          }
08099          /* Logic:
08100           * If the current message is not the first OR
08101           * if we're listening to the first new message and there are
08102           * also urgent messages, then prompt for navigation to the
08103           * previous message
08104           */
08105          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08106             res = ast_play_and_wait(chan, "vm-prev");
08107          }
08108          if (!res && !skipadvanced)
08109             res = ast_play_and_wait(chan, "vm-advopts");
08110          if (!res)
08111             res = ast_play_and_wait(chan, "vm-repeat");
08112          /* Logic:
08113           * If we're not listening to the last message OR
08114           * we're listening to the last urgent message and there are
08115           * also new non-urgent messages, then prompt for navigation
08116           * to the next message
08117           */
08118          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08119             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08120             res = ast_play_and_wait(chan, "vm-next");
08121          }
08122          if (!res) {
08123             if (!vms->deleted[vms->curmsg])
08124                res = ast_play_and_wait(chan, "vm-delete");
08125             else
08126                res = ast_play_and_wait(chan, "vm-undelete");
08127             if (!res)
08128                res = ast_play_and_wait(chan, "vm-toforward");
08129             if (!res)
08130                res = ast_play_and_wait(chan, "vm-savemessage");
08131          }
08132       }
08133       if (!res) {
08134          res = ast_play_and_wait(chan, "vm-helpexit");
08135       }
08136       if (!res)
08137          res = ast_waitfordigit(chan, 6000);
08138       if (!res) {
08139          vms->repeats++;
08140          if (vms->repeats > 2) {
08141             res = 't';
08142          }
08143       }
08144    }
08145    return res;
08146 }

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

Definition at line 8148 of file app_voicemail.c.

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

Referenced by vm_instructions().

08149 {
08150    int res = 0;
08151    /* Play instructions and wait for new command */
08152    while (!res) {
08153       if (vms->lastmsg > -1) {
08154          res = ast_play_and_wait(chan, "vm-listen");
08155          if (!res)
08156             res = vm_play_folder_name(chan, vms->vmbox);
08157          if (!res)
08158             res = ast_play_and_wait(chan, "press");
08159          if (!res)
08160             res = ast_play_and_wait(chan, "digits/1");
08161       }
08162       if (!res)
08163          res = ast_play_and_wait(chan, "vm-opts");
08164       if (!res) {
08165          vms->starting = 0;
08166          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08167       }
08168    }
08169    return res;
08170 }

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

Definition at line 8019 of file app_voicemail.c.

References ast_fileexists(), ast_play_and_wait(), ast_test_flag, ast_vm_user::context, DISPOSE, 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_zh(), and VM_TEMPGREETWARN.

Referenced by vm_execmain().

08020 {
08021    char prefile[256];
08022    
08023    /* Notify the user that the temp greeting is set and give them the option to remove it */
08024    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08025    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08026       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08027       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08028          ast_play_and_wait(chan, "vm-tempgreetactive");
08029       }
08030       DISPOSE(prefile, -1);
08031    }
08032 
08033    /* Play voicemail intro - syntax is different for different languages */
08034    if (!strcasecmp(chan->language, "de")) {  /* GERMAN syntax */
08035       return vm_intro_de(chan, vms);
08036    } else if (!strcasecmp(chan->language, "es")) { /* SPANISH syntax */
08037       return vm_intro_es(chan, vms);
08038    } else if (!strcasecmp(chan->language, "it")) { /* ITALIAN syntax */
08039       return vm_intro_it(chan, vms);
08040    } else if (!strcasecmp(chan->language, "fr")) { /* FRENCH syntax */
08041       return vm_intro_fr(chan, vms);
08042    } else if (!strcasecmp(chan->language, "nl")) { /* DUTCH syntax */
08043       return vm_intro_nl(chan, vms);
08044    } else if (!strcasecmp(chan->language, "pt")) { /* PORTUGUESE syntax */
08045       return vm_intro_pt(chan, vms);
08046    } else if (!strcasecmp(chan->language, "pt_BR")) { /* BRAZILIAN PORTUGUESE syntax */
08047       return vm_intro_pt_BR(chan, vms);
08048    } else if (!strcasecmp(chan->language, "cz")) { /* CZECH syntax */
08049       return vm_intro_cz(chan, vms);
08050    } else if (!strcasecmp(chan->language, "gr")) { /* GREEK syntax */
08051       return vm_intro_gr(chan, vms);
08052    } else if (!strcasecmp(chan->language, "pl")) { /* POLISH syntax */
08053       return vm_intro_pl(chan, vms);
08054    } else if (!strcasecmp(chan->language, "se")) { /* SWEDISH syntax */
08055       return vm_intro_se(chan, vms);
08056    } else if (!strcasecmp(chan->language, "no")) { /* NORWEGIAN syntax */
08057       return vm_intro_no(chan, vms);
08058    } else if (!strcasecmp(chan->language, "ru")) { /* RUSSIAN syntax */
08059       return vm_intro_multilang(chan, vms, "n");
08060    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08061       return vm_intro_zh(chan, vms);
08062    } else if (!strcasecmp(chan->language, "ua")) { /* UKRAINIAN syntax */
08063       return vm_intro_multilang(chan, vms, "n");
08064    } else if (!strcasecmp(chan->language, "he")) { /* HEBREW syntax */
08065        return vm_intro_he(chan, vms);
08066    } else {             /* Default to ENGLISH */
08067       return vm_intro_en(chan, vms);
08068    }
08069 }

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

Definition at line 7920 of file app_voicemail.c.

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

Referenced by vm_intro().

07921 {
07922    int res;
07923    res = ast_play_and_wait(chan, "vm-youhave");
07924    if (!res) {
07925       if (vms->newmessages) {
07926          if (vms->newmessages == 1) {
07927             res = ast_play_and_wait(chan, "digits/jednu");
07928          } else {
07929             res = say_and_wait(chan, vms->newmessages, chan->language);
07930          }
07931          if (!res) {
07932             if ((vms->newmessages == 1))
07933                res = ast_play_and_wait(chan, "vm-novou");
07934             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
07935                res = ast_play_and_wait(chan, "vm-nove");
07936             if (vms->newmessages > 4)
07937                res = ast_play_and_wait(chan, "vm-novych");
07938          }
07939          if (vms->oldmessages && !res)
07940             res = ast_play_and_wait(chan, "vm-and");
07941          else if (!res) {
07942             if ((vms->newmessages == 1))
07943                res = ast_play_and_wait(chan, "vm-zpravu");
07944             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
07945                res = ast_play_and_wait(chan, "vm-zpravy");
07946             if (vms->newmessages > 4)
07947                res = ast_play_and_wait(chan, "vm-zprav");
07948          }
07949       }
07950       if (!res && vms->oldmessages) {
07951          res = say_and_wait(chan, vms->oldmessages, chan->language);
07952          if (!res) {
07953             if ((vms->oldmessages == 1))
07954                res = ast_play_and_wait(chan, "vm-starou");
07955             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
07956                res = ast_play_and_wait(chan, "vm-stare");
07957             if (vms->oldmessages > 4)
07958                res = ast_play_and_wait(chan, "vm-starych");
07959          }
07960          if (!res) {
07961             if ((vms->oldmessages == 1))
07962                res = ast_play_and_wait(chan, "vm-zpravu");
07963             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
07964                res = ast_play_and_wait(chan, "vm-zpravy");
07965             if (vms->oldmessages > 4)
07966                res = ast_play_and_wait(chan, "vm-zprav");
07967          }
07968       }
07969       if (!res) {
07970          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07971             res = ast_play_and_wait(chan, "vm-no");
07972             if (!res)
07973                res = ast_play_and_wait(chan, "vm-zpravy");
07974          }
07975       }
07976    }
07977    return res;
07978 }

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

Definition at line 7616 of file app_voicemail.c.

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

Referenced by vm_intro().

07617 {
07618    /* Introduce messages they have */
07619    int res;
07620    res = ast_play_and_wait(chan, "vm-youhave");
07621    if (!res) {
07622       if (vms->newmessages) {
07623          if ((vms->newmessages == 1))
07624             res = ast_play_and_wait(chan, "digits/1F");
07625          else
07626             res = say_and_wait(chan, vms->newmessages, chan->language);
07627          if (!res)
07628             res = ast_play_and_wait(chan, "vm-INBOX");
07629          if (vms->oldmessages && !res)
07630             res = ast_play_and_wait(chan, "vm-and");
07631          else if (!res) {
07632             if ((vms->newmessages == 1))
07633                res = ast_play_and_wait(chan, "vm-message");
07634             else
07635                res = ast_play_and_wait(chan, "vm-messages");
07636          }
07637             
07638       }
07639       if (!res && vms->oldmessages) {
07640          if (vms->oldmessages == 1)
07641             res = ast_play_and_wait(chan, "digits/1F");
07642          else
07643             res = say_and_wait(chan, vms->oldmessages, chan->language);
07644          if (!res)
07645             res = ast_play_and_wait(chan, "vm-Old");
07646          if (!res) {
07647             if (vms->oldmessages == 1)
07648                res = ast_play_and_wait(chan, "vm-message");
07649             else
07650                res = ast_play_and_wait(chan, "vm-messages");
07651          }
07652       }
07653       if (!res) {
07654          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07655             res = ast_play_and_wait(chan, "vm-no");
07656             if (!res)
07657                res = ast_play_and_wait(chan, "vm-messages");
07658          }
07659       }
07660    }
07661    return res;
07662 }

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

Definition at line 7365 of file app_voicemail.c.

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

Referenced by vm_intro().

07366 {
07367    int res;
07368 
07369    /* Introduce messages they have */
07370    res = ast_play_and_wait(chan, "vm-youhave");
07371    if (!res) {
07372       if (vms->urgentmessages) {
07373          res = say_and_wait(chan, vms->urgentmessages, chan->language);
07374          if (!res)
07375             res = ast_play_and_wait(chan, "vm-Urgent");
07376          if ((vms->oldmessages || vms->newmessages) && !res) {
07377             res = ast_play_and_wait(chan, "vm-and");
07378          } else if (!res) {
07379             if ((vms->urgentmessages == 1))
07380                res = ast_play_and_wait(chan, "vm-message");
07381             else
07382                res = ast_play_and_wait(chan, "vm-messages");
07383          }
07384       }
07385       if (vms->newmessages) {
07386          res = say_and_wait(chan, vms->newmessages, chan->language);
07387          if (!res)
07388             res = ast_play_and_wait(chan, "vm-INBOX");
07389          if (vms->oldmessages && !res)
07390             res = ast_play_and_wait(chan, "vm-and");
07391          else if (!res) {
07392             if ((vms->newmessages == 1))
07393                res = ast_play_and_wait(chan, "vm-message");
07394             else
07395                res = ast_play_and_wait(chan, "vm-messages");
07396          }
07397             
07398       }
07399       if (!res && vms->oldmessages) {
07400          res = say_and_wait(chan, vms->oldmessages, chan->language);
07401          if (!res)
07402             res = ast_play_and_wait(chan, "vm-Old");
07403          if (!res) {
07404             if (vms->oldmessages == 1)
07405                res = ast_play_and_wait(chan, "vm-message");
07406             else
07407                res = ast_play_and_wait(chan, "vm-messages");
07408          }
07409       }
07410       if (!res) {
07411          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
07412             res = ast_play_and_wait(chan, "vm-no");
07413             if (!res)
07414                res = ast_play_and_wait(chan, "vm-messages");
07415          }
07416       }
07417    }
07418    return res;
07419 }

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

Definition at line 7665 of file app_voicemail.c.

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

Referenced by vm_intro().

07666 {
07667    /* Introduce messages they have */
07668    int res;
07669    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07670       res = ast_play_and_wait(chan, "vm-youhaveno");
07671       if (!res)
07672          res = ast_play_and_wait(chan, "vm-messages");
07673    } else {
07674       res = ast_play_and_wait(chan, "vm-youhave");
07675    }
07676    if (!res) {
07677       if (vms->newmessages) {
07678          if (!res) {
07679             if ((vms->newmessages == 1)) {
07680                res = ast_play_and_wait(chan, "digits/1M");
07681                if (!res)
07682                   res = ast_play_and_wait(chan, "vm-message");
07683                if (!res)
07684                   res = ast_play_and_wait(chan, "vm-INBOXs");
07685             } else {
07686                res = say_and_wait(chan, vms->newmessages, chan->language);
07687                if (!res)
07688                   res = ast_play_and_wait(chan, "vm-messages");
07689                if (!res)
07690                   res = ast_play_and_wait(chan, "vm-INBOX");
07691             }
07692          }
07693          if (vms->oldmessages && !res)
07694             res = ast_play_and_wait(chan, "vm-and");
07695       }
07696       if (vms->oldmessages) {
07697          if (!res) {
07698             if (vms->oldmessages == 1) {
07699                res = ast_play_and_wait(chan, "digits/1M");
07700                if (!res)
07701                   res = ast_play_and_wait(chan, "vm-message");
07702                if (!res)
07703                   res = ast_play_and_wait(chan, "vm-Olds");
07704             } else {
07705                res = say_and_wait(chan, vms->oldmessages, chan->language);
07706                if (!res)
07707                   res = ast_play_and_wait(chan, "vm-messages");
07708                if (!res)
07709                   res = ast_play_and_wait(chan, "vm-Old");
07710             }
07711          }
07712       }
07713    }
07714 return res;
07715 }

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

Definition at line 7763 of file app_voicemail.c.

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

Referenced by vm_intro().

07764 {
07765    /* Introduce messages they have */
07766    int res;
07767    res = ast_play_and_wait(chan, "vm-youhave");
07768    if (!res) {
07769       if (vms->newmessages) {
07770          res = say_and_wait(chan, vms->newmessages, chan->language);
07771          if (!res)
07772             res = ast_play_and_wait(chan, "vm-INBOX");
07773          if (vms->oldmessages && !res)
07774             res = ast_play_and_wait(chan, "vm-and");
07775          else if (!res) {
07776             if ((vms->newmessages == 1))
07777                res = ast_play_and_wait(chan, "vm-message");
07778             else
07779                res = ast_play_and_wait(chan, "vm-messages");
07780          }
07781             
07782       }
07783       if (!res && vms->oldmessages) {
07784          res = say_and_wait(chan, vms->oldmessages, chan->language);
07785          if (!res)
07786             res = ast_play_and_wait(chan, "vm-Old");
07787          if (!res) {
07788             if (vms->oldmessages == 1)
07789                res = ast_play_and_wait(chan, "vm-message");
07790             else
07791                res = ast_play_and_wait(chan, "vm-messages");
07792          }
07793       }
07794       if (!res) {
07795          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07796             res = ast_play_and_wait(chan, "vm-no");
07797             if (!res)
07798                res = ast_play_and_wait(chan, "vm-messages");
07799          }
07800       }
07801    }
07802    return res;
07803 }

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

Definition at line 7164 of file app_voicemail.c.

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

Referenced by vm_intro().

07165 {
07166    int res = 0;
07167 
07168    if (vms->newmessages) {
07169       res = ast_play_and_wait(chan, "vm-youhave");
07170       if (!res) 
07171          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07172       if (!res) {
07173          if ((vms->newmessages == 1)) {
07174             res = ast_play_and_wait(chan, "vm-INBOX");
07175             if (!res)
07176                res = ast_play_and_wait(chan, "vm-message");
07177          } else {
07178             res = ast_play_and_wait(chan, "vm-INBOXs");
07179             if (!res)
07180                res = ast_play_and_wait(chan, "vm-messages");
07181          }
07182       }
07183    } else if (vms->oldmessages){
07184       res = ast_play_and_wait(chan, "vm-youhave");
07185       if (!res)
07186          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07187       if ((vms->oldmessages == 1)){
07188          res = ast_play_and_wait(chan, "vm-Old");
07189          if (!res)
07190             res = ast_play_and_wait(chan, "vm-message");
07191       } else {
07192          res = ast_play_and_wait(chan, "vm-Olds");
07193          if (!res)
07194             res = ast_play_and_wait(chan, "vm-messages");
07195       }
07196    } else if (!vms->oldmessages && !vms->newmessages) 
07197       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07198    return res;
07199 }

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

Definition at line 7298 of file app_voicemail.c.

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

Referenced by vm_intro().

07299 {
07300    int res = 0;
07301 
07302    /* Introduce messages they have */
07303    if (!res) {
07304       if ((vms->newmessages) || (vms->oldmessages)) {
07305          res = ast_play_and_wait(chan, "vm-youhave");
07306       }
07307       /*
07308        * The word "shtei" refers to the number 2 in hebrew when performing a count
07309        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
07310        * an element, this is one of them.
07311        */
07312       if (vms->newmessages) {
07313          if (!res) {
07314             if (vms->newmessages == 1) {
07315                res = ast_play_and_wait(chan, "vm-INBOX1");
07316             } else {
07317                if (vms->newmessages == 2) {
07318                   res = ast_play_and_wait(chan, "vm-shtei");
07319                } else {
07320                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07321                }
07322                res = ast_play_and_wait(chan, "vm-INBOX");
07323             }
07324          }
07325          if (vms->oldmessages && !res) {
07326             res = ast_play_and_wait(chan, "vm-and");
07327             if (vms->oldmessages == 1) {
07328                res = ast_play_and_wait(chan, "vm-Old1");
07329             } else {
07330                if (vms->oldmessages == 2) {
07331                   res = ast_play_and_wait(chan, "vm-shtei");
07332                } else {
07333                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07334                }
07335                res = ast_play_and_wait(chan, "vm-Old");
07336             }
07337          }
07338       }
07339       if (!res && vms->oldmessages && !vms->newmessages) {
07340          if (!res) {
07341             if (vms->oldmessages == 1) {
07342                res = ast_play_and_wait(chan, "vm-Old1");
07343             } else {
07344                if (vms->oldmessages == 2) {
07345                   res = ast_play_and_wait(chan, "vm-shtei");
07346                } else {
07347                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
07348                }
07349                res = ast_play_and_wait(chan, "vm-Old");
07350             }
07351          }
07352       }
07353       if (!res) {
07354          if (!vms->oldmessages && !vms->newmessages) {
07355             if (!res) {
07356                res = ast_play_and_wait(chan, "vm-nomessages");
07357             }
07358          }
07359       }
07360    }
07361    return res;
07362 }

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

Definition at line 7422 of file app_voicemail.c.

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

Referenced by vm_intro().

07423 {
07424    /* Introduce messages they have */
07425    int res;
07426    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
07427       res = ast_play_and_wait(chan, "vm-no") ||
07428          ast_play_and_wait(chan, "vm-message");
07429    else
07430       res = ast_play_and_wait(chan, "vm-youhave");
07431    if (!res && vms->newmessages) {
07432       res = (vms->newmessages == 1) ?
07433          ast_play_and_wait(chan, "digits/un") ||
07434          ast_play_and_wait(chan, "vm-nuovo") ||
07435          ast_play_and_wait(chan, "vm-message") :
07436          /* 2 or more new messages */
07437          say_and_wait(chan, vms->newmessages, chan->language) ||
07438          ast_play_and_wait(chan, "vm-nuovi") ||
07439          ast_play_and_wait(chan, "vm-messages");
07440       if (!res && vms->oldmessages)
07441          res = ast_play_and_wait(chan, "vm-and");
07442    }
07443    if (!res && vms->oldmessages) {
07444       res = (vms->oldmessages == 1) ?
07445          ast_play_and_wait(chan, "digits/un") ||
07446          ast_play_and_wait(chan, "vm-vecchio") ||
07447          ast_play_and_wait(chan, "vm-message") :
07448          /* 2 or more old messages */
07449          say_and_wait(chan, vms->oldmessages, chan->language) ||
07450          ast_play_and_wait(chan, "vm-vecchi") ||
07451          ast_play_and_wait(chan, "vm-messages");
07452    }
07453    return res;
07454 }

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

Definition at line 7258 of file app_voicemail.c.

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

Referenced by vm_intro().

07259 {
07260    int res;
07261    int lastnum = 0;
07262 
07263    res = ast_play_and_wait(chan, "vm-youhave");
07264 
07265    if (!res && vms->newmessages) {
07266       lastnum = vms->newmessages;
07267 
07268       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07269          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
07270       }
07271 
07272       if (!res && vms->oldmessages) {
07273          res = ast_play_and_wait(chan, "vm-and");
07274       }
07275    }
07276 
07277    if (!res && vms->oldmessages) {
07278       lastnum = vms->oldmessages;
07279 
07280       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07281          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
07282       }
07283    }
07284 
07285    if (!res) {
07286       if (lastnum == 0) {
07287          res = ast_play_and_wait(chan, "vm-no");
07288       }
07289       if (!res) {
07290          res = ast_say_counted_noun(chan, lastnum, "vm-message");
07291       }
07292    }
07293 
07294    return res;
07295 }

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

Definition at line 7806 of file app_voicemail.c.

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

Referenced by vm_intro().

07807 {
07808    /* Introduce messages they have */
07809    int res;
07810    res = ast_play_and_wait(chan, "vm-youhave");
07811    if (!res) {
07812       if (vms->newmessages) {
07813          res = say_and_wait(chan, vms->newmessages, chan->language);
07814          if (!res) {
07815             if (vms->newmessages == 1)
07816                res = ast_play_and_wait(chan, "vm-INBOXs");
07817             else
07818                res = ast_play_and_wait(chan, "vm-INBOX");
07819          }
07820          if (vms->oldmessages && !res)
07821             res = ast_play_and_wait(chan, "vm-and");
07822          else if (!res) {
07823             if ((vms->newmessages == 1))
07824                res = ast_play_and_wait(chan, "vm-message");
07825             else
07826                res = ast_play_and_wait(chan, "vm-messages");
07827          }
07828             
07829       }
07830       if (!res && vms->oldmessages) {
07831          res = say_and_wait(chan, vms->oldmessages, chan->language);
07832          if (!res) {
07833             if (vms->oldmessages == 1)
07834                res = ast_play_and_wait(chan, "vm-Olds");
07835             else
07836                res = ast_play_and_wait(chan, "vm-Old");
07837          }
07838          if (!res) {
07839             if (vms->oldmessages == 1)
07840                res = ast_play_and_wait(chan, "vm-message");
07841             else
07842                res = ast_play_and_wait(chan, "vm-messages");
07843          }
07844       }
07845       if (!res) {
07846          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07847             res = ast_play_and_wait(chan, "vm-no");
07848             if (!res)
07849                res = ast_play_and_wait(chan, "vm-messages");
07850          }
07851       }
07852    }
07853    return res;
07854 }

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

Definition at line 7572 of file app_voicemail.c.

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

Referenced by vm_intro().

07573 {
07574    /* Introduce messages they have */
07575    int res;
07576 
07577    res = ast_play_and_wait(chan, "vm-youhave");
07578    if (res)
07579       return res;
07580 
07581    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07582       res = ast_play_and_wait(chan, "vm-no");
07583       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07584       return res;
07585    }
07586 
07587    if (vms->newmessages) {
07588       if ((vms->newmessages == 1)) {
07589          res = ast_play_and_wait(chan, "digits/1");
07590          res = res ? res : ast_play_and_wait(chan, "vm-ny");
07591          res = res ? res : ast_play_and_wait(chan, "vm-message");
07592       } else {
07593          res = say_and_wait(chan, vms->newmessages, chan->language);
07594          res = res ? res : ast_play_and_wait(chan, "vm-nye");
07595          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07596       }
07597       if (!res && vms->oldmessages)
07598          res = ast_play_and_wait(chan, "vm-and");
07599    }
07600    if (!res && vms->oldmessages) {
07601       if (vms->oldmessages == 1) {
07602          res = ast_play_and_wait(chan, "digits/1");
07603          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
07604          res = res ? res : ast_play_and_wait(chan, "vm-message");
07605       } else {
07606          res = say_and_wait(chan, vms->oldmessages, chan->language);
07607          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
07608          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07609       }
07610    }
07611 
07612    return res;
07613 }

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

Definition at line 7457 of file app_voicemail.c.

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

Referenced by vm_intro().

07458 {
07459    /* Introduce messages they have */
07460    int res;
07461    div_t num;
07462 
07463    if (!vms->oldmessages && !vms->newmessages) {
07464       res = ast_play_and_wait(chan, "vm-no");
07465       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07466       return res;
07467    } else {
07468       res = ast_play_and_wait(chan, "vm-youhave");
07469    }
07470 
07471    if (vms->newmessages) {
07472       num = div(vms->newmessages, 10);
07473       if (vms->newmessages == 1) {
07474          res = ast_play_and_wait(chan, "digits/1-a");
07475          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
07476          res = res ? res : ast_play_and_wait(chan, "vm-message");
07477       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07478          if (num.rem == 2) {
07479             if (!num.quot) {
07480                res = ast_play_and_wait(chan, "digits/2-ie");
07481             } else {
07482                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
07483                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07484             }
07485          } else {
07486             res = say_and_wait(chan, vms->newmessages, chan->language);
07487          }
07488          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
07489          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07490       } else {
07491          res = say_and_wait(chan, vms->newmessages, chan->language);
07492          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
07493          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07494       }
07495       if (!res && vms->oldmessages)
07496          res = ast_play_and_wait(chan, "vm-and");
07497    }
07498    if (!res && vms->oldmessages) {
07499       num = div(vms->oldmessages, 10);
07500       if (vms->oldmessages == 1) {
07501          res = ast_play_and_wait(chan, "digits/1-a");
07502          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
07503          res = res ? res : ast_play_and_wait(chan, "vm-message");
07504       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07505          if (num.rem == 2) {
07506             if (!num.quot) {
07507                res = ast_play_and_wait(chan, "digits/2-ie");
07508             } else {
07509                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
07510                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07511             }
07512          } else {
07513             res = say_and_wait(chan, vms->oldmessages, chan->language);
07514          }
07515          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
07516          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07517       } else {
07518          res = say_and_wait(chan, vms->oldmessages, chan->language);
07519          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
07520          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07521       }
07522    }
07523 
07524    return res;
07525 }

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

Definition at line 7857 of file app_voicemail.c.

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

Referenced by vm_intro().

07858 {
07859    /* Introduce messages they have */
07860    int res;
07861    res = ast_play_and_wait(chan, "vm-youhave");
07862    if (!res) {
07863       if (vms->newmessages) {
07864          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07865          if (!res) {
07866             if ((vms->newmessages == 1)) {
07867                res = ast_play_and_wait(chan, "vm-message");
07868                if (!res)
07869                   res = ast_play_and_wait(chan, "vm-INBOXs");
07870             } else {
07871                res = ast_play_and_wait(chan, "vm-messages");
07872                if (!res)
07873                   res = ast_play_and_wait(chan, "vm-INBOX");
07874             }
07875          }
07876          if (vms->oldmessages && !res)
07877             res = ast_play_and_wait(chan, "vm-and");
07878       }
07879       if (!res && vms->oldmessages) {
07880          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07881          if (!res) {
07882             if (vms->oldmessages == 1) {
07883                res = ast_play_and_wait(chan, "vm-message");
07884                if (!res)
07885                   res = ast_play_and_wait(chan, "vm-Olds");
07886             } else {
07887                res = ast_play_and_wait(chan, "vm-messages");
07888                if (!res)
07889                   res = ast_play_and_wait(chan, "vm-Old");
07890             }
07891          }
07892       }
07893       if (!res) {
07894          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07895             res = ast_play_and_wait(chan, "vm-no");
07896             if (!res)
07897                res = ast_play_and_wait(chan, "vm-messages");
07898          }
07899       }
07900    }
07901    return res;
07902 }

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

Definition at line 7718 of file app_voicemail.c.

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

Referenced by vm_intro().

07718                                                                          {
07719    /* Introduce messages they have */
07720    int res;
07721    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07722       res = ast_play_and_wait(chan, "vm-nomessages");
07723       return res;
07724    } else {
07725       res = ast_play_and_wait(chan, "vm-youhave");
07726    }
07727    if (vms->newmessages) {
07728       if (!res)
07729          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07730       if ((vms->newmessages == 1)) {
07731          if (!res)
07732             res = ast_play_and_wait(chan, "vm-message");
07733          if (!res)
07734             res = ast_play_and_wait(chan, "vm-INBOXs");
07735       } else {
07736          if (!res)
07737             res = ast_play_and_wait(chan, "vm-messages");
07738          if (!res)
07739             res = ast_play_and_wait(chan, "vm-INBOX");
07740       }
07741       if (vms->oldmessages && !res)
07742          res = ast_play_and_wait(chan, "vm-and");
07743    }
07744    if (vms->oldmessages) {
07745       if (!res)
07746          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07747       if (vms->oldmessages == 1) {
07748          if (!res)
07749             res = ast_play_and_wait(chan, "vm-message");
07750          if (!res)
07751             res = ast_play_and_wait(chan, "vm-Olds");
07752       } else {
07753          if (!res)
07754             res = ast_play_and_wait(chan, "vm-messages");
07755          if (!res)
07756             res = ast_play_and_wait(chan, "vm-Old");
07757       }
07758    }
07759    return res;
07760 }

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

Definition at line 7528 of file app_voicemail.c.

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

Referenced by vm_intro().

07529 {
07530    /* Introduce messages they have */
07531    int res;
07532 
07533    res = ast_play_and_wait(chan, "vm-youhave");
07534    if (res)
07535       return res;
07536 
07537    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07538       res = ast_play_and_wait(chan, "vm-no");
07539       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07540       return res;
07541    }
07542 
07543    if (vms->newmessages) {
07544       if ((vms->newmessages == 1)) {
07545          res = ast_play_and_wait(chan, "digits/ett");
07546          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
07547          res = res ? res : ast_play_and_wait(chan, "vm-message");
07548       } else {
07549          res = say_and_wait(chan, vms->newmessages, chan->language);
07550          res = res ? res : ast_play_and_wait(chan, "vm-nya");
07551          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07552       }
07553       if (!res && vms->oldmessages)
07554          res = ast_play_and_wait(chan, "vm-and");
07555    }
07556    if (!res && vms->oldmessages) {
07557       if (vms->oldmessages == 1) {
07558          res = ast_play_and_wait(chan, "digits/ett");
07559          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
07560          res = res ? res : ast_play_and_wait(chan, "vm-message");
07561       } else {
07562          res = say_and_wait(chan, vms->oldmessages, chan->language);
07563          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
07564          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07565       }
07566    }
07567 
07568    return res;
07569 }

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

Definition at line 7981 of file app_voicemail.c.

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

Referenced by vm_intro().

07982 {
07983    int res;
07984    /* Introduce messages they have */
07985    res = ast_play_and_wait(chan, "vm-you");
07986 
07987    if (!res && vms->newmessages) {
07988       res = ast_play_and_wait(chan, "vm-have");
07989       if (!res)
07990          res = say_and_wait(chan, vms->newmessages, chan->language);
07991       if (!res)
07992          res = ast_play_and_wait(chan, "vm-tong");
07993       if (!res)
07994          res = ast_play_and_wait(chan, "vm-INBOX");
07995       if (vms->oldmessages && !res)
07996          res = ast_play_and_wait(chan, "vm-and");
07997       else if (!res) 
07998          res = ast_play_and_wait(chan, "vm-messages");
07999    }
08000    if (!res && vms->oldmessages) {
08001       res = ast_play_and_wait(chan, "vm-have");
08002       if (!res)
08003          res = say_and_wait(chan, vms->oldmessages, chan->language);
08004       if (!res)
08005          res = ast_play_and_wait(chan, "vm-tong");
08006       if (!res)
08007          res = ast_play_and_wait(chan, "vm-Old");
08008       if (!res)
08009          res = ast_play_and_wait(chan, "vm-messages");
08010    }
08011    if (!res && !vms->oldmessages && !vms->newmessages) {
08012       res = ast_play_and_wait(chan, "vm-haveno");
08013       if (!res)
08014          res = ast_play_and_wait(chan, "vm-messages");
08015    }
08016    return res;
08017 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

02726 {
02727    switch (ast_lock_path(path)) {
02728    case AST_LOCK_TIMEOUT:
02729       return -1;
02730    default:
02731       return 0;
02732    }
02733 }

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

Definition at line 1272 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01273 {
01274    FILE *p = NULL;
01275    int pfd = mkstemp(template);
01276    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01277    if (pfd > -1) {
01278       p = fdopen(pfd, "w+");
01279       if (!p) {
01280          close(pfd);
01281          pfd = -1;
01282       }
01283    }
01284    return p;
01285 }

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 8182 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, check_password(), ast_vm_user::context, 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().

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

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 8274 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(), check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::mailbox, 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().

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

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

Definition at line 7133 of file app_voicemail.c.

References ast_play_and_wait(), 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_zh().

07134 {
07135    int cmd;
07136 
07137    if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) { /* Italian, Spanish, French or Portuguese syntax */
07138       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07139       return cmd ? cmd : ast_play_and_wait(chan, box);
07140    } else if (!strcasecmp(chan->language, "gr")){
07141       return vm_play_folder_name_gr(chan, box);
07142    } else if (!strcasecmp(chan->language, "pl")){
07143       return vm_play_folder_name_pl(chan, box);
07144    } else if (!strcasecmp(chan->language, "ua")){  /* Ukrainian syntax */
07145       return vm_play_folder_name_ua(chan, box);
07146    } else {  /* Default English */
07147       cmd = ast_play_and_wait(chan, box);
07148       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07149    }
07150 }

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

Definition at line 7086 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07087 {
07088    int cmd;
07089    char *buf;
07090 
07091    buf = alloca(strlen(box)+2); 
07092    strcpy(buf, box);
07093    strcat(buf,"s");
07094 
07095    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07096       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07097       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07098    } else {
07099       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07100       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07101    }
07102 }

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

Definition at line 7104 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07105 {
07106    int cmd;
07107 
07108    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07109       if (!strcasecmp(box, "vm-INBOX"))
07110          cmd = ast_play_and_wait(chan, "vm-new-e");
07111       else
07112          cmd = ast_play_and_wait(chan, "vm-old-e");
07113       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07114    } else {
07115       cmd = ast_play_and_wait(chan, "vm-messages");
07116       return cmd ? cmd : ast_play_and_wait(chan, box);
07117    }
07118 }

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

Definition at line 7120 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07121 {
07122    int cmd;
07123 
07124    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07125       cmd = ast_play_and_wait(chan, "vm-messages");
07126       return cmd ? cmd : ast_play_and_wait(chan, box);
07127    } else {
07128       cmd = ast_play_and_wait(chan, box);
07129       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07130    }
07131 }

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 8405 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(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

08406 {
08407    int cmd = 0;
08408    int retries = 0;
08409    int duration = 0;
08410    char prefile[PATH_MAX] = "";
08411    unsigned char buf[256];
08412    int bytes = 0;
08413 
08414    if (ast_adsi_available(chan)) {
08415       bytes += adsi_logo(buf + bytes);
08416       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
08417       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08418       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08419       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08420       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08421    }
08422 
08423    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08424    while ((cmd >= 0) && (cmd != 't')) {
08425       if (cmd)
08426          retries = 0;
08427       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08428       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
08429          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08430          cmd = 't';  
08431       } else {
08432          switch (cmd) {
08433          case '1':
08434             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08435             break;
08436          case '2':
08437             DELETE(prefile, -1, prefile, vmu);
08438             ast_play_and_wait(chan, "vm-tempremoved");
08439             cmd = 't';  
08440             break;
08441          case '*': 
08442             cmd = 't';
08443             break;
08444          default:
08445             cmd = ast_play_and_wait(chan,
08446                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
08447                   "vm-tempgreeting2" : "vm-tempgreeting");
08448             if (!cmd)
08449                cmd = ast_waitfordigit(chan,6000);
08450             if (!cmd)
08451                retries++;
08452             if (retries > 3)
08453                cmd = 't';
08454          }
08455       }
08456       DISPOSE(prefile, -1);
08457    }
08458    if (cmd == 't')
08459       cmd = 0;
08460    return cmd;
08461 }

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

Definition at line 9688 of file app_voicemail.c.

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

Referenced by load_module().

09689 {
09690    char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
09691    struct ast_vm_user vmus;
09692    char *options = NULL;
09693    int silent = 0, skipuser = 0;
09694    int res = -1;
09695    
09696    if (s) {
09697       s = ast_strdupa(s);
09698       user = strsep(&s, ",");
09699       options = strsep(&s, ",");
09700       if (user) {
09701          s = user;
09702          user = strsep(&s, "@");
09703          context = strsep(&s, "");
09704          if (!ast_strlen_zero(user))
09705             skipuser++;
09706          ast_copy_string(mailbox, user, sizeof(mailbox));
09707       }
09708    }
09709 
09710    if (options) {
09711       silent = (strchr(options, 's')) != NULL;
09712    }
09713 
09714    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
09715       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
09716       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
09717       ast_play_and_wait(chan, "auth-thankyou");
09718       res = 0;
09719    }
09720 
09721    return res;
09722 }

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

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 3814 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().

03815 {
03816    const struct vm_zone *z = NULL;
03817    struct timeval t = ast_tvnow();
03818 
03819    /* Does this user have a timezone specified? */
03820    if (!ast_strlen_zero(vmu->zonetag)) {
03821       /* Find the zone in the list */
03822       AST_LIST_LOCK(&zones);
03823       AST_LIST_TRAVERSE(&zones, z, list) {
03824          if (!strcmp(z->name, vmu->zonetag))
03825             break;
03826       }
03827       AST_LIST_UNLOCK(&zones);
03828    }
03829    ast_localtime(&t, tm, z ? z->timezone : NULL);
03830    return tm;
03831 }

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

Definition at line 6536 of file app_voicemail.c.

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

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

06537 {
06538    int res;
06539    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
06540       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
06541    return res;
06542 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "DAHDI Telephony w/PRI & SS7" , .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 11488 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 504 of file app_voicemail.c.

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

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

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 687 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 578 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 581 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 583 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 584 of file app_voicemail.c.

Definition at line 11488 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 671 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

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

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

Referenced by load_config(), and play_message_callerid().

struct ast_cli_entry cli_voicemail[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_voicemail_show_users, "List defined voicemail boxes"),
   AST_CLI_DEFINE(handle_voicemail_show_zones, "List zone message formats"),
   AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"),
}

Definition at line 9920 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* descrip_vm [static]

Definition at line 508 of file app_voicemail.c.

char* descrip_vm_box_exists [static]

Definition at line 555 of file app_voicemail.c.

char* descrip_vmain [static]

Definition at line 537 of file app_voicemail.c.

char* descrip_vmauthenticate [static]

Definition at line 567 of file app_voicemail.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]
char* emailbody = NULL [static]

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

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

char* emailsubject = NULL [static]

Definition at line 678 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

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

char ext_pass_cmd[128] [static]

Definition at line 483 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 595 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 681 of file app_voicemail.c.

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

struct ast_flags globalflags = {0} [static]
char listen_control_forward_key[12] [static]

Definition at line 652 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 654 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 655 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 653 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 656 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

Definition at line 9678 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char mailcmd[160] [static]

Definition at line 594 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 591 of file app_voicemail.c.

int maxgreet [static]

Definition at line 601 of file app_voicemail.c.

int maxlogins [static]

Definition at line 603 of file app_voicemail.c.

int maxmsg [static]

Definition at line 590 of file app_voicemail.c.

int maxsilence [static]

Definition at line 589 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 604 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 621 of file app_voicemail.c.

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

int my_umask [static]

Definition at line 486 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 679 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 682 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 680 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 616 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 611 of file app_voicemail.c.

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

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 617 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 618 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 490 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 668 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char serveremail[80] [static]

Definition at line 593 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 592 of file app_voicemail.c.

int skipms [static]

Definition at line 602 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 596 of file app_voicemail.c.

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

Definition at line 506 of file app_voicemail.c.

char* synopsis_vm_box_exists [static]
Initial value:
"Check to see if Voicemail mailbox exists"

Definition at line 552 of file app_voicemail.c.

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

Definition at line 535 of file app_voicemail.c.

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

Definition at line 565 of file app_voicemail.c.

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

Definition at line 502 of file app_voicemail.c.

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

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

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

Definition at line 663 of file app_voicemail.c.

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

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

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

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

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

Definition at line 659 of file app_voicemail.c.

Referenced by load_config(), and vm_authenticate().

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

Definition at line 662 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 481 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 597 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 600 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 599 of file app_voicemail.c.

double volgain [static]

Definition at line 598 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 588 of file app_voicemail.c.

Referenced by build_peer().


Generated on 3 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1