Wed Oct 29 05:02:53 2014

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/astobj2.h"
#include "asterisk/event.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.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  inprocess
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  vm_state
struct  vm_zone

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 DATA_EXPORT_VM_USERS(USER)
#define DATA_EXPORT_VM_ZONES(ZONE)
#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 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 OPERATOR_EXIT   300
#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  vm_box {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER
}
enum  vm_option_args { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }
enum  vm_option_flags {
  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  vm_passwordlocation { OPT_PWLOC_VOICEMAILCONF = 0, OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2 }

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int actual_load_config (int reload, struct ast_config *cfg, struct ast_config *ucfg)
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.
 AST_APP_OPTIONS (vm_app_options,{AST_APP_OPTION('s', OPT_SILENT), AST_APP_OPTION('b', OPT_BUSY_GREETING), AST_APP_OPTION('u', OPT_UNAVAIL_GREETING), AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN), AST_APP_OPTION_ARG('d', OPT_DTMFEXIT, OPT_ARG_DTMFEXIT), AST_APP_OPTION('p', OPT_PREPEND_MAILBOX), AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER), AST_APP_OPTION('U', OPT_MESSAGE_Urgent),})
 AST_DATA_STRUCTURE (vm_zone, DATA_EXPORT_VM_ZONES)
 AST_DATA_STRUCTURE (ast_vm_user, DATA_EXPORT_VM_USERS)
static AST_LIST_HEAD_STATIC (zones, vm_zone)
static AST_LIST_HEAD_STATIC (users, ast_vm_user)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,.load=load_module,.unload=unload_module,.reload=reload,.nonoptreq="res_adsi,res_smdi",)
 AST_MUTEX_DEFINE_STATIC (poll_lock)
static AST_RWLIST_HEAD_STATIC (mwi_subs, mwi_sub)
static const char * ast_str_encode_mime (struct ast_str **end, ssize_t maxlen, const char *start, 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 const char * ast_str_quote (struct ast_str **buf, ssize_t maxlen, const char *from)
 Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
 AST_TEST_DEFINE (test_voicemail_vmuser)
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 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 get_folder_by_name (const char *name)
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 inprocess_cmp_fn (void *obj, void *arg, int flags)
static int inprocess_count (const char *context, const char *mailbox, int delta)
static int inprocess_hash_fn (const void *obj, const int flags)
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 (struct ast_vm_user *vmu, 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, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static void poll_subscribed_mailbox (struct mwi_sub *mwi_sub)
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, const char *category, const char *flag)
static void queue_mwi_event (const char *box, int urgent, int new, int old)
static void read_password_from_file (const char *secretfn, char *password, int passwordlen)
static int reload (void)
static void rename_file (char *sfn, char *dfn)
 Renames a message in a mailbox folder.
static int resequence_mailbox (struct ast_vm_user *vmu, char *dir, int stopcount)
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_and_high (const char *input, char *buf, size_t buflen)
 Strips control and non 7-bit clean characters from input string.
static const char * substitute_escapes (const char *value)
static int unload_module (void)
static int valid_config (const struct ast_config *cfg)
 Check if configuration file is valid.
static int vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
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, const char *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_vi (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Vietnamese 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, const char *data)
static int vm_execmain (struct ast_channel *chan, const char *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_cs (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_vi (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 vm_users_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int vm_users_data_provider_get_helper (const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
static int vmauthenticate (struct ast_channel *chan, const char *data)
static int vmsayname_exec (struct ast_channel *chan, const char *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.
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)
static int write_password_to_file (const char *secretfn, const char *password)

Variables

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 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 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}
struct ao2_containerinprocess_container
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 char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
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 pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
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 * sayname_app = "VMSayName"
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_data_entry vm_data_providers []
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_prepend_timeout [80] = "vm-then-pound"
static char vm_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
static struct ast_data_handler vm_users_data_provider
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, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage
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 438 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 461 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 462 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 435 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 431 of file app_voicemail.c.

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

Definition at line 748 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11362 of file app_voicemail.c.

#define DATA_EXPORT_VM_ZONES ( ZONE   ) 
Value:
ZONE(vm_zone, name, AST_DATA_STRING)      \
   ZONE(vm_zone, timezone, AST_DATA_STRING)  \
   ZONE(vm_zone, msg_format, AST_DATA_STRING)

Definition at line 11389 of file app_voicemail.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 443 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 445 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 446 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 444 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 447 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 818 of file app_voicemail.c.

Referenced by actual_load_config().

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

Definition at line 466 of file app_voicemail.c.

Referenced by add_email_attachment(), base_encode(), make_email_file(), ochar(), and sendpage().

#define ERROR_LOCK_PATH   -100

Definition at line 491 of file app_voicemail.c.

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

Definition at line 746 of file app_voicemail.c.

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

#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"

Definition at line 454 of file app_voicemail.c.

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

#define MAX_DATETIME_FORMAT   512

Definition at line 469 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 470 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 456 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

#define MAXMSGLIMIT   9999

Definition at line 457 of file app_voicemail.c.

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

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 459 of file app_voicemail.c.

Referenced by actual_load_config().

#define OPERATOR_EXIT   300

Definition at line 492 of file app_voicemail.c.

Referenced by leave_voicemail(), vm_exec(), and vm_execmain().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 761 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 760 of file app_voicemail.c.

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

#define RENAME ( a,
b,
c,
d,
e,
f,
g,
 )     (rename_file(g,h));
#define RETRIEVE ( a,
b,
c,
 ) 
#define SENDMAIL   "/usr/sbin/sendmail -t"

Definition at line 452 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

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

#define VALID_DTMF   "1234567890*#"

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

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

#define VM_ATTACH   (1 << 11)
#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 484 of file app_voicemail.c.

Referenced by apply_option(), AST_TEST_DEFINE(), 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 482 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 476 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_message().

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 480 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_newuser().

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 479 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_newuser().

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 490 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 489 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_instructions_en().

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 488 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and close_mailbox().

#define VM_OPERATOR   (1 << 1)

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

Definition at line 473 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), leave_voicemail(), 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 481 of file app_voicemail.c.

Referenced by actual_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 472 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_record_review().

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 474 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_message().

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 477 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and play_message().

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 486 of file app_voicemail.c.

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

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 478 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_execmain().

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 475 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_execmain().

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 487 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_intro().

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 685 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 437 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 433 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 434 of file app_voicemail.c.

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


Enumeration Type Documentation

enum vm_box
Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 495 of file app_voicemail.c.

00495             {
00496    NEW_FOLDER,
00497    OLD_FOLDER,
00498    WORK_FOLDER,
00499    FAMILY_FOLDER,
00500    FRIENDS_FOLDER,
00501    GREETINGS_FOLDER
00502 };

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 516 of file app_voicemail.c.

00516                     {
00517    OPT_ARG_RECORDGAIN = 0,
00518    OPT_ARG_PLAYFOLDER = 1,
00519    OPT_ARG_DTMFEXIT   = 2,
00520    /* This *must* be the last value in this enum! */
00521    OPT_ARG_ARRAY_SIZE = 3,
00522 };

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

00504                      {
00505    OPT_SILENT =           (1 << 0),
00506    OPT_BUSY_GREETING =    (1 << 1),
00507    OPT_UNAVAIL_GREETING = (1 << 2),
00508    OPT_RECORDGAIN =       (1 << 3),
00509    OPT_PREPEND_MAILBOX =  (1 << 4),
00510    OPT_AUTOPLAY =         (1 << 6),
00511    OPT_DTMFEXIT =         (1 << 7),
00512    OPT_MESSAGE_Urgent =   (1 << 8),
00513    OPT_MESSAGE_PRIORITY = (1 << 9)
00514 };

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 524 of file app_voicemail.c.

00524                          {
00525    OPT_PWLOC_VOICEMAILCONF = 0,
00526    OPT_PWLOC_SPOOLDIR      = 1,
00527    OPT_PWLOC_USERSCONF     = 2,
00528 };


Function Documentation

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

Definition at line 5409 of file app_voicemail.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

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

05410 {
05411    DIR *dir;
05412    struct dirent *de;
05413    char fn[256];
05414    int ret = 0;
05415 
05416    /* If no mailbox, return immediately */
05417    if (ast_strlen_zero(mailbox))
05418       return 0;
05419 
05420    if (ast_strlen_zero(folder))
05421       folder = "INBOX";
05422    if (ast_strlen_zero(context))
05423       context = "default";
05424 
05425    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05426 
05427    if (!(dir = opendir(fn)))
05428       return 0;
05429 
05430    while ((de = readdir(dir))) {
05431       if (!strncasecmp(de->d_name, "msg", 3)) {
05432          if (shortcircuit) {
05433             ret = 1;
05434             break;
05435          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05436             ret++;
05437          }
05438       }
05439    }
05440 
05441    closedir(dir);
05442 
05443    return ret;
05444 }

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

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

11066 {
11067    struct ast_vm_user svm;
11068    AST_DECLARE_APP_ARGS(arg,
11069       AST_APP_ARG(mbox);
11070       AST_APP_ARG(context);
11071    );
11072 
11073    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11074 
11075    if (ast_strlen_zero(arg.mbox)) {
11076       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11077       return -1;
11078    }
11079 
11080    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11081    return 0;
11082 }

static int actual_load_config ( int  reload,
struct ast_config cfg,
struct ast_config ucfg 
) [static]

Definition at line 11899 of file app_voicemail.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), 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_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, 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, ext_pass_check_cmd, ext_pass_cmd, externnotify, 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, locale, LOG_ERROR, ast_vm_user::mailbox, mailcmd, MAX_NUM_CID_CONTEXTS, maxdeletedmsg, maxgreet, maxlogins, MAXMSG, maxmsg, MAXMSGLIMIT, maxsilence, MINPASSWORD, minpassword, ast_variable::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, ast_vm_user::password, ast_vm_user::passwordlocation, passwordlocation, poll_freq, poll_mailboxes, poll_thread, populate_defaults(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, serveremail, silencethreshold, skipms, smdi_iface, start_poll_thread(), stop_poll_thread(), substitute_escapes(), THRESHOLD_SILENCE, userscontext, 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_pls_try_again, vm_prepend_timeout, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SPOOL_DIR, VM_SVMAIL, VM_TEMPGREETWARN, vmfmts, vmmaxsecs, vmminsecs, volgain, and zonetag.

Referenced by load_config().

11900 {
11901    struct ast_vm_user *current;
11902    char *cat;
11903    struct ast_variable *var;
11904    const char *val;
11905    char *q, *stringp, *tmp;
11906    int x;
11907    unsigned int tmpadsi[4];
11908    char secretfn[PATH_MAX] = "";
11909 
11910 #ifdef IMAP_STORAGE
11911    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
11912 #endif
11913    /* set audio control prompts */
11914    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
11915    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
11916    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
11917    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
11918    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
11919 
11920    /* Free all the users structure */  
11921    free_vm_users();
11922 
11923    /* Free all the zones structure */
11924    free_vm_zones();
11925 
11926    AST_LIST_LOCK(&users);  
11927 
11928    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
11929    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
11930 
11931    if (cfg) {
11932       /* General settings */
11933 
11934       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
11935          val = "default";
11936       ast_copy_string(userscontext, val, sizeof(userscontext));
11937       /* Attach voice message to mail message ? */
11938       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
11939          val = "yes";
11940       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
11941 
11942       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
11943          val = "no";
11944       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
11945 
11946       volgain = 0.0;
11947       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
11948          sscanf(val, "%30lf", &volgain);
11949 
11950 #ifdef ODBC_STORAGE
11951       strcpy(odbc_database, "asterisk");
11952       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
11953          ast_copy_string(odbc_database, val, sizeof(odbc_database));
11954       }
11955       strcpy(odbc_table, "voicemessages");
11956       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
11957          ast_copy_string(odbc_table, val, sizeof(odbc_table));
11958       }
11959 #endif      
11960       /* Mail command */
11961       strcpy(mailcmd, SENDMAIL);
11962       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
11963          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
11964 
11965       maxsilence = 0;
11966       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
11967          maxsilence = atoi(val);
11968          if (maxsilence > 0)
11969             maxsilence *= 1000;
11970       }
11971       
11972       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
11973          maxmsg = MAXMSG;
11974       } else {
11975          maxmsg = atoi(val);
11976          if (maxmsg < 0) {
11977             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
11978             maxmsg = MAXMSG;
11979          } else if (maxmsg > MAXMSGLIMIT) {
11980             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11981             maxmsg = MAXMSGLIMIT;
11982          }
11983       }
11984 
11985       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
11986          maxdeletedmsg = 0;
11987       } else {
11988          if (sscanf(val, "%30d", &x) == 1)
11989             maxdeletedmsg = x;
11990          else if (ast_true(val))
11991             maxdeletedmsg = MAXMSG;
11992          else
11993             maxdeletedmsg = 0;
11994 
11995          if (maxdeletedmsg < 0) {
11996             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
11997             maxdeletedmsg = MAXMSG;
11998          } else if (maxdeletedmsg > MAXMSGLIMIT) {
11999             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
12000             maxdeletedmsg = MAXMSGLIMIT;
12001          }
12002       }
12003 
12004       /* Load date format config for voicemail mail */
12005       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
12006          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
12007       }
12008 
12009       /* Load date format config for voicemail pager mail */
12010       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
12011          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
12012       }
12013 
12014       /* External password changing command */
12015       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
12016          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
12017          pwdchange = PWDCHANGE_EXTERNAL;
12018       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
12019          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
12020          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
12021       }
12022  
12023       /* External password validation command */
12024       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
12025          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
12026          ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
12027       }
12028 
12029 #ifdef IMAP_STORAGE
12030       /* IMAP server address */
12031       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
12032          ast_copy_string(imapserver, val, sizeof(imapserver));
12033       } else {
12034          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
12035       }
12036       /* IMAP server port */
12037       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
12038          ast_copy_string(imapport, val, sizeof(imapport));
12039       } else {
12040          ast_copy_string(imapport, "143", sizeof(imapport));
12041       }
12042       /* IMAP server flags */
12043       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
12044          ast_copy_string(imapflags, val, sizeof(imapflags));
12045       }
12046       /* IMAP server master username */
12047       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
12048          ast_copy_string(authuser, val, sizeof(authuser));
12049       }
12050       /* IMAP server master password */
12051       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
12052          ast_copy_string(authpassword, val, sizeof(authpassword));
12053       }
12054       /* Expunge on exit */
12055       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
12056          if (ast_false(val))
12057             expungeonhangup = 0;
12058          else
12059             expungeonhangup = 1;
12060       } else {
12061          expungeonhangup = 1;
12062       }
12063       /* IMAP voicemail folder */
12064       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
12065          ast_copy_string(imapfolder, val, sizeof(imapfolder));
12066       } else {
12067          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
12068       }
12069       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
12070          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
12071       }
12072       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
12073          imapgreetings = ast_true(val);
12074       } else {
12075          imapgreetings = 0;
12076       }
12077       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
12078          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
12079       } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
12080          /* Also support greetingsfolder as documented in voicemail.conf.sample */
12081          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
12082       } else {
12083          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
12084       }
12085 
12086       /* There is some very unorthodox casting done here. This is due
12087        * to the way c-client handles the argument passed in. It expects a 
12088        * void pointer and casts the pointer directly to a long without
12089        * first dereferencing it. */
12090       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
12091          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
12092       } else {
12093          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
12094       }
12095 
12096       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
12097          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
12098       } else {
12099          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
12100       }
12101 
12102       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
12103          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
12104       } else {
12105          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
12106       }
12107 
12108       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
12109          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
12110       } else {
12111          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
12112       }
12113 
12114       /* Increment configuration version */
12115       imapversion++;
12116 #endif
12117       /* External voicemail notify application */
12118       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
12119          ast_copy_string(externnotify, val, sizeof(externnotify));
12120          ast_debug(1, "found externnotify: %s\n", externnotify);
12121       } else {
12122          externnotify[0] = '\0';
12123       }
12124 
12125       /* SMDI voicemail notification */
12126       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
12127          ast_debug(1, "Enabled SMDI voicemail notification\n");
12128          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
12129             smdi_iface = ast_smdi_interface_find(val);
12130          } else {
12131             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
12132             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
12133          }
12134          if (!smdi_iface) {
12135             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
12136          } 
12137       }
12138 
12139       /* Silence treshold */
12140       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
12141       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
12142          silencethreshold = atoi(val);
12143       
12144       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
12145          val = ASTERISK_USERNAME;
12146       ast_copy_string(serveremail, val, sizeof(serveremail));
12147       
12148       vmmaxsecs = 0;
12149       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
12150          if (sscanf(val, "%30d", &x) == 1) {
12151             vmmaxsecs = x;
12152          } else {
12153             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
12154          }
12155       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
12156          static int maxmessage_deprecate = 0;
12157          if (maxmessage_deprecate == 0) {
12158             maxmessage_deprecate = 1;
12159             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
12160          }
12161          if (sscanf(val, "%30d", &x) == 1) {
12162             vmmaxsecs = x;
12163          } else {
12164             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
12165          }
12166       }
12167 
12168       vmminsecs = 0;
12169       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
12170          if (sscanf(val, "%30d", &x) == 1) {
12171             vmminsecs = x;
12172             if (maxsilence / 1000 >= vmminsecs) {
12173                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
12174             }
12175          } else {
12176             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
12177          }
12178       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
12179          static int maxmessage_deprecate = 0;
12180          if (maxmessage_deprecate == 0) {
12181             maxmessage_deprecate = 1;
12182             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
12183          }
12184          if (sscanf(val, "%30d", &x) == 1) {
12185             vmminsecs = x;
12186             if (maxsilence / 1000 >= vmminsecs) {
12187                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
12188             }
12189          } else {
12190             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
12191          }
12192       }
12193 
12194       val = ast_variable_retrieve(cfg, "general", "format");
12195       if (!val) {
12196          val = "wav";   
12197       } else {
12198          tmp = ast_strdupa(val);
12199          val = ast_format_str_reduce(tmp);
12200          if (!val) {
12201             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
12202             val = "wav";
12203          }
12204       }
12205       ast_copy_string(vmfmts, val, sizeof(vmfmts));
12206 
12207       skipms = 3000;
12208       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
12209          if (sscanf(val, "%30d", &x) == 1) {
12210             maxgreet = x;
12211          } else {
12212             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
12213          }
12214       }
12215 
12216       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
12217          if (sscanf(val, "%30d", &x) == 1) {
12218             skipms = x;
12219          } else {
12220             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
12221          }
12222       }
12223 
12224       maxlogins = 3;
12225       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
12226          if (sscanf(val, "%30d", &x) == 1) {
12227             maxlogins = x;
12228          } else {
12229             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
12230          }
12231       }
12232 
12233       minpassword = MINPASSWORD;
12234       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
12235          if (sscanf(val, "%30d", &x) == 1) {
12236             minpassword = x;
12237          } else {
12238             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
12239          }
12240       }
12241 
12242       /* Force new user to record name ? */
12243       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
12244          val = "no";
12245       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
12246 
12247       /* Force new user to record greetings ? */
12248       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
12249          val = "no";
12250       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
12251 
12252       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
12253          ast_debug(1, "VM_CID Internal context string: %s\n", val);
12254          stringp = ast_strdupa(val);
12255          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
12256             if (!ast_strlen_zero(stringp)) {
12257                q = strsep(&stringp, ",");
12258                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
12259                   q++;
12260                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
12261                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
12262             } else {
12263                cidinternalcontexts[x][0] = '\0';
12264             }
12265          }
12266       }
12267       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
12268          ast_debug(1, "VM Review Option disabled globally\n");
12269          val = "no";
12270       }
12271       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
12272 
12273       /* Temporary greeting reminder */
12274       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
12275          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
12276          val = "no";
12277       } else {
12278          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
12279       }
12280       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
12281       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
12282          ast_debug(1, "VM next message wrap disabled globally\n");
12283          val = "no";
12284       }
12285       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);  
12286 
12287       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
12288          ast_debug(1, "VM Operator break disabled globally\n");
12289          val = "no";
12290       }
12291       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
12292 
12293       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
12294          ast_debug(1, "VM CID Info before msg disabled globally\n");
12295          val = "no";
12296       } 
12297       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
12298 
12299       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
12300          ast_debug(1, "Send Voicemail msg disabled globally\n");
12301          val = "no";
12302       }
12303       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
12304    
12305       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
12306          ast_debug(1, "ENVELOPE before msg enabled globally\n");
12307          val = "yes";
12308       }
12309       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
12310 
12311       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
12312          ast_debug(1, "Move Heard enabled globally\n");
12313          val = "yes";
12314       }
12315       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
12316 
12317       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
12318          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
12319          val = "no";
12320       }
12321       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);   
12322 
12323       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
12324          ast_debug(1, "Duration info before msg enabled globally\n");
12325          val = "yes";
12326       }
12327       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
12328 
12329       saydurationminfo = 2;
12330       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
12331          if (sscanf(val, "%30d", &x) == 1) {
12332             saydurationminfo = x;
12333          } else {
12334             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
12335          }
12336       }
12337 
12338       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
12339          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
12340          val = "no";
12341       }
12342       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
12343 
12344       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
12345          ast_copy_string(dialcontext, val, sizeof(dialcontext));
12346          ast_debug(1, "found dialout context: %s\n", dialcontext);
12347       } else {
12348          dialcontext[0] = '\0';  
12349       }
12350       
12351       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
12352          ast_copy_string(callcontext, val, sizeof(callcontext));
12353          ast_debug(1, "found callback context: %s\n", callcontext);
12354       } else {
12355          callcontext[0] = '\0';
12356       }
12357 
12358       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
12359          ast_copy_string(exitcontext, val, sizeof(exitcontext));
12360          ast_debug(1, "found operator context: %s\n", exitcontext);
12361       } else {
12362          exitcontext[0] = '\0';
12363       }
12364       
12365       /* load password sounds configuration */
12366       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
12367          ast_copy_string(vm_password, val, sizeof(vm_password));
12368       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
12369          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
12370       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
12371          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
12372       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
12373          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
12374       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
12375          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
12376       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
12377          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
12378       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
12379          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
12380       }
12381       if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
12382          ast_copy_string(vm_prepend_timeout, val, sizeof(vm_prepend_timeout));
12383       }
12384       /* load configurable audio prompts */
12385       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
12386          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
12387       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
12388          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
12389       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
12390          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
12391       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
12392          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
12393       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
12394          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
12395 
12396       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
12397          val = "no";
12398       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
12399 
12400       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
12401          val = "voicemail.conf";
12402       }
12403       if (!(strcmp(val, "spooldir"))) {
12404          passwordlocation = OPT_PWLOC_SPOOLDIR;
12405       } else {
12406          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
12407       }
12408 
12409       poll_freq = DEFAULT_POLL_FREQ;
12410       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
12411          if (sscanf(val, "%30u", &poll_freq) != 1) {
12412             poll_freq = DEFAULT_POLL_FREQ;
12413             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
12414          }
12415       }
12416 
12417       poll_mailboxes = 0;
12418       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
12419          poll_mailboxes = ast_true(val);
12420 
12421       memset(fromstring, 0, sizeof(fromstring));
12422       memset(pagerfromstring, 0, sizeof(pagerfromstring));
12423       strcpy(charset, "ISO-8859-1");
12424       if (emailbody) {
12425          ast_free(emailbody);
12426          emailbody = NULL;
12427       }
12428       if (emailsubject) {
12429          ast_free(emailsubject);
12430          emailsubject = NULL;
12431       }
12432       if (pagerbody) {
12433          ast_free(pagerbody);
12434          pagerbody = NULL;
12435       }
12436       if (pagersubject) {
12437          ast_free(pagersubject);
12438          pagersubject = NULL;
12439       }
12440       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
12441          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
12442       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
12443          ast_copy_string(fromstring, val, sizeof(fromstring));
12444       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
12445          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
12446       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
12447          ast_copy_string(charset, val, sizeof(charset));
12448       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
12449          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12450          for (x = 0; x < 4; x++) {
12451             memcpy(&adsifdn[x], &tmpadsi[x], 1);
12452          }
12453       }
12454       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
12455          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12456          for (x = 0; x < 4; x++) {
12457             memcpy(&adsisec[x], &tmpadsi[x], 1);
12458          }
12459       }
12460       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
12461          if (atoi(val)) {
12462             adsiver = atoi(val);
12463          }
12464       }
12465       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
12466          ast_copy_string(zonetag, val, sizeof(zonetag));
12467       }
12468       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
12469          ast_copy_string(locale, val, sizeof(locale));
12470       }
12471       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
12472          emailsubject = ast_strdup(substitute_escapes(val));
12473       }
12474       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
12475          emailbody = ast_strdup(substitute_escapes(val));
12476       }
12477       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
12478          pagersubject = ast_strdup(substitute_escapes(val));
12479       }
12480       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
12481          pagerbody = ast_strdup(substitute_escapes(val));
12482       }
12483 
12484       /* load mailboxes from users.conf */
12485       if (ucfg) { 
12486          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
12487             if (!strcasecmp(cat, "general")) {
12488                continue;
12489             }
12490             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
12491                continue;
12492             if ((current = find_or_create(userscontext, cat))) {
12493                populate_defaults(current);
12494                apply_options_full(current, ast_variable_browse(ucfg, cat));
12495                ast_copy_string(current->context, userscontext, sizeof(current->context));
12496                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
12497                   current->passwordlocation = OPT_PWLOC_USERSCONF;
12498                }
12499 
12500                switch (current->passwordlocation) {
12501                case OPT_PWLOC_SPOOLDIR:
12502                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
12503                   read_password_from_file(secretfn, current->password, sizeof(current->password));
12504                }
12505             }
12506          }
12507       }
12508 
12509       /* load mailboxes from voicemail.conf */
12510       cat = ast_category_browse(cfg, NULL);
12511       while (cat) {
12512          if (strcasecmp(cat, "general")) {
12513             var = ast_variable_browse(cfg, cat);
12514             if (strcasecmp(cat, "zonemessages")) {
12515                /* Process mailboxes in this context */
12516                while (var) {
12517                   append_mailbox(cat, var->name, var->value);
12518                   var = var->next;
12519                }
12520             } else {
12521                /* Timezones in this context */
12522                while (var) {
12523                   struct vm_zone *z;
12524                   if ((z = ast_malloc(sizeof(*z)))) {
12525                      char *msg_format, *tzone;
12526                      msg_format = ast_strdupa(var->value);
12527                      tzone = strsep(&msg_format, "|,");
12528                      if (msg_format) {
12529                         ast_copy_string(z->name, var->name, sizeof(z->name));
12530                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
12531                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
12532                         AST_LIST_LOCK(&zones);
12533                         AST_LIST_INSERT_HEAD(&zones, z, list);
12534                         AST_LIST_UNLOCK(&zones);
12535                      } else {
12536                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
12537                         ast_free(z);
12538                      }
12539                   } else {
12540                      AST_LIST_UNLOCK(&users);
12541                      return -1;
12542                   }
12543                   var = var->next;
12544                }
12545             }
12546          }
12547          cat = ast_category_browse(cfg, cat);
12548       }
12549 
12550       AST_LIST_UNLOCK(&users);
12551 
12552       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
12553          start_poll_thread();
12554       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
12555          stop_poll_thread();;
12556 
12557       return 0;
12558    } else {
12559       AST_LIST_UNLOCK(&users);
12560       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
12561       return 0;
12562    }
12563 }

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 4823 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, my_umask, VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

Referenced by make_email_file().

04824 {
04825    char tmpdir[256], newtmp[256];
04826    char fname[256];
04827    char tmpcmd[256];
04828    int tmpfd = -1;
04829    int soxstatus = 0;
04830 
04831    /* Eww. We want formats to tell us their own MIME type */
04832    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04833 
04834    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04835       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04836       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04837       tmpfd = mkstemp(newtmp);
04838       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04839       ast_debug(3, "newtmp: %s\n", newtmp);
04840       if (tmpfd > -1) {
04841          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04842          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04843             attach = newtmp;
04844             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04845          } else {
04846             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04847                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04848             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04849          }
04850       }
04851    }
04852    fprintf(p, "--%s" ENDL, bound);
04853    if (msgnum > -1)
04854       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04855    else
04856       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04857    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04858    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04859    if (msgnum > -1)
04860       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04861    else
04862       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04863    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04864    base_encode(fname, p);
04865    if (last)
04866       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04867    if (tmpfd > -1) {
04868       if (soxstatus == 0) {
04869          unlink(fname);
04870       }
04871       close(tmpfd);
04872       unlink(newtmp);
04873    }
04874    return 0;
04875 }

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

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

06433 {
06434    int x;
06435    if (!ast_adsi_available(chan))
06436       return;
06437    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06438    if (x < 0)
06439       return;
06440    if (!x) {
06441       if (adsi_load_vmail(chan, useadsi)) {
06442          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06443          return;
06444       }
06445    } else
06446       *useadsi = 1;
06447 }

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

Definition at line 6627 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(), ast_mutex_lock, ast_mutex_unlock, vm_state::curmsg, vm_state::deleted, and vm_state::lastmsg.

Referenced by vm_execmain().

06628 {
06629    int bytes = 0;
06630    unsigned char buf[256];
06631    unsigned char keys[8];
06632 
06633    int x;
06634 
06635    if (!ast_adsi_available(chan))
06636       return;
06637 
06638    /* New meaning for keys */
06639    for (x = 0; x < 5; x++)
06640       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06641 
06642    keys[6] = 0x0;
06643    keys[7] = 0x0;
06644 
06645    if (!vms->curmsg) {
06646       /* No prev key, provide "Folder" instead */
06647       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06648    }
06649    if (vms->curmsg >= vms->lastmsg) {
06650       /* If last message ... */
06651       if (vms->curmsg) {
06652          /* but not only message, provide "Folder" instead */
06653          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06654       } else {
06655          /* Otherwise if only message, leave blank */
06656          keys[3] = 1;
06657       }
06658    }
06659 
06660    /* If deleted, show "undeleted" */
06661 #ifdef IMAP_STORAGE
06662    ast_mutex_lock(&vms->lock);
06663 #endif
06664    if (vms->deleted[vms->curmsg]) {
06665       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06666    }
06667 #ifdef IMAP_STORAGE
06668    ast_mutex_unlock(&vms->lock);
06669 #endif
06670 
06671    /* Except "Exit" */
06672    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06673    bytes += ast_adsi_set_keys(buf + bytes, keys);
06674    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06675 
06676    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06677 }

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

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

06498 {
06499    unsigned char buf[256];
06500    int bytes = 0;
06501    unsigned char keys[8];
06502    int x, y;
06503 
06504    if (!ast_adsi_available(chan))
06505       return;
06506 
06507    for (x = 0; x < 5; x++) {
06508       y = ADSI_KEY_APPS + 12 + start + x;
06509       if (y > ADSI_KEY_APPS + 12 + 4)
06510          y = 0;
06511       keys[x] = ADSI_KEY_SKT | y;
06512    }
06513    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06514    keys[6] = 0;
06515    keys[7] = 0;
06516 
06517    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06518    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06519    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06520    bytes += ast_adsi_set_keys(buf + bytes, keys);
06521    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06522 
06523    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06524 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06783 {
06784    unsigned char buf[256];
06785    int bytes = 0;
06786 
06787    if (!ast_adsi_available(chan))
06788       return;
06789    bytes += adsi_logo(buf + bytes);
06790    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06791    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06792    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06793    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06794 
06795    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06796 }

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

Definition at line 6303 of file app_voicemail.c.

References addesc, 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, and mbox().

Referenced by adsi_begin().

06304 {
06305    unsigned char buf[256];
06306    int bytes = 0;
06307    int x;
06308    char num[5];
06309 
06310    *useadsi = 0;
06311    bytes += ast_adsi_data_mode(buf + bytes);
06312    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06313 
06314    bytes = 0;
06315    bytes += adsi_logo(buf);
06316    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06317 #ifdef DISPLAY
06318    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06319 #endif
06320    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06321    bytes += ast_adsi_data_mode(buf + bytes);
06322    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06323 
06324    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06325       bytes = 0;
06326       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06327       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06328       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06329       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06330       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06331       return 0;
06332    }
06333 
06334 #ifdef DISPLAY
06335    /* Add a dot */
06336    bytes = 0;
06337    bytes += ast_adsi_logo(buf);
06338    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06339    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06340    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06341    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06342 #endif
06343    bytes = 0;
06344    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06345    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06346    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06347    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06348    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06349    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06350    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06351 
06352 #ifdef DISPLAY
06353    /* Add another dot */
06354    bytes = 0;
06355    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06356    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06357 
06358    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06359    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06360 #endif
06361 
06362    bytes = 0;
06363    /* These buttons we load but don't use yet */
06364    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06365    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06366    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06367    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06368    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06369    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06370    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06371 
06372 #ifdef DISPLAY
06373    /* Add another dot */
06374    bytes = 0;
06375    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06376    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06377    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06378 #endif
06379 
06380    bytes = 0;
06381    for (x = 0; x < 5; x++) {
06382       snprintf(num, sizeof(num), "%d", x);
06383       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06384    }
06385    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06386    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06387 
06388 #ifdef DISPLAY
06389    /* Add another dot */
06390    bytes = 0;
06391    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06392    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06393    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06394 #endif
06395 
06396    if (ast_adsi_end_download(chan)) {
06397       bytes = 0;
06398       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06399       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06400       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06401       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06402       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06403       return 0;
06404    }
06405    bytes = 0;
06406    bytes += ast_adsi_download_disconnect(buf + bytes);
06407    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06408    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06409 
06410    ast_debug(1, "Done downloading scripts...\n");
06411 
06412 #ifdef DISPLAY
06413    /* Add last dot */
06414    bytes = 0;
06415    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06416    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06417 #endif
06418    ast_debug(1, "Restarting session...\n");
06419 
06420    bytes = 0;
06421    /* Load the session now */
06422    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06423       *useadsi = 1;
06424       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06425    } else
06426       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06427 
06428    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06429    return 0;
06430 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06450 {
06451    unsigned char buf[256];
06452    int bytes = 0;
06453    unsigned char keys[8];
06454    int x;
06455    if (!ast_adsi_available(chan))
06456       return;
06457 
06458    for (x = 0; x < 8; x++)
06459       keys[x] = 0;
06460    /* Set one key for next */
06461    keys[3] = ADSI_KEY_APPS + 3;
06462 
06463    bytes += adsi_logo(buf + bytes);
06464    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06465    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06466    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06467    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06468    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06469    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06470    bytes += ast_adsi_set_keys(buf + bytes, keys);
06471    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06472    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06473 }

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

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

06296 {
06297    int bytes = 0;
06298    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06299    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06300    return bytes;
06301 }

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

Definition at line 6526 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_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), vm_state::curbox, vm_state::curmsg, vm_state::deleted, vm_state::fn, vm_state::lastmsg, and name.

Referenced by play_message(), and vm_execmain().

06527 {
06528    int bytes = 0;
06529    unsigned char buf[256]; 
06530    char buf1[256], buf2[256];
06531    char fn2[PATH_MAX];
06532 
06533    char cid[256] = "";
06534    char *val;
06535    char *name, *num;
06536    char datetime[21] = "";
06537    FILE *f;
06538 
06539    unsigned char keys[8];
06540 
06541    int x;
06542 
06543    if (!ast_adsi_available(chan))
06544       return;
06545 
06546    /* Retrieve important info */
06547    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06548    f = fopen(fn2, "r");
06549    if (f) {
06550       while (!feof(f)) {   
06551          if (!fgets((char *) buf, sizeof(buf), f)) {
06552             continue;
06553          }
06554          if (!feof(f)) {
06555             char *stringp = NULL;
06556             stringp = (char *) buf;
06557             strsep(&stringp, "=");
06558             val = strsep(&stringp, "=");
06559             if (!ast_strlen_zero(val)) {
06560                if (!strcmp((char *) buf, "callerid"))
06561                   ast_copy_string(cid, val, sizeof(cid));
06562                if (!strcmp((char *) buf, "origdate"))
06563                   ast_copy_string(datetime, val, sizeof(datetime));
06564             }
06565          }
06566       }
06567       fclose(f);
06568    }
06569    /* New meaning for keys */
06570    for (x = 0; x < 5; x++)
06571       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06572    keys[6] = 0x0;
06573    keys[7] = 0x0;
06574 
06575    if (!vms->curmsg) {
06576       /* No prev key, provide "Folder" instead */
06577       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06578    }
06579    if (vms->curmsg >= vms->lastmsg) {
06580       /* If last message ... */
06581       if (vms->curmsg) {
06582          /* but not only message, provide "Folder" instead */
06583          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06584          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06585 
06586       } else {
06587          /* Otherwise if only message, leave blank */
06588          keys[3] = 1;
06589       }
06590    }
06591 
06592    if (!ast_strlen_zero(cid)) {
06593       ast_callerid_parse(cid, &name, &num);
06594       if (!name)
06595          name = num;
06596    } else
06597       name = "Unknown Caller";
06598 
06599    /* If deleted, show "undeleted" */
06600 #ifdef IMAP_STORAGE
06601    ast_mutex_lock(&vms->lock);
06602 #endif
06603    if (vms->deleted[vms->curmsg]) {
06604       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06605    }
06606 #ifdef IMAP_STORAGE
06607    ast_mutex_unlock(&vms->lock);
06608 #endif
06609 
06610    /* Except "Exit" */
06611    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06612    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06613       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06614    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06615 
06616    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06617    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06618    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06619    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06620    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06621    bytes += ast_adsi_set_keys(buf + bytes, keys);
06622    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06623 
06624    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06625 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06476 {
06477    unsigned char buf[256];
06478    int bytes = 0;
06479    unsigned char keys[8];
06480    int x;
06481    if (!ast_adsi_available(chan))
06482       return;
06483 
06484    for (x = 0; x < 8; x++)
06485       keys[x] = 0;
06486    /* Set one key for next */
06487    keys[3] = ADSI_KEY_APPS + 3;
06488 
06489    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06490    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06491    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06492    bytes += ast_adsi_set_keys(buf + bytes, keys);
06493    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06494    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06495 }

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

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

06680 {
06681    unsigned char buf[256] = "";
06682    char buf1[256] = "", buf2[256] = "";
06683    int bytes = 0;
06684    unsigned char keys[8];
06685    int x;
06686 
06687    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06688    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06689    if (!ast_adsi_available(chan))
06690       return;
06691    if (vms->newmessages) {
06692       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06693       if (vms->oldmessages) {
06694          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06695          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06696       } else {
06697          snprintf(buf2, sizeof(buf2), "%s.", newm);
06698       }
06699    } else if (vms->oldmessages) {
06700       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06701       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06702    } else {
06703       strcpy(buf1, "You have no messages.");
06704       buf2[0] = ' ';
06705       buf2[1] = '\0';
06706    }
06707    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06708    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06709    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06710 
06711    for (x = 0; x < 6; x++)
06712       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06713    keys[6] = 0;
06714    keys[7] = 0;
06715 
06716    /* Don't let them listen if there are none */
06717    if (vms->lastmsg < 0)
06718       keys[0] = 1;
06719    bytes += ast_adsi_set_keys(buf + bytes, keys);
06720 
06721    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06722 
06723    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06724 }

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

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

06727 {
06728    unsigned char buf[256] = "";
06729    char buf1[256] = "", buf2[256] = "";
06730    int bytes = 0;
06731    unsigned char keys[8];
06732    int x;
06733 
06734    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06735 
06736    if (!ast_adsi_available(chan))
06737       return;
06738 
06739    /* Original command keys */
06740    for (x = 0; x < 6; x++)
06741       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06742 
06743    keys[6] = 0;
06744    keys[7] = 0;
06745 
06746    if ((vms->lastmsg + 1) < 1)
06747       keys[0] = 0;
06748 
06749    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06750       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06751 
06752    if (vms->lastmsg + 1)
06753       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06754    else
06755       strcpy(buf2, "no messages.");
06756    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06757    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06758    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06759    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06760    bytes += ast_adsi_set_keys(buf + bytes, keys);
06761 
06762    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06763 
06764    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06765    
06766 }

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 13271 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_test_suite_event_notify, 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(), name, play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, valid_config(), and wait_file().

Referenced by vm_execmain().

13272 {
13273    int res = 0;
13274    char filename[PATH_MAX];
13275    struct ast_config *msg_cfg = NULL;
13276    const char *origtime, *context;
13277    char *name, *num;
13278    int retries = 0;
13279    char *cid;
13280    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
13281 
13282    vms->starting = 0; 
13283 
13284    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13285 
13286    /* Retrieve info from VM attribute file */
13287    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
13288    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
13289    msg_cfg = ast_config_load(filename, config_flags);
13290    DISPOSE(vms->curdir, vms->curmsg);
13291    if (!valid_config(msg_cfg)) {
13292       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
13293       return 0;
13294    }
13295 
13296    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
13297       ast_config_destroy(msg_cfg);
13298       return 0;
13299    }
13300 
13301    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
13302 
13303    context = ast_variable_retrieve(msg_cfg, "message", "context");
13304    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
13305       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
13306    switch (option) {
13307    case 3: /* Play message envelope */
13308       if (!res)
13309          res = play_message_datetime(chan, vmu, origtime, filename);
13310       if (!res)
13311          res = play_message_callerid(chan, vms, cid, context, 0);
13312 
13313       res = 't';
13314       break;
13315 
13316    case 2:  /* Call back */
13317 
13318       if (ast_strlen_zero(cid))
13319          break;
13320 
13321       ast_callerid_parse(cid, &name, &num);
13322       while ((res > -1) && (res != 't')) {
13323          switch (res) {
13324          case '1':
13325             if (num) {
13326                /* Dial the CID number */
13327                res = dialout(chan, vmu, num, vmu->callback);
13328                if (res) {
13329                   ast_config_destroy(msg_cfg);
13330                   return 9;
13331                }
13332             } else {
13333                res = '2';
13334             }
13335             break;
13336 
13337          case '2':
13338             /* Want to enter a different number, can only do this if there's a dialout context for this user */
13339             if (!ast_strlen_zero(vmu->dialout)) {
13340                res = dialout(chan, vmu, NULL, vmu->dialout);
13341                if (res) {
13342                   ast_config_destroy(msg_cfg);
13343                   return 9;
13344                }
13345             } else {
13346                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
13347                res = ast_play_and_wait(chan, "vm-sorry");
13348             }
13349             ast_config_destroy(msg_cfg);
13350             return res;
13351          case '*':
13352             res = 't';
13353             break;
13354          case '3':
13355          case '4':
13356          case '5':
13357          case '6':
13358          case '7':
13359          case '8':
13360          case '9':
13361          case '0':
13362 
13363             res = ast_play_and_wait(chan, "vm-sorry");
13364             retries++;
13365             break;
13366          default:
13367             if (num) {
13368                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
13369                res = ast_play_and_wait(chan, "vm-num-i-have");
13370                if (!res)
13371                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
13372                if (!res)
13373                   res = ast_play_and_wait(chan, "vm-tocallnum");
13374                /* Only prompt for a caller-specified number if there is a dialout context specified */
13375                if (!ast_strlen_zero(vmu->dialout)) {
13376                   if (!res)
13377                      res = ast_play_and_wait(chan, "vm-calldiffnum");
13378                }
13379             } else {
13380                res = ast_play_and_wait(chan, "vm-nonumber");
13381                if (!ast_strlen_zero(vmu->dialout)) {
13382                   if (!res)
13383                      res = ast_play_and_wait(chan, "vm-toenternumber");
13384                }
13385             }
13386             if (!res) {
13387                res = ast_play_and_wait(chan, "vm-star-cancel");
13388             }
13389             if (!res) {
13390                res = ast_waitfordigit(chan, 6000);
13391             }
13392             if (!res) {
13393                retries++;
13394                if (retries > 3) {
13395                   res = 't';
13396                }
13397             }
13398             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
13399             break; 
13400             
13401          }
13402          if (res == 't')
13403             res = 0;
13404          else if (res == '*')
13405             res = -1;
13406       }
13407       break;
13408       
13409    case 1:  /* Reply */
13410       /* Send reply directly to sender */
13411       if (ast_strlen_zero(cid))
13412          break;
13413 
13414       ast_callerid_parse(cid, &name, &num);
13415       if (!num) {
13416          ast_verb(3, "No CID number available, no reply sent\n");
13417          if (!res)
13418             res = ast_play_and_wait(chan, "vm-nonumber");
13419          ast_config_destroy(msg_cfg);
13420          return res;
13421       } else {
13422          struct ast_vm_user vmu2;
13423          if (find_user(&vmu2, vmu->context, num)) {
13424             struct leave_vm_options leave_options;
13425             char mailbox[AST_MAX_EXTENSION * 2 + 2];
13426             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
13427 
13428             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
13429             
13430             memset(&leave_options, 0, sizeof(leave_options));
13431             leave_options.record_gain = record_gain;
13432             res = leave_voicemail(chan, mailbox, &leave_options);
13433             if (!res)
13434                res = 't';
13435             ast_config_destroy(msg_cfg);
13436             return res;
13437          } else {
13438             /* Sender has no mailbox, can't reply */
13439             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
13440             ast_play_and_wait(chan, "vm-nobox");
13441             res = 't';
13442             ast_config_destroy(msg_cfg);
13443             return res;
13444          }
13445       } 
13446       res = 0;
13447 
13448       break;
13449    }
13450 
13451    ast_config_destroy(msg_cfg);
13452 
13453 #ifndef IMAP_STORAGE
13454    if (!res) {
13455       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13456       vms->heard[msg] = 1;
13457       res = wait_file(chan, vms, vms->fn);
13458    }
13459 #endif
13460    return res;
13461 }

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

Definition at line 10792 of file app_voicemail.c.

References apply_options(), ast_alloca, ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, find_or_create(), ast_vm_user::fullname, inboxcount2(), LOG_WARNING, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, ast_vm_user::pager, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), queue_mwi_event(), read_password_from_file(), and VM_SPOOL_DIR.

Referenced by actual_load_config().

10793 {
10794    /* Assumes lock is already held */
10795    char *tmp;
10796    char *stringp;
10797    char *s;
10798    struct ast_vm_user *vmu;
10799    char *mailbox_full;
10800    int new = 0, old = 0, urgent = 0;
10801    char secretfn[PATH_MAX] = "";
10802 
10803    tmp = ast_strdupa(data);
10804 
10805    if (!(vmu = find_or_create(context, box)))
10806       return -1;
10807 
10808    populate_defaults(vmu);
10809 
10810    stringp = tmp;
10811    if ((s = strsep(&stringp, ","))) {
10812       if (!ast_strlen_zero(s) && s[0] == '*') {
10813          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10814             "\n\tmust be reset in voicemail.conf.\n", box);
10815       }
10816       /* assign password regardless of validity to prevent NULL password from being assigned */
10817       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10818    }
10819    if (stringp && (s = strsep(&stringp, ","))) {
10820       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10821    }
10822    if (stringp && (s = strsep(&stringp, ","))) {
10823       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10824    }
10825    if (stringp && (s = strsep(&stringp, ","))) {
10826       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10827    }
10828    if (stringp && (s = strsep(&stringp, ","))) {
10829       apply_options(vmu, s);
10830    }
10831 
10832    switch (vmu->passwordlocation) {
10833    case OPT_PWLOC_SPOOLDIR:
10834       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10835       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10836    }
10837 
10838    mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
10839    strcpy(mailbox_full, box);
10840    strcat(mailbox_full, "@");
10841    strcat(mailbox_full, context);
10842 
10843    inboxcount2(mailbox_full, &urgent, &new, &old);
10844    queue_mwi_event(mailbox_full, urgent, new, old);
10845 
10846    return 0;
10847 }

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

References apply_options(), ast_copy_string(), ast_log(), AST_LOG_WARNING, ast_set2_flag, ast_strdup, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, ast_vm_user::language, ast_vm_user::locale, LOG_WARNING, ast_vm_user::maxdeletedmsg, MAXMSG, ast_vm_user::maxmsg, MAXMSGLIMIT, ast_vm_user::maxsecs, ast_vm_user::minsecs, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, ast_vm_user::serveremail, substitute_escapes(), VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, vmmaxsecs, vmminsecs, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by apply_options(), and apply_options_full().

01064 {
01065    int x;
01066    if (!strcasecmp(var, "attach")) {
01067       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01068    } else if (!strcasecmp(var, "attachfmt")) {
01069       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01070    } else if (!strcasecmp(var, "serveremail")) {
01071       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01072    } else if (!strcasecmp(var, "emailbody")) {
01073       vmu->emailbody = ast_strdup(substitute_escapes(value));
01074    } else if (!strcasecmp(var, "emailsubject")) {
01075       vmu->emailsubject = ast_strdup(substitute_escapes(value));
01076    } else if (!strcasecmp(var, "language")) {
01077       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01078    } else if (!strcasecmp(var, "tz")) {
01079       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01080    } else if (!strcasecmp(var, "locale")) {
01081       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01082 #ifdef IMAP_STORAGE
01083    } else if (!strcasecmp(var, "imapuser")) {
01084       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01085       vmu->imapversion = imapversion;
01086    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01087       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01088       vmu->imapversion = imapversion;
01089    } else if (!strcasecmp(var, "imapfolder")) {
01090       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01091    } else if (!strcasecmp(var, "imapvmshareid")) {
01092       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01093       vmu->imapversion = imapversion;
01094 #endif
01095    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01096       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01097    } else if (!strcasecmp(var, "saycid")){
01098       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01099    } else if (!strcasecmp(var, "sendvoicemail")){
01100       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01101    } else if (!strcasecmp(var, "review")){
01102       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01103    } else if (!strcasecmp(var, "tempgreetwarn")){
01104       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01105    } else if (!strcasecmp(var, "messagewrap")){
01106       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01107    } else if (!strcasecmp(var, "operator")) {
01108       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01109    } else if (!strcasecmp(var, "envelope")){
01110       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01111    } else if (!strcasecmp(var, "moveheard")){
01112       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01113    } else if (!strcasecmp(var, "sayduration")){
01114       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01115    } else if (!strcasecmp(var, "saydurationm")){
01116       if (sscanf(value, "%30d", &x) == 1) {
01117          vmu->saydurationm = x;
01118       } else {
01119          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01120       }
01121    } else if (!strcasecmp(var, "forcename")){
01122       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01123    } else if (!strcasecmp(var, "forcegreetings")){
01124       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01125    } else if (!strcasecmp(var, "callback")) {
01126       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01127    } else if (!strcasecmp(var, "dialout")) {
01128       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01129    } else if (!strcasecmp(var, "exitcontext")) {
01130       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01131    } else if (!strcasecmp(var, "minsecs")) {
01132       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01133          vmu->minsecs = x;
01134       } else {
01135          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01136          vmu->minsecs = vmminsecs;
01137       }
01138    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01139       vmu->maxsecs = atoi(value);
01140       if (vmu->maxsecs <= 0) {
01141          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01142          vmu->maxsecs = vmmaxsecs;
01143       } else {
01144          vmu->maxsecs = atoi(value);
01145       }
01146       if (!strcasecmp(var, "maxmessage"))
01147          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01148    } else if (!strcasecmp(var, "maxmsg")) {
01149       vmu->maxmsg = atoi(value);
01150       /* Accept maxmsg=0 (Greetings only voicemail) */
01151       if (vmu->maxmsg < 0) {
01152          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01153          vmu->maxmsg = MAXMSG;
01154       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01155          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01156          vmu->maxmsg = MAXMSGLIMIT;
01157       }
01158    } else if (!strcasecmp(var, "nextaftercmd")) {
01159       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01160    } else if (!strcasecmp(var, "backupdeleted")) {
01161       if (sscanf(value, "%30d", &x) == 1)
01162          vmu->maxdeletedmsg = x;
01163       else if (ast_true(value))
01164          vmu->maxdeletedmsg = MAXMSG;
01165       else
01166          vmu->maxdeletedmsg = 0;
01167 
01168       if (vmu->maxdeletedmsg < 0) {
01169          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01170          vmu->maxdeletedmsg = MAXMSG;
01171       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01172          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01173          vmu->maxdeletedmsg = MAXMSGLIMIT;
01174       }
01175    } else if (!strcasecmp(var, "volgain")) {
01176       sscanf(value, "%30lf", &vmu->volgain);
01177    } else if (!strcasecmp(var, "passwordlocation")) {
01178       if (!strcasecmp(value, "spooldir")) {
01179          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01180       } else {
01181          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01182       }
01183    } else if (!strcasecmp(var, "options")) {
01184       apply_options(vmu, value);
01185    }
01186 }

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

Destructively Parse options and apply.

Definition at line 1304 of file app_voicemail.c.

References apply_option(), ast_strdupa, value, and var.

Referenced by append_mailbox(), apply_option(), and AST_TEST_DEFINE().

01305 {  
01306    char *stringp;
01307    char *s;
01308    char *var, *value;
01309    stringp = ast_strdupa(options);
01310    while ((s = strsep(&stringp, "|"))) {
01311       value = s;
01312       if ((var = strsep(&value, "=")) && value) {
01313          apply_option(vmu, var, value);
01314       }
01315    }  
01316 }

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

References apply_option(), ast_copy_string(), ast_free, ast_log(), ast_strdup, ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::fullname, LOG_WARNING, ast_vm_user::mailbox, ast_variable::name, ast_variable::next, ast_vm_user::pager, ast_vm_user::password, substitute_escapes(), ast_vm_user::uniqueid, and ast_variable::value.

Referenced by actual_load_config(), and find_user_realtime().

01324 {
01325    for (; var; var = var->next) {
01326       if (!strcasecmp(var->name, "vmsecret")) {
01327          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01328       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01329          if (ast_strlen_zero(retval->password)) {
01330             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01331                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01332                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01333             } else {
01334                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01335             }
01336          }
01337       } else if (!strcasecmp(var->name, "uniqueid")) {
01338          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01339       } else if (!strcasecmp(var->name, "pager")) {
01340          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01341       } else if (!strcasecmp(var->name, "email")) {
01342          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01343       } else if (!strcasecmp(var->name, "fullname")) {
01344          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01345       } else if (!strcasecmp(var->name, "context")) {
01346          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01347       } else if (!strcasecmp(var->name, "emailsubject")) {
01348          ast_free(retval->emailsubject);
01349          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01350       } else if (!strcasecmp(var->name, "emailbody")) {
01351          ast_free(retval->emailbody);
01352          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01353 #ifdef IMAP_STORAGE
01354       } else if (!strcasecmp(var->name, "imapuser")) {
01355          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01356          retval->imapversion = imapversion;
01357       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01358          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01359          retval->imapversion = imapversion;
01360       } else if (!strcasecmp(var->name, "imapfolder")) {
01361          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01362       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01363          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01364          retval->imapversion = imapversion;
01365 #endif
01366       } else
01367          apply_option(retval, var->name, var->value);
01368    }
01369 }

AST_APP_OPTIONS ( vm_app_options   ) 
AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)
AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)
static AST_LIST_HEAD_STATIC ( zones  ,
vm_zone   
) [static]
static AST_LIST_HEAD_STATIC ( users  ,
ast_vm_user   
) [static]
AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
tdesc  ,
load = load_module,
unload = unload_module,
reload = reload,
nonoptreq = "res_adsi,res_smdi" 
)
AST_MUTEX_DEFINE_STATIC ( poll_lock   ) 
static AST_RWLIST_HEAD_STATIC ( mwi_subs  ,
mwi_sub   
) [static]
static const char* ast_str_encode_mime ( struct ast_str **  end,
ssize_t  maxlen,
const char *  start,
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:
end An expandable buffer for holding the result
maxlen Always zero, but see
See also:
ast_str
Parameters:
start A string to be encoded
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 4498 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

04499 {
04500    struct ast_str *tmp = ast_str_alloca(80);
04501    int first_section = 1;
04502 
04503    ast_str_reset(*end);
04504    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04505    for (; *start; start++) {
04506       int need_encoding = 0;
04507       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04508          need_encoding = 1;
04509       }
04510       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04511          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04512          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04513          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04514          /* Start new line */
04515          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04516          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04517          first_section = 0;
04518       }
04519       if (need_encoding && *start == ' ') {
04520          ast_str_append(&tmp, -1, "_");
04521       } else if (need_encoding) {
04522          ast_str_append(&tmp, -1, "=%hhX", *start);
04523       } else {
04524          ast_str_append(&tmp, -1, "%c", *start);
04525       }
04526    }
04527    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04528    return ast_str_buffer(*end);
04529 }

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

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

Parameters:
from The string to work with.
buf The buffer into which to write the modified quoted string.
maxlen Always zero, but see
See also:
ast_str
Returns:
The destination string with quotes wrapped on it (the to field).

Definition at line 4426 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

04427 {
04428    const char *ptr;
04429 
04430    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04431    ast_str_set(buf, maxlen, "\"");
04432    for (ptr = from; *ptr; ptr++) {
04433       if (*ptr == '"' || *ptr == '\\') {
04434          ast_str_append(buf, maxlen, "\\%c", *ptr);
04435       } else {
04436          ast_str_append(buf, maxlen, "%c", *ptr);
04437       }
04438    }
04439    ast_str_append(buf, maxlen, "\"");
04440 
04441    return ast_str_buffer(*buf);
04442 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10849 of file app_voicemail.c.

References apply_options(), ast_calloc, ast_set_flag, AST_TEST_FAIL, ast_test_flag, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, free_user(), ast_vm_user::maxdeletedmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, OPT_PWLOC_SPOOLDIR, ast_vm_user::passwordlocation, populate_defaults(), ast_vm_user::saydurationm, ast_vm_user::serveremail, TEST_EXECUTE, TEST_INIT, VM_ALLOCED, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, ast_vm_user::volgain, and ast_vm_user::zonetag.

10850 {
10851    int res = 0;
10852    struct ast_vm_user *vmu;
10853    /* language parameter seems to only be used for display in manager action */
10854    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10855       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10856       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10857       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10858       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10859       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10860       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
10861       "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
10862       "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
10863 #ifdef IMAP_STORAGE
10864    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10865       "imapfolder=INBOX|imapvmshareid=6000";
10866 #endif
10867 
10868    switch (cmd) {
10869    case TEST_INIT:
10870       info->name = "vmuser";
10871       info->category = "/apps/app_voicemail/";
10872       info->summary = "Vmuser unit test";
10873       info->description =
10874          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10875       return AST_TEST_NOT_RUN;
10876    case TEST_EXECUTE:
10877       break;
10878    }
10879 
10880    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10881       return AST_TEST_NOT_RUN;
10882    }
10883    populate_defaults(vmu);
10884    ast_set_flag(vmu, VM_ALLOCED);
10885 
10886    apply_options(vmu, options_string);
10887 
10888    if (!ast_test_flag(vmu, VM_ATTACH)) {
10889       ast_test_status_update(test, "Parse failure for attach option\n");
10890       res = 1;
10891    }
10892    if (strcasecmp(vmu->attachfmt, "wav49")) {
10893       ast_test_status_update(test, "Parse failure for attachftm option\n");
10894       res = 1;
10895    }
10896    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10897       ast_test_status_update(test, "Parse failure for serveremail option\n");
10898       res = 1;
10899    }
10900    if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
10901       ast_test_status_update(test, "Parse failure for emailsubject option\n");
10902       res = 1;
10903    }
10904    if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
10905       ast_test_status_update(test, "Parse failure for emailbody option\n");
10906       res = 1;
10907    }
10908    if (strcasecmp(vmu->zonetag, "central")) {
10909       ast_test_status_update(test, "Parse failure for tz option\n");
10910       res = 1;
10911    }
10912    if (!ast_test_flag(vmu, VM_DELETE)) {
10913       ast_test_status_update(test, "Parse failure for delete option\n");
10914       res = 1;
10915    }
10916    if (!ast_test_flag(vmu, VM_SAYCID)) {
10917       ast_test_status_update(test, "Parse failure for saycid option\n");
10918       res = 1;
10919    }
10920    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10921       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10922       res = 1;
10923    }
10924    if (!ast_test_flag(vmu, VM_REVIEW)) {
10925       ast_test_status_update(test, "Parse failure for review option\n");
10926       res = 1;
10927    }
10928    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10929       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10930       res = 1;
10931    }
10932    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10933       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10934       res = 1;
10935    }
10936    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10937       ast_test_status_update(test, "Parse failure for operator option\n");
10938       res = 1;
10939    }
10940    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10941       ast_test_status_update(test, "Parse failure for envelope option\n");
10942       res = 1;
10943    }
10944    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10945       ast_test_status_update(test, "Parse failure for moveheard option\n");
10946       res = 1;
10947    }
10948    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10949       ast_test_status_update(test, "Parse failure for sayduration option\n");
10950       res = 1;
10951    }
10952    if (vmu->saydurationm != 5) {
10953       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10954       res = 1;
10955    }
10956    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10957       ast_test_status_update(test, "Parse failure for forcename option\n");
10958       res = 1;
10959    }
10960    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10961       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10962       res = 1;
10963    }
10964    if (strcasecmp(vmu->callback, "somecontext")) {
10965       ast_test_status_update(test, "Parse failure for callbacks option\n");
10966       res = 1;
10967    }
10968    if (strcasecmp(vmu->dialout, "somecontext2")) {
10969       ast_test_status_update(test, "Parse failure for dialout option\n");
10970       res = 1;
10971    }
10972    if (strcasecmp(vmu->exit, "somecontext3")) {
10973       ast_test_status_update(test, "Parse failure for exitcontext option\n");
10974       res = 1;
10975    }
10976    if (vmu->minsecs != 10) {
10977       ast_test_status_update(test, "Parse failure for minsecs option\n");
10978       res = 1;
10979    }
10980    if (vmu->maxsecs != 100) {
10981       ast_test_status_update(test, "Parse failure for maxsecs option\n");
10982       res = 1;
10983    }
10984    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10985       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10986       res = 1;
10987    }
10988    if (vmu->maxdeletedmsg != 50) {
10989       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10990       res = 1;
10991    }
10992    if (vmu->volgain != 1.3) {
10993       ast_test_status_update(test, "Parse failure for volgain option\n");
10994       res = 1;
10995    }
10996    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10997       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10998       res = 1;
10999    }
11000 #ifdef IMAP_STORAGE
11001    apply_options(vmu, option_string2);
11002 
11003    if (strcasecmp(vmu->imapuser, "imapuser")) {
11004       ast_test_status_update(test, "Parse failure for imapuser option\n");
11005       res = 1;
11006    }
11007    if (strcasecmp(vmu->imappassword, "imappasswd")) {
11008       ast_test_status_update(test, "Parse failure for imappasswd option\n");
11009       res = 1;
11010    }
11011    if (strcasecmp(vmu->imapfolder, "INBOX")) {
11012       ast_test_status_update(test, "Parse failure for imapfolder option\n");
11013       res = 1;
11014    }
11015    if (strcasecmp(vmu->imapvmshareid, "6000")) {
11016       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
11017       res = 1;
11018    }
11019 #endif
11020 
11021    free_user(vmu);
11022    return res ? AST_TEST_FAIL : AST_TEST_PASS;
11023 }

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

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

Referenced by add_email_attachment().

04303 {
04304    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04305       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04306       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04307       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04308    int i, hiteof = 0;
04309    FILE *fi;
04310    struct baseio bio;
04311 
04312    memset(&bio, 0, sizeof(bio));
04313    bio.iocp = BASEMAXINLINE;
04314 
04315    if (!(fi = fopen(filename, "rb"))) {
04316       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04317       return -1;
04318    }
04319 
04320    while (!hiteof){
04321       unsigned char igroup[3], ogroup[4];
04322       int c, n;
04323 
04324       memset(igroup, 0, sizeof(igroup));
04325 
04326       for (n = 0; n < 3; n++) {
04327          if ((c = inchar(&bio, fi)) == EOF) {
04328             hiteof = 1;
04329             break;
04330          }
04331 
04332          igroup[n] = (unsigned char) c;
04333       }
04334 
04335       if (n > 0) {
04336          ogroup[0]= dtable[igroup[0] >> 2];
04337          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04338          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04339          ogroup[3]= dtable[igroup[2] & 0x3F];
04340 
04341          if (n < 3) {
04342             ogroup[3] = '=';
04343 
04344             if (n < 2)
04345                ogroup[2] = '=';
04346          }
04347 
04348          for (i = 0; i < 4; i++)
04349             ochar(&bio, ogroup[i], so);
04350       }
04351    }
04352 
04353    fclose(fi);
04354    
04355    if (fputs(ENDL, so) == EOF) {
04356       return 0;
04357    }
04358 
04359    return 1;
04360 }

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

References ast_copy_string(), ast_realtime_require_field(), ast_test_suite_event_notify, ast_update2_realtime(), ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, RQ_CHAR, and SENTINEL.

Referenced by vm_change_password().

01283 {
01284    int res = -1;
01285    if (!strcmp(vmu->password, password)) {
01286       /* No change (but an update would return 0 rows updated, so we opt out here) */
01287       return 0;
01288    }
01289 
01290    if (strlen(password) > 10) {
01291       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01292    }
01293    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01294       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01295       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01296       res = 0;
01297    }
01298    return res;
01299 }

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

Referenced by make_email_file(), and sendpage().

04472 {
04473    for (; *str; str++) {
04474       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04475          return 1;
04476       }
04477    }
04478    return 0;
04479 }

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

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

Referenced by vm_newuser(), and vm_options().

01242 {
01243    /* check minimum length */
01244    if (strlen(password) < minpassword)
01245       return 1;
01246    /* check that password does not contain '*' character */
01247    if (!ast_strlen_zero(password) && password[0] == '*')
01248       return 1;
01249    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01250       char cmd[255], buf[255];
01251 
01252       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01253 
01254       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01255       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01256          ast_debug(5, "Result: %s\n", buf);
01257          if (!strncasecmp(buf, "VALID", 5)) {
01258             ast_debug(3, "Passed password check: '%s'\n", buf);
01259             return 0;
01260          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01261             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01262             return 0;
01263          } else {
01264             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01265             return 1;
01266          }
01267       }
01268    }
01269    return 0;
01270 }

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

Definition at line 7991 of file app_voicemail.c.

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

Referenced by vm_execmain().

07992 {
07993    int x = 0;
07994    int last_msg_idx = 0;
07995 
07996 #ifndef IMAP_STORAGE
07997    int res = 0, nummsg;
07998    char fn2[PATH_MAX];
07999 #endif
08000 
08001    if (vms->lastmsg <= -1) {
08002       goto done;
08003    }
08004 
08005    vms->curmsg = -1;
08006 #ifndef IMAP_STORAGE
08007    /* Get the deleted messages fixed */
08008    if (vm_lock_path(vms->curdir)) {
08009       return ERROR_LOCK_PATH;
08010    }
08011 
08012    /* update count as message may have arrived while we've got mailbox open */
08013    last_msg_idx = last_message_index(vmu, vms->curdir);
08014    if (last_msg_idx != vms->lastmsg) {
08015       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
08016    }
08017 
08018    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
08019    for (x = 0; x < last_msg_idx + 1; x++) {
08020       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
08021          /* Save this message.  It's not in INBOX or hasn't been heard */
08022          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08023          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
08024             break;
08025          }
08026          vms->curmsg++;
08027          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
08028          if (strcmp(vms->fn, fn2)) {
08029             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
08030          }
08031       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
08032          /* Move to old folder before deleting */
08033          res = save_to_folder(vmu, vms, x, 1);
08034          if (res == ERROR_LOCK_PATH) {
08035             /* If save failed do not delete the message */
08036             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08037             vms->deleted[x] = 0;
08038             vms->heard[x] = 0;
08039             --x;
08040          }
08041       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08042          /* Move to deleted folder */
08043          res = save_to_folder(vmu, vms, x, 10);
08044          if (res == ERROR_LOCK_PATH) {
08045             /* If save failed do not delete the message */
08046             vms->deleted[x] = 0;
08047             vms->heard[x] = 0;
08048             --x;
08049          }
08050       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08051          /* If realtime storage enabled - we should explicitly delete this message,
08052          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08053          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08054          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08055             DELETE(vms->curdir, x, vms->fn, vmu);
08056          }
08057       }
08058    }
08059 
08060    /* Delete ALL remaining messages */
08061    nummsg = x - 1;
08062    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08063       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08064       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08065          DELETE(vms->curdir, x, vms->fn, vmu);
08066       }
08067    }
08068    ast_unlock_path(vms->curdir);
08069 #else /* defined(IMAP_STORAGE) */
08070    ast_mutex_lock(&vms->lock);
08071    if (vms->deleted) {
08072       /* Since we now expunge after each delete, deleting in reverse order
08073        * ensures that no reordering occurs between each step. */
08074       last_msg_idx = vms->dh_arraysize;
08075       for (x = last_msg_idx - 1; x >= 0; x--) {
08076          if (vms->deleted[x]) {
08077             ast_debug(3, "IMAP delete of %d\n", x);
08078             DELETE(vms->curdir, x, vms->fn, vmu);
08079          }
08080       }
08081    }
08082 #endif
08083 
08084 done:
08085    if (vms->deleted) {
08086       ast_free(vms->deleted);
08087       vms->deleted = NULL;
08088    }
08089    if (vms->heard) {
08090       ast_free(vms->heard);
08091       vms->heard = NULL;
08092    }
08093    vms->dh_arraysize = 0;
08094 #ifdef IMAP_STORAGE
08095    ast_mutex_unlock(&vms->lock);
08096 #endif
08097 
08098    return 0;
08099 }

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

Definition at line 11169 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11170 {
11171    int which = 0;
11172    int wordlen;
11173    struct ast_vm_user *vmu;
11174    const char *context = "";
11175 
11176    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11177    if (pos > 4)
11178       return NULL;
11179    if (pos == 3)
11180       return (state == 0) ? ast_strdup("for") : NULL;
11181    wordlen = strlen(word);
11182    AST_LIST_TRAVERSE(&users, vmu, list) {
11183       if (!strncasecmp(word, vmu->context, wordlen)) {
11184          if (context && strcmp(context, vmu->context) && ++which > state)
11185             return ast_strdup(vmu->context);
11186          /* ignore repeated contexts ? */
11187          context = vmu->context;
11188       }
11189    }
11190    return NULL;
11191 }

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

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

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), copy_plain_file(), iax2_register(), and vm_forwardoptions().

04108 {
04109    int ifd;
04110    int ofd;
04111    int res;
04112    int len;
04113    char buf[4096];
04114 
04115 #ifdef HARDLINK_WHEN_POSSIBLE
04116    /* Hard link if possible; saves disk space & is faster */
04117    if (link(infile, outfile)) {
04118 #endif
04119       if ((ifd = open(infile, O_RDONLY)) < 0) {
04120          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04121          return -1;
04122       }
04123       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04124          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04125          close(ifd);
04126          return -1;
04127       }
04128       do {
04129          len = read(ifd, buf, sizeof(buf));
04130          if (len < 0) {
04131             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04132             close(ifd);
04133             close(ofd);
04134             unlink(outfile);
04135          } else if (len) {
04136             res = write(ofd, buf, len);
04137             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04138                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04139                close(ifd);
04140                close(ofd);
04141                unlink(outfile);
04142             }
04143          }
04144       } while (len);
04145       close(ifd);
04146       close(ofd);
04147       return 0;
04148 #ifdef HARDLINK_WHEN_POSSIBLE
04149    } else {
04150       /* Hard link succeeded */
04151       return 0;
04152    }
04153 #endif
04154 }

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 
flag This is only used by file storage based mailboxes.
Returns:
zero on success, -1 on error.

Definition at line 5343 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::caller, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), maxmsg, mbox(), ast_party_id::name, notify_new_message(), ast_party_id::number, S_COR, STORE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, ast_party_number::valid, vm_delete(), and vm_lock_path().

Referenced by forward_message(), and leave_voicemail().

05344 {
05345    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05346    const char *frombox = mbox(vmu, imbox);
05347    const char *userfolder;
05348    int recipmsgnum;
05349    int res = 0;
05350 
05351    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05352 
05353    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05354       userfolder = "Urgent";
05355    } else {
05356       userfolder = "INBOX";
05357    }
05358 
05359    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05360 
05361    if (!dir)
05362       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05363    else
05364       ast_copy_string(fromdir, dir, sizeof(fromdir));
05365 
05366    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05367    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05368 
05369    if (vm_lock_path(todir))
05370       return ERROR_LOCK_PATH;
05371 
05372    recipmsgnum = last_message_index(recip, todir) + 1;
05373    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05374       make_file(topath, sizeof(topath), todir, recipmsgnum);
05375 #ifndef ODBC_STORAGE
05376       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05377          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05378       } else {
05379 #endif
05380          /* If we are prepending a message for ODBC, then the message already
05381           * exists in the database, but we want to force copying from the
05382           * filesystem (since only the FS contains the prepend). */
05383          copy_plain_file(frompath, topath);
05384          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05385          vm_delete(topath);
05386 #ifndef ODBC_STORAGE
05387       }
05388 #endif
05389    } else {
05390       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05391       res = -1;
05392    }
05393    ast_unlock_path(todir);
05394    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05395       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05396       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05397       flag);
05398    
05399    return res;
05400 }

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

04166 {
04167    char frompath2[PATH_MAX], topath2[PATH_MAX];
04168    struct ast_variable *tmp,*var = NULL;
04169    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04170    ast_filecopy(frompath, topath, NULL);
04171    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04172    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04173    if (ast_check_realtime("voicemail_data")) {
04174       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04175       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04176       for (tmp = var; tmp; tmp = tmp->next) {
04177          if (!strcasecmp(tmp->name, "origmailbox")) {
04178             origmailbox = tmp->value;
04179          } else if (!strcasecmp(tmp->name, "context")) {
04180             context = tmp->value;
04181          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04182             macrocontext = tmp->value;
04183          } else if (!strcasecmp(tmp->name, "exten")) {
04184             exten = tmp->value;
04185          } else if (!strcasecmp(tmp->name, "priority")) {
04186             priority = tmp->value;
04187          } else if (!strcasecmp(tmp->name, "callerchan")) {
04188             callerchan = tmp->value;
04189          } else if (!strcasecmp(tmp->name, "callerid")) {
04190             callerid = tmp->value;
04191          } else if (!strcasecmp(tmp->name, "origdate")) {
04192             origdate = tmp->value;
04193          } else if (!strcasecmp(tmp->name, "origtime")) {
04194             origtime = tmp->value;
04195          } else if (!strcasecmp(tmp->name, "category")) {
04196             category = tmp->value;
04197          } else if (!strcasecmp(tmp->name, "duration")) {
04198             duration = tmp->value;
04199          }
04200       }
04201       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);
04202    }
04203    copy(frompath2, topath2);
04204    ast_variables_destroy(var);
04205 }

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

04003 {
04004 
04005    int vmcount = 0;
04006    DIR *vmdir = NULL;
04007    struct dirent *vment = NULL;
04008 
04009    if (vm_lock_path(dir))
04010       return ERROR_LOCK_PATH;
04011 
04012    if ((vmdir = opendir(dir))) {
04013       while ((vment = readdir(vmdir))) {
04014          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
04015             vmcount++;
04016          }
04017       }
04018       closedir(vmdir);
04019    }
04020    ast_unlock_path(dir);
04021    
04022    return vmcount;
04023 }

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

01706 {
01707    mode_t   mode = VOICEMAIL_DIR_MODE;
01708    int res;
01709 
01710    make_dir(dest, len, context, ext, folder);
01711    if ((res = ast_mkdir(dest, mode))) {
01712       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01713       return -1;
01714    }
01715    return 0;
01716 }

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

Definition at line 13198 of file app_voicemail.c.

References ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_suite_event_notify, 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().

13199 {
13200    int cmd = 0;
13201    char destination[80] = "";
13202    int retries = 0;
13203 
13204    if (!num) {
13205       ast_verb(3, "Destination number will be entered manually\n");
13206       while (retries < 3 && cmd != 't') {
13207          destination[1] = '\0';
13208          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13209          if (!cmd)
13210             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13211          if (!cmd)
13212             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13213          if (!cmd) {
13214             cmd = ast_waitfordigit(chan, 6000);
13215             if (cmd)
13216                destination[0] = cmd;
13217          }
13218          if (!cmd) {
13219             retries++;
13220          } else {
13221 
13222             if (cmd < 0)
13223                return 0;
13224             if (cmd == '*') {
13225                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13226                return 0;
13227             }
13228             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13229                retries++;
13230             else
13231                cmd = 't';
13232          }
13233          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13234       }
13235       if (retries >= 3) {
13236          return 0;
13237       }
13238       
13239    } else {
13240       if (option_verbose > 2)
13241          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13242       ast_copy_string(destination, num, sizeof(destination));
13243    }
13244 
13245    if (!ast_strlen_zero(destination)) {
13246       if (destination[strlen(destination) -1 ] == '*')
13247          return 0; 
13248       if (option_verbose > 2)
13249          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13250       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13251       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13252       chan->priority = 0;
13253       return 9;
13254    }
13255    return 0;
13256 }

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

Definition at line 10752 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

10753 {
10754    struct ast_vm_user *vmu;
10755 
10756    if (!ast_strlen_zero(box) && box[0] == '*') {
10757       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10758             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10759             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10760             "\n\tand will be ignored.\n", box, context);
10761       return NULL;
10762    }
10763 
10764    AST_LIST_TRAVERSE(&users, vmu, list) {
10765       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10766          if (strcasecmp(vmu->context, context)) {
10767             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10768                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10769                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10770                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10771          }
10772          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10773          return NULL;
10774       }
10775       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10776          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10777          return NULL;
10778       }
10779    }
10780    
10781    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10782       return NULL;
10783    
10784    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10785    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10786 
10787    AST_LIST_INSERT_TAIL(&users, vmu, list);
10788    
10789    return vmu;
10790 }

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

References AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_malloc, ast_set2_flag, ast_strdup, ast_test_flag, ast_vm_user::emailbody, ast_vm_user::emailsubject, 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().

01445 {
01446    /* This function could be made to generate one from a database, too */
01447    struct ast_vm_user *vmu = NULL, *cur;
01448    AST_LIST_LOCK(&users);
01449 
01450    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01451       context = "default";
01452 
01453    AST_LIST_TRAVERSE(&users, cur, list) {
01454 #ifdef IMAP_STORAGE
01455       if (cur->imapversion != imapversion) {
01456          continue;
01457       }
01458 #endif
01459       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01460          break;
01461       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01462          break;
01463    }
01464    if (cur) {
01465       /* Make a copy, so that on a reload, we have no race */
01466       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01467          *vmu = *cur;
01468          if (!ivm) {
01469             vmu->emailbody = ast_strdup(cur->emailbody);
01470             vmu->emailsubject = ast_strdup(cur->emailsubject);
01471          }
01472          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01473          AST_LIST_NEXT(vmu, list) = NULL;
01474       }
01475    } else
01476       vmu = find_user_realtime(ivm, context, mailbox);
01477    AST_LIST_UNLOCK(&users);
01478    return vmu;
01479 }

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

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

Referenced by find_user().

01404 {
01405    struct ast_variable *var;
01406    struct ast_vm_user *retval;
01407 
01408    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01409       if (ivm) {
01410          memset(retval, 0, sizeof(*retval));
01411       }
01412       populate_defaults(retval);
01413       if (!ivm) {
01414          ast_set_flag(retval, VM_ALLOCED);
01415       }
01416       if (mailbox) {
01417          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01418       }
01419       if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
01420          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01421       } else {
01422          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01423       }
01424       if (var) {
01425          apply_options_full(retval, var);
01426          ast_variables_destroy(var);
01427       } else { 
01428          if (!ivm) 
01429             free_user(retval);
01430          retval = NULL;
01431       }  
01432    } 
01433    return retval;
01434 }

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:
chan 
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 
urgent 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 7193 of file app_voicemail.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), 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_test_suite_event_notify, ast_waitfordigit(), ast_channel::caller, 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, ast_party_caller::id, inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), serveremail, STORE, ast_party_name::str, ast_party_number::str, vm_state::username, ast_party_name::valid, ast_party_number::valid, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), VM_FWDURGAUTO, VM_SPOOL_DIR, and vmfmts.

Referenced by vm_execmain().

07194 {
07195 #ifdef IMAP_STORAGE
07196    int todircount = 0;
07197    struct vm_state *dstvms;
07198 #endif
07199    char username[70]="";
07200    char fn[PATH_MAX]; /* for playback of name greeting */
07201    char ecodes[16] = "#";
07202    int res = 0, cmd = 0;
07203    struct ast_vm_user *receiver = NULL, *vmtmp;
07204    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
07205    char *stringp;
07206    const char *s;
07207    int saved_messages = 0;
07208    int valid_extensions = 0;
07209    char *dir;
07210    int curmsg;
07211    char urgent_str[7] = "";
07212    int prompt_played = 0;
07213 #ifndef IMAP_STORAGE
07214    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
07215 #endif
07216    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
07217       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
07218    }
07219 
07220    if (vms == NULL) return -1;
07221    dir = vms->curdir;
07222    curmsg = vms->curmsg;
07223 
07224    ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
07225    while (!res && !valid_extensions) {
07226       int use_directory = 0;
07227       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
07228          int done = 0;
07229          int retries = 0;
07230          cmd = 0;
07231          while ((cmd >= 0) && !done ){
07232             if (cmd)
07233                retries = 0;
07234             switch (cmd) {
07235             case '1': 
07236                use_directory = 0;
07237                done = 1;
07238                break;
07239             case '2': 
07240                use_directory = 1;
07241                done = 1;
07242                break;
07243             case '*': 
07244                cmd = 't';
07245                done = 1;
07246                break;
07247             default: 
07248                /* Press 1 to enter an extension press 2 to use the directory */
07249                cmd = ast_play_and_wait(chan, "vm-forward");
07250                if (!cmd) {
07251                   cmd = ast_waitfordigit(chan, 3000);
07252                }
07253                if (!cmd) {
07254                   retries++;
07255                }
07256                if (retries > 3) {
07257                   cmd = 't';
07258                   done = 1;
07259                }
07260                ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
07261             }
07262          }
07263          if (cmd < 0 || cmd == 't')
07264             break;
07265       }
07266       
07267       if (use_directory) {
07268          /* use app_directory */
07269          
07270          char old_context[sizeof(chan->context)];
07271          char old_exten[sizeof(chan->exten)];
07272          int old_priority;
07273          struct ast_app* directory_app;
07274 
07275          directory_app = pbx_findapp("Directory");
07276          if (directory_app) {
07277             char vmcontext[256];
07278             /* make backup copies */
07279             memcpy(old_context, chan->context, sizeof(chan->context));
07280             memcpy(old_exten, chan->exten, sizeof(chan->exten));
07281             old_priority = chan->priority;
07282             
07283             /* call the the Directory, changes the channel */
07284             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
07285             res = pbx_exec(chan, directory_app, vmcontext);
07286             
07287             ast_copy_string(username, chan->exten, sizeof(username));
07288             
07289             /* restore the old context, exten, and priority */
07290             memcpy(chan->context, old_context, sizeof(chan->context));
07291             memcpy(chan->exten, old_exten, sizeof(chan->exten));
07292             chan->priority = old_priority;
07293          } else {
07294             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
07295             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
07296          }
07297       } else {
07298          /* Ask for an extension */
07299          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
07300          prompt_played++;
07301          if (res || prompt_played > 4)
07302             break;
07303          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
07304             break;
07305       }
07306       
07307       /* start all over if no username */
07308       if (ast_strlen_zero(username))
07309          continue;
07310       stringp = username;
07311       s = strsep(&stringp, "*");
07312       /* start optimistic */
07313       valid_extensions = 1;
07314       while (s) {
07315          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
07316             int oldmsgs;
07317             int newmsgs;
07318             int capacity;
07319             if (inboxcount(s, &newmsgs, &oldmsgs)) {
07320                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
07321                /* Shouldn't happen, but allow trying another extension if it does */
07322                res = ast_play_and_wait(chan, "pbx-invalid");
07323                valid_extensions = 0;
07324                break;
07325             }
07326             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
07327             if ((newmsgs + oldmsgs) >= capacity) {
07328                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
07329                res = ast_play_and_wait(chan, "vm-mailboxfull");
07330                valid_extensions = 0;
07331                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07332                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07333                   free_user(vmtmp);
07334                }
07335                inprocess_count(receiver->mailbox, receiver->context, -1);
07336                break;
07337             }
07338             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
07339          } else {
07340             /* XXX Optimization for the future.  When we encounter a single bad extension,
07341              * bailing out on all of the extensions may not be the way to go.  We should
07342              * probably just bail on that single extension, then allow the user to enter
07343              * several more. XXX
07344              */
07345             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07346                free_user(receiver);
07347             }
07348             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
07349             /* "I am sorry, that's not a valid extension.  Please try again." */
07350             res = ast_play_and_wait(chan, "pbx-invalid");
07351             valid_extensions = 0;
07352             break;
07353          }
07354 
07355          /* play name if available, else play extension number */
07356          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
07357          RETRIEVE(fn, -1, s, receiver->context);
07358          if (ast_fileexists(fn, NULL, NULL) > 0) {
07359             res = ast_stream_and_wait(chan, fn, ecodes);
07360             if (res) {
07361                DISPOSE(fn, -1);
07362                return res;
07363             }
07364          } else {
07365             res = ast_say_digit_str(chan, s, ecodes, chan->language);
07366          }
07367          DISPOSE(fn, -1);
07368 
07369          s = strsep(&stringp, "*");
07370       }
07371       /* break from the loop of reading the extensions */
07372       if (valid_extensions)
07373          break;
07374    }
07375    /* check if we're clear to proceed */
07376    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
07377       return res;
07378    if (is_new_message == 1) {
07379       struct leave_vm_options leave_options;
07380       char mailbox[AST_MAX_EXTENSION * 2 + 2];
07381       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
07382 
07383       /* Send VoiceMail */
07384       memset(&leave_options, 0, sizeof(leave_options));
07385       leave_options.record_gain = record_gain;
07386       cmd = leave_voicemail(chan, mailbox, &leave_options);
07387    } else {
07388       /* Forward VoiceMail */
07389       long duration = 0;
07390       struct vm_state vmstmp;
07391       int copy_msg_result = 0;
07392       memcpy(&vmstmp, vms, sizeof(vmstmp));
07393 
07394       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
07395 
07396       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
07397       if (!cmd) {
07398          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
07399 #ifdef IMAP_STORAGE
07400             int attach_user_voicemail;
07401             char *myserveremail = serveremail;
07402             
07403             /* get destination mailbox */
07404             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
07405             if (!dstvms) {
07406                dstvms = create_vm_state_from_user(vmtmp);
07407             }
07408             if (dstvms) {
07409                init_mailstream(dstvms, 0);
07410                if (!dstvms->mailstream) {
07411                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
07412                } else {
07413                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
07414                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
07415                }
07416             } else {
07417                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
07418             }
07419             if (!ast_strlen_zero(vmtmp->serveremail))
07420                myserveremail = vmtmp->serveremail;
07421             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
07422             /* NULL category for IMAP storage */
07423             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
07424                dstvms->curbox,
07425                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
07426                S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
07427                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
07428                NULL, urgent_str);
07429 #else
07430             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
07431 #endif
07432             saved_messages++;
07433             AST_LIST_REMOVE_CURRENT(list);
07434             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07435             free_user(vmtmp);
07436             if (res)
07437                break;
07438          }
07439          AST_LIST_TRAVERSE_SAFE_END;
07440          if (saved_messages > 0 && !copy_msg_result) {
07441             /* give confirmation that the message was saved */
07442             /* commented out since we can't forward batches yet
07443             if (saved_messages == 1)
07444                res = ast_play_and_wait(chan, "vm-message");
07445             else
07446                res = ast_play_and_wait(chan, "vm-messages");
07447             if (!res)
07448                res = ast_play_and_wait(chan, "vm-saved"); */
07449 #ifdef IMAP_STORAGE
07450             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
07451             if (ast_strlen_zero(vmstmp.introfn))
07452 #endif
07453             res = ast_play_and_wait(chan, "vm-msgsaved");
07454          }
07455 #ifndef IMAP_STORAGE
07456          else {
07457             /* with IMAP, mailbox full warning played by imap_check_limits */
07458             res = ast_play_and_wait(chan, "vm-mailboxfull");
07459          }
07460          /* Restore original message without prepended message if backup exists */
07461          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07462          strcpy(textfile, msgfile);
07463          strcpy(backup, msgfile);
07464          strcpy(backup_textfile, msgfile);
07465          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07466          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
07467          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07468          if (ast_fileexists(backup, NULL, NULL) > 0) {
07469             ast_filerename(backup, msgfile, NULL);
07470             rename(backup_textfile, textfile);
07471          }
07472 #endif
07473       }
07474       DISPOSE(dir, curmsg);
07475 #ifndef IMAP_STORAGE
07476       if (cmd) { /* assuming hangup, cleanup backup file */
07477          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07478          strcpy(textfile, msgfile);
07479          strcpy(backup_textfile, msgfile);
07480          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07481          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07482          rename(backup_textfile, textfile);
07483       }
07484 #endif
07485    }
07486 
07487    /* If anything failed above, we still have this list to free */
07488    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07489       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07490       free_user(vmtmp);
07491    }
07492    return res ? res : cmd;
07493 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1760 of file app_voicemail.c.

References ast_free, ast_test_flag, ast_vm_user::emailbody, ast_vm_user::emailsubject, and VM_ALLOCED.

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

01761 {
01762    if (ast_test_flag(vmu, VM_ALLOCED)) {
01763 
01764       ast_free(vmu->emailbody);
01765       vmu->emailbody = NULL;
01766 
01767       ast_free(vmu->emailsubject);
01768       vmu->emailsubject = NULL;
01769 
01770       ast_free(vmu);
01771    }
01772 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11781 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 actual_load_config(), and unload_module().

11782 {
11783    struct ast_vm_user *current;
11784    AST_LIST_LOCK(&users);
11785    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11786       ast_set_flag(current, VM_ALLOCED);
11787       free_user(current);
11788    }
11789    AST_LIST_UNLOCK(&users);
11790 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11793 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11794 {
11795    struct vm_zone *zcur;
11796    AST_LIST_LOCK(&zones);
11797    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11798       free_zone(zcur);
11799    AST_LIST_UNLOCK(&zones);
11800 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5111 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

05112 {
05113    ast_free(z);
05114 }

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

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

Referenced by leave_voicemail().

05068 {
05069    struct ast_tm tm;
05070    struct timeval t = ast_tvnow();
05071    
05072    ast_localtime(&t, &tm, "UTC");
05073 
05074    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05075 }

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

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

Referenced by get_folder2().

06803 {
06804    int x;
06805    int d;
06806    char fn[PATH_MAX];
06807    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06808    if (d)
06809       return d;
06810    for (x = start; x < 5; x++) { /* For all folders */
06811       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06812          return d;
06813       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06814       if (d)
06815          return d;
06816       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06817 
06818       /* The inbox folder can have its name changed under certain conditions
06819        * so this checks if the sound file exists for the inbox folder name and
06820        * if it doesn't, plays the default name instead. */
06821       if (x == 0) {
06822          if (ast_fileexists(fn, NULL, NULL)) {
06823             d = vm_play_folder_name(chan, fn);
06824          } else {
06825             ast_verb(1, "failed to find %s\n", fn);
06826             d = vm_play_folder_name(chan, "vm-INBOX");
06827          }
06828       } else {
06829          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06830          d = vm_play_folder_name(chan, fn);
06831       }
06832 
06833       if (d)
06834          return d;
06835       d = ast_waitfordigit(chan, 500);
06836       if (d)
06837          return d;
06838    }
06839 
06840    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06841    if (d)
06842       return d;
06843    d = ast_waitfordigit(chan, 4000);
06844    return d;
06845 }

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

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

Referenced by vm_execmain().

06860 {
06861    int res = 0;
06862    int loops = 0;
06863 
06864    res = ast_play_and_wait(chan, fn);  /* Folder name */
06865    while (((res < '0') || (res > '9')) &&
06866          (res != '#') && (res >= 0) &&
06867          loops < 4) {
06868       res = get_folder(chan, 0);
06869       loops++;
06870    }
06871    if (loops == 4) { /* give up */
06872       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06873       return '#';
06874    }
06875    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06876    return res;
06877 }

static int get_folder_by_name ( const char *  name  )  [static]

Definition at line 1747 of file app_voicemail.c.

References ARRAY_LEN, and mailbox_folders.

Referenced by vm_execmain().

01748 {
01749    size_t i;
01750 
01751    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01752       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01753          return i;
01754       }
01755    }
01756 
01757    return -1;
01758 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11551 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_task::mailbox, poll_subscribed_mailbox(), and mwi_sub_task::uniqueid.

Referenced by mwi_sub_event_cb().

11552 {
11553    unsigned int len;
11554    struct mwi_sub *mwi_sub;
11555    struct mwi_sub_task *p = datap;
11556 
11557    len = sizeof(*mwi_sub);
11558    if (!ast_strlen_zero(p->mailbox))
11559       len += strlen(p->mailbox);
11560 
11561    if (!ast_strlen_zero(p->context))
11562       len += strlen(p->context) + 1; /* Allow for seperator */
11563 
11564    if (!(mwi_sub = ast_calloc(1, len)))
11565       return -1;
11566 
11567    mwi_sub->uniqueid = p->uniqueid;
11568    if (!ast_strlen_zero(p->mailbox))
11569       strcpy(mwi_sub->mailbox, p->mailbox);
11570 
11571    if (!ast_strlen_zero(p->context)) {
11572       strcat(mwi_sub->mailbox, "@");
11573       strcat(mwi_sub->mailbox, p->context);
11574    }
11575 
11576    AST_RWLIST_WRLOCK(&mwi_subs);
11577    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11578    AST_RWLIST_UNLOCK(&mwi_subs);
11579    ast_free((void *) p->mailbox);
11580    ast_free((void *) p->context);
11581    ast_free(p);
11582    poll_subscribed_mailbox(mwi_sub);
11583    return 0;
11584 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11529 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, and mwi_sub_destroy().

Referenced by mwi_unsub_event_cb().

11530 {
11531    struct mwi_sub *mwi_sub;
11532    uint32_t *uniqueid = datap;
11533    
11534    AST_RWLIST_WRLOCK(&mwi_subs);
11535    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11536       if (mwi_sub->uniqueid == *uniqueid) {
11537          AST_LIST_REMOVE_CURRENT(entry);
11538          break;
11539       }
11540    }
11541    AST_RWLIST_TRAVERSE_SAFE_END
11542    AST_RWLIST_UNLOCK(&mwi_subs);
11543 
11544    if (mwi_sub)
11545       mwi_sub_destroy(mwi_sub);
11546 
11547    ast_free(uniqueid);  
11548    return 0;
11549 }

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

11307 {
11308    switch (cmd) {
11309    case CLI_INIT:
11310       e->command = "voicemail reload";
11311       e->usage =
11312          "Usage: voicemail reload\n"
11313          "       Reload voicemail configuration\n";
11314       return NULL;
11315    case CLI_GENERATE:
11316       return NULL;
11317    }
11318 
11319    if (a->argc != 2)
11320       return CLI_SHOWUSAGE;
11321 
11322    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11323    load_config(1);
11324    
11325    return CLI_SUCCESS;
11326 }

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

11195 {
11196    struct ast_vm_user *vmu;
11197 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11198    const char *context = NULL;
11199    int users_counter = 0;
11200 
11201    switch (cmd) {
11202    case CLI_INIT:
11203       e->command = "voicemail show users";
11204       e->usage =
11205          "Usage: voicemail show users [for <context>]\n"
11206          "       Lists all mailboxes currently set up\n";
11207       return NULL;
11208    case CLI_GENERATE:
11209       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11210    }  
11211 
11212    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11213       return CLI_SHOWUSAGE;
11214    if (a->argc == 5) {
11215       if (strcmp(a->argv[3],"for"))
11216          return CLI_SHOWUSAGE;
11217       context = a->argv[4];
11218    }
11219 
11220    if (ast_check_realtime("voicemail")) {
11221       if (!context) {
11222          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11223          return CLI_SHOWUSAGE;
11224       }
11225       return show_users_realtime(a->fd, context);
11226    }
11227 
11228    AST_LIST_LOCK(&users);
11229    if (AST_LIST_EMPTY(&users)) {
11230       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11231       AST_LIST_UNLOCK(&users);
11232       return CLI_FAILURE;
11233    }
11234    if (!context) {
11235       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11236    } else {
11237       int count = 0;
11238       AST_LIST_TRAVERSE(&users, vmu, list) {
11239          if (!strcmp(context, vmu->context)) {
11240             count++;
11241             break;
11242          }
11243       }
11244       if (count) {
11245          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11246       } else {
11247          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11248          AST_LIST_UNLOCK(&users);
11249          return CLI_FAILURE;
11250       }
11251    }
11252    AST_LIST_TRAVERSE(&users, vmu, list) {
11253       int newmsgs = 0, oldmsgs = 0;
11254       char count[12], tmp[256] = "";
11255 
11256       if (!context || !strcmp(context, vmu->context)) {
11257          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11258          inboxcount(tmp, &newmsgs, &oldmsgs);
11259          snprintf(count, sizeof(count), "%d", newmsgs);
11260          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11261          users_counter++;
11262       }
11263    }
11264    AST_LIST_UNLOCK(&users);
11265    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11266    return CLI_SUCCESS;
11267 }

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 11270 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, and ast_cli_entry::usage.

11271 {
11272    struct vm_zone *zone;
11273 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11274    char *res = CLI_SUCCESS;
11275 
11276    switch (cmd) {
11277    case CLI_INIT:
11278       e->command = "voicemail show zones";
11279       e->usage =
11280          "Usage: voicemail show zones\n"
11281          "       Lists zone message formats\n";
11282       return NULL;
11283    case CLI_GENERATE:
11284       return NULL;
11285    }
11286 
11287    if (a->argc != 3)
11288       return CLI_SHOWUSAGE;
11289 
11290    AST_LIST_LOCK(&zones);
11291    if (!AST_LIST_EMPTY(&zones)) {
11292       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11293       AST_LIST_TRAVERSE(&zones, zone, list) {
11294          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11295       }
11296    } else {
11297       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11298       res = CLI_FAILURE;
11299    }
11300    AST_LIST_UNLOCK(&zones);
11301 
11302    return res;
11303 }

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 __has_voicemail(). 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 5455 of file app_voicemail.c.

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

Referenced by load_module(), and vm_execmain().

05456 {
05457    char tmp[256], *tmp2 = tmp, *box, *context;
05458    ast_copy_string(tmp, mailbox, sizeof(tmp));
05459    if (ast_strlen_zero(folder)) {
05460       folder = "INBOX";
05461    }
05462    while ((box = strsep(&tmp2, ",&"))) {
05463       if ((context = strchr(box, '@')))
05464          *context++ = '\0';
05465       else
05466          context = "default";
05467       if (__has_voicemail(context, box, folder, 1))
05468          return 1;
05469       /* If we are checking INBOX, we should check Urgent as well */
05470       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05471          return 1;
05472       }
05473    }
05474    return 0;
05475 }

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

Definition at line 5537 of file app_voicemail.c.

References inboxcount2().

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

05538 {
05539    int urgentmsgs = 0;
05540    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05541    if (newmsgs) {
05542       *newmsgs += urgentmsgs;
05543    }
05544    return res;
05545 }

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

Definition at line 5478 of file app_voicemail.c.

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

Referenced by append_mailbox(), inboxcount(), load_module(), poll_subscribed_mailbox(), run_externnotify(), and vm_users_data_provider_get_helper().

05479 {
05480    char tmp[256];
05481    char *context;
05482 
05483    /* If no mailbox, return immediately */
05484    if (ast_strlen_zero(mailbox))
05485       return 0;
05486 
05487    if (newmsgs)
05488       *newmsgs = 0;
05489    if (oldmsgs)
05490       *oldmsgs = 0;
05491    if (urgentmsgs)
05492       *urgentmsgs = 0;
05493 
05494    if (strchr(mailbox, ',')) {
05495       int tmpnew, tmpold, tmpurgent;
05496       char *mb, *cur;
05497 
05498       ast_copy_string(tmp, mailbox, sizeof(tmp));
05499       mb = tmp;
05500       while ((cur = strsep(&mb, ", "))) {
05501          if (!ast_strlen_zero(cur)) {
05502             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05503                return -1;
05504             else {
05505                if (newmsgs)
05506                   *newmsgs += tmpnew; 
05507                if (oldmsgs)
05508                   *oldmsgs += tmpold;
05509                if (urgentmsgs)
05510                   *urgentmsgs += tmpurgent;
05511             }
05512          }
05513       }
05514       return 0;
05515    }
05516 
05517    ast_copy_string(tmp, mailbox, sizeof(tmp));
05518    
05519    if ((context = strchr(tmp, '@')))
05520       *context++ = '\0';
05521    else
05522       context = "default";
05523 
05524    if (newmsgs)
05525       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05526    if (oldmsgs)
05527       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05528    if (urgentmsgs)
05529       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05530 
05531    return 0;
05532 }

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

utility used by inchar(), for base_encode()

Definition at line 4237 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(), netconsole(), sip_addheader(), and sip_removeheader().

04238 {
04239    int l;
04240 
04241    if (bio->ateof)
04242       return 0;
04243 
04244    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04245       if (ferror(fi))
04246          return -1;
04247 
04248       bio->ateof = 1;
04249       return 0;
04250    }
04251 
04252    bio->iolen = l;
04253    bio->iocp = 0;
04254 
04255    return 1;
04256 }

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

utility used by base_encode()

Definition at line 4261 of file app_voicemail.c.

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

Referenced by base_encode().

04262 {
04263    if (bio->iocp>=bio->iolen) {
04264       if (!inbuf(bio, fi))
04265          return EOF;
04266    }
04267 
04268    return bio->iobuf[bio->iocp++];
04269 }

static int inprocess_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 942 of file app_voicemail.c.

References CMP_MATCH, inprocess::context, and inprocess::mailbox.

Referenced by load_module().

00943 {
00944    struct inprocess *i = obj, *j = arg;
00945    if (strcmp(i->mailbox, j->mailbox)) {
00946       return 0;
00947    }
00948    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00949 }

static int inprocess_count ( const char *  context,
const char *  mailbox,
int  delta 
) [static]

Definition at line 951 of file app_voicemail.c.

References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_alloca, ast_atomic_fetchadd_int(), ast_log(), inprocess::context, inprocess::count, inprocess_container, LOG_WARNING, and inprocess::mailbox.

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

00952 {
00953    struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00954    arg->context = arg->mailbox + strlen(mailbox) + 1;
00955    strcpy(arg->mailbox, mailbox); /* SAFE */
00956    strcpy(arg->context, context); /* SAFE */
00957    ao2_lock(inprocess_container);
00958    if ((i = ao2_find(inprocess_container, arg, 0))) {
00959       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00960       ao2_unlock(inprocess_container);
00961       ao2_ref(i, -1);
00962       return ret;
00963    }
00964    if (delta < 0) {
00965       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00966    }
00967    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00968       ao2_unlock(inprocess_container);
00969       return 0;
00970    }
00971    i->context = i->mailbox + strlen(mailbox) + 1;
00972    strcpy(i->mailbox, mailbox); /* SAFE */
00973    strcpy(i->context, context); /* SAFE */
00974    i->count = delta;
00975    ao2_link(inprocess_container, i);
00976    ao2_unlock(inprocess_container);
00977    ao2_ref(i, -1);
00978    return 0;
00979 }

static int inprocess_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 936 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

00937 {
00938    const struct inprocess *i = obj;
00939    return atoi(i->mailbox);
00940 }

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

Definition at line 5077 of file app_voicemail.c.

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

Referenced by leave_voicemail().

05078 {
05079    int res;
05080    char fn[PATH_MAX];
05081    char dest[PATH_MAX];
05082 
05083    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05084 
05085    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05086       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05087       return -1;
05088    }
05089 
05090    RETRIEVE(fn, -1, ext, context);
05091    if (ast_fileexists(fn, NULL, NULL) > 0) {
05092       res = ast_stream_and_wait(chan, fn, ecodes);
05093       if (res) {
05094          DISPOSE(fn, -1);
05095          return res;
05096       }
05097    } else {
05098       /* Dispose just in case */
05099       DISPOSE(fn, -1);
05100       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05101       if (res)
05102          return res;
05103       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05104       if (res)
05105          return res;
05106    }
05107    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05108    return res;
05109 }

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

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

Referenced by actual_load_config().

01379 {
01380    int i;
01381    char *local_key = ast_strdupa(key);
01382 
01383    for (i = 0; i < strlen(key); ++i) {
01384       if (!strchr(VALID_DTMF, *local_key)) {
01385          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01386          return 0;
01387       }
01388       local_key++;
01389    }
01390    return 1;
01391 }

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

References ast_debug, map, ast_vm_user::maxmsg, and MAXMSGLIMIT.

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

04057 {
04058    int x;
04059    unsigned char map[MAXMSGLIMIT] = "";
04060    DIR *msgdir;
04061    struct dirent *msgdirent;
04062    int msgdirint;
04063    char extension[4];
04064    int stopcount = 0;
04065 
04066    /* Reading the entire directory into a file map scales better than
04067     * doing a stat repeatedly on a predicted sequence.  I suspect this
04068     * is partially due to stat(2) internally doing a readdir(2) itself to
04069     * find each file. */
04070    if (!(msgdir = opendir(dir))) {
04071       return -1;
04072    }
04073 
04074    while ((msgdirent = readdir(msgdir))) {
04075       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04076          map[msgdirint] = 1;
04077          stopcount++;
04078          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04079       }
04080    }
04081    closedir(msgdir);
04082 
04083    for (x = 0; x < vmu->maxmsg; x++) {
04084       if (map[x] == 1) {
04085          stopcount--;
04086       } else if (map[x] == 0 && !stopcount) {
04087          break;
04088       }
04089    }
04090 
04091    return x - 1;
04092 }

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 5613 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_verb, ast_waitstream(), ast_channel::caller, 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(), ast_party_redirecting::from, get_date(), ast_party_caller::id, inboxcount(), inprocess_count(), INTRO, invent_message(), last_message_index(), LOG_DEBUG, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, my_umask, ast_party_id::name, vm_state::newmessages, notify_new_message(), ast_party_id::number, OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, ast_channel::redirecting, RENAME, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, ast_party_name::str, ast_party_number::str, transfer, ast_party_name::valid, ast_party_number::valid, vm_lock_path(), VM_OPERATOR, VM_SPOOL_DIR, vmfmts, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

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

05614 {
05615 #ifdef IMAP_STORAGE
05616    int newmsgs, oldmsgs;
05617 #else
05618    char urgdir[PATH_MAX];
05619 #endif
05620    char txtfile[PATH_MAX];
05621    char tmptxtfile[PATH_MAX];
05622    struct vm_state *vms = NULL;
05623    char callerid[256];
05624    FILE *txt;
05625    char date[256];
05626    int txtdes;
05627    int res = 0;
05628    int msgnum;
05629    int duration = 0;
05630    int sound_duration = 0;
05631    int ausemacro = 0;
05632    int ousemacro = 0;
05633    int ouseexten = 0;
05634    char tmpdur[16];
05635    char priority[16];
05636    char origtime[16];
05637    char dir[PATH_MAX];
05638    char tmpdir[PATH_MAX];
05639    char fn[PATH_MAX];
05640    char prefile[PATH_MAX] = "";
05641    char tempfile[PATH_MAX] = "";
05642    char ext_context[256] = "";
05643    char fmt[80];
05644    char *context;
05645    char ecodes[17] = "#";
05646    struct ast_str *tmp = ast_str_create(16);
05647    char *tmpptr;
05648    struct ast_vm_user *vmu;
05649    struct ast_vm_user svm;
05650    const char *category = NULL;
05651    const char *code;
05652    const char *alldtmf = "0123456789ABCD*#";
05653    char flag[80];
05654 
05655    if (!tmp) {
05656       return -1;
05657    }
05658 
05659    ast_str_set(&tmp, 0, "%s", ext);
05660    ext = ast_str_buffer(tmp);
05661    if ((context = strchr(ext, '@'))) {
05662       *context++ = '\0';
05663       tmpptr = strchr(context, '&');
05664    } else {
05665       tmpptr = strchr(ext, '&');
05666    }
05667 
05668    if (tmpptr)
05669       *tmpptr++ = '\0';
05670 
05671    ast_channel_lock(chan);
05672    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
05673       category = ast_strdupa(category);
05674    }
05675    ast_channel_unlock(chan);
05676 
05677    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
05678       ast_copy_string(flag, "Urgent", sizeof(flag));
05679    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
05680       ast_copy_string(flag, "PRIORITY", sizeof(flag));
05681    } else {
05682       flag[0] = '\0';
05683    }
05684 
05685    ast_debug(3, "Before find_user\n");
05686    if (!(vmu = find_user(&svm, context, ext))) {
05687       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
05688       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05689       ast_free(tmp);
05690       return res;
05691    }
05692    /* Setup pre-file if appropriate */
05693    if (strcmp(vmu->context, "default"))
05694       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
05695    else
05696       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
05697 
05698    /* Set the path to the prefile. Will be one of 
05699       VM_SPOOL_DIRcontext/ext/busy
05700       VM_SPOOL_DIRcontext/ext/unavail
05701       Depending on the flag set in options.
05702    */
05703    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
05704       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
05705    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
05706       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
05707    }
05708    /* Set the path to the tmpfile as
05709       VM_SPOOL_DIR/context/ext/temp
05710       and attempt to create the folder structure.
05711    */
05712    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
05713    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
05714       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
05715       ast_free(tmp);
05716       return -1;
05717    }
05718    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
05719    if (ast_fileexists(tempfile, NULL, NULL) > 0)
05720       ast_copy_string(prefile, tempfile, sizeof(prefile));
05721 
05722    DISPOSE(tempfile, -1);
05723    /* It's easier just to try to make it than to check for its existence */
05724 #ifndef IMAP_STORAGE
05725    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
05726 #else
05727    snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
05728    if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
05729       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
05730    }
05731 #endif
05732 
05733    /* Check current or macro-calling context for special extensions */
05734    if (ast_test_flag(vmu, VM_OPERATOR)) {
05735       if (!ast_strlen_zero(vmu->exit)) {
05736          if (ast_exists_extension(chan, vmu->exit, "o", 1,
05737             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05738             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05739             ouseexten = 1;
05740          }
05741       } else if (ast_exists_extension(chan, chan->context, "o", 1,
05742          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05743          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05744          ouseexten = 1;
05745       } else if (!ast_strlen_zero(chan->macrocontext)
05746          && ast_exists_extension(chan, chan->macrocontext, "o", 1,
05747             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05748          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05749          ousemacro = 1;
05750       }
05751    }
05752 
05753    if (!ast_strlen_zero(vmu->exit)) {
05754       if (ast_exists_extension(chan, vmu->exit, "a", 1,
05755          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05756          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05757       }
05758    } else if (ast_exists_extension(chan, chan->context, "a", 1,
05759       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05760       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05761    } else if (!ast_strlen_zero(chan->macrocontext)
05762       && ast_exists_extension(chan, chan->macrocontext, "a", 1,
05763          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05764       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05765       ausemacro = 1;
05766    }
05767 
05768    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05769       for (code = alldtmf; *code; code++) {
05770          char e[2] = "";
05771          e[0] = *code;
05772          if (strchr(ecodes, e[0]) == NULL
05773             && ast_canmatch_extension(chan,
05774                (!ast_strlen_zero(options->exitcontext) ? options->exitcontext : chan->context),
05775                e, 1, S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05776             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05777          }
05778       }
05779    }
05780 
05781    /* Play the beginning intro if desired */
05782    if (!ast_strlen_zero(prefile)) {
05783 #ifdef ODBC_STORAGE
05784       int success = 
05785 #endif
05786          RETRIEVE(prefile, -1, ext, context);
05787       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05788          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05789             res = ast_waitstream(chan, ecodes);
05790 #ifdef ODBC_STORAGE
05791          if (success == -1) {
05792             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05793             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05794             store_file(prefile, vmu->mailbox, vmu->context, -1);
05795          }
05796 #endif
05797       } else {
05798          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05799          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05800       }
05801       DISPOSE(prefile, -1);
05802       if (res < 0) {
05803          ast_debug(1, "Hang up during prefile playback\n");
05804          free_user(vmu);
05805          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05806          ast_free(tmp);
05807          return -1;
05808       }
05809    }
05810    if (res == '#') {
05811       /* On a '#' we skip the instructions */
05812       ast_set_flag(options, OPT_SILENT);
05813       res = 0;
05814    }
05815    /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
05816    if (vmu->maxmsg == 0) {
05817       if (option_debug > 2)
05818          ast_log(LOG_DEBUG, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
05819       pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05820       goto leave_vm_out;
05821    }
05822    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05823       res = ast_stream_and_wait(chan, INTRO, ecodes);
05824       if (res == '#') {
05825          ast_set_flag(options, OPT_SILENT);
05826          res = 0;
05827       }
05828    }
05829    if (res > 0)
05830       ast_stopstream(chan);
05831    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05832     other than the operator -- an automated attendant or mailbox login for example */
05833    if (res == '*') {
05834       chan->exten[0] = 'a';
05835       chan->exten[1] = '\0';
05836       if (!ast_strlen_zero(vmu->exit)) {
05837          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05838       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05839          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05840       }
05841       chan->priority = 0;
05842       free_user(vmu);
05843       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05844       ast_free(tmp);
05845       return 0;
05846    }
05847 
05848    /* Check for a '0' here */
05849    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05850    transfer:
05851       if (ouseexten || ousemacro) {
05852          chan->exten[0] = 'o';
05853          chan->exten[1] = '\0';
05854          if (!ast_strlen_zero(vmu->exit)) {
05855             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05856          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05857             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05858          }
05859          ast_play_and_wait(chan, "transfer");
05860          chan->priority = 0;
05861          free_user(vmu);
05862          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05863       }
05864       ast_free(tmp);
05865       return OPERATOR_EXIT;
05866    }
05867 
05868    /* Allow all other digits to exit Voicemail and return to the dialplan */
05869    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05870       if (!ast_strlen_zero(options->exitcontext)) {
05871          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05872       }
05873       free_user(vmu);
05874       ast_free(tmp);
05875       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05876       return res;
05877    }
05878 
05879    if (res < 0) {
05880       free_user(vmu);
05881       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05882       ast_free(tmp);
05883       return -1;
05884    }
05885    /* The meat of recording the message...  All the announcements and beeps have been played*/
05886    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05887    if (!ast_strlen_zero(fmt)) {
05888       msgnum = 0;
05889 
05890 #ifdef IMAP_STORAGE
05891       /* Is ext a mailbox? */
05892       /* must open stream for this user to get info! */
05893       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05894       if (res < 0) {
05895          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05896          ast_free(tmp);
05897          return -1;
05898       }
05899       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05900       /* It is possible under certain circumstances that inboxcount did not
05901        * create a vm_state when it was needed. This is a catchall which will
05902        * rarely be used.
05903        */
05904          if (!(vms = create_vm_state_from_user(vmu))) {
05905             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05906             ast_free(tmp);
05907             return -1;
05908          }
05909       }
05910       vms->newmessages++;
05911       
05912       /* here is a big difference! We add one to it later */
05913       msgnum = newmsgs + oldmsgs;
05914       ast_debug(3, "Messagecount set to %d\n", msgnum);
05915       snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05916       /* set variable for compatibility */
05917       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05918 
05919       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
05920          goto leave_vm_out;
05921       }
05922 #else
05923       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
05924          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05925          if (!res)
05926             res = ast_waitstream(chan, "");
05927          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05928          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05929          inprocess_count(vmu->mailbox, vmu->context, -1);
05930          goto leave_vm_out;
05931       }
05932 
05933 #endif
05934       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05935       txtdes = mkstemp(tmptxtfile);
05936       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05937       if (txtdes < 0) {
05938          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05939          if (!res)
05940             res = ast_waitstream(chan, "");
05941          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05942          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05943          inprocess_count(vmu->mailbox, vmu->context, -1);
05944          goto leave_vm_out;
05945       }
05946 
05947       /* Now play the beep once we have the message number for our next message. */
05948       if (res >= 0) {
05949          /* Unless we're *really* silent, try to send the beep */
05950          res = ast_stream_and_wait(chan, "beep", "");
05951       }
05952             
05953       /* Store information in real-time storage */
05954       if (ast_check_realtime("voicemail_data")) {
05955          snprintf(priority, sizeof(priority), "%d", chan->priority);
05956          snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
05957          get_date(date, sizeof(date));
05958          ast_callerid_merge(callerid, sizeof(callerid),
05959             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05960             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05961             "Unknown");
05962          ast_store_realtime("voicemail_data",
05963             "origmailbox", ext,
05964             "context", chan->context,
05965             "macrocontext", chan->macrocontext,
05966             "exten", chan->exten,
05967             "priority", priority,
05968             "callerchan", chan->name,
05969             "callerid", callerid,
05970             "origdate", date,
05971             "origtime", origtime,
05972             "category", S_OR(category, ""),
05973             "filename", tmptxtfile,
05974             SENTINEL);
05975       }
05976 
05977       /* Store information */
05978       txt = fdopen(txtdes, "w+");
05979       if (txt) {
05980          get_date(date, sizeof(date));
05981          ast_callerid_merge(callerid, sizeof(callerid),
05982             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05983             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05984             "Unknown");
05985          fprintf(txt, 
05986             ";\n"
05987             "; Message Information file\n"
05988             ";\n"
05989             "[message]\n"
05990             "origmailbox=%s\n"
05991             "context=%s\n"
05992             "macrocontext=%s\n"
05993             "exten=%s\n"
05994             "rdnis=%s\n"
05995             "priority=%d\n"
05996             "callerchan=%s\n"
05997             "callerid=%s\n"
05998             "origdate=%s\n"
05999             "origtime=%ld\n"
06000             "category=%s\n",
06001             ext,
06002             chan->context,
06003             chan->macrocontext, 
06004             chan->exten,
06005             S_COR(chan->redirecting.from.number.valid,
06006                chan->redirecting.from.number.str, "unknown"),
06007             chan->priority,
06008             chan->name,
06009             callerid,
06010             date, (long) time(NULL),
06011             category ? category : "");
06012       } else {
06013          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
06014          inprocess_count(vmu->mailbox, vmu->context, -1);
06015          if (ast_check_realtime("voicemail_data")) {
06016             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06017          }
06018          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
06019          goto leave_vm_out;
06020       }
06021       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag);
06022 
06023       if (txt) {
06024          fprintf(txt, "flag=%s\n", flag);
06025          if (sound_duration < vmu->minsecs) {
06026             fclose(txt);
06027             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->minsecs);
06028             ast_filedelete(tmptxtfile, NULL);
06029             unlink(tmptxtfile);
06030             if (ast_check_realtime("voicemail_data")) {
06031                ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06032             }
06033             inprocess_count(vmu->mailbox, vmu->context, -1);
06034          } else {
06035             fprintf(txt, "duration=%d\n", duration);
06036             fclose(txt);
06037             if (vm_lock_path(dir)) {
06038                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
06039                /* Delete files */
06040                ast_filedelete(tmptxtfile, NULL);
06041                unlink(tmptxtfile);
06042                inprocess_count(vmu->mailbox, vmu->context, -1);
06043             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
06044                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
06045                unlink(tmptxtfile);
06046                ast_unlock_path(dir);
06047                inprocess_count(vmu->mailbox, vmu->context, -1);
06048                if (ast_check_realtime("voicemail_data")) {
06049                   ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06050                }
06051             } else {
06052 #ifndef IMAP_STORAGE
06053                msgnum = last_message_index(vmu, dir) + 1;
06054 #endif
06055                make_file(fn, sizeof(fn), dir, msgnum);
06056 
06057                /* assign a variable with the name of the voicemail file */ 
06058 #ifndef IMAP_STORAGE
06059                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
06060 #else
06061                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
06062 #endif
06063 
06064                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
06065                ast_filerename(tmptxtfile, fn, NULL);
06066                rename(tmptxtfile, txtfile);
06067                inprocess_count(vmu->mailbox, vmu->context, -1);
06068 
06069                /* Properly set permissions on voicemail text descriptor file.
06070                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
06071                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
06072                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
06073 
06074                ast_unlock_path(dir);
06075                if (ast_check_realtime("voicemail_data")) {
06076                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
06077                   ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
06078                }
06079                /* We must store the file first, before copying the message, because
06080                 * ODBC storage does the entire copy with SQL.
06081                 */
06082                if (ast_fileexists(fn, NULL, NULL) > 0) {
06083                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
06084                }
06085 
06086                /* Are there to be more recipients of this message? */
06087                while (tmpptr) {
06088                   struct ast_vm_user recipu, *recip;
06089                   char *exten, *cntx;
06090 
06091                   exten = strsep(&tmpptr, "&");
06092                   cntx = strchr(exten, '@');
06093                   if (cntx) {
06094                      *cntx = '\0';
06095                      cntx++;
06096                   }
06097                   if ((recip = find_user(&recipu, cntx, exten))) {
06098                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
06099                      free_user(recip);
06100                   }
06101                }
06102 #ifndef IMAP_STORAGE
06103                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
06104                   /* Move the message from INBOX to Urgent folder if this is urgent! */
06105                   char sfn[PATH_MAX];
06106                   char dfn[PATH_MAX];
06107                   int x;
06108                   /* It's easier just to try to make it than to check for its existence */
06109                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
06110                   x = last_message_index(vmu, urgdir) + 1;
06111                   make_file(sfn, sizeof(sfn), dir, msgnum);
06112                   make_file(dfn, sizeof(dfn), urgdir, x);
06113                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
06114                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
06115                   /* Notification must happen for this new message in Urgent folder, not INBOX */
06116                   ast_copy_string(fn, dfn, sizeof(fn));
06117                   msgnum = x;
06118                }
06119 #endif
06120                /* Notification needs to happen after the copy, though. */
06121                if (ast_fileexists(fn, NULL, NULL)) {
06122 #ifdef IMAP_STORAGE
06123                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
06124                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
06125                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
06126                      flag);
06127 #else
06128                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
06129                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
06130                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
06131                      flag);
06132 #endif
06133                }
06134 
06135                /* Disposal needs to happen after the optional move and copy */
06136                if (ast_fileexists(fn, NULL, NULL)) {
06137                   DISPOSE(dir, msgnum);
06138                }
06139             }
06140          }
06141       } else {
06142          inprocess_count(vmu->mailbox, vmu->context, -1);
06143       }
06144       if (res == '0') {
06145          goto transfer;
06146       } else if (res > 0 && res != 't')
06147          res = 0;
06148 
06149       if (sound_duration < vmu->minsecs)
06150          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
06151          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06152       else
06153          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
06154    } else
06155       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
06156 leave_vm_out:
06157    free_user(vmu);
06158 
06159 #ifdef IMAP_STORAGE
06160    /* expunge message - use UID Expunge if supported on IMAP server*/
06161    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
06162    if (expungeonhangup == 1) {
06163       ast_mutex_lock(&vms->lock);
06164 #ifdef HAVE_IMAP_TK2006
06165       if (LEVELUIDPLUS (vms->mailstream)) {
06166          mail_expunge_full(vms->mailstream, NIL, EX_UID);
06167       } else 
06168 #endif
06169          mail_expunge(vms->mailstream);
06170       ast_mutex_unlock(&vms->lock);
06171    }
06172 #endif
06173 
06174    ast_free(tmp);
06175    return res;
06176 }

static int load_config ( int  reload  )  [static]

Definition at line 11849 of file app_voicemail.c.

References actual_load_config(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_unload_realtime(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, and VOICEMAIL_CONFIG.

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

11850 {
11851    struct ast_config *cfg, *ucfg;
11852    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11853    int res;
11854 
11855    ast_unload_realtime("voicemail");
11856    ast_unload_realtime("voicemail_data");
11857 
11858    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11859       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11860          return 0;
11861       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11862          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11863          ucfg = NULL;
11864       }
11865       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11866       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11867          ast_config_destroy(ucfg);
11868          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11869          return 0;
11870       }
11871    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11872       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11873       return 0;
11874    } else {
11875       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11876       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11877          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11878          ucfg = NULL;
11879       }
11880    }
11881 
11882    res = actual_load_config(reload, cfg, ucfg);
11883 
11884    ast_config_destroy(cfg);
11885    ast_config_destroy(ucfg);
11886 
11887    return res;
11888 }

static int load_module ( void   )  [static]

Definition at line 13150 of file app_voicemail.c.

References ao2_container_alloc, app, app2, app3, app4, ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_data_register_multiple, ast_install_vm_functions(), ast_log(), AST_LOG_WARNING, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application_xml, ast_taskprocessor_get(), AST_TEST_REGISTER, cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), inprocess_cmp_fn(), inprocess_container, inprocess_hash_fn(), load_config(), mailbox_exists_acf, manager_list_voicemail_users(), messagecount(), mwi_subscription_tps, my_umask, RQ_CHAR, RQ_UINTEGER3, sayname(), sayname_app, SENTINEL, vm_box_exists(), vm_data_providers, vm_exec(), vm_execmain(), VM_SPOOL_DIR, vmauthenticate(), and vmsayname_exec().

13151 {
13152    int res;
13153    my_umask = umask(0);
13154    umask(my_umask);
13155 
13156    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13157       return AST_MODULE_LOAD_DECLINE;
13158    }
13159 
13160    /* compute the location of the voicemail spool directory */
13161    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13162    
13163    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13164       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13165    }
13166 
13167    if ((res = load_config(0)))
13168       return res;
13169 
13170    res = ast_register_application_xml(app, vm_exec);
13171    res |= ast_register_application_xml(app2, vm_execmain);
13172    res |= ast_register_application_xml(app3, vm_box_exists);
13173    res |= ast_register_application_xml(app4, vmauthenticate);
13174    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13175    res |= ast_custom_function_register(&mailbox_exists_acf);
13176    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13177 #ifdef TEST_FRAMEWORK
13178    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13179    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13180    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13181    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13182    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13183 #endif
13184 
13185    if (res)
13186       return res;
13187 
13188    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13189    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13190 
13191    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13192    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13193    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13194 
13195    return res;
13196 }

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.
context 
ext 
folder 

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1659 of file app_voicemail.c.

References VM_SPOOL_DIR.

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

01660 {
01661    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01662 }

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.
fromfolder 
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.
attach2 
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.
flag 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 4554 of file app_voicemail.c.

References add_email_attachment(), ast_channel_unref, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_free, ast_localtime(), ast_log(), AST_LOG_WARNING, ast_random(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime(), ast_strftime_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), valid_config(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

04555 {
04556    char date[256];
04557    char host[MAXHOSTNAMELEN] = "";
04558    char who[256];
04559    char bound[256];
04560    char dur[256];
04561    struct ast_tm tm;
04562    char enc_cidnum[256] = "", enc_cidname[256] = "";
04563    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04564    char *greeting_attachment; 
04565    char filename[256];
04566 
04567    if (!str1 || !str2) {
04568       ast_free(str1);
04569       ast_free(str2);
04570       return;
04571    }
04572 
04573    if (cidnum) {
04574       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04575    }
04576    if (cidname) {
04577       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04578    }
04579    gethostname(host, sizeof(host) - 1);
04580 
04581    if (strchr(srcemail, '@')) {
04582       ast_copy_string(who, srcemail, sizeof(who));
04583    } else {
04584       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04585    }
04586 
04587    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04588    if (greeting_attachment) {
04589       *greeting_attachment++ = '\0';
04590    }
04591 
04592    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04593    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04594    fprintf(p, "Date: %s" ENDL, date);
04595 
04596    /* Set date format for voicemail mail */
04597    ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04598 
04599    if (!ast_strlen_zero(fromstring)) {
04600       struct ast_channel *ast;
04601       if ((ast = ast_dummy_channel_alloc())) {
04602          char *ptr;
04603          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04604          ast_str_substitute_variables(&str1, 0, ast, fromstring);
04605 
04606          if (check_mime(ast_str_buffer(str1))) {
04607             int first_line = 1;
04608             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04609             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04610                *ptr = '\0';
04611                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04612                first_line = 0;
04613                /* Substring is smaller, so this will never grow */
04614                ast_str_set(&str2, 0, "%s", ptr + 1);
04615             }
04616             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04617          } else {
04618             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04619          }
04620          ast = ast_channel_unref(ast);
04621       } else {
04622          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04623       }
04624    } else {
04625       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04626    }
04627 
04628    if (check_mime(vmu->fullname)) {
04629       int first_line = 1;
04630       char *ptr;
04631       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
04632       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04633          *ptr = '\0';
04634          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04635          first_line = 0;
04636          /* Substring is smaller, so this will never grow */
04637          ast_str_set(&str2, 0, "%s", ptr + 1);
04638       }
04639       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
04640    } else {
04641       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
04642    }
04643 
04644    if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
04645       char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
04646       struct ast_channel *ast;
04647       if ((ast = ast_dummy_channel_alloc())) {
04648          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04649          ast_str_substitute_variables(&str1, 0, ast, e_subj);
04650          if (check_mime(ast_str_buffer(str1))) {
04651             int first_line = 1;
04652             char *ptr;
04653             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04654             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04655                *ptr = '\0';
04656                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04657                first_line = 0;
04658                /* Substring is smaller, so this will never grow */
04659                ast_str_set(&str2, 0, "%s", ptr + 1);
04660             }
04661             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04662          } else {
04663             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04664          }
04665          ast = ast_channel_unref(ast);
04666       } else {
04667          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04668       }
04669    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04670       if (ast_strlen_zero(flag)) {
04671          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04672       } else {
04673          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04674       }
04675    } else {
04676       if (ast_strlen_zero(flag)) {
04677          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04678       } else {
04679          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04680       }
04681    }
04682 
04683    fprintf(p, "Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
04684       (unsigned int) ast_random(), mailbox, (int) getpid(), host);
04685    if (imap) {
04686       /* additional information needed for IMAP searching */
04687       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04688       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04689       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04690       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04691 #ifdef IMAP_STORAGE
04692       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04693 #else
04694       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04695 #endif
04696       /* flag added for Urgent */
04697       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04698       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04699       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04700       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04701       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04702       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04703       if (!ast_strlen_zero(category)) {
04704          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04705       } else {
04706          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04707       }
04708       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04709       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04710       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
04711    }
04712    if (!ast_strlen_zero(cidnum)) {
04713       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04714    }
04715    if (!ast_strlen_zero(cidname)) {
04716       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04717    }
04718    fprintf(p, "MIME-Version: 1.0" ENDL);
04719    if (attach_user_voicemail) {
04720       /* Something unique. */
04721       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%u", msgnum + 1, mailbox,
04722          (int) getpid(), (unsigned int) ast_random());
04723 
04724       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04725       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04726       fprintf(p, "--%s" ENDL, bound);
04727    }
04728    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04729    if (emailbody || vmu->emailbody) {
04730       char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
04731       struct ast_channel *ast;
04732       if ((ast = ast_dummy_channel_alloc())) {
04733          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04734          ast_str_substitute_variables(&str1, 0, ast, e_body);
04735 #ifdef IMAP_STORAGE
04736             {
04737                /* Convert body to native line terminators for IMAP backend */
04738                char *line = ast_str_buffer(str1), *next;
04739                do {
04740                   /* Terminate line before outputting it to the file */
04741                   if ((next = strchr(line, '\n'))) {
04742                      *next++ = '\0';
04743                   }
04744                   fprintf(p, "%s" ENDL, line);
04745                   line = next;
04746                } while (!ast_strlen_zero(line));
04747             }
04748 #else
04749          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04750 #endif
04751          ast = ast_channel_unref(ast);
04752       } else {
04753          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04754       }
04755    } else if (msgnum > -1) {
04756       if (strcmp(vmu->mailbox, mailbox)) {
04757          /* Forwarded type */
04758          struct ast_config *msg_cfg;
04759          const char *v;
04760          int inttime;
04761          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04762          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04763          /* Retrieve info from VM attribute file */
04764          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04765          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04766          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04767             strcat(fromfile, ".txt");
04768          }
04769          if ((msg_cfg = ast_config_load(fromfile, config_flags)) && valid_config(msg_cfg)) {
04770             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04771                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04772             }
04773 
04774             /* You might be tempted to do origdate, except that a) it's in the wrong
04775              * format, and b) it's missing for IMAP recordings. */
04776             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04777                struct timeval tv = { inttime, };
04778                struct ast_tm tm;
04779                ast_localtime(&tv, &tm, NULL);
04780                ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04781             }
04782             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04783                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04784                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04785                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04786                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04787                date, origcallerid, origdate);
04788             ast_config_destroy(msg_cfg);
04789          } else {
04790             goto plain_message;
04791          }
04792       } else {
04793 plain_message:
04794          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04795             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04796             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04797             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04798             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04799       }
04800    } else {
04801       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04802             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04803    }
04804 
04805    if (imap || attach_user_voicemail) {
04806       if (!ast_strlen_zero(attach2)) {
04807          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04808          ast_debug(5, "creating second attachment filename %s\n", filename);
04809          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04810          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04811          ast_debug(5, "creating attachment filename %s\n", filename);
04812          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04813       } else {
04814          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04815          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04816          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04817       }
04818    }
04819    ast_free(str1);
04820    ast_free(str2);
04821 }

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.
dir 
num 

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1676 of file app_voicemail.c.

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

01677 {
01678    return snprintf(dest, len, "%s/msg%04d", dir, num);
01679 }

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

Manager list voicemail users command.

Definition at line 11680 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, mailcmd, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, ast_vm_user::saydurationm, serveremail, 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().

11681 {
11682    struct ast_vm_user *vmu = NULL;
11683    const char *id = astman_get_header(m, "ActionID");
11684    char actionid[128] = "";
11685 
11686    if (!ast_strlen_zero(id))
11687       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11688 
11689    AST_LIST_LOCK(&users);
11690 
11691    if (AST_LIST_EMPTY(&users)) {
11692       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11693       AST_LIST_UNLOCK(&users);
11694       return RESULT_SUCCESS;
11695    }
11696    
11697    astman_send_ack(s, m, "Voicemail user list will follow");
11698    
11699    AST_LIST_TRAVERSE(&users, vmu, list) {
11700       char dirname[256];
11701 
11702 #ifdef IMAP_STORAGE
11703       int new, old;
11704       inboxcount(vmu->mailbox, &new, &old);
11705 #endif
11706       
11707       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11708       astman_append(s,
11709          "%s"
11710          "Event: VoicemailUserEntry\r\n"
11711          "VMContext: %s\r\n"
11712          "VoiceMailbox: %s\r\n"
11713          "Fullname: %s\r\n"
11714          "Email: %s\r\n"
11715          "Pager: %s\r\n"
11716          "ServerEmail: %s\r\n"
11717          "MailCommand: %s\r\n"
11718          "Language: %s\r\n"
11719          "TimeZone: %s\r\n"
11720          "Callback: %s\r\n"
11721          "Dialout: %s\r\n"
11722          "UniqueID: %s\r\n"
11723          "ExitContext: %s\r\n"
11724          "SayDurationMinimum: %d\r\n"
11725          "SayEnvelope: %s\r\n"
11726          "SayCID: %s\r\n"
11727          "AttachMessage: %s\r\n"
11728          "AttachmentFormat: %s\r\n"
11729          "DeleteMessage: %s\r\n"
11730          "VolumeGain: %.2f\r\n"
11731          "CanReview: %s\r\n"
11732          "CallOperator: %s\r\n"
11733          "MaxMessageCount: %d\r\n"
11734          "MaxMessageLength: %d\r\n"
11735          "NewMessageCount: %d\r\n"
11736 #ifdef IMAP_STORAGE
11737          "OldMessageCount: %d\r\n"
11738          "IMAPUser: %s\r\n"
11739 #endif
11740          "\r\n",
11741          actionid,
11742          vmu->context,
11743          vmu->mailbox,
11744          vmu->fullname,
11745          vmu->email,
11746          vmu->pager,
11747          ast_strlen_zero(vmu->serveremail) ? serveremail : vmu->serveremail,
11748          mailcmd,
11749          vmu->language,
11750          vmu->zonetag,
11751          vmu->callback,
11752          vmu->dialout,
11753          vmu->uniqueid,
11754          vmu->exit,
11755          vmu->saydurationm,
11756          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11757          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11758          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11759          vmu->attachfmt,
11760          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11761          vmu->volgain,
11762          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11763          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11764          vmu->maxmsg,
11765          vmu->maxsecs,
11766 #ifdef IMAP_STORAGE
11767          new, old, vmu->imapuser
11768 #else
11769          count_messages(vmu, dirname)
11770 #endif
11771          );
11772    }     
11773    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11774 
11775    AST_LIST_UNLOCK(&users);
11776 
11777    return RESULT_SUCCESS;
11778 }

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

Definition at line 11501 of file app_voicemail.c.

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_samp2tv(), ast_tvadd(), ast_tvnow(), poll_cond, poll_freq, poll_subscribed_mailboxes(), and poll_thread_run.

Referenced by start_poll_thread().

11502 {
11503    while (poll_thread_run) {
11504       struct timespec ts = { 0, };
11505       struct timeval wait;
11506 
11507       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11508       ts.tv_sec = wait.tv_sec;
11509       ts.tv_nsec = wait.tv_usec * 1000;
11510 
11511       ast_mutex_lock(&poll_lock);
11512       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11513       ast_mutex_unlock(&poll_lock);
11514 
11515       if (!poll_thread_run)
11516          break;
11517 
11518       poll_subscribed_mailboxes();
11519    }
11520 
11521    return NULL;
11522 }

static const char* mbox ( struct ast_vm_user vmu,
int  id 
) [static]

Definition at line 1737 of file app_voicemail.c.

References ARRAY_LEN, and mailbox_folders.

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

01738 {
01739 #ifdef IMAP_STORAGE
01740    if (vmu && id == 0) {
01741       return vmu->imapfolder;
01742    }
01743 #endif
01744    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01745 }

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

Definition at line 5404 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

05405 {
05406    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05407 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11524 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

11525 {
11526    ast_free(mwi_sub);
11527 }

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

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

11613 {
11614    struct mwi_sub_task *mwist;
11615    
11616    if (ast_event_get_type(event) != AST_EVENT_SUB)
11617       return;
11618 
11619    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11620       return;
11621 
11622    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11623       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11624       return;
11625    }
11626    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11627    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11628    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11629    
11630    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11631       ast_free(mwist);
11632    }
11633 }

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

Definition at line 11586 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_log(), ast_taskprocessor_push(), handle_unsubscribe(), LOG_ERROR, mwi_subscription_tps, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

11587 {
11588    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11589 
11590    if (!uniqueid) {
11591       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11592       return;
11593    }
11594 
11595    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11596       ast_free(uniqueid);
11597       return;
11598    }
11599 
11600    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11601       ast_free(uniqueid);
11602       return;
11603    }
11604 
11605    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11606    *uniqueid = u;
11607    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11608       ast_free(uniqueid);
11609    }
11610 }

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.
flag 
Returns:
zero on success, -1 on error.

Definition at line 7090 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_manager_event, 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, ast_vm_user::mailbox, make_dir(), make_file(), mbox(), vm_state::newmessages, ast_vm_user::pager, pbx_builtin_getvar_helper(), queue_mwi_event(), RETRIEVE, run_externnotify(), sendmail(), sendpage(), ast_vm_user::serveremail, serveremail, VM_ATTACH, vm_delete(), VM_DELETE, and VM_SPOOL_DIR.

Referenced by copy_message(), and leave_voicemail().

07091 {
07092    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07093    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07094    const char *category;
07095    char *myserveremail = serveremail;
07096 
07097    ast_channel_lock(chan);
07098    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07099       category = ast_strdupa(category);
07100    }
07101    ast_channel_unlock(chan);
07102 
07103 #ifndef IMAP_STORAGE
07104    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07105 #else
07106    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07107 #endif
07108    make_file(fn, sizeof(fn), todir, msgnum);
07109    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07110 
07111    if (!ast_strlen_zero(vmu->attachfmt)) {
07112       if (strstr(fmt, vmu->attachfmt))
07113          fmt = vmu->attachfmt;
07114       else
07115          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);
07116    }
07117 
07118    /* Attach only the first format */
07119    fmt = ast_strdupa(fmt);
07120    stringp = fmt;
07121    strsep(&stringp, "|");
07122 
07123    if (!ast_strlen_zero(vmu->serveremail))
07124       myserveremail = vmu->serveremail;
07125 
07126    if (!ast_strlen_zero(vmu->email)) {
07127       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07128 
07129       if (attach_user_voicemail)
07130          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07131 
07132       /* XXX possible imap issue, should category be NULL XXX */
07133       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07134 
07135       if (attach_user_voicemail)
07136          DISPOSE(todir, msgnum);
07137    }
07138 
07139    if (!ast_strlen_zero(vmu->pager)) {
07140       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07141    }
07142 
07143    if (ast_test_flag(vmu, VM_DELETE))
07144       DELETE(todir, msgnum, fn, vmu);
07145 
07146    /* Leave voicemail for someone */
07147    if (ast_app_has_voicemail(ext_context, NULL)) 
07148       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07149 
07150    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07151 
07152    ast_manager_event(chan, 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);
07153    run_externnotify(vmu->context, vmu->mailbox, flag);
07154 
07155 #ifdef IMAP_STORAGE
07156    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07157    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07158       vm_imap_delete(NULL, vms->curmsg, vmu);
07159       vms->newmessages--;  /* Fix new message count */
07160    }
07161 #endif
07162 
07163    return 0;
07164 }

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

utility used by base_encode()

Definition at line 4274 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04275 {
04276    if (bio->linelength >= BASELINELEN) {
04277       if (fputs(ENDL, so) == EOF) {
04278          return -1;
04279       }
04280 
04281       bio->linelength = 0;
04282    }
04283 
04284    if (putc(((unsigned char) c), so) == EOF) {
04285       return -1;
04286    }
04287 
04288    bio->linelength++;
04289 
04290    return 1;
04291 }

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

Definition at line 7938 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, ERROR_LOCK_PATH, last_message_index(), vm_state::lastmsg, LOG_NOTICE, ast_vm_user::maxmsg, mbox(), resequence_mailbox(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

Referenced by vm_execmain().

07939 {
07940    int count_msg, last_msg;
07941 
07942    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07943 
07944    /* Rename the member vmbox HERE so that we don't try to return before
07945     * we know what's going on.
07946     */
07947    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07948 
07949    /* Faster to make the directory than to check if it exists. */
07950    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07951 
07952    /* traverses directory using readdir (or select query for ODBC) */
07953    count_msg = count_messages(vmu, vms->curdir);
07954    if (count_msg < 0) {
07955       return count_msg;
07956    } else {
07957       vms->lastmsg = count_msg - 1;
07958    }
07959 
07960    if (vm_allocate_dh(vms, vmu, count_msg)) {
07961       return -1;
07962    }
07963 
07964    /*
07965    The following test is needed in case sequencing gets messed up.
07966    There appears to be more than one way to mess up sequence, so
07967    we will not try to find all of the root causes--just fix it when
07968    detected.
07969    */
07970 
07971    if (vm_lock_path(vms->curdir)) {
07972       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07973       return ERROR_LOCK_PATH;
07974    }
07975 
07976    /* for local storage, checks directory for messages up to maxmsg limit */
07977    last_msg = last_message_index(vmu, vms->curdir);
07978    ast_unlock_path(vms->curdir);
07979 
07980    if (last_msg < -1) {
07981       return last_msg;
07982    } else if (vms->lastmsg != last_msg) {
07983       ast_log(LOG_NOTICE, "Resequencing Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
07984       resequence_mailbox(vmu, vms->curdir, count_msg);
07985    }
07986 
07987    return 0;
07988 }

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

Definition at line 7712 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_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, 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, valid_config(), 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_vi(), vm_browse_messages_zh(), and vm_execmain().

07713 {
07714    int res = 0;
07715    char filename[256], *cid;
07716    const char *origtime, *context, *category, *duration, *flag;
07717    struct ast_config *msg_cfg;
07718    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07719 
07720    vms->starting = 0;
07721    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07722    adsi_message(chan, vms);
07723    if (!vms->curmsg) {
07724       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07725    } else if (vms->curmsg == vms->lastmsg) {
07726       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07727    }
07728 
07729    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07730    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07731    msg_cfg = ast_config_load(filename, config_flags);
07732    if (!valid_config(msg_cfg)) {
07733       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07734       return 0;
07735    }
07736    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07737 
07738    /* Play the word urgent if we are listening to urgent messages */
07739    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07740       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07741    }
07742 
07743    if (!res) {
07744       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07745       /* POLISH syntax */
07746       if (!strncasecmp(chan->language, "pl", 2)) {
07747          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07748             int ten, one;
07749             char nextmsg[256];
07750             ten = (vms->curmsg + 1) / 10;
07751             one = (vms->curmsg + 1) % 10;
07752 
07753             if (vms->curmsg < 20) {
07754                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07755                res = wait_file2(chan, vms, nextmsg);
07756             } else {
07757                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07758                res = wait_file2(chan, vms, nextmsg);
07759                if (one > 0) {
07760                   if (!res) {
07761                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07762                      res = wait_file2(chan, vms, nextmsg);
07763                   }
07764                }
07765             }
07766          }
07767          if (!res)
07768             res = wait_file2(chan, vms, "vm-message");
07769       /* HEBREW syntax */
07770       } else if (!strncasecmp(chan->language, "he", 2)) {
07771          if (!vms->curmsg) {
07772             res = wait_file2(chan, vms, "vm-message");
07773             res = wait_file2(chan, vms, "vm-first");
07774          } else if (vms->curmsg == vms->lastmsg) {
07775             res = wait_file2(chan, vms, "vm-message");
07776             res = wait_file2(chan, vms, "vm-last");
07777          } else {
07778             res = wait_file2(chan, vms, "vm-message");
07779             res = wait_file2(chan, vms, "vm-number");
07780             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07781          }
07782       /* VIETNAMESE syntax */
07783       } else if (!strncasecmp(chan->language, "vi", 2)) {
07784          if (!vms->curmsg) {
07785             res = wait_file2(chan, vms, "vm-message");
07786             res = wait_file2(chan, vms, "vm-first");
07787          } else if (vms->curmsg == vms->lastmsg) {
07788             res = wait_file2(chan, vms, "vm-message");
07789             res = wait_file2(chan, vms, "vm-last");
07790          } else {
07791             res = wait_file2(chan, vms, "vm-message");
07792             res = wait_file2(chan, vms, "vm-number");
07793             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07794          }
07795       } else {
07796          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07797             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07798          } else { /* DEFAULT syntax */
07799             res = wait_file2(chan, vms, "vm-message");
07800          }
07801          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07802             if (!res) {
07803                ast_test_suite_event_notify("PLAYBACK", "Message: message number");
07804                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07805             }
07806          }
07807       }
07808    }
07809 
07810    if (!valid_config(msg_cfg)) {
07811       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07812       return 0;
07813    }
07814 
07815    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07816       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07817       DISPOSE(vms->curdir, vms->curmsg);
07818       ast_config_destroy(msg_cfg);
07819       return 0;
07820    }
07821 
07822    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07823    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07824    category = ast_variable_retrieve(msg_cfg, "message", "category");
07825 
07826    context = ast_variable_retrieve(msg_cfg, "message", "context");
07827    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07828       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07829    if (!res) {
07830       res = play_message_category(chan, category);
07831    }
07832    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
07833       res = play_message_datetime(chan, vmu, origtime, filename);
07834    }
07835    if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
07836       res = play_message_callerid(chan, vms, cid, context, 0);
07837    }
07838    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
07839       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07840    }
07841    /* Allow pressing '1' to skip envelope / callerid */
07842    if (res == '1') {
07843       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07844       res = 0;
07845    }
07846    ast_config_destroy(msg_cfg);
07847 
07848    if (!res) {
07849       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07850 #ifdef IMAP_STORAGE
07851       ast_mutex_lock(&vms->lock);
07852 #endif
07853       vms->heard[vms->curmsg] = 1;
07854 #ifdef IMAP_STORAGE
07855       ast_mutex_unlock(&vms->lock);
07856       /*IMAP storage stores any prepended message from a forward
07857        * as a separate file from the rest of the message
07858        */
07859       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07860          wait_file(chan, vms, vms->introfn);
07861       }
07862 #endif
07863       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07864          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07865          res = 0;
07866       }
07867       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07868    }
07869    DISPOSE(vms->curdir, vms->curmsg);
07870    return res;
07871 }

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

Definition at line 7598 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, name, VM_SPOOL_DIR, and wait_file2().

Referenced by advanced_options(), and play_message().

07599 {
07600    int res = 0;
07601    int i;
07602    char *callerid, *name;
07603    char prefile[PATH_MAX] = "";
07604    
07605 
07606    /* If voicemail cid is not enabled, or we didn't get cid or context from
07607     * the attribute file, leave now.
07608     *
07609     * TODO Still need to change this so that if this function is called by the
07610     * message envelope (and someone is explicitly requesting to hear the CID),
07611     * it does not check to see if CID is enabled in the config file.
07612     */
07613    if ((cid == NULL)||(context == NULL))
07614       return res;
07615 
07616    /* Strip off caller ID number from name */
07617    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07618    ast_callerid_parse(cid, &name, &callerid);
07619    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07620       /* Check for internal contexts and only */
07621       /* say extension when the call didn't come from an internal context in the list */
07622       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07623          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07624          if ((strcmp(cidinternalcontexts[i], context) == 0))
07625             break;
07626       }
07627       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07628          if (!res) {
07629             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07630             if (!ast_strlen_zero(prefile)) {
07631             /* See if we can find a recorded name for this person instead of their extension number */
07632                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07633                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07634                   if (!callback)
07635                      res = wait_file2(chan, vms, "vm-from");
07636                   res = ast_stream_and_wait(chan, prefile, "");
07637                } else {
07638                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07639                   /* Say "from extension" as one saying to sound smoother */
07640                   if (!callback)
07641                      res = wait_file2(chan, vms, "vm-from-extension");
07642                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07643                }
07644             }
07645          }
07646       } else if (!res) {
07647          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07648          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07649          if (!callback)
07650             res = wait_file2(chan, vms, "vm-from-phonenumber");
07651          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07652       }
07653    } else {
07654       /* Number unknown */
07655       ast_debug(1, "VM-CID: From an unknown number\n");
07656       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07657       res = wait_file2(chan, vms, "vm-unknown-caller");
07658    }
07659    return res;
07660 }

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

Definition at line 7509 of file app_voicemail.c.

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

Referenced by play_message().

07510 {
07511    int res = 0;
07512 
07513    if (!ast_strlen_zero(category))
07514       res = ast_play_and_wait(chan, category);
07515 
07516    if (res) {
07517       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07518       res = 0;
07519    }
07520 
07521    return res;
07522 }

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

Definition at line 7524 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(), pbx_builtin_setvar_helper(), and ast_vm_user::zonetag.

Referenced by advanced_options(), and play_message().

07525 {
07526    int res = 0;
07527    struct vm_zone *the_zone = NULL;
07528    time_t t;
07529 
07530    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07531       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07532       return 0;
07533    }
07534 
07535    /* Does this user have a timezone specified? */
07536    if (!ast_strlen_zero(vmu->zonetag)) {
07537       /* Find the zone in the list */
07538       struct vm_zone *z;
07539       AST_LIST_LOCK(&zones);
07540       AST_LIST_TRAVERSE(&zones, z, list) {
07541          if (!strcmp(z->name, vmu->zonetag)) {
07542             the_zone = z;
07543             break;
07544          }
07545       }
07546       AST_LIST_UNLOCK(&zones);
07547    }
07548 
07549 /* No internal variable parsing for now, so we'll comment it out for the time being */
07550 #if 0
07551    /* Set the DIFF_* variables */
07552    ast_localtime(&t, &time_now, NULL);
07553    tv_now = ast_tvnow();
07554    ast_localtime(&tv_now, &time_then, NULL);
07555 
07556    /* Day difference */
07557    if (time_now.tm_year == time_then.tm_year)
07558       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07559    else
07560       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07561    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07562 
07563    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07564 #endif
07565    if (the_zone) {
07566       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07567    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07568       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07569    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07570       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07571    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07572       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);
07573    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07574       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07575    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07576       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07577    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07578       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07579    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07580       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);
07581    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07582       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07583    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07584       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07585    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07586       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL);
07587    } else {
07588       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07589    }
07590 #if 0
07591    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07592 #endif
07593    return res;
07594 }

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

Definition at line 7662 of file app_voicemail.c.

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

Referenced by play_message().

07663 {
07664    int res = 0;
07665    int durationm;
07666    int durations;
07667    /* Verify that we have a duration for the message */
07668    if (duration == NULL)
07669       return res;
07670 
07671    /* Convert from seconds to minutes */
07672    durations = atoi(duration);
07673    durationm = (durations / 60);
07674 
07675    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07676 
07677    if ((!res) && (durationm >= minduration)) {
07678       res = wait_file2(chan, vms, "vm-duration");
07679 
07680       /* POLISH syntax */
07681       if (!strncasecmp(chan->language, "pl", 2)) {
07682          div_t num = div(durationm, 10);
07683 
07684          if (durationm == 1) {
07685             res = ast_play_and_wait(chan, "digits/1z");
07686             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07687          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07688             if (num.rem == 2) {
07689                if (!num.quot) {
07690                   res = ast_play_and_wait(chan, "digits/2-ie");
07691                } else {
07692                   res = say_and_wait(chan, durationm - 2 , chan->language);
07693                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07694                }
07695             } else {
07696                res = say_and_wait(chan, durationm, chan->language);
07697             }
07698             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07699          } else {
07700             res = say_and_wait(chan, durationm, chan->language);
07701             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07702          }
07703       /* DEFAULT syntax */
07704       } else {
07705          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07706          res = wait_file2(chan, vms, "vm-minutes");
07707       }
07708    }
07709    return res;
07710 }

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,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 13463 of file app_voicemail.c.

References acceptdtmf, ast_channel_setoption(), ast_copy_string(), 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, maxsilence, silencethreshold, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

13466 {
13467    /* Record message & let caller review or re-record it, or set options if applicable */
13468    int res = 0;
13469    int cmd = 0;
13470    int max_attempts = 3;
13471    int attempts = 0;
13472    int recorded = 0;
13473    int msg_exists = 0;
13474    signed char zero_gain = 0;
13475    char tempfile[PATH_MAX];
13476    char *acceptdtmf = "#";
13477    char *canceldtmf = "";
13478    int canceleddtmf = 0;
13479 
13480    /* Note that urgent and private are for flagging messages as such in the future */
13481 
13482    /* barf if no pointer passed to store duration in */
13483    if (duration == NULL) {
13484       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13485       return -1;
13486    }
13487 
13488    if (!outsidecaller)
13489       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13490    else
13491       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13492 
13493    cmd = '3';  /* Want to start by recording */
13494 
13495    while ((cmd >= 0) && (cmd != 't')) {
13496       switch (cmd) {
13497       case '1':
13498          if (!msg_exists) {
13499             /* In this case, 1 is to record a message */
13500             cmd = '3';
13501             break;
13502          } else {
13503             /* Otherwise 1 is to save the existing message */
13504             ast_verb(3, "Saving message as is\n");
13505             if (!outsidecaller) 
13506                ast_filerename(tempfile, recordfile, NULL);
13507             ast_stream_and_wait(chan, "vm-msgsaved", "");
13508             if (!outsidecaller) {
13509                /* Saves to IMAP server only if imapgreeting=yes */
13510                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13511                DISPOSE(recordfile, -1);
13512             }
13513             cmd = 't';
13514             return res;
13515          }
13516       case '2':
13517          /* Review */
13518          ast_verb(3, "Reviewing the message\n");
13519          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13520          break;
13521       case '3':
13522          msg_exists = 0;
13523          /* Record */
13524          if (recorded == 1) 
13525             ast_verb(3, "Re-recording the message\n");
13526          else  
13527             ast_verb(3, "Recording the message\n");
13528          
13529          if (recorded && outsidecaller) {
13530             cmd = ast_play_and_wait(chan, INTRO);
13531             cmd = ast_play_and_wait(chan, "beep");
13532          }
13533          recorded = 1;
13534          /* 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 */
13535          if (record_gain)
13536             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13537          if (ast_test_flag(vmu, VM_OPERATOR))
13538             canceldtmf = "0";
13539          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13540          if (strchr(canceldtmf, cmd)) {
13541          /* need this flag here to distinguish between pressing '0' during message recording or after */
13542             canceleddtmf = 1;
13543          }
13544          if (record_gain)
13545             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13546          if (cmd == -1) {
13547             /* User has hung up, no options to give */
13548             if (!outsidecaller) {
13549                /* user was recording a greeting and they hung up, so let's delete the recording. */
13550                ast_filedelete(tempfile, NULL);
13551             }     
13552             return cmd;
13553          }
13554          if (cmd == '0') {
13555             break;
13556          } else if (cmd == '*') {
13557             break;
13558 #if 0
13559          } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13560             /* Message is too short */
13561             ast_verb(3, "Message too short\n");
13562             cmd = ast_play_and_wait(chan, "vm-tooshort");
13563             cmd = ast_filedelete(tempfile, NULL);
13564             break;
13565          } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13566             /* Message is all silence */
13567             ast_verb(3, "Nothing recorded\n");
13568             cmd = ast_filedelete(tempfile, NULL);
13569             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13570             if (!cmd)
13571                cmd = ast_play_and_wait(chan, "vm-speakup");
13572             break;
13573 #endif
13574          } else {
13575             /* If all is well, a message exists */
13576             msg_exists = 1;
13577             cmd = 0;
13578          }
13579          break;
13580       case '4':
13581          if (outsidecaller) {  /* only mark vm messages */
13582             /* Mark Urgent */
13583             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13584                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13585                res = ast_play_and_wait(chan, "vm-marked-urgent");
13586                strcpy(flag, "Urgent");
13587             } else if (flag) {
13588                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13589                res = ast_play_and_wait(chan, "vm-marked-nonurgent");
13590                strcpy(flag, "");
13591             } else {
13592                ast_play_and_wait(chan, "vm-sorry");
13593             }
13594             cmd = 0;
13595          } else {
13596             cmd = ast_play_and_wait(chan, "vm-sorry");
13597          }
13598          break;
13599       case '5':
13600       case '6':
13601       case '7':
13602       case '8':
13603       case '9':
13604       case '*':
13605       case '#':
13606          cmd = ast_play_and_wait(chan, "vm-sorry");
13607          break;
13608 #if 0 
13609 /*  XXX Commented out for the moment because of the dangers of deleting
13610     a message while recording (can put the message numbers out of sync) */
13611       case '*':
13612          /* Cancel recording, delete message, offer to take another message*/
13613          cmd = ast_play_and_wait(chan, "vm-deleted");
13614          cmd = ast_filedelete(tempfile, NULL);
13615          if (outsidecaller) {
13616             res = vm_exec(chan, NULL);
13617             return res;
13618          }
13619          else
13620             return 1;
13621 #endif
13622       case '0':
13623          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13624             cmd = ast_play_and_wait(chan, "vm-sorry");
13625             break;
13626          }
13627          if (msg_exists || recorded) {
13628             cmd = ast_play_and_wait(chan, "vm-saveoper");
13629             if (!cmd)
13630                cmd = ast_waitfordigit(chan, 3000);
13631             if (cmd == '1') {
13632                ast_filerename(tempfile, recordfile, NULL);
13633                ast_play_and_wait(chan, "vm-msgsaved");
13634                cmd = '0';
13635             } else if (cmd == '4') {
13636                if (flag) {
13637                   ast_play_and_wait(chan, "vm-marked-urgent");
13638                   strcpy(flag, "Urgent");
13639                }
13640                ast_play_and_wait(chan, "vm-msgsaved");
13641                cmd = '0';
13642             } else {
13643                ast_play_and_wait(chan, "vm-deleted");
13644                DELETE(tempfile, -1, tempfile, vmu);
13645                cmd = '0';
13646             }
13647          }
13648          return cmd;
13649       default:
13650          /* If the caller is an ouside caller, and the review option is enabled,
13651             allow them to review the message, but let the owner of the box review
13652             their OGM's */
13653          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13654             return cmd;
13655          if (msg_exists) {
13656             cmd = ast_play_and_wait(chan, "vm-review");
13657             if (!cmd && outsidecaller) {
13658                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13659                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13660                } else if (flag) {
13661                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13662                }
13663             }
13664          } else {
13665             cmd = ast_play_and_wait(chan, "vm-torerecord");
13666             if (!cmd)
13667                cmd = ast_waitfordigit(chan, 600);
13668          }
13669          
13670          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13671             cmd = ast_play_and_wait(chan, "vm-reachoper");
13672             if (!cmd)
13673                cmd = ast_waitfordigit(chan, 600);
13674          }
13675 #if 0
13676          if (!cmd)
13677             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13678 #endif
13679          if (!cmd)
13680             cmd = ast_waitfordigit(chan, 6000);
13681          if (!cmd) {
13682             attempts++;
13683          }
13684          if (attempts > max_attempts) {
13685             cmd = 't';
13686          }
13687       }
13688    }
13689    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13690       /* Hang up or timeout, so delete the recording. */
13691       ast_filedelete(tempfile, NULL);
13692    }
13693 
13694    if (cmd != 't' && outsidecaller)
13695       ast_play_and_wait(chan, "vm-goodbye");
13696 
13697    return cmd;
13698 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11473 of file app_voicemail.c.

References inboxcount2(), queue_mwi_event(), and run_externnotify().

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11474 {
11475    int new = 0, old = 0, urgent = 0;
11476 
11477    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11478 
11479    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11480       mwi_sub->old_urgent = urgent;
11481       mwi_sub->old_new = new;
11482       mwi_sub->old_old = old;
11483       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11484       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11485    }
11486 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11488 of file app_voicemail.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), and poll_subscribed_mailbox().

Referenced by mb_poll_thread().

11489 {
11490    struct mwi_sub *mwi_sub;
11491 
11492    AST_RWLIST_RDLOCK(&mwi_subs);
11493    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11494       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11495          poll_subscribed_mailbox(mwi_sub);
11496       }
11497    }
11498    AST_RWLIST_UNLOCK(&mwi_subs);
11499 }

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
  • emailsubject, emailbody set to NULL

Definition at line 1021 of file app_voicemail.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_free, ast_vm_user::callback, callcontext, dialcontext, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, exitcontext, globalflags, locale, ast_vm_user::locale, ast_vm_user::maxdeletedmsg, maxdeletedmsg, ast_vm_user::maxmsg, maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, passwordlocation, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, saydurationminfo, vmmaxsecs, vmminsecs, volgain, ast_vm_user::volgain, zonetag, and ast_vm_user::zonetag.

Referenced by actual_load_config(), append_mailbox(), AST_TEST_DEFINE(), and find_user_realtime().

01022 {
01023    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
01024    vmu->passwordlocation = passwordlocation;
01025    if (saydurationminfo) {
01026       vmu->saydurationm = saydurationminfo;
01027    }
01028    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
01029    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
01030    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
01031    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
01032    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
01033    if (vmminsecs) {
01034       vmu->minsecs = vmminsecs;
01035    }
01036    if (vmmaxsecs) {
01037       vmu->maxsecs = vmmaxsecs;
01038    }
01039    if (maxmsg) {
01040       vmu->maxmsg = maxmsg;
01041    }
01042    if (maxdeletedmsg) {
01043       vmu->maxdeletedmsg = maxdeletedmsg;
01044    }
01045    vmu->volgain = volgain;
01046    ast_free(vmu->emailsubject);
01047    vmu->emailsubject = NULL;
01048    ast_free(vmu->emailbody);
01049    vmu->emailbody = NULL;
01050 #ifdef IMAP_STORAGE
01051    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
01052 #endif
01053 }

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

Definition at line 4362 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_locale(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, emaildateformat, ast_vm_user::fullname, ast_vm_user::locale, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, pbx_builtin_setvar_helper(), S_OR, and valid_config().

Referenced by make_email_file(), and sendpage().

04363 {
04364    char callerid[256];
04365    char num[12];
04366    char fromdir[256], fromfile[256];
04367    struct ast_config *msg_cfg;
04368    const char *origcallerid, *origtime;
04369    char origcidname[80], origcidnum[80], origdate[80];
04370    int inttime;
04371    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04372 
04373    /* Prepare variables for substitution in email body and subject */
04374    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04375    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04376    snprintf(num, sizeof(num), "%d", msgnum);
04377    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04378    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04379    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04380    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04381       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04382    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04383    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04384    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04385    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04386    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04387 
04388    /* Retrieve info from VM attribute file */
04389    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04390    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04391    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04392       strcat(fromfile, ".txt");
04393    }
04394    if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
04395       if (option_debug > 0) {
04396          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04397       }
04398       return;
04399    }
04400 
04401    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04402       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04403       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04404       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04405       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04406    }
04407 
04408    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04409       struct timeval tv = { inttime, };
04410       struct ast_tm tm;
04411       ast_localtime(&tv, &tm, NULL);
04412       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04413       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04414    }
04415    ast_config_destroy(msg_cfg);
04416 }

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

Definition at line 7053 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, and ast_strlen_zero().

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

07054 {
07055    struct ast_event *event;
07056    char *mailbox, *context;
07057 
07058    /* Strip off @default */
07059    context = mailbox = ast_strdupa(box);
07060    strsep(&context, "@");
07061    if (ast_strlen_zero(context))
07062       context = "default";
07063 
07064    if (!(event = ast_event_new(AST_EVENT_MWI,
07065          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07066          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07067          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07068          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07069          AST_EVENT_IE_END))) {
07070       return;
07071    }
07072 
07073    ast_event_queue_and_cache(event);
07074 }

static void read_password_from_file ( const char *  secretfn,
char *  password,
int  passwordlen 
) [static]

Definition at line 12579 of file app_voicemail.c.

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log(), ast_variable_retrieve(), LOG_NOTICE, and valid_config().

Referenced by actual_load_config(), and append_mailbox().

12579                                                                                            {
12580    struct ast_config *pwconf;
12581    struct ast_flags config_flags = { 0 };
12582 
12583    pwconf = ast_config_load(secretfn, config_flags);
12584    if (valid_config(pwconf)) {
12585       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12586       if (val) {
12587          ast_copy_string(password, val, passwordlen);
12588          ast_config_destroy(pwconf);
12589          return;
12590       }
12591       ast_config_destroy(pwconf);
12592    }
12593    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12594 }

static int reload ( void   )  [static]

Definition at line 13110 of file app_voicemail.c.

References load_config().

13111 {
13112    return load_config(1);
13113 }

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

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

04033 {
04034    char stxt[PATH_MAX];
04035    char dtxt[PATH_MAX];
04036    ast_filerename(sfn, dfn, NULL);
04037    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04038    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04039    if (ast_check_realtime("voicemail_data")) {
04040       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04041    }
04042    rename(stxt, dtxt);
04043 }

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

Definition at line 6179 of file app_voicemail.c.

References ast_unlock_path(), ast_vm_user::context, ERROR_LOCK_PATH, EXISTS, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, RENAME, and vm_lock_path().

Referenced by open_mailbox().

06180 {
06181    /* we know the actual number of messages, so stop process when number is hit */
06182 
06183    int x, dest;
06184    char sfn[PATH_MAX];
06185    char dfn[PATH_MAX];
06186 
06187    if (vm_lock_path(dir)) {
06188       return ERROR_LOCK_PATH;
06189    }
06190 
06191    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06192       make_file(sfn, sizeof(sfn), dir, x);
06193       if (EXISTS(dir, x, sfn, NULL)) {
06194 
06195          if (x != dest) {
06196             make_file(dfn, sizeof(dfn), dir, dest);
06197             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06198          }
06199 
06200          dest++;
06201       }
06202    }
06203    ast_unlock_path(dir);
06204 
06205    return dest;
06206 }

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

01492 {
01493    /* This function could be made to generate one from a database, too */
01494    struct ast_vm_user *cur;
01495    int res = -1;
01496    AST_LIST_LOCK(&users);
01497    AST_LIST_TRAVERSE(&users, cur, list) {
01498       if ((!context || !strcasecmp(context, cur->context)) &&
01499          (!strcasecmp(mailbox, cur->mailbox)))
01500             break;
01501    }
01502    if (cur) {
01503       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01504       res = 0;
01505    }
01506    AST_LIST_UNLOCK(&users);
01507    return res;
01508 }

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

Definition at line 5547 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, externnotify, ast_smdi_mwi_message::fwd_st, inboxcount2(), S_OR, smdi_iface, and SMDI_MWI_WAIT_TIMEOUT.

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

05548 {
05549    char arguments[255];
05550    char ext_context[256] = "";
05551    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05552    struct ast_smdi_mwi_message *mwi_msg;
05553 
05554    if (!ast_strlen_zero(context))
05555       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05556    else
05557       ast_copy_string(ext_context, extension, sizeof(ext_context));
05558 
05559    if (smdi_iface) {
05560       if (ast_app_has_voicemail(ext_context, NULL)) 
05561          ast_smdi_mwi_set(smdi_iface, extension);
05562       else
05563          ast_smdi_mwi_unset(smdi_iface, extension);
05564 
05565       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05566          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05567          if (!strncmp(mwi_msg->cause, "INV", 3))
05568             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05569          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05570             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05571          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05572          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05573       } else {
05574          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05575       }
05576    }
05577 
05578    if (!ast_strlen_zero(externnotify)) {
05579       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05580          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05581       } else {
05582          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
05583             externnotify, S_OR(context, "\"\""),
05584             extension, newvoicemails,
05585             oldvoicemails, urgentvoicemails);
05586          ast_debug(1, "Executing %s\n", arguments);
05587          ast_safe_system(arguments);
05588       }
05589    }
05590 }

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

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

06217 {
06218 #ifdef IMAP_STORAGE
06219    /* we must use mbox(x) folder names, and copy the message there */
06220    /* simple. huh? */
06221    char sequence[10];
06222    char mailbox[256];
06223    int res;
06224 
06225    /* get the real IMAP message number for this message */
06226    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06227    
06228    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06229    ast_mutex_lock(&vms->lock);
06230    /* if save to Old folder, put in INBOX as read */
06231    if (box == OLD_FOLDER) {
06232       mail_setflag(vms->mailstream, sequence, "\\Seen");
06233       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06234    } else if (box == NEW_FOLDER) {
06235       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06236       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06237    }
06238    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06239       ast_mutex_unlock(&vms->lock);
06240       return 0;
06241    }
06242    /* Create the folder if it don't exist */
06243    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06244    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06245    if (mail_create(vms->mailstream, mailbox) == NIL) 
06246       ast_debug(5, "Folder exists.\n");
06247    else
06248       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06249    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06250    ast_mutex_unlock(&vms->lock);
06251    return res;
06252 #else
06253    char *dir = vms->curdir;
06254    char *username = vms->username;
06255    char *context = vmu->context;
06256    char sfn[PATH_MAX];
06257    char dfn[PATH_MAX];
06258    char ddir[PATH_MAX];
06259    const char *dbox = mbox(vmu, box);
06260    int x, i;
06261    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06262 
06263    if (vm_lock_path(ddir))
06264       return ERROR_LOCK_PATH;
06265 
06266    x = last_message_index(vmu, ddir) + 1;
06267 
06268    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06269       x--;
06270       for (i = 1; i <= x; i++) {
06271          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06272          make_file(sfn, sizeof(sfn), ddir, i);
06273          make_file(dfn, sizeof(dfn), ddir, i - 1);
06274          if (EXISTS(ddir, i, sfn, NULL)) {
06275             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06276          } else
06277             break;
06278       }
06279    } else {
06280       if (x >= vmu->maxmsg) {
06281          ast_unlock_path(ddir);
06282          return -1;
06283       }
06284    }
06285    make_file(sfn, sizeof(sfn), dir, msg);
06286    make_file(dfn, sizeof(dfn), ddir, x);
06287    if (strcmp(sfn, dfn)) {
06288       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06289    }
06290    ast_unlock_path(ddir);
06291 #endif
06292    return 0;
06293 }

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

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

Referenced by load_module(), and vmsayname_exec().

12566 {
12567    int res = -1;
12568    char dir[PATH_MAX];
12569    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12570    ast_debug(2, "About to try retrieving name file %s\n", dir);
12571    RETRIEVE(dir, -1, mailbox, context);
12572    if (ast_fileexists(dir, NULL, NULL)) {
12573       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12574    }
12575    DISPOSE(dir, -1);
12576    return res;
12577 }

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

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

Referenced by forward_message(), and notify_new_message().

04878 {
04879    FILE *p = NULL;
04880    char tmp[80] = "/tmp/astmail-XXXXXX";
04881    char tmp2[256];
04882    char *stringp;
04883 
04884    if (vmu && ast_strlen_zero(vmu->email)) {
04885       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04886       return(0);
04887    }
04888 
04889    /* Mail only the first format */
04890    format = ast_strdupa(format);
04891    stringp = format;
04892    strsep(&stringp, "|");
04893 
04894    if (!strcmp(format, "wav49"))
04895       format = "WAV";
04896    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %u\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04897    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04898       command hangs */
04899    if ((p = vm_mkftemp(tmp)) == NULL) {
04900       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04901       return -1;
04902    } else {
04903       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04904       fclose(p);
04905       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04906       ast_safe_system(tmp2);
04907       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04908    }
04909    return 0;
04910 }

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

References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_free, ast_log(), AST_LOG_WARNING, ast_safe_system(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strftime(), ast_strftime_locale(), ast_strlen_zero(), check_mime(), ENDL, ast_vm_user::fullname, ast_vm_user::locale, mailcmd, MAXHOSTNAMELEN, pagerbody, pagerdateformat, pagerfromstring, pagersubject, prep_email_sub_vars(), S_OR, strip_control_and_high(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

04913 {
04914    char enc_cidnum[256], enc_cidname[256];
04915    char date[256];
04916    char host[MAXHOSTNAMELEN] = "";
04917    char who[256];
04918    char dur[PATH_MAX];
04919    char tmp[80] = "/tmp/astmail-XXXXXX";
04920    char tmp2[PATH_MAX];
04921    struct ast_tm tm;
04922    FILE *p;
04923    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04924 
04925    if (!str1 || !str2) {
04926       ast_free(str1);
04927       ast_free(str2);
04928       return -1;
04929    }
04930 
04931    if (cidnum) {
04932       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04933    }
04934    if (cidname) {
04935       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04936    }
04937 
04938    if ((p = vm_mkftemp(tmp)) == NULL) {
04939       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04940       ast_free(str1);
04941       ast_free(str2);
04942       return -1;
04943    }
04944    gethostname(host, sizeof(host)-1);
04945    if (strchr(srcemail, '@')) {
04946       ast_copy_string(who, srcemail, sizeof(who));
04947    } else {
04948       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04949    }
04950    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04951    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04952    fprintf(p, "Date: %s\n", date);
04953 
04954    /* Reformat for custom pager format */
04955    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04956 
04957    if (!ast_strlen_zero(pagerfromstring)) {
04958       struct ast_channel *ast;
04959       if ((ast = ast_dummy_channel_alloc())) {
04960          char *ptr;
04961          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04962          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04963 
04964          if (check_mime(ast_str_buffer(str1))) {
04965             int first_line = 1;
04966             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04967             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04968                *ptr = '\0';
04969                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04970                first_line = 0;
04971                /* Substring is smaller, so this will never grow */
04972                ast_str_set(&str2, 0, "%s", ptr + 1);
04973             }
04974             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04975          } else {
04976             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04977          }
04978          ast = ast_channel_unref(ast);
04979       } else {
04980          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04981       }
04982    } else {
04983       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04984    }
04985 
04986    if (check_mime(vmu->fullname)) {
04987       int first_line = 1;
04988       char *ptr;
04989       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04990       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04991          *ptr = '\0';
04992          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04993          first_line = 0;
04994          /* Substring is smaller, so this will never grow */
04995          ast_str_set(&str2, 0, "%s", ptr + 1);
04996       }
04997       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04998    } else {
04999       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
05000    }
05001 
05002    if (!ast_strlen_zero(pagersubject)) {
05003       struct ast_channel *ast;
05004       if ((ast = ast_dummy_channel_alloc())) {
05005          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05006          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
05007          if (check_mime(ast_str_buffer(str1))) {
05008             int first_line = 1;
05009             char *ptr;
05010             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
05011             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
05012                *ptr = '\0';
05013                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
05014                first_line = 0;
05015                /* Substring is smaller, so this will never grow */
05016                ast_str_set(&str2, 0, "%s", ptr + 1);
05017             }
05018             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
05019          } else {
05020             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
05021          }
05022          ast = ast_channel_unref(ast);
05023       } else {
05024          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05025       }
05026    } else {
05027       if (ast_strlen_zero(flag)) {
05028          fprintf(p, "Subject: New VM\n\n");
05029       } else {
05030          fprintf(p, "Subject: New %s VM\n\n", flag);
05031       }
05032    }
05033 
05034    if (pagerbody) {
05035       struct ast_channel *ast;
05036       if ((ast = ast_dummy_channel_alloc())) {
05037          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05038          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
05039          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
05040          ast = ast_channel_unref(ast);
05041       } else {
05042          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05043       }
05044    } else {
05045       fprintf(p, "New %s long %s msg in box %s\n"
05046             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
05047    }
05048 
05049    fclose(p);
05050    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
05051    ast_safe_system(tmp2);
05052    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
05053    ast_free(str1);
05054    ast_free(str2);
05055    return 0;
05056 }

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

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

11131 {
11132    struct ast_config *cfg;
11133    const char *cat = NULL;
11134 
11135    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11136       "context", context, SENTINEL))) {
11137       return CLI_FAILURE;
11138    }
11139 
11140    ast_cli(fd,
11141       "\n"
11142       "=============================================================\n"
11143       "=== Configured Voicemail Users ==============================\n"
11144       "=============================================================\n"
11145       "===\n");
11146 
11147    while ((cat = ast_category_browse(cfg, cat))) {
11148       struct ast_variable *var = NULL;
11149       ast_cli(fd,
11150          "=== Mailbox ...\n"
11151          "===\n");
11152       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11153          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11154       ast_cli(fd,
11155          "===\n"
11156          "=== ---------------------------------------------------------\n"
11157          "===\n");
11158    }
11159 
11160    ast_cli(fd,
11161       "=============================================================\n"
11162       "\n");
11163 
11164    ast_config_destroy(cfg);
11165 
11166    return CLI_SUCCESS;
11167 }

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

Definition at line 11656 of file app_voicemail.c.

References ast_cond_signal, ast_event_unsubscribe(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, mwi_sub_sub, mwi_unsub_sub, poll_cond, poll_thread, and poll_thread_run.

Referenced by actual_load_config(), and unload_module().

11657 {
11658    poll_thread_run = 0;
11659 
11660    if (mwi_sub_sub) {
11661       ast_event_unsubscribe(mwi_sub_sub);
11662       mwi_sub_sub = NULL;
11663    }
11664 
11665    if (mwi_unsub_sub) {
11666       ast_event_unsubscribe(mwi_unsub_sub);
11667       mwi_unsub_sub = NULL;
11668    }
11669 
11670    ast_mutex_lock(&poll_lock);
11671    ast_cond_signal(&poll_cond);
11672    ast_mutex_unlock(&poll_lock);
11673 
11674    pthread_join(poll_thread, NULL);
11675 
11676    poll_thread = AST_PTHREADT_NULL;
11677 }

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

Strips control and non 7-bit clean characters from input string.

Note:
To map control and none 7-bit characters to a 7-bit clean characters please use ast_str_encode_mine().

Definition at line 991 of file app_voicemail.c.

Referenced by make_email_file(), and sendpage().

00992 {
00993    char *bufptr = buf;
00994    for (; *input; input++) {
00995       if (*input < 32) {
00996          continue;
00997       }
00998       *bufptr++ = *input;
00999       if (bufptr == buf + buflen - 1) {
01000          break;
01001       }
01002    }
01003    *bufptr = '\0';
01004    return buf;
01005 }

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

Definition at line 11802 of file app_voicemail.c.

References ast_log(), AST_LOG_NOTICE, ast_str_append(), ast_str_buffer(), ast_str_reset(), and ast_str_thread_get().

Referenced by actual_load_config(), apply_option(), and apply_options_full().

11803 {
11804    char *current;
11805 
11806    /* Add 16 for fudge factor */
11807    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11808 
11809    ast_str_reset(str);
11810    
11811    /* Substitute strings \r, \n, and \t into the appropriate characters */
11812    for (current = (char *) value; *current; current++) {
11813       if (*current == '\\') {
11814          current++;
11815          if (!*current) {
11816             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11817             break;
11818          }
11819          switch (*current) {
11820          case '\\':
11821             ast_str_append(&str, 0, "\\");
11822             break;
11823          case 'r':
11824             ast_str_append(&str, 0, "\r");
11825             break;
11826          case 'n':
11827 #ifdef IMAP_STORAGE
11828             if (!str->used || str->str[str->used - 1] != '\r') {
11829                ast_str_append(&str, 0, "\r");
11830             }
11831 #endif
11832             ast_str_append(&str, 0, "\n");
11833             break;
11834          case 't':
11835             ast_str_append(&str, 0, "\t");
11836             break;
11837          default:
11838             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11839             break;
11840          }
11841       } else {
11842          ast_str_append(&str, 0, "%c", *current);
11843       }
11844    }
11845 
11846    return ast_str_buffer(str);
11847 }

static int unload_module ( void   )  [static]

Definition at line 13115 of file app_voicemail.c.

References ao2_ref, app, app2, app3, app4, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_manager_unregister(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), AST_TEST_UNREGISTER, ast_uninstall_vm_functions(), ast_unload_realtime(), ast_unregister_application(), cli_voicemail, free_vm_users(), free_vm_zones(), inprocess_container, mailbox_exists_acf, mwi_subscription_tps, poll_thread, sayname_app, and stop_poll_thread().

13116 {
13117    int res;
13118 
13119    res = ast_unregister_application(app);
13120    res |= ast_unregister_application(app2);
13121    res |= ast_unregister_application(app3);
13122    res |= ast_unregister_application(app4);
13123    res |= ast_unregister_application(sayname_app);
13124    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13125    res |= ast_manager_unregister("VoicemailUsersList");
13126    res |= ast_data_unregister(NULL);
13127 #ifdef TEST_FRAMEWORK
13128    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13129    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13130    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13131    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13132    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13133 #endif
13134    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13135    ast_uninstall_vm_functions();
13136    ao2_ref(inprocess_container, -1);
13137 
13138    if (poll_thread != AST_PTHREADT_NULL)
13139       stop_poll_thread();
13140 
13141    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13142    ast_unload_realtime("voicemail");
13143    ast_unload_realtime("voicemail_data");
13144 
13145    free_vm_users();
13146    free_vm_zones();
13147    return res;
13148 }

static int valid_config ( const struct ast_config cfg  )  [inline, static]

Check if configuration file is valid.

Definition at line 1513 of file app_voicemail.c.

References CONFIG_STATUS_FILEINVALID.

Referenced by advanced_options(), make_email_file(), play_message(), prep_email_sub_vars(), read_password_from_file(), vm_change_password(), and vm_forwardoptions().

01514 {
01515    return cfg && cfg != CONFIG_STATUS_FILEINVALID;
01516 }

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

Definition at line 1774 of file app_voicemail.c.

References ast_calloc, ast_free, vm_state::deleted, vm_state::dh_arraysize, vm_state::heard, and ast_vm_user::maxmsg.

Referenced by open_mailbox().

01774                                                                                         {
01775 
01776    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01777 
01778    /* remove old allocation */
01779    if (vms->deleted) {
01780       ast_free(vms->deleted);
01781       vms->deleted = NULL;
01782    }
01783    if (vms->heard) {
01784       ast_free(vms->heard);
01785       vms->heard = NULL;
01786    }
01787    vms->dh_arraysize = 0;
01788 
01789    if (arraysize > 0) {
01790       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01791          return -1;
01792       }
01793       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01794          ast_free(vms->deleted);
01795          vms->deleted = NULL;
01796          return -1;
01797       }
01798       vms->dh_arraysize = arraysize;
01799    }
01800 
01801    return 0;
01802 }

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

References adsi_begin(), adsi_login(), adsi_password(), ast_copy_string(), ast_debug, ast_exists_extension(), 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::caller, ast_channel::context, find_user(), ast_party_caller::id, ast_party_id::number, ast_vm_user::password, S_COR, ast_party_number::str, ast_party_number::valid, and vm_password.

Referenced by vm_execmain(), and vmauthenticate().

09813 {
09814    int useadsi = 0, valid = 0, logretries = 0;
09815    char password[AST_MAX_EXTENSION]="", *passptr;
09816    struct ast_vm_user vmus, *vmu = NULL;
09817 
09818    /* If ADSI is supported, setup login screen */
09819    adsi_begin(chan, &useadsi);
09820    if (!skipuser && useadsi)
09821       adsi_login(chan);
09822    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09823       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09824       return -1;
09825    }
09826 
09827    /* Authenticate them and get their mailbox/password */
09828 
09829    while (!valid && (logretries < max_logins)) {
09830       /* Prompt for, and read in the username */
09831       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09832          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09833          return -1;
09834       }
09835       if (ast_strlen_zero(mailbox)) {
09836          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09837             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09838          } else {
09839             ast_verb(3, "Username not entered\n"); 
09840             return -1;
09841          }
09842       } else if (mailbox[0] == '*') {
09843          /* user entered '*' */
09844          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09845          if (ast_exists_extension(chan, chan->context, "a", 1,
09846             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09847             return -1;
09848          }
09849          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09850          mailbox[0] = '\0';
09851       }
09852 
09853       if (useadsi)
09854          adsi_password(chan);
09855 
09856       if (!ast_strlen_zero(prefix)) {
09857          char fullusername[80] = "";
09858          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09859          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09860          ast_copy_string(mailbox, fullusername, mailbox_size);
09861       }
09862 
09863       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09864       vmu = find_user(&vmus, context, mailbox);
09865       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09866          /* saved password is blank, so don't bother asking */
09867          password[0] = '\0';
09868       } else {
09869          if (ast_streamfile(chan, vm_password, chan->language)) {
09870             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09871             return -1;
09872          }
09873          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09874             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09875             return -1;
09876          } else if (password[0] == '*') {
09877             /* user entered '*' */
09878             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09879             if (ast_exists_extension(chan, chan->context, "a", 1,
09880                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09881                mailbox[0] = '*';
09882                return -1;
09883             }
09884             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09885             mailbox[0] = '\0';
09886             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09887             vmu = NULL;
09888          }
09889       }
09890 
09891       if (vmu) {
09892          passptr = vmu->password;
09893          if (passptr[0] == '-') passptr++;
09894       }
09895       if (vmu && !strcmp(passptr, password))
09896          valid++;
09897       else {
09898          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09899          if (!ast_strlen_zero(prefix))
09900             mailbox[0] = '\0';
09901       }
09902       logretries++;
09903       if (!valid) {
09904          if (skipuser || logretries >= max_logins) {
09905             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09906                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09907                return -1;
09908             }
09909          } else {
09910             if (useadsi)
09911                adsi_login(chan);
09912             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09913                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09914                return -1;
09915             }
09916          }
09917          if (ast_waitstream(chan, "")) /* Channel is hung up */
09918             return -1;
09919       }
09920    }
09921    if (!valid && (logretries >= max_logins)) {
09922       ast_stopstream(chan);
09923       ast_play_and_wait(chan, "vm-goodbye");
09924       return -1;
09925    }
09926    if (vmu && !skipuser) {
09927       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09928    }
09929    return 0;
09930 }

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

Definition at line 11025 of file app_voicemail.c.

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

11026 {
11027    struct ast_vm_user svm;
11028    char *context, *box;
11029    AST_DECLARE_APP_ARGS(args,
11030       AST_APP_ARG(mbox);
11031       AST_APP_ARG(options);
11032    );
11033    static int dep_warning = 0;
11034 
11035    if (ast_strlen_zero(data)) {
11036       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
11037       return -1;
11038    }
11039 
11040    if (!dep_warning) {
11041       dep_warning = 1;
11042       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
11043    }
11044 
11045    box = ast_strdupa(data);
11046 
11047    AST_STANDARD_APP_ARGS(args, box);
11048 
11049    if (args.options) {
11050    }
11051 
11052    if ((context = strchr(args.mbox, '@'))) {
11053       *context = '\0';
11054       context++;
11055    }
11056 
11057    if (find_user(&svm, context, args.mbox)) {
11058       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
11059    } else
11060       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
11061 
11062    return 0;
11063 }

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 9789 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(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

09790 {
09791    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09792       return vm_browse_messages_es(chan, vms, vmu);
09793    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09794       return vm_browse_messages_gr(chan, vms, vmu);
09795    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09796       return vm_browse_messages_he(chan, vms, vmu);
09797    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09798       return vm_browse_messages_it(chan, vms, vmu);
09799    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09800       return vm_browse_messages_pt(chan, vms, vmu);
09801    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09802       return vm_browse_messages_vi(chan, vms, vmu);
09803    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09804       return vm_browse_messages_zh(chan, vms, vmu);
09805    } else {                                             /* Default to English syntax */
09806       return vm_browse_messages_en(chan, vms, vmu);
09807    }
09808 }

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

09629 {
09630    int cmd = 0;
09631 
09632    if (vms->lastmsg > -1) {
09633       cmd = play_message(chan, vmu, vms);
09634    } else {
09635       cmd = ast_play_and_wait(chan, "vm-youhave");
09636       if (!cmd) 
09637          cmd = ast_play_and_wait(chan, "vm-no");
09638       if (!cmd) {
09639          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09640          cmd = ast_play_and_wait(chan, vms->fn);
09641       }
09642       if (!cmd)
09643          cmd = ast_play_and_wait(chan, "vm-messages");
09644    }
09645    return cmd;
09646 }

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

09683 {
09684    int cmd;
09685 
09686    if (vms->lastmsg > -1) {
09687       cmd = play_message(chan, vmu, vms);
09688    } else {
09689       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09690       if (!cmd)
09691          cmd = ast_play_and_wait(chan, "vm-messages");
09692       if (!cmd) {
09693          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09694          cmd = ast_play_and_wait(chan, vms->fn);
09695       }
09696    }
09697    return cmd;
09698 }

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

09577 {
09578    int cmd = 0;
09579 
09580    if (vms->lastmsg > -1) {
09581       cmd = play_message(chan, vmu, vms);
09582    } else {
09583       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09584       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09585          if (!cmd) {
09586             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09587             cmd = ast_play_and_wait(chan, vms->fn);
09588          }
09589          if (!cmd)
09590             cmd = ast_play_and_wait(chan, "vm-messages");
09591       } else {
09592          if (!cmd)
09593             cmd = ast_play_and_wait(chan, "vm-messages");
09594          if (!cmd) {
09595             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09596             cmd = ast_play_and_wait(chan, vms->fn);
09597          }
09598       }
09599    } 
09600    return cmd;
09601 }

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

Definition at line 9604 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09605 {
09606    int cmd = 0;
09607 
09608    if (vms->lastmsg > -1) {
09609       cmd = play_message(chan, vmu, vms);
09610    } else {
09611       if (!strcasecmp(vms->fn, "INBOX")) {
09612          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09613       } else {
09614          cmd = ast_play_and_wait(chan, "vm-nomessages");
09615       }
09616    }
09617    return cmd;
09618 }

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

09657 {
09658    int cmd;
09659 
09660    if (vms->lastmsg > -1) {
09661       cmd = play_message(chan, vmu, vms);
09662    } else {
09663       cmd = ast_play_and_wait(chan, "vm-no");
09664       if (!cmd)
09665          cmd = ast_play_and_wait(chan, "vm-message");
09666       if (!cmd) {
09667          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09668          cmd = ast_play_and_wait(chan, vms->fn);
09669       }
09670    }
09671    return cmd;
09672 }

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

09709 {
09710    int cmd;
09711 
09712    if (vms->lastmsg > -1) {
09713       cmd = play_message(chan, vmu, vms);
09714    } else {
09715       cmd = ast_play_and_wait(chan, "vm-no");
09716       if (!cmd) {
09717          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09718          cmd = ast_play_and_wait(chan, vms->fn);
09719       }
09720       if (!cmd)
09721          cmd = ast_play_and_wait(chan, "vm-messages");
09722    }
09723    return cmd;
09724 }

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

Vietnamese syntax for 'You have N messages' greeting.

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

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

09763 {
09764    int cmd = 0;
09765 
09766    if (vms->lastmsg > -1) {
09767       cmd = play_message(chan, vmu, vms);
09768    } else {
09769       cmd = ast_play_and_wait(chan, "vm-no");
09770       if (!cmd) {
09771          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09772          cmd = ast_play_and_wait(chan, vms->fn);
09773       }
09774    }
09775    return cmd;
09776 }

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

09735 {
09736    int cmd;
09737 
09738    if (vms->lastmsg > -1) {
09739       cmd = play_message(chan, vmu, vms);
09740    } else {
09741       cmd = ast_play_and_wait(chan, "vm-you");
09742       if (!cmd) 
09743          cmd = ast_play_and_wait(chan, "vm-haveno");
09744       if (!cmd)
09745          cmd = ast_play_and_wait(chan, "vm-messages");
09746       if (!cmd) {
09747          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09748          cmd = ast_play_and_wait(chan, vms->fn);
09749       }
09750    }
09751    return cmd;
09752 }

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

References ast_alloca, ast_category_browse(), ast_category_get(), ast_config_destroy(), ast_config_load, ast_config_text_file_save(), ast_copy_string(), ast_debug, ast_free, ast_log(), AST_LOG_WARNING, ast_test_suite_event_notify, ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, ast_vm_user::context, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, reset_user_pw(), valid_config(), value, var, VM_SPOOL_DIR, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser(), and vm_options().

01526 {
01527    struct ast_config   *cfg = NULL;
01528    struct ast_variable *var = NULL;
01529    struct ast_category *cat = NULL;
01530    char *category = NULL, *value = NULL, *new = NULL;
01531    const char *tmp = NULL;
01532    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01533    char secretfn[PATH_MAX] = "";
01534    int found = 0;
01535 
01536    if (!change_password_realtime(vmu, newpassword))
01537       return;
01538 
01539    /* check if we should store the secret in the spool directory next to the messages */
01540    switch (vmu->passwordlocation) {
01541    case OPT_PWLOC_SPOOLDIR:
01542       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01543       if (write_password_to_file(secretfn, newpassword) == 0) {
01544          ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
01545          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01546          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01547          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01548          break;
01549       } else {
01550          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01551       }
01552       /* Fall-through */
01553    case OPT_PWLOC_VOICEMAILCONF:
01554       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
01555          while ((category = ast_category_browse(cfg, category))) {
01556             if (!strcasecmp(category, vmu->context)) {
01557                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01558                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01559                   break;
01560                }
01561                value = strstr(tmp, ",");
01562                if (!value) {
01563                   new = ast_alloca(strlen(newpassword)+1);
01564                   sprintf(new, "%s", newpassword);
01565                } else {
01566                   new = ast_alloca((strlen(value) + strlen(newpassword) + 1));
01567                   sprintf(new, "%s%s", newpassword, value);
01568                }
01569                if (!(cat = ast_category_get(cfg, category))) {
01570                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01571                   break;
01572                }
01573                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01574                found = 1;
01575             }
01576          }
01577          /* save the results */
01578          if (found) {
01579             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
01580             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01581             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01582             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01583             ast_config_destroy(cfg);
01584             break;
01585          }
01586 
01587          ast_config_destroy(cfg);
01588       }
01589       /* Fall-through */
01590    case OPT_PWLOC_USERSCONF:
01591       /* check users.conf and update the password stored for the mailbox */
01592       /* if no vmsecret entry exists create one. */
01593       if ((cfg = ast_config_load("users.conf", config_flags)) && valid_config(cfg)) {
01594          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01595          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01596             ast_debug(4, "users.conf: %s\n", category);
01597             if (!strcasecmp(category, vmu->mailbox)) {
01598                if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
01599                   ast_debug(3, "looks like we need to make vmsecret!\n");
01600                   var = ast_variable_new("vmsecret", newpassword, "");
01601                } else {
01602                   var = NULL;
01603                }
01604                new = ast_alloca(strlen(newpassword) + 1);
01605                sprintf(new, "%s", newpassword);
01606                if (!(cat = ast_category_get(cfg, category))) {
01607                   ast_debug(4, "failed to get category!\n");
01608                   ast_free(var);
01609                   break;
01610                }
01611                if (!var) {
01612                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01613                } else {
01614                   ast_variable_append(cat, var);
01615                }
01616                found = 1;
01617                break;
01618             }
01619          }
01620          /* save the results and clean things up */
01621          if (found) {
01622             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
01623             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01624             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01625             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01626          }
01627 
01628          ast_config_destroy(cfg);
01629       }
01630    }
01631 }

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

Definition at line 1633 of file app_voicemail.c.

References ast_copy_string(), ast_debug, ast_safe_system(), ast_test_suite_event_notify, ast_vm_user::context, ext_pass_cmd, ast_vm_user::mailbox, ast_vm_user::password, and reset_user_pw().

Referenced by vm_newuser(), and vm_options().

01634 {
01635    char buf[255];
01636    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01637    ast_debug(1, "External password: %s\n",buf);
01638    if (!ast_safe_system(buf)) {
01639       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01640       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01641       /* Reset the password in memory, too */
01642       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01643    }
01644 }

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

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

01189 {
01190    int fds[2], pid = 0;
01191 
01192    memset(buf, 0, len);
01193 
01194    if (pipe(fds)) {
01195       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01196    } else {
01197       /* good to go*/
01198       pid = ast_safe_fork(0);
01199 
01200       if (pid < 0) {
01201          /* ok maybe not */
01202          close(fds[0]);
01203          close(fds[1]);
01204          snprintf(buf, len, "FAILURE: Fork failed");
01205       } else if (pid) {
01206          /* parent */
01207          close(fds[1]);
01208          if (read(fds[0], buf, len) < 0) {
01209             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01210          }
01211          close(fds[0]);
01212       } else {
01213          /*  child */
01214          AST_DECLARE_APP_ARGS(arg,
01215             AST_APP_ARG(v)[20];
01216          );
01217          char *mycmd = ast_strdupa(command);
01218 
01219          close(fds[0]);
01220          dup2(fds[1], STDOUT_FILENO);
01221          close(fds[1]);
01222          ast_close_fds_above_n(STDOUT_FILENO);
01223 
01224          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01225 
01226          execv(arg.v[0], arg.v); 
01227          printf("FAILURE: %s", strerror(errno));
01228          _exit(0);
01229       }
01230    }
01231    return buf;
01232 }

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

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

Referenced by copy_message(), and notify_new_message().

04217 {
04218    char *txt;
04219    int txtsize = 0;
04220 
04221    txtsize = (strlen(file) + 5)*sizeof(char);
04222    txt = ast_alloca(txtsize);
04223    /* Sprintf here would safe because we alloca'd exactly the right length,
04224     * but trying to eliminate all sprintf's anyhow
04225     */
04226    if (ast_check_realtime("voicemail_data")) {
04227       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04228    }
04229    snprintf(txt, txtsize, "%s.txt", file);
04230    unlink(txt);
04231    return ast_filedelete(file, NULL);
04232 }

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

Definition at line 10684 of file app_voicemail.c.

References ast_channel::_state, args, 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_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_vm_options::exitcontext, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and leave_vm_options::record_gain.

Referenced by load_module(), and play_record_review().

10685 {
10686    int res = 0;
10687    char *tmp;
10688    struct leave_vm_options leave_options;
10689    struct ast_flags flags = { 0 };
10690    char *opts[OPT_ARG_ARRAY_SIZE];
10691    AST_DECLARE_APP_ARGS(args,
10692       AST_APP_ARG(argv0);
10693       AST_APP_ARG(argv1);
10694    );
10695    
10696    memset(&leave_options, 0, sizeof(leave_options));
10697 
10698    if (chan->_state != AST_STATE_UP)
10699       ast_answer(chan);
10700 
10701    if (!ast_strlen_zero(data)) {
10702       tmp = ast_strdupa(data);
10703       AST_STANDARD_APP_ARGS(args, tmp);
10704       if (args.argc == 2) {
10705          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10706             return -1;
10707          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10708          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10709             int gain;
10710 
10711             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10712                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10713                return -1;
10714             } else {
10715                leave_options.record_gain = (signed char) gain;
10716             }
10717          }
10718          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10719             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10720                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10721          }
10722       }
10723    } else {
10724       char temp[256];
10725       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10726       if (res < 0)
10727          return res;
10728       if (ast_strlen_zero(temp))
10729          return 0;
10730       args.argv0 = ast_strdupa(temp);
10731    }
10732 
10733    res = leave_voicemail(chan, args.argv0, &leave_options);
10734    if (res == 't') {
10735       ast_play_and_wait(chan, "vm-goodbye");
10736       res = 0;
10737    }
10738 
10739    if (res == OPERATOR_EXIT) {
10740       res = 0;
10741    }
10742 
10743    if (res == ERROR_LOCK_PATH) {
10744       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10745       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10746       res = 0;
10747    }
10748 
10749    return res;
10750 }

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

Definition at line 9932 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(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_LOG_WARNING, ast_manager_event, 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_test_suite_assert, ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, vm_state::context, ast_channel::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(), get_folder_by_name(), globalflags, has_voicemail(), vm_state::heard, language, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), maxlogins, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, OLD_FOLDER, vm_state::oldmessages, open_mailbox(), OPERATOR_EXIT, 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_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, vm_state::vmbox, and vmfmts.

Referenced by load_module().

09933 {
09934    /* XXX This is, admittedly, some pretty horrendous code.  For some
09935       reason it just seemed a lot easier to do with GOTO's.  I feel
09936       like I'm back in my GWBASIC days. XXX */
09937    int res = -1;
09938    int cmd = 0;
09939    int valid = 0;
09940    char prefixstr[80] ="";
09941    char ext_context[256]="";
09942    int box;
09943    int useadsi = 0;
09944    int skipuser = 0;
09945    struct vm_state vms;
09946    struct ast_vm_user *vmu = NULL, vmus;
09947    char *context = NULL;
09948    int silentexit = 0;
09949    struct ast_flags flags = { 0 };
09950    signed char record_gain = 0;
09951    int play_auto = 0;
09952    int play_folder = 0;
09953    int in_urgent = 0;
09954 #ifdef IMAP_STORAGE
09955    int deleted = 0;
09956 #endif
09957 
09958    /* Add the vm_state to the active list and keep it active */
09959    memset(&vms, 0, sizeof(vms));
09960 
09961    vms.lastmsg = -1;
09962 
09963    memset(&vmus, 0, sizeof(vmus));
09964 
09965    ast_test_suite_event_notify("START", "Message: vm_execmain started");
09966    if (chan->_state != AST_STATE_UP) {
09967       ast_debug(1, "Before ast_answer\n");
09968       ast_answer(chan);
09969    }
09970 
09971    if (!ast_strlen_zero(data)) {
09972       char *opts[OPT_ARG_ARRAY_SIZE];
09973       char *parse;
09974       AST_DECLARE_APP_ARGS(args,
09975          AST_APP_ARG(argv0);
09976          AST_APP_ARG(argv1);
09977       );
09978 
09979       parse = ast_strdupa(data);
09980 
09981       AST_STANDARD_APP_ARGS(args, parse);
09982 
09983       if (args.argc == 2) {
09984          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09985             return -1;
09986          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09987             int gain;
09988             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
09989                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09990                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09991                   return -1;
09992                } else {
09993                   record_gain = (signed char) gain;
09994                }
09995             } else {
09996                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
09997             }
09998          }
09999          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
10000             play_auto = 1;
10001             if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
10002                /* See if it is a folder name first */
10003                if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
10004                   if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
10005                      play_folder = -1;
10006                   }
10007                } else {
10008                   play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
10009                }
10010             } else {
10011                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
10012             }
10013             if (play_folder > 9 || play_folder < 0) {
10014                ast_log(AST_LOG_WARNING,
10015                   "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
10016                   opts[OPT_ARG_PLAYFOLDER]);
10017                play_folder = 0;
10018             }
10019          }
10020       } else {
10021          /* old style options parsing */
10022          while (*(args.argv0)) {
10023             if (*(args.argv0) == 's')
10024                ast_set_flag(&flags, OPT_SILENT);
10025             else if (*(args.argv0) == 'p')
10026                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
10027             else 
10028                break;
10029             (args.argv0)++;
10030          }
10031 
10032       }
10033 
10034       valid = ast_test_flag(&flags, OPT_SILENT);
10035 
10036       if ((context = strchr(args.argv0, '@')))
10037          *context++ = '\0';
10038 
10039       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
10040          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
10041       else
10042          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
10043 
10044       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
10045          skipuser++;
10046       else
10047          valid = 0;
10048    }
10049 
10050    if (!valid)
10051       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
10052 
10053    ast_debug(1, "After vm_authenticate\n");
10054 
10055    if (vms.username[0] == '*') {
10056       ast_debug(1, "user pressed * in context '%s'\n", chan->context);
10057 
10058       /* user entered '*' */
10059       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
10060          ast_test_suite_event_notify("REDIRECT", "Message: redirecting user to 'a' extension");
10061          res = 0; /* prevent hangup */
10062          goto out;
10063       }
10064    }
10065 
10066    if (!res) {
10067       valid = 1;
10068       if (!skipuser)
10069          vmu = &vmus;
10070    } else {
10071       res = 0;
10072    }
10073 
10074    /* If ADSI is supported, setup login screen */
10075    adsi_begin(chan, &useadsi);
10076 
10077    ast_test_suite_assert(valid);
10078    if (!valid) {
10079       goto out;
10080    }
10081    ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated");
10082 
10083 #ifdef IMAP_STORAGE
10084    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
10085    pthread_setspecific(ts_vmstate.key, &vms);
10086 
10087    vms.interactive = 1;
10088    vms.updated = 1;
10089    if (vmu)
10090       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
10091    vmstate_insert(&vms);
10092    init_vm_state(&vms);
10093 #endif
10094    
10095    /* Set language from config to override channel language */
10096    if (!ast_strlen_zero(vmu->language))
10097       ast_string_field_set(chan, language, vmu->language);
10098 
10099    /* Retrieve urgent, old and new message counts */
10100    ast_debug(1, "Before open_mailbox\n");
10101    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
10102    if (res < 0)
10103       goto out;
10104    vms.oldmessages = vms.lastmsg + 1;
10105    ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
10106    /* check INBOX */
10107    res = open_mailbox(&vms, vmu, NEW_FOLDER);
10108    if (res < 0)
10109       goto out;
10110    vms.newmessages = vms.lastmsg + 1;
10111    ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
10112    /* Start in Urgent */
10113    in_urgent = 1;
10114    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
10115    if (res < 0)
10116       goto out;
10117    vms.urgentmessages = vms.lastmsg + 1;
10118    ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
10119 
10120    /* Select proper mailbox FIRST!! */
10121    if (play_auto) {
10122       ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages");
10123       if (vms.urgentmessages) {
10124          in_urgent = 1;
10125          res = open_mailbox(&vms, vmu, 11);
10126       } else {
10127          in_urgent = 0;
10128          res = open_mailbox(&vms, vmu, play_folder);
10129       }
10130       if (res < 0)
10131          goto out;
10132 
10133       /* If there are no new messages, inform the user and hangup */
10134       if (vms.lastmsg == -1) {
10135          in_urgent = 0;
10136          cmd = vm_browse_messages(chan, &vms, vmu);
10137          res = 0;
10138          goto out;
10139       }
10140    } else {
10141       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
10142          /* If we only have old messages start here */
10143          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
10144          in_urgent = 0;
10145          play_folder = 1;
10146          if (res < 0)
10147             goto out;
10148       } else if (!vms.urgentmessages && vms.newmessages) {
10149          /* If we have new messages but none are urgent */
10150          in_urgent = 0;
10151          res = open_mailbox(&vms, vmu, NEW_FOLDER);
10152          if (res < 0)
10153             goto out;
10154       }
10155    }
10156 
10157    if (useadsi)
10158       adsi_status(chan, &vms);
10159    res = 0;
10160 
10161    /* Check to see if this is a new user */
10162    if (!strcasecmp(vmu->mailbox, vmu->password) && 
10163       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
10164       if (ast_play_and_wait(chan, "vm-newuser") == -1)
10165          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
10166       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
10167       if ((cmd == 't') || (cmd == '#')) {
10168          /* Timeout */
10169          ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out");
10170          res = 0;
10171          goto out;
10172       } else if (cmd < 0) {
10173          /* Hangup */
10174          ast_test_suite_event_notify("HANGUP", "Message: hangup detected");
10175          res = -1;
10176          goto out;
10177       }
10178    }
10179 #ifdef IMAP_STORAGE
10180       ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
10181       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
10182          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
10183          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10184       }
10185       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
10186       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
10187          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
10188          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10189       }
10190 #endif
10191 
10192    ast_test_suite_event_notify("INTRO", "Message: playing intro menu");
10193    if (play_auto) {
10194       cmd = '1';
10195    } else {
10196       cmd = vm_intro(chan, vmu, &vms);
10197    }
10198    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10199 
10200    vms.repeats = 0;
10201    vms.starting = 1;
10202    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
10203       /* Run main menu */
10204       switch (cmd) {
10205       case '1': /* First message */
10206          vms.curmsg = 0;
10207          /* Fall through */
10208       case '5': /* Play current message */
10209          ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
10210          cmd = vm_browse_messages(chan, &vms, vmu);
10211          break;
10212       case '2': /* Change folders */
10213          ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder");
10214          if (useadsi)
10215             adsi_folders(chan, 0, "Change to folder...");
10216 
10217          cmd = get_folder2(chan, "vm-changeto", 0);
10218          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10219          if (cmd == '#') {
10220             cmd = 0;
10221          } else if (cmd > 0) {
10222             cmd = cmd - '0';
10223             res = close_mailbox(&vms, vmu);
10224             if (res == ERROR_LOCK_PATH)
10225                goto out;
10226             /* If folder is not urgent, set in_urgent to zero! */
10227             if (cmd != 11) in_urgent = 0;
10228             res = open_mailbox(&vms, vmu, cmd);
10229             if (res < 0)
10230                goto out;
10231             play_folder = cmd;
10232             cmd = 0;
10233          }
10234          if (useadsi)
10235             adsi_status2(chan, &vms);
10236 
10237          if (!cmd) {
10238             cmd = vm_play_folder_name(chan, vms.vmbox);
10239          }
10240 
10241          vms.starting = 1;
10242          vms.curmsg = 0;
10243          break;
10244       case '3': /* Advanced options */
10245          ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");
10246          cmd = 0;
10247          vms.repeats = 0;
10248          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
10249             switch (cmd) {
10250             case '1': /* Reply */
10251                if (vms.lastmsg > -1 && !vms.starting) {
10252                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
10253                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10254                      res = cmd;
10255                      goto out;
10256                   }
10257                } else {
10258                   cmd = ast_play_and_wait(chan, "vm-sorry");
10259                }
10260                cmd = 't';
10261                break;
10262             case '2': /* Callback */
10263                if (!vms.starting)
10264                   ast_verb(3, "Callback Requested\n");
10265                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
10266                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
10267                   if (cmd == 9) {
10268                      silentexit = 1;
10269                      goto out;
10270                   } else if (cmd == ERROR_LOCK_PATH) {
10271                      res = cmd;
10272                      goto out;
10273                   }
10274                } else {
10275                   cmd = ast_play_and_wait(chan, "vm-sorry");
10276                }
10277                cmd = 't';
10278                break;
10279             case '3': /* Envelope */
10280                if (vms.lastmsg > -1 && !vms.starting) {
10281                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
10282                   if (cmd == ERROR_LOCK_PATH) {
10283                      res = cmd;
10284                      goto out;
10285                   }
10286                } else {
10287                   cmd = ast_play_and_wait(chan, "vm-sorry");
10288                }
10289                cmd = 't';
10290                break;
10291             case '4': /* Dialout */
10292                if (!ast_strlen_zero(vmu->dialout)) {
10293                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
10294                   if (cmd == 9) {
10295                      silentexit = 1;
10296                      goto out;
10297                   }
10298                } else {
10299                   cmd = ast_play_and_wait(chan, "vm-sorry");
10300                }
10301                cmd = 't';
10302                break;
10303 
10304             case '5': /* Leave VoiceMail */
10305                if (ast_test_flag(vmu, VM_SVMAIL)) {
10306                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
10307                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10308                      res = cmd;
10309                      goto out;
10310                   }
10311                } else {
10312                   cmd = ast_play_and_wait(chan, "vm-sorry");
10313                }
10314                cmd = 't';
10315                break;
10316 
10317             case '*': /* Return to main menu */
10318                cmd = 't';
10319                break;
10320 
10321             default:
10322                cmd = 0;
10323                if (!vms.starting) {
10324                   cmd = ast_play_and_wait(chan, "vm-toreply");
10325                }
10326                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
10327                   cmd = ast_play_and_wait(chan, "vm-tocallback");
10328                }
10329                if (!cmd && !vms.starting) {
10330                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
10331                }
10332                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
10333                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
10334                }
10335                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd) {
10336                   cmd = ast_play_and_wait(chan, "vm-leavemsg");
10337                }
10338                if (!cmd) {
10339                   cmd = ast_play_and_wait(chan, "vm-starmain");
10340                }
10341                if (!cmd) {
10342                   cmd = ast_waitfordigit(chan, 6000);
10343                }
10344                if (!cmd) {
10345                   vms.repeats++;
10346                }
10347                if (vms.repeats > 3) {
10348                   cmd = 't';
10349                }
10350                ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10351             }
10352          }
10353          if (cmd == 't') {
10354             cmd = 0;
10355             vms.repeats = 0;
10356          }
10357          break;
10358       case '4': /* Go to the previous message */
10359          ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1);
10360          if (vms.curmsg > 0) {
10361             vms.curmsg--;
10362             cmd = play_message(chan, vmu, &vms);
10363          } else {
10364             /* Check if we were listening to new
10365                messages.  If so, go to Urgent messages
10366                instead of saying "no more messages"
10367             */
10368             if (in_urgent == 0 && vms.urgentmessages > 0) {
10369                /* Check for Urgent messages */
10370                in_urgent = 1;
10371                res = close_mailbox(&vms, vmu);
10372                if (res == ERROR_LOCK_PATH)
10373                   goto out;
10374                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
10375                if (res < 0)
10376                   goto out;
10377                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
10378                vms.curmsg = vms.lastmsg;
10379                if (vms.lastmsg < 0) {
10380                   cmd = ast_play_and_wait(chan, "vm-nomore");
10381                }
10382             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10383                vms.curmsg = vms.lastmsg;
10384                cmd = play_message(chan, vmu, &vms);
10385             } else {
10386                cmd = ast_play_and_wait(chan, "vm-nomore");
10387             }
10388          }
10389          break;
10390       case '6': /* Go to the next message */
10391          ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1);
10392          if (vms.curmsg < vms.lastmsg) {
10393             vms.curmsg++;
10394             cmd = play_message(chan, vmu, &vms);
10395          } else {
10396             if (in_urgent && vms.newmessages > 0) {
10397                /* Check if we were listening to urgent
10398                 * messages.  If so, go to regular new messages
10399                 * instead of saying "no more messages"
10400                 */
10401                in_urgent = 0;
10402                res = close_mailbox(&vms, vmu);
10403                if (res == ERROR_LOCK_PATH)
10404                   goto out;
10405                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10406                if (res < 0)
10407                   goto out;
10408                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10409                vms.curmsg = -1;
10410                if (vms.lastmsg < 0) {
10411                   cmd = ast_play_and_wait(chan, "vm-nomore");
10412                }
10413             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10414                vms.curmsg = 0;
10415                cmd = play_message(chan, vmu, &vms);
10416             } else {
10417                cmd = ast_play_and_wait(chan, "vm-nomore");
10418             }
10419          }
10420          break;
10421       case '7': /* Delete the current message */
10422          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
10423             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
10424             if (useadsi)
10425                adsi_delete(chan, &vms);
10426             if (vms.deleted[vms.curmsg]) {
10427                if (play_folder == 0) {
10428                   if (in_urgent) {
10429                      vms.urgentmessages--;
10430                   } else {
10431                      vms.newmessages--;
10432                   }
10433                }
10434                else if (play_folder == 1)
10435                   vms.oldmessages--;
10436                cmd = ast_play_and_wait(chan, "vm-deleted");
10437             } else {
10438                if (play_folder == 0) {
10439                   if (in_urgent) {
10440                      vms.urgentmessages++;
10441                   } else {
10442                      vms.newmessages++;
10443                   }
10444                }
10445                else if (play_folder == 1)
10446                   vms.oldmessages++;
10447                cmd = ast_play_and_wait(chan, "vm-undeleted");
10448             }
10449             if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10450                if (vms.curmsg < vms.lastmsg) {
10451                   vms.curmsg++;
10452                   cmd = play_message(chan, vmu, &vms);
10453                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10454                   vms.curmsg = 0;
10455                   cmd = play_message(chan, vmu, &vms);
10456                } else {
10457                   /* Check if we were listening to urgent
10458                      messages.  If so, go to regular new messages
10459                      instead of saying "no more messages"
10460                   */
10461                   if (in_urgent == 1) {
10462                      /* Check for new messages */
10463                      in_urgent = 0;
10464                      res = close_mailbox(&vms, vmu);
10465                      if (res == ERROR_LOCK_PATH)
10466                         goto out;
10467                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
10468                      if (res < 0)
10469                         goto out;
10470                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10471                      vms.curmsg = -1;
10472                      if (vms.lastmsg < 0) {
10473                         cmd = ast_play_and_wait(chan, "vm-nomore");
10474                      }
10475                   } else {
10476                      cmd = ast_play_and_wait(chan, "vm-nomore");
10477                   }
10478                }
10479             }
10480          } else /* Delete not valid if we haven't selected a message */
10481             cmd = 0;
10482 #ifdef IMAP_STORAGE
10483          deleted = 1;
10484 #endif
10485          break;
10486    
10487       case '8': /* Forward the current message */
10488          if (vms.lastmsg > -1) {
10489             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10490             if (cmd == ERROR_LOCK_PATH) {
10491                res = cmd;
10492                goto out;
10493             }
10494          } else {
10495             /* Check if we were listening to urgent
10496                messages.  If so, go to regular new messages
10497                instead of saying "no more messages"
10498             */
10499             if (in_urgent == 1 && vms.newmessages > 0) {
10500                /* Check for new messages */
10501                in_urgent = 0;
10502                res = close_mailbox(&vms, vmu);
10503                if (res == ERROR_LOCK_PATH)
10504                   goto out;
10505                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10506                if (res < 0)
10507                   goto out;
10508                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10509                vms.curmsg = -1;
10510                if (vms.lastmsg < 0) {
10511                   cmd = ast_play_and_wait(chan, "vm-nomore");
10512                }
10513             } else {
10514                cmd = ast_play_and_wait(chan, "vm-nomore");
10515             }
10516          }
10517          break;
10518       case '9': /* Save message to folder */
10519          ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
10520          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
10521             /* No message selected */
10522             cmd = 0;
10523             break;
10524          }
10525          if (useadsi)
10526             adsi_folders(chan, 1, "Save to folder...");
10527          cmd = get_folder2(chan, "vm-savefolder", 1);
10528          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10529          box = 0; /* Shut up compiler */
10530          if (cmd == '#') {
10531             cmd = 0;
10532             break;
10533          } else if (cmd > 0) {
10534             box = cmd = cmd - '0';
10535             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
10536             if (cmd == ERROR_LOCK_PATH) {
10537                res = cmd;
10538                goto out;
10539 #ifndef IMAP_STORAGE
10540             } else if (!cmd) {
10541                vms.deleted[vms.curmsg] = 1;
10542 #endif
10543             } else {
10544                vms.deleted[vms.curmsg] = 0;
10545                vms.heard[vms.curmsg] = 0;
10546             }
10547          }
10548          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
10549          if (useadsi)
10550             adsi_message(chan, &vms);
10551          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
10552          if (!cmd) {
10553             cmd = ast_play_and_wait(chan, "vm-message");
10554             if (!cmd) 
10555                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
10556             if (!cmd)
10557                cmd = ast_play_and_wait(chan, "vm-savedto");
10558             if (!cmd)
10559                cmd = vm_play_folder_name(chan, vms.fn);
10560          } else {
10561             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10562          }
10563          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
10564             if (vms.curmsg < vms.lastmsg) {
10565                vms.curmsg++;
10566                cmd = play_message(chan, vmu, &vms);
10567             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10568                vms.curmsg = 0;
10569                cmd = play_message(chan, vmu, &vms);
10570             } else {
10571                /* Check if we were listening to urgent
10572                   messages.  If so, go to regular new messages
10573                   instead of saying "no more messages"
10574                */
10575                if (in_urgent == 1 && vms.newmessages > 0) {
10576                   /* Check for new messages */
10577                   in_urgent = 0;
10578                   res = close_mailbox(&vms, vmu);
10579                   if (res == ERROR_LOCK_PATH)
10580                      goto out;
10581                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
10582                   if (res < 0)
10583                      goto out;
10584                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10585                   vms.curmsg = -1;
10586                   if (vms.lastmsg < 0) {
10587                      cmd = ast_play_and_wait(chan, "vm-nomore");
10588                   }
10589                } else {
10590                   cmd = ast_play_and_wait(chan, "vm-nomore");
10591                }
10592             }
10593          }
10594          break;
10595       case '*': /* Help */
10596          if (!vms.starting) {
10597             cmd = ast_play_and_wait(chan, "vm-onefor");
10598             if (!strncasecmp(chan->language, "he", 2)) {
10599                cmd = ast_play_and_wait(chan, "vm-for");
10600             }
10601             if (!cmd)
10602                cmd = vm_play_folder_name(chan, vms.vmbox);
10603             if (!cmd)
10604                cmd = ast_play_and_wait(chan, "vm-opts");
10605             if (!cmd)
10606                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
10607          } else
10608             cmd = 0;
10609          break;
10610       case '0': /* Mailbox options */
10611          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
10612          if (useadsi)
10613             adsi_status(chan, &vms);
10614          break;
10615       default: /* Nothing */
10616          ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
10617          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
10618          break;
10619       }
10620    }
10621    if ((cmd == 't') || (cmd == '#')) {
10622       /* Timeout */
10623       res = 0;
10624    } else {
10625       /* Hangup */
10626       res = -1;
10627    }
10628 
10629 out:
10630    if (res > -1) {
10631       ast_stopstream(chan);
10632       adsi_goodbye(chan);
10633       if (valid && res != OPERATOR_EXIT) {
10634          if (silentexit)
10635             res = ast_play_and_wait(chan, "vm-dialout");
10636          else 
10637             res = ast_play_and_wait(chan, "vm-goodbye");
10638       }
10639       if ((valid && res > 0) || res == OPERATOR_EXIT) {
10640          res = 0;
10641       }
10642       if (useadsi)
10643          ast_adsi_unload_session(chan);
10644    }
10645    if (vmu)
10646       close_mailbox(&vms, vmu);
10647    if (valid) {
10648       int new = 0, old = 0, urgent = 0;
10649       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
10650       ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
10651       /* Urgent flag not passwd to externnotify here */
10652       run_externnotify(vmu->context, vmu->mailbox, NULL);
10653       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
10654       queue_mwi_event(ext_context, urgent, new, old);
10655    }
10656 #ifdef IMAP_STORAGE
10657    /* expunge message - use UID Expunge if supported on IMAP server*/
10658    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10659    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10660       ast_mutex_lock(&vms.lock);
10661 #ifdef HAVE_IMAP_TK2006
10662       if (LEVELUIDPLUS (vms.mailstream)) {
10663          mail_expunge_full(vms.mailstream, NIL, EX_UID);
10664       } else 
10665 #endif
10666          mail_expunge(vms.mailstream);
10667       ast_mutex_unlock(&vms.lock);
10668    }
10669    /*  before we delete the state, we should copy pertinent info
10670     *  back to the persistent model */
10671    if (vmu) {
10672       vmstate_delete(&vms);
10673    }
10674 #endif
10675    if (vmu)
10676       free_user(vmu);
10677 
10678 #ifdef IMAP_STORAGE
10679    pthread_setspecific(ts_vmstate.key, NULL);
10680 #endif
10681    return res;
10682 }

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 
vm_fmts 
context 
record_gain 
duration 
vms 
flag 

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

References ast_category_get(), ast_channel_setoption(), ast_config_destroy(), ast_config_load, ast_config_text_file_save(), ast_filecopy(), ast_filerename(), AST_OPTION_RXGAIN, ast_play_and_prepend(), ast_play_and_wait(), ast_stream_and_wait(), ast_test_suite_event_notify, ast_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), CONFIG_FLAG_NOCACHE, copy(), INTRO, make_file(), ast_vm_user::maxsecs, maxsilence, play_record_review(), silencethreshold, valid_config(), vm_pls_try_again, and vm_prepend_timeout.

Referenced by forward_message().

06899 {
06900    int cmd = 0;
06901    int retries = 0, prepend_duration = 0, already_recorded = 0;
06902    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06903    char textfile[PATH_MAX];
06904    struct ast_config *msg_cfg;
06905    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06906 #ifndef IMAP_STORAGE
06907    signed char zero_gain = 0;
06908 #endif
06909    const char *duration_str;
06910 
06911    /* Must always populate duration correctly */
06912    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06913    strcpy(textfile, msgfile);
06914    strcpy(backup, msgfile);
06915    strcpy(backup_textfile, msgfile);
06916    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06917    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06918    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06919 
06920    if ((msg_cfg = ast_config_load(textfile, config_flags)) && valid_config(msg_cfg) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06921       *duration = atoi(duration_str);
06922    } else {
06923       *duration = 0;
06924    }
06925 
06926    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06927       if (cmd)
06928          retries = 0;
06929       switch (cmd) {
06930       case '1': 
06931 
06932 #ifdef IMAP_STORAGE
06933          /* Record new intro file */
06934          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06935          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06936          ast_play_and_wait(chan, INTRO);
06937          ast_play_and_wait(chan, "beep");
06938          cmd = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag);
06939          if (cmd == -1) {
06940             break;
06941          }
06942          cmd = 't';
06943 #else
06944 
06945          /* prepend a message to the current message, update the metadata and return */
06946 
06947          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06948          strcpy(textfile, msgfile);
06949          strncat(textfile, ".txt", sizeof(textfile) - 1);
06950          *duration = 0;
06951 
06952          /* if we can't read the message metadata, stop now */
06953          if (!valid_config(msg_cfg)) {
06954             cmd = 0;
06955             break;
06956          }
06957 
06958          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06959 #ifndef IMAP_STORAGE
06960          if (already_recorded) {
06961             ast_filecopy(backup, msgfile, NULL);
06962             copy(backup_textfile, textfile);
06963          }
06964          else {
06965             ast_filecopy(msgfile, backup, NULL);
06966             copy(textfile, backup_textfile);
06967          }
06968 #endif
06969          already_recorded = 1;
06970 
06971          if (record_gain)
06972             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06973 
06974          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
06975 
06976          if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
06977             ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
06978             ast_stream_and_wait(chan, vm_prepend_timeout, "");
06979             ast_filerename(backup, msgfile, NULL);
06980          }
06981 
06982          if (record_gain)
06983             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06984 
06985          
06986          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06987             *duration = atoi(duration_str);
06988 
06989          if (prepend_duration) {
06990             struct ast_category *msg_cat;
06991             /* need enough space for a maximum-length message duration */
06992             char duration_buf[12];
06993 
06994             *duration += prepend_duration;
06995             msg_cat = ast_category_get(msg_cfg, "message");
06996             snprintf(duration_buf, 11, "%ld", *duration);
06997             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06998                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06999             }
07000          }
07001 
07002 #endif
07003          break;
07004       case '2': 
07005          /* NULL out introfile so we know there is no intro! */
07006 #ifdef IMAP_STORAGE
07007          *vms->introfn = '\0';
07008 #endif
07009          cmd = 't';
07010          break;
07011       case '*':
07012          cmd = '*';
07013          break;
07014       default: 
07015          /* If time_out and return to menu, reset already_recorded */
07016          already_recorded = 0;
07017 
07018          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
07019             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
07020          if (!cmd) {
07021             cmd = ast_play_and_wait(chan, "vm-starmain");
07022             /* "press star to return to the main menu" */
07023          }
07024          if (!cmd) {
07025             cmd = ast_waitfordigit(chan, 6000);
07026          }
07027          if (!cmd) {
07028             retries++;
07029          }
07030          if (retries > 3) {
07031             cmd = '*'; /* Let's cancel this beast */
07032          }
07033          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
07034       }
07035    }
07036 
07037    if (valid_config(msg_cfg))
07038       ast_config_destroy(msg_cfg);
07039    if (prepend_duration)
07040       *duration = prepend_duration;
07041 
07042    if (already_recorded && cmd == -1) {
07043       /* restore original message if prepention cancelled */
07044       ast_filerename(backup, msgfile, NULL);
07045       rename(backup_textfile, textfile);
07046    }
07047 
07048    if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */
07049       cmd = 0;
07050    return cmd;
07051 }

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

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

Referenced by vm_execmain().

09252 {
09253    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09254       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09255    } else {             /* Default to ENGLISH */
09256       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09257    }
09258 }

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

References ast_mutex_lock, ast_mutex_unlock, 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().

09140 {
09141    int res = 0;
09142    /* Play instructions and wait for new command */
09143    while (!res) {
09144       if (vms->starting) {
09145          if (vms->lastmsg > -1) {
09146             if (skipadvanced)
09147                res = ast_play_and_wait(chan, "vm-onefor-full");
09148             else
09149                res = ast_play_and_wait(chan, "vm-onefor");
09150             if (!res)
09151                res = vm_play_folder_name(chan, vms->vmbox);
09152          }
09153          if (!res) {
09154             if (skipadvanced)
09155                res = ast_play_and_wait(chan, "vm-opts-full");
09156             else
09157                res = ast_play_and_wait(chan, "vm-opts");
09158          }
09159       } else {
09160          /* Added for additional help */
09161          if (skipadvanced) {
09162             res = ast_play_and_wait(chan, "vm-onefor-full");
09163             if (!res)
09164                res = vm_play_folder_name(chan, vms->vmbox);
09165             res = ast_play_and_wait(chan, "vm-opts-full");
09166          }
09167          /* Logic:
09168           * If the current message is not the first OR
09169           * if we're listening to the first new message and there are
09170           * also urgent messages, then prompt for navigation to the
09171           * previous message
09172           */
09173          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09174             res = ast_play_and_wait(chan, "vm-prev");
09175          }
09176          if (!res && !skipadvanced)
09177             res = ast_play_and_wait(chan, "vm-advopts");
09178          if (!res)
09179             res = ast_play_and_wait(chan, "vm-repeat");
09180          /* Logic:
09181           * If we're not listening to the last message OR
09182           * we're listening to the last urgent message and there are
09183           * also new non-urgent messages, then prompt for navigation
09184           * to the next message
09185           */
09186          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09187             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09188             res = ast_play_and_wait(chan, "vm-next");
09189          }
09190          if (!res) {
09191             int curmsg_deleted;
09192 #ifdef IMAP_STORAGE
09193             ast_mutex_lock(&vms->lock);
09194 #endif
09195             curmsg_deleted = vms->deleted[vms->curmsg];
09196 #ifdef IMAP_STORAGE
09197             ast_mutex_unlock(&vms->lock);
09198 #endif
09199             if (!curmsg_deleted) {
09200                res = ast_play_and_wait(chan, "vm-delete");
09201             } else {
09202                res = ast_play_and_wait(chan, "vm-undelete");
09203             }
09204             if (!res) {
09205                res = ast_play_and_wait(chan, "vm-toforward");
09206             }
09207             if (!res) {
09208                res = ast_play_and_wait(chan, "vm-savemessage");
09209             }
09210          }
09211       }
09212       if (!res) {
09213          res = ast_play_and_wait(chan, "vm-helpexit");
09214       }
09215       if (!res)
09216          res = ast_waitfordigit(chan, 6000);
09217       if (!res) {
09218          vms->repeats++;
09219          if (vms->repeats > 2) {
09220             res = 't';
09221          }
09222       }
09223    }
09224    return res;
09225 }

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

09228 {
09229    int res = 0;
09230    /* Play instructions and wait for new command */
09231    while (!res) {
09232       if (vms->lastmsg > -1) {
09233          res = ast_play_and_wait(chan, "vm-listen");
09234          if (!res)
09235             res = vm_play_folder_name(chan, vms->vmbox);
09236          if (!res)
09237             res = ast_play_and_wait(chan, "press");
09238          if (!res)
09239             res = ast_play_and_wait(chan, "digits/1");
09240       }
09241       if (!res)
09242          res = ast_play_and_wait(chan, "vm-opts");
09243       if (!res) {
09244          vms->starting = 0;
09245          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09246       }
09247    }
09248    return res;
09249 }

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

Definition at line 9077 of file app_voicemail.c.

References ast_fileexists(), ast_log(), ast_play_and_wait(), ast_test_flag, ast_vm_user::context, DISPOSE, LOG_WARNING, ast_vm_user::mailbox, RETRIEVE, vm_state::username, vm_intro_cs(), 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_vi(), vm_intro_zh(), VM_SPOOL_DIR, and VM_TEMPGREETWARN.

Referenced by vm_execmain().

09078 {
09079    char prefile[256];
09080    
09081    /* Notify the user that the temp greeting is set and give them the option to remove it */
09082    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09083    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09084       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09085       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09086          ast_play_and_wait(chan, "vm-tempgreetactive");
09087       }
09088       DISPOSE(prefile, -1);
09089    }
09090 
09091    /* Play voicemail intro - syntax is different for different languages */
09092    if (0) {
09093       return 0;
09094    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09095       return vm_intro_cs(chan, vms);
09096    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09097       static int deprecation_warning = 0;
09098       if (deprecation_warning++ % 10 == 0) {
09099          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09100       }
09101       return vm_intro_cs(chan, vms);
09102    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09103       return vm_intro_de(chan, vms);
09104    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09105       return vm_intro_es(chan, vms);
09106    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09107       return vm_intro_fr(chan, vms);
09108    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09109       return vm_intro_gr(chan, vms);
09110    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09111       return vm_intro_he(chan, vms);
09112    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09113       return vm_intro_it(chan, vms);
09114    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09115       return vm_intro_nl(chan, vms);
09116    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09117       return vm_intro_no(chan, vms);
09118    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09119       return vm_intro_pl(chan, vms);
09120    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09121       return vm_intro_pt_BR(chan, vms);
09122    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09123       return vm_intro_pt(chan, vms);
09124    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09125       return vm_intro_multilang(chan, vms, "n");
09126    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09127       return vm_intro_se(chan, vms);
09128    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09129       return vm_intro_multilang(chan, vms, "n");
09130    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09131       return vm_intro_vi(chan, vms);
09132    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09133       return vm_intro_zh(chan, vms);
09134    } else {                                             /* Default to ENGLISH */
09135       return vm_intro_en(chan, vms);
09136    }
09137 }

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

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

08948 {
08949    int res;
08950    res = ast_play_and_wait(chan, "vm-youhave");
08951    if (!res) {
08952       if (vms->newmessages) {
08953          if (vms->newmessages == 1) {
08954             res = ast_play_and_wait(chan, "digits/jednu");
08955          } else {
08956             res = say_and_wait(chan, vms->newmessages, chan->language);
08957          }
08958          if (!res) {
08959             if ((vms->newmessages == 1))
08960                res = ast_play_and_wait(chan, "vm-novou");
08961             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08962                res = ast_play_and_wait(chan, "vm-nove");
08963             if (vms->newmessages > 4)
08964                res = ast_play_and_wait(chan, "vm-novych");
08965          }
08966          if (vms->oldmessages && !res)
08967             res = ast_play_and_wait(chan, "vm-and");
08968          else if (!res) {
08969             if ((vms->newmessages == 1))
08970                res = ast_play_and_wait(chan, "vm-zpravu");
08971             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08972                res = ast_play_and_wait(chan, "vm-zpravy");
08973             if (vms->newmessages > 4)
08974                res = ast_play_and_wait(chan, "vm-zprav");
08975          }
08976       }
08977       if (!res && vms->oldmessages) {
08978          res = say_and_wait(chan, vms->oldmessages, chan->language);
08979          if (!res) {
08980             if ((vms->oldmessages == 1))
08981                res = ast_play_and_wait(chan, "vm-starou");
08982             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08983                res = ast_play_and_wait(chan, "vm-stare");
08984             if (vms->oldmessages > 4)
08985                res = ast_play_and_wait(chan, "vm-starych");
08986          }
08987          if (!res) {
08988             if ((vms->oldmessages == 1))
08989                res = ast_play_and_wait(chan, "vm-zpravu");
08990             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08991                res = ast_play_and_wait(chan, "vm-zpravy");
08992             if (vms->oldmessages > 4)
08993                res = ast_play_and_wait(chan, "vm-zprav");
08994          }
08995       }
08996       if (!res) {
08997          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08998             res = ast_play_and_wait(chan, "vm-no");
08999             if (!res)
09000                res = ast_play_and_wait(chan, "vm-zpravy");
09001          }
09002       }
09003    }
09004    return res;
09005 }

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

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

08644 {
08645    /* Introduce messages they have */
08646    int res;
08647    res = ast_play_and_wait(chan, "vm-youhave");
08648    if (!res) {
08649       if (vms->newmessages) {
08650          if ((vms->newmessages == 1))
08651             res = ast_play_and_wait(chan, "digits/1F");
08652          else
08653             res = say_and_wait(chan, vms->newmessages, chan->language);
08654          if (!res)
08655             res = ast_play_and_wait(chan, "vm-INBOX");
08656          if (vms->oldmessages && !res)
08657             res = ast_play_and_wait(chan, "vm-and");
08658          else if (!res) {
08659             if ((vms->newmessages == 1))
08660                res = ast_play_and_wait(chan, "vm-message");
08661             else
08662                res = ast_play_and_wait(chan, "vm-messages");
08663          }
08664             
08665       }
08666       if (!res && vms->oldmessages) {
08667          if (vms->oldmessages == 1)
08668             res = ast_play_and_wait(chan, "digits/1F");
08669          else
08670             res = say_and_wait(chan, vms->oldmessages, chan->language);
08671          if (!res)
08672             res = ast_play_and_wait(chan, "vm-Old");
08673          if (!res) {
08674             if (vms->oldmessages == 1)
08675                res = ast_play_and_wait(chan, "vm-message");
08676             else
08677                res = ast_play_and_wait(chan, "vm-messages");
08678          }
08679       }
08680       if (!res) {
08681          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08682             res = ast_play_and_wait(chan, "vm-no");
08683             if (!res)
08684                res = ast_play_and_wait(chan, "vm-messages");
08685          }
08686       }
08687    }
08688    return res;
08689 }

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

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

08393 {
08394    int res;
08395 
08396    /* Introduce messages they have */
08397    res = ast_play_and_wait(chan, "vm-youhave");
08398    if (!res) {
08399       if (vms->urgentmessages) {
08400          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08401          if (!res)
08402             res = ast_play_and_wait(chan, "vm-Urgent");
08403          if ((vms->oldmessages || vms->newmessages) && !res) {
08404             res = ast_play_and_wait(chan, "vm-and");
08405          } else if (!res) {
08406             if ((vms->urgentmessages == 1))
08407                res = ast_play_and_wait(chan, "vm-message");
08408             else
08409                res = ast_play_and_wait(chan, "vm-messages");
08410          }
08411       }
08412       if (vms->newmessages) {
08413          res = say_and_wait(chan, vms->newmessages, chan->language);
08414          if (!res)
08415             res = ast_play_and_wait(chan, "vm-INBOX");
08416          if (vms->oldmessages && !res)
08417             res = ast_play_and_wait(chan, "vm-and");
08418          else if (!res) {
08419             if ((vms->newmessages == 1))
08420                res = ast_play_and_wait(chan, "vm-message");
08421             else
08422                res = ast_play_and_wait(chan, "vm-messages");
08423          }
08424             
08425       }
08426       if (!res && vms->oldmessages) {
08427          res = say_and_wait(chan, vms->oldmessages, chan->language);
08428          if (!res)
08429             res = ast_play_and_wait(chan, "vm-Old");
08430          if (!res) {
08431             if (vms->oldmessages == 1)
08432                res = ast_play_and_wait(chan, "vm-message");
08433             else
08434                res = ast_play_and_wait(chan, "vm-messages");
08435          }
08436       }
08437       if (!res) {
08438          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08439             res = ast_play_and_wait(chan, "vm-no");
08440             if (!res)
08441                res = ast_play_and_wait(chan, "vm-messages");
08442          }
08443       }
08444    }
08445    return res;
08446 }

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

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

08693 {
08694    /* Introduce messages they have */
08695    int res;
08696    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08697       res = ast_play_and_wait(chan, "vm-youhaveno");
08698       if (!res)
08699          res = ast_play_and_wait(chan, "vm-messages");
08700    } else {
08701       res = ast_play_and_wait(chan, "vm-youhave");
08702    }
08703    if (!res) {
08704       if (vms->newmessages) {
08705          if (!res) {
08706             if ((vms->newmessages == 1)) {
08707                res = ast_play_and_wait(chan, "digits/1M");
08708                if (!res)
08709                   res = ast_play_and_wait(chan, "vm-message");
08710                if (!res)
08711                   res = ast_play_and_wait(chan, "vm-INBOXs");
08712             } else {
08713                res = say_and_wait(chan, vms->newmessages, chan->language);
08714                if (!res)
08715                   res = ast_play_and_wait(chan, "vm-messages");
08716                if (!res)
08717                   res = ast_play_and_wait(chan, "vm-INBOX");
08718             }
08719          }
08720          if (vms->oldmessages && !res)
08721             res = ast_play_and_wait(chan, "vm-and");
08722       }
08723       if (vms->oldmessages) {
08724          if (!res) {
08725             if (vms->oldmessages == 1) {
08726                res = ast_play_and_wait(chan, "digits/1M");
08727                if (!res)
08728                   res = ast_play_and_wait(chan, "vm-message");
08729                if (!res)
08730                   res = ast_play_and_wait(chan, "vm-Olds");
08731             } else {
08732                res = say_and_wait(chan, vms->oldmessages, chan->language);
08733                if (!res)
08734                   res = ast_play_and_wait(chan, "vm-messages");
08735                if (!res)
08736                   res = ast_play_and_wait(chan, "vm-Old");
08737             }
08738          }
08739       }
08740    }
08741 return res;
08742 }

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

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

08791 {
08792    /* Introduce messages they have */
08793    int res;
08794    res = ast_play_and_wait(chan, "vm-youhave");
08795    if (!res) {
08796       if (vms->newmessages) {
08797          res = say_and_wait(chan, vms->newmessages, chan->language);
08798          if (!res)
08799             res = ast_play_and_wait(chan, "vm-INBOX");
08800          if (vms->oldmessages && !res)
08801             res = ast_play_and_wait(chan, "vm-and");
08802          else if (!res) {
08803             if ((vms->newmessages == 1))
08804                res = ast_play_and_wait(chan, "vm-message");
08805             else
08806                res = ast_play_and_wait(chan, "vm-messages");
08807          }
08808             
08809       }
08810       if (!res && vms->oldmessages) {
08811          res = say_and_wait(chan, vms->oldmessages, chan->language);
08812          if (!res)
08813             res = ast_play_and_wait(chan, "vm-Old");
08814          if (!res) {
08815             if (vms->oldmessages == 1)
08816                res = ast_play_and_wait(chan, "vm-message");
08817             else
08818                res = ast_play_and_wait(chan, "vm-messages");
08819          }
08820       }
08821       if (!res) {
08822          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08823             res = ast_play_and_wait(chan, "vm-no");
08824             if (!res)
08825                res = ast_play_and_wait(chan, "vm-messages");
08826          }
08827       }
08828    }
08829    return res;
08830 }

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

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

08192 {
08193    int res = 0;
08194 
08195    if (vms->newmessages) {
08196       res = ast_play_and_wait(chan, "vm-youhave");
08197       if (!res) 
08198          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08199       if (!res) {
08200          if ((vms->newmessages == 1)) {
08201             res = ast_play_and_wait(chan, "vm-INBOX");
08202             if (!res)
08203                res = ast_play_and_wait(chan, "vm-message");
08204          } else {
08205             res = ast_play_and_wait(chan, "vm-INBOXs");
08206             if (!res)
08207                res = ast_play_and_wait(chan, "vm-messages");
08208          }
08209       }
08210    } else if (vms->oldmessages){
08211       res = ast_play_and_wait(chan, "vm-youhave");
08212       if (!res)
08213          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08214       if ((vms->oldmessages == 1)){
08215          res = ast_play_and_wait(chan, "vm-Old");
08216          if (!res)
08217             res = ast_play_and_wait(chan, "vm-message");
08218       } else {
08219          res = ast_play_and_wait(chan, "vm-Olds");
08220          if (!res)
08221             res = ast_play_and_wait(chan, "vm-messages");
08222       }
08223    } else if (!vms->oldmessages && !vms->newmessages) 
08224       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08225    return res;
08226 }

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

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

08326 {
08327    int res = 0;
08328 
08329    /* Introduce messages they have */
08330    if (!res) {
08331       if ((vms->newmessages) || (vms->oldmessages)) {
08332          res = ast_play_and_wait(chan, "vm-youhave");
08333       }
08334       /*
08335        * The word "shtei" refers to the number 2 in hebrew when performing a count
08336        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08337        * an element, this is one of them.
08338        */
08339       if (vms->newmessages) {
08340          if (!res) {
08341             if (vms->newmessages == 1) {
08342                res = ast_play_and_wait(chan, "vm-INBOX1");
08343             } else {
08344                if (vms->newmessages == 2) {
08345                   res = ast_play_and_wait(chan, "vm-shtei");
08346                } else {
08347                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08348                }
08349                res = ast_play_and_wait(chan, "vm-INBOX");
08350             }
08351          }
08352          if (vms->oldmessages && !res) {
08353             res = ast_play_and_wait(chan, "vm-and");
08354             if (vms->oldmessages == 1) {
08355                res = ast_play_and_wait(chan, "vm-Old1");
08356             } else {
08357                if (vms->oldmessages == 2) {
08358                   res = ast_play_and_wait(chan, "vm-shtei");
08359                } else {
08360                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08361                }
08362                res = ast_play_and_wait(chan, "vm-Old");
08363             }
08364          }
08365       }
08366       if (!res && vms->oldmessages && !vms->newmessages) {
08367          if (!res) {
08368             if (vms->oldmessages == 1) {
08369                res = ast_play_and_wait(chan, "vm-Old1");
08370             } else {
08371                if (vms->oldmessages == 2) {
08372                   res = ast_play_and_wait(chan, "vm-shtei");
08373                } else {
08374                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08375                }
08376                res = ast_play_and_wait(chan, "vm-Old");
08377             }
08378          }
08379       }
08380       if (!res) {
08381          if (!vms->oldmessages && !vms->newmessages) {
08382             if (!res) {
08383                res = ast_play_and_wait(chan, "vm-nomessages");
08384             }
08385          }
08386       }
08387    }
08388    return res;
08389 }

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

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

08450 {
08451    /* Introduce messages they have */
08452    int res;
08453    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08454       res = ast_play_and_wait(chan, "vm-no") ||
08455          ast_play_and_wait(chan, "vm-message");
08456    else
08457       res = ast_play_and_wait(chan, "vm-youhave");
08458    if (!res && vms->newmessages) {
08459       res = (vms->newmessages == 1) ?
08460          ast_play_and_wait(chan, "digits/un") ||
08461          ast_play_and_wait(chan, "vm-nuovo") ||
08462          ast_play_and_wait(chan, "vm-message") :
08463          /* 2 or more new messages */
08464          say_and_wait(chan, vms->newmessages, chan->language) ||
08465          ast_play_and_wait(chan, "vm-nuovi") ||
08466          ast_play_and_wait(chan, "vm-messages");
08467       if (!res && vms->oldmessages)
08468          res = ast_play_and_wait(chan, "vm-and");
08469    }
08470    if (!res && vms->oldmessages) {
08471       res = (vms->oldmessages == 1) ?
08472          ast_play_and_wait(chan, "digits/un") ||
08473          ast_play_and_wait(chan, "vm-vecchio") ||
08474          ast_play_and_wait(chan, "vm-message") :
08475          /* 2 or more old messages */
08476          say_and_wait(chan, vms->oldmessages, chan->language) ||
08477          ast_play_and_wait(chan, "vm-vecchi") ||
08478          ast_play_and_wait(chan, "vm-messages");
08479    }
08480    return res;
08481 }

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

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

08286 {
08287    int res;
08288    int lastnum = 0;
08289 
08290    res = ast_play_and_wait(chan, "vm-youhave");
08291 
08292    if (!res && vms->newmessages) {
08293       lastnum = vms->newmessages;
08294 
08295       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08296          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08297       }
08298 
08299       if (!res && vms->oldmessages) {
08300          res = ast_play_and_wait(chan, "vm-and");
08301       }
08302    }
08303 
08304    if (!res && vms->oldmessages) {
08305       lastnum = vms->oldmessages;
08306 
08307       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08308          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08309       }
08310    }
08311 
08312    if (!res) {
08313       if (lastnum == 0) {
08314          res = ast_play_and_wait(chan, "vm-no");
08315       }
08316       if (!res) {
08317          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08318       }
08319    }
08320 
08321    return res;
08322 }

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

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

08834 {
08835    /* Introduce messages they have */
08836    int res;
08837    res = ast_play_and_wait(chan, "vm-youhave");
08838    if (!res) {
08839       if (vms->newmessages) {
08840          res = say_and_wait(chan, vms->newmessages, chan->language);
08841          if (!res) {
08842             if (vms->newmessages == 1)
08843                res = ast_play_and_wait(chan, "vm-INBOXs");
08844             else
08845                res = ast_play_and_wait(chan, "vm-INBOX");
08846          }
08847          if (vms->oldmessages && !res)
08848             res = ast_play_and_wait(chan, "vm-and");
08849          else if (!res) {
08850             if ((vms->newmessages == 1))
08851                res = ast_play_and_wait(chan, "vm-message");
08852             else
08853                res = ast_play_and_wait(chan, "vm-messages");
08854          }
08855             
08856       }
08857       if (!res && vms->oldmessages) {
08858          res = say_and_wait(chan, vms->oldmessages, chan->language);
08859          if (!res) {
08860             if (vms->oldmessages == 1)
08861                res = ast_play_and_wait(chan, "vm-Olds");
08862             else
08863                res = ast_play_and_wait(chan, "vm-Old");
08864          }
08865          if (!res) {
08866             if (vms->oldmessages == 1)
08867                res = ast_play_and_wait(chan, "vm-message");
08868             else
08869                res = ast_play_and_wait(chan, "vm-messages");
08870          }
08871       }
08872       if (!res) {
08873          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08874             res = ast_play_and_wait(chan, "vm-no");
08875             if (!res)
08876                res = ast_play_and_wait(chan, "vm-messages");
08877          }
08878       }
08879    }
08880    return res;
08881 }

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

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

08600 {
08601    /* Introduce messages they have */
08602    int res;
08603 
08604    res = ast_play_and_wait(chan, "vm-youhave");
08605    if (res)
08606       return res;
08607 
08608    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08609       res = ast_play_and_wait(chan, "vm-no");
08610       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08611       return res;
08612    }
08613 
08614    if (vms->newmessages) {
08615       if ((vms->newmessages == 1)) {
08616          res = ast_play_and_wait(chan, "digits/1");
08617          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08618          res = res ? res : ast_play_and_wait(chan, "vm-message");
08619       } else {
08620          res = say_and_wait(chan, vms->newmessages, chan->language);
08621          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08622          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08623       }
08624       if (!res && vms->oldmessages)
08625          res = ast_play_and_wait(chan, "vm-and");
08626    }
08627    if (!res && vms->oldmessages) {
08628       if (vms->oldmessages == 1) {
08629          res = ast_play_and_wait(chan, "digits/1");
08630          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08631          res = res ? res : ast_play_and_wait(chan, "vm-message");
08632       } else {
08633          res = say_and_wait(chan, vms->oldmessages, chan->language);
08634          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08635          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08636       }
08637    }
08638 
08639    return res;
08640 }

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

Definition at line 8484 of file app_voicemail.c.

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

Referenced by vm_intro().

08485 {
08486    /* Introduce messages they have */
08487    int res;
08488    div_t num;
08489 
08490    if (!vms->oldmessages && !vms->newmessages) {
08491       res = ast_play_and_wait(chan, "vm-no");
08492       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08493       return res;
08494    } else {
08495       res = ast_play_and_wait(chan, "vm-youhave");
08496    }
08497 
08498    if (vms->newmessages) {
08499       num = div(vms->newmessages, 10);
08500       if (vms->newmessages == 1) {
08501          res = ast_play_and_wait(chan, "digits/1-a");
08502          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08503          res = res ? res : ast_play_and_wait(chan, "vm-message");
08504       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08505          if (num.rem == 2) {
08506             if (!num.quot) {
08507                res = ast_play_and_wait(chan, "digits/2-ie");
08508             } else {
08509                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08510                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08511             }
08512          } else {
08513             res = say_and_wait(chan, vms->newmessages, chan->language);
08514          }
08515          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08516          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08517       } else {
08518          res = say_and_wait(chan, vms->newmessages, chan->language);
08519          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08520          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08521       }
08522       if (!res && vms->oldmessages)
08523          res = ast_play_and_wait(chan, "vm-and");
08524    }
08525    if (!res && vms->oldmessages) {
08526       num = div(vms->oldmessages, 10);
08527       if (vms->oldmessages == 1) {
08528          res = ast_play_and_wait(chan, "digits/1-a");
08529          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08530          res = res ? res : ast_play_and_wait(chan, "vm-message");
08531       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08532          if (num.rem == 2) {
08533             if (!num.quot) {
08534                res = ast_play_and_wait(chan, "digits/2-ie");
08535             } else {
08536                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08537                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08538             }
08539          } else {
08540             res = say_and_wait(chan, vms->oldmessages, chan->language);
08541          }
08542          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08543          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08544       } else {
08545          res = say_and_wait(chan, vms->oldmessages, chan->language);
08546          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08547          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08548       }
08549    }
08550 
08551    return res;
08552 }

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

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

08885 {
08886    /* Introduce messages they have */
08887    int res;
08888    res = ast_play_and_wait(chan, "vm-youhave");
08889    if (!res) {
08890       if (vms->newmessages) {
08891          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08892          if (!res) {
08893             if ((vms->newmessages == 1)) {
08894                res = ast_play_and_wait(chan, "vm-message");
08895                if (!res)
08896                   res = ast_play_and_wait(chan, "vm-INBOXs");
08897             } else {
08898                res = ast_play_and_wait(chan, "vm-messages");
08899                if (!res)
08900                   res = ast_play_and_wait(chan, "vm-INBOX");
08901             }
08902          }
08903          if (vms->oldmessages && !res)
08904             res = ast_play_and_wait(chan, "vm-and");
08905       }
08906       if (!res && vms->oldmessages) {
08907          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08908          if (!res) {
08909             if (vms->oldmessages == 1) {
08910                res = ast_play_and_wait(chan, "vm-message");
08911                if (!res)
08912                   res = ast_play_and_wait(chan, "vm-Olds");
08913             } else {
08914                res = ast_play_and_wait(chan, "vm-messages");
08915                if (!res)
08916                   res = ast_play_and_wait(chan, "vm-Old");
08917             }
08918          }
08919       }
08920       if (!res) {
08921          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08922             res = ast_play_and_wait(chan, "vm-no");
08923             if (!res)
08924                res = ast_play_and_wait(chan, "vm-messages");
08925          }
08926       }
08927    }
08928    return res;
08929 }

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

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

08745                                                                           {
08746    /* Introduce messages they have */
08747    int res;
08748    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08749       res = ast_play_and_wait(chan, "vm-nomessages");
08750       return res;
08751    } else {
08752       res = ast_play_and_wait(chan, "vm-youhave");
08753    }
08754    if (vms->newmessages) {
08755       if (!res)
08756          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08757       if ((vms->newmessages == 1)) {
08758          if (!res)
08759             res = ast_play_and_wait(chan, "vm-message");
08760          if (!res)
08761             res = ast_play_and_wait(chan, "vm-INBOXs");
08762       } else {
08763          if (!res)
08764             res = ast_play_and_wait(chan, "vm-messages");
08765          if (!res)
08766             res = ast_play_and_wait(chan, "vm-INBOX");
08767       }
08768       if (vms->oldmessages && !res)
08769          res = ast_play_and_wait(chan, "vm-and");
08770    }
08771    if (vms->oldmessages) {
08772       if (!res)
08773          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08774       if (vms->oldmessages == 1) {
08775          if (!res)
08776             res = ast_play_and_wait(chan, "vm-message");
08777          if (!res)
08778             res = ast_play_and_wait(chan, "vm-Olds");
08779       } else {
08780          if (!res)
08781             res = ast_play_and_wait(chan, "vm-messages");
08782          if (!res)
08783             res = ast_play_and_wait(chan, "vm-Old");
08784       }
08785    }
08786    return res;
08787 }

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

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

08556 {
08557    /* Introduce messages they have */
08558    int res;
08559 
08560    res = ast_play_and_wait(chan, "vm-youhave");
08561    if (res)
08562       return res;
08563 
08564    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08565       res = ast_play_and_wait(chan, "vm-no");
08566       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08567       return res;
08568    }
08569 
08570    if (vms->newmessages) {
08571       if ((vms->newmessages == 1)) {
08572          res = ast_play_and_wait(chan, "digits/ett");
08573          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08574          res = res ? res : ast_play_and_wait(chan, "vm-message");
08575       } else {
08576          res = say_and_wait(chan, vms->newmessages, chan->language);
08577          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08578          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08579       }
08580       if (!res && vms->oldmessages)
08581          res = ast_play_and_wait(chan, "vm-and");
08582    }
08583    if (!res && vms->oldmessages) {
08584       if (vms->oldmessages == 1) {
08585          res = ast_play_and_wait(chan, "digits/ett");
08586          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08587          res = res ? res : ast_play_and_wait(chan, "vm-message");
08588       } else {
08589          res = say_and_wait(chan, vms->oldmessages, chan->language);
08590          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08591          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08592       }
08593    }
08594 
08595    return res;
08596 }

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

Definition at line 9047 of file app_voicemail.c.

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

Referenced by vm_intro().

09048 {
09049    int res;
09050 
09051    /* Introduce messages they have */
09052    res = ast_play_and_wait(chan, "vm-youhave");
09053    if (!res) {
09054       if (vms->newmessages) {
09055          res = say_and_wait(chan, vms->newmessages, chan->language);
09056          if (!res)
09057             res = ast_play_and_wait(chan, "vm-INBOX");
09058          if (vms->oldmessages && !res)
09059             res = ast_play_and_wait(chan, "vm-and");
09060       }
09061       if (!res && vms->oldmessages) {
09062          res = say_and_wait(chan, vms->oldmessages, chan->language);
09063          if (!res)
09064             res = ast_play_and_wait(chan, "vm-Old");        
09065       }
09066       if (!res) {
09067          if (!vms->oldmessages && !vms->newmessages) {
09068             res = ast_play_and_wait(chan, "vm-no");
09069             if (!res)
09070                res = ast_play_and_wait(chan, "vm-message");
09071          }
09072       }
09073    }
09074    return res;
09075 }

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

Definition at line 9008 of file app_voicemail.c.

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

Referenced by vm_intro().

09009 {
09010    int res;
09011    /* Introduce messages they have */
09012    res = ast_play_and_wait(chan, "vm-you");
09013 
09014    if (!res && vms->newmessages) {
09015       res = ast_play_and_wait(chan, "vm-have");
09016       if (!res)
09017          res = say_and_wait(chan, vms->newmessages, chan->language);
09018       if (!res)
09019          res = ast_play_and_wait(chan, "vm-tong");
09020       if (!res)
09021          res = ast_play_and_wait(chan, "vm-INBOX");
09022       if (vms->oldmessages && !res)
09023          res = ast_play_and_wait(chan, "vm-and");
09024       else if (!res) 
09025          res = ast_play_and_wait(chan, "vm-messages");
09026    }
09027    if (!res && vms->oldmessages) {
09028       res = ast_play_and_wait(chan, "vm-have");
09029       if (!res)
09030          res = say_and_wait(chan, vms->oldmessages, chan->language);
09031       if (!res)
09032          res = ast_play_and_wait(chan, "vm-tong");
09033       if (!res)
09034          res = ast_play_and_wait(chan, "vm-Old");
09035       if (!res)
09036          res = ast_play_and_wait(chan, "vm-messages");
09037    }
09038    if (!res && !vms->oldmessages && !vms->newmessages) {
09039       res = ast_play_and_wait(chan, "vm-haveno");
09040       if (!res)
09041          res = ast_play_and_wait(chan, "vm-messages");
09042    }
09043    return res;
09044 }

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 3291 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(), resequence_mailbox(), and save_to_folder().

03292 {
03293    switch (ast_lock_path(path)) {
03294    case AST_LOCK_TIMEOUT:
03295       return -1;
03296    default:
03297       return 0;
03298    }
03299 }

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

Definition at line 1682 of file app_voicemail.c.

References my_umask, and VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01683 {
01684    FILE *p = NULL;
01685    int pfd = mkstemp(template);
01686    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01687    if (pfd > -1) {
01688       p = fdopen(pfd, "w+");
01689       if (!p) {
01690          close(pfd);
01691          pfd = -1;
01692       }
01693    }
01694    return p;
01695 }

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 9261 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, ast_test_suite_event_notify, check_password(), ast_vm_user::context, ext_pass_cmd, maxgreet, play_record_review(), pwdchange, 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, vm_pls_try_again, vm_reenterpassword, and VM_SPOOL_DIR.

Referenced by vm_execmain().

09262 {
09263    int cmd = 0;
09264    int duration = 0;
09265    int tries = 0;
09266    char newpassword[80] = "";
09267    char newpassword2[80] = "";
09268    char prefile[PATH_MAX] = "";
09269    unsigned char buf[256];
09270    int bytes = 0;
09271 
09272    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09273    if (ast_adsi_available(chan)) {
09274       bytes += adsi_logo(buf + bytes);
09275       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09276       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09277       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09278       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09279       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09280    }
09281 
09282    /* If forcename is set, have the user record their name */
09283    if (ast_test_flag(vmu, VM_FORCENAME)) {
09284       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09285       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09286          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09287          if (cmd < 0 || cmd == 't' || cmd == '#')
09288             return cmd;
09289       }
09290    }
09291 
09292    /* If forcegreetings is set, have the user record their greetings */
09293    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09294       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09295       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09296          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09297          if (cmd < 0 || cmd == 't' || cmd == '#')
09298             return cmd;
09299       }
09300 
09301       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09302       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09303          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09304          if (cmd < 0 || cmd == 't' || cmd == '#')
09305             return cmd;
09306       }
09307    }
09308 
09309    /*
09310     * Change the password last since new users will be able to skip over any steps this one comes before
09311     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09312     */
09313    for (;;) {
09314       newpassword[1] = '\0';
09315       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09316       if (cmd == '#')
09317          newpassword[0] = '\0';
09318       if (cmd < 0 || cmd == 't' || cmd == '#')
09319          return cmd;
09320       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09321       if (cmd < 0 || cmd == 't' || cmd == '#')
09322          return cmd;
09323       cmd = check_password(vmu, newpassword); /* perform password validation */
09324       if (cmd != 0) {
09325          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09326          cmd = ast_play_and_wait(chan, vm_invalid_password);
09327       } else {
09328          newpassword2[1] = '\0';
09329          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09330          if (cmd == '#')
09331             newpassword2[0] = '\0';
09332          if (cmd < 0 || cmd == 't' || cmd == '#')
09333             return cmd;
09334          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09335          if (cmd < 0 || cmd == 't' || cmd == '#')
09336             return cmd;
09337          if (!strcmp(newpassword, newpassword2))
09338             break;
09339          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09340          cmd = ast_play_and_wait(chan, vm_mismatch);
09341       }
09342       if (++tries == 3)
09343          return -1;
09344       if (cmd != 0) {
09345          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09346       }
09347    }
09348    if (pwdchange & PWDCHANGE_INTERNAL)
09349       vm_change_password(vmu, newpassword);
09350    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09351       vm_change_password_shell(vmu, newpassword);
09352 
09353    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09354    cmd = ast_play_and_wait(chan, vm_passchanged);
09355 
09356    return cmd;
09357 }

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 9359 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_suite_event_notify, ast_waitfordigit(), check_password(), ast_vm_user::context, DISPOSE, ext_pass_cmd, ast_vm_user::mailbox, maxgreet, ast_vm_user::password, play_record_review(), pwdchange, 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_pls_try_again, vm_reenterpassword, VM_SPOOL_DIR, and vm_tempgreeting().

Referenced by vm_execmain().

09360 {
09361    int cmd = 0;
09362    int retries = 0;
09363    int duration = 0;
09364    char newpassword[80] = "";
09365    char newpassword2[80] = "";
09366    char prefile[PATH_MAX] = "";
09367    unsigned char buf[256];
09368    int bytes = 0;
09369 
09370    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09371    if (ast_adsi_available(chan)) {
09372       bytes += adsi_logo(buf + bytes);
09373       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09374       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09375       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09376       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09377       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09378    }
09379    while ((cmd >= 0) && (cmd != 't')) {
09380       if (cmd)
09381          retries = 0;
09382       switch (cmd) {
09383       case '1': /* Record your unavailable message */
09384          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09385          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09386          break;
09387       case '2':  /* Record your busy message */
09388          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09389          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09390          break;
09391       case '3': /* Record greeting */
09392          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09393          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09394          break;
09395       case '4':  /* manage the temporary greeting */
09396          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09397          break;
09398       case '5': /* change password */
09399          if (vmu->password[0] == '-') {
09400             cmd = ast_play_and_wait(chan, "vm-no");
09401             break;
09402          }
09403          newpassword[1] = '\0';
09404          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09405          if (cmd == '#')
09406             newpassword[0] = '\0';
09407          else {
09408             if (cmd < 0)
09409                break;
09410             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09411                break;
09412             }
09413          }
09414          cmd = check_password(vmu, newpassword); /* perform password validation */
09415          if (cmd != 0) {
09416             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09417             cmd = ast_play_and_wait(chan, vm_invalid_password);
09418             if (!cmd) {
09419                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09420             }
09421             break;
09422          }
09423          newpassword2[1] = '\0';
09424          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09425          if (cmd == '#')
09426             newpassword2[0] = '\0';
09427          else {
09428             if (cmd < 0)
09429                break;
09430 
09431             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09432                break;
09433             }
09434          }
09435          if (strcmp(newpassword, newpassword2)) {
09436             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09437             cmd = ast_play_and_wait(chan, vm_mismatch);
09438             if (!cmd) {
09439                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09440             }
09441             break;
09442          }
09443 
09444          if (pwdchange & PWDCHANGE_INTERNAL) {
09445             vm_change_password(vmu, newpassword);
09446          }
09447          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09448             vm_change_password_shell(vmu, newpassword);
09449          }
09450 
09451          ast_debug(1, "User %s set password to %s of length %d\n",
09452             vms->username, newpassword, (int) strlen(newpassword));
09453          cmd = ast_play_and_wait(chan, vm_passchanged);
09454          break;
09455       case '*': 
09456          cmd = 't';
09457          break;
09458       default: 
09459          cmd = 0;
09460          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09461          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09462          if (ast_fileexists(prefile, NULL, NULL)) {
09463             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09464          }
09465          DISPOSE(prefile, -1);
09466          if (!cmd) {
09467             cmd = ast_play_and_wait(chan, "vm-options");
09468          }
09469          if (!cmd) {
09470             cmd = ast_waitfordigit(chan, 6000);
09471          }
09472          if (!cmd) {
09473             retries++;
09474          }
09475          if (retries > 3) {
09476             cmd = 't';
09477          }
09478          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09479       }
09480    }
09481    if (cmd == 't')
09482       cmd = 0;
09483    return cmd;
09484 }

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

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

08155 {
08156    int cmd;
08157 
08158    if (  !strncasecmp(chan->language, "it", 2) ||
08159         !strncasecmp(chan->language, "es", 2) ||
08160         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08161       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08162       return cmd ? cmd : ast_play_and_wait(chan, box);
08163    } else if (!strncasecmp(chan->language, "gr", 2)) {
08164       return vm_play_folder_name_gr(chan, box);
08165    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08166       return ast_play_and_wait(chan, box);
08167    } else if (!strncasecmp(chan->language, "pl", 2)) {
08168       return vm_play_folder_name_pl(chan, box);
08169    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08170       return vm_play_folder_name_ua(chan, box);
08171    } else if (!strncasecmp(chan->language, "vi", 2)) {
08172       return ast_play_and_wait(chan, box);
08173    } else {  /* Default English */
08174       cmd = ast_play_and_wait(chan, box);
08175       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08176    }
08177 }

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

Definition at line 8107 of file app_voicemail.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

08108 {
08109    int cmd;
08110    char *buf;
08111 
08112    buf = ast_alloca(strlen(box) + 2);
08113    strcpy(buf, box);
08114    strcat(buf, "s");
08115 
08116    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08117       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08118       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08119    } else {
08120       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08121       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08122    }
08123 }

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

Definition at line 8125 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08126 {
08127    int cmd;
08128 
08129    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08130       if (!strcasecmp(box, "vm-INBOX"))
08131          cmd = ast_play_and_wait(chan, "vm-new-e");
08132       else
08133          cmd = ast_play_and_wait(chan, "vm-old-e");
08134       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08135    } else {
08136       cmd = ast_play_and_wait(chan, "vm-messages");
08137       return cmd ? cmd : ast_play_and_wait(chan, box);
08138    }
08139 }

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

Definition at line 8141 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08142 {
08143    int cmd;
08144 
08145    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08146       cmd = ast_play_and_wait(chan, "vm-messages");
08147       return cmd ? cmd : ast_play_and_wait(chan, box);
08148    } else {
08149       cmd = ast_play_and_wait(chan, box);
08150       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08151    }
08152 }

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 9502 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_test_suite_event_notify, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, maxgreet, play_record_review(), RETRIEVE, vm_state::username, and VM_SPOOL_DIR.

Referenced by vm_options().

09503 {
09504    int cmd = 0;
09505    int retries = 0;
09506    int duration = 0;
09507    char prefile[PATH_MAX] = "";
09508    unsigned char buf[256];
09509    int bytes = 0;
09510 
09511    if (ast_adsi_available(chan)) {
09512       bytes += adsi_logo(buf + bytes);
09513       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09514       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09515       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09516       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09517       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09518    }
09519 
09520    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09521    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09522    while ((cmd >= 0) && (cmd != 't')) {
09523       if (cmd)
09524          retries = 0;
09525       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09526       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09527          cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09528          if (cmd == -1) {
09529             break;
09530          }
09531          cmd = 't';  
09532       } else {
09533          switch (cmd) {
09534          case '1':
09535             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09536             break;
09537          case '2':
09538             DELETE(prefile, -1, prefile, vmu);
09539             ast_play_and_wait(chan, "vm-tempremoved");
09540             cmd = 't';  
09541             break;
09542          case '*': 
09543             cmd = 't';
09544             break;
09545          default:
09546             cmd = ast_play_and_wait(chan,
09547                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09548                   "vm-tempgreeting2" : "vm-tempgreeting");
09549             if (!cmd) {
09550                cmd = ast_waitfordigit(chan, 6000);
09551             }
09552             if (!cmd) {
09553                retries++;
09554             }
09555             if (retries > 3) {
09556                cmd = 't';
09557             }
09558             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09559          }
09560       }
09561       DISPOSE(prefile, -1);
09562    }
09563    if (cmd == 't')
09564       cmd = 0;
09565    return cmd;
09566 }

static int vm_users_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 11450 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and vm_users_data_provider_get_helper().

11452 {
11453    struct ast_vm_user *user;
11454 
11455    AST_LIST_LOCK(&users);
11456    AST_LIST_TRAVERSE(&users, user, list) {
11457       vm_users_data_provider_get_helper(search, data_root, user);
11458    }
11459    AST_LIST_UNLOCK(&users);
11460 
11461    return 0;
11462 }

static int vm_users_data_provider_get_helper ( const struct ast_data_search search,
struct ast_data data_root,
struct ast_vm_user user 
) [static]

Definition at line 11403 of file app_voicemail.c.

References ast_data_add_int(), ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::context, inboxcount2(), ast_vm_user::mailbox, and ast_vm_user::zonetag.

Referenced by vm_users_data_provider_get().

11405 {
11406    struct ast_data *data_user, *data_zone;
11407    struct ast_data *data_state;
11408    struct vm_zone *zone = NULL;
11409    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11410    char ext_context[256] = "";
11411 
11412    data_user = ast_data_add_node(data_root, "user");
11413    if (!data_user) {
11414       return -1;
11415    }
11416 
11417    ast_data_add_structure(ast_vm_user, data_user, user);
11418 
11419    AST_LIST_LOCK(&zones);
11420    AST_LIST_TRAVERSE(&zones, zone, list) {
11421       if (!strcmp(zone->name, user->zonetag)) {
11422          break;
11423       }
11424    }
11425    AST_LIST_UNLOCK(&zones);
11426 
11427    /* state */
11428    data_state = ast_data_add_node(data_user, "state");
11429    if (!data_state) {
11430       return -1;
11431    }
11432    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11433    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11434    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11435    ast_data_add_int(data_state, "newmsg", newmsg);
11436    ast_data_add_int(data_state, "oldmsg", oldmsg);
11437 
11438    if (zone) {
11439       data_zone = ast_data_add_node(data_user, "zone");
11440       ast_data_add_structure(vm_zone, data_zone, zone);
11441    }
11442 
11443    if (!ast_data_search_match(search, data_user)) {
11444       ast_data_remove_node(data_root, data_user);
11445    }
11446 
11447    return 0;
11448 }

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

Definition at line 11089 of file app_voicemail.c.

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

Referenced by load_module().

11090 {
11091    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11092    struct ast_vm_user vmus;
11093    char *options = NULL;
11094    int silent = 0, skipuser = 0;
11095    int res = -1;
11096    
11097    if (data) {
11098       s = ast_strdupa(data);
11099       user = strsep(&s, ",");
11100       options = strsep(&s, ",");
11101       if (user) {
11102          s = user;
11103          user = strsep(&s, "@");
11104          context = strsep(&s, "");
11105          if (!ast_strlen_zero(user))
11106             skipuser++;
11107          ast_copy_string(mailbox, user, sizeof(mailbox));
11108       }
11109    }
11110 
11111    if (options) {
11112       silent = (strchr(options, 's')) != NULL;
11113    }
11114 
11115    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11116       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11117       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11118       ast_play_and_wait(chan, "auth-thankyou");
11119       res = 0;
11120    } else if (mailbox[0] == '*') {
11121       /* user entered '*' */
11122       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11123          res = 0; /* prevent hangup */
11124       }
11125    }
11126 
11127    return res;
11128 }

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

Definition at line 12629 of file app_voicemail.c.

References ast_debug, AST_DIGIT_ANY, ast_log(), ast_say_character_str(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), LOG_WARNING, and sayname().

Referenced by load_module().

12630 {
12631    char *context;
12632    char *args_copy;
12633    int res;
12634 
12635    if (ast_strlen_zero(data)) {
12636       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12637       return -1;
12638    }
12639 
12640    args_copy = ast_strdupa(data);
12641    if ((context = strchr(args_copy, '@'))) {
12642       *context++ = '\0';
12643    } else {
12644       context = "default";
12645    }
12646 
12647    if ((res = sayname(chan, args_copy, context) < 0)) {
12648       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12649       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12650       if (!res) {
12651          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12652       }
12653    }
12654 
12655    return res;
12656 }

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.

Returns:
tm so it can be used as a function argument.

Definition at line 4448 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

04449 {
04450    const struct vm_zone *z = NULL;
04451    struct timeval t = ast_tvnow();
04452 
04453    /* Does this user have a timezone specified? */
04454    if (!ast_strlen_zero(vmu->zonetag)) {
04455       /* Find the zone in the list */
04456       AST_LIST_LOCK(&zones);
04457       AST_LIST_TRAVERSE(&zones, z, list) {
04458          if (!strcmp(z->name, vmu->zonetag))
04459             break;
04460       }
04461       AST_LIST_UNLOCK(&zones);
04462    }
04463    ast_localtime(&t, tm, z ? z->timezone : NULL);
04464    return tm;
04465 }

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

07496 {
07497    int res;
07498    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07499       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07500    return res;
07501 }

static int write_password_to_file ( const char *  secretfn,
const char *  password 
) [static]

Definition at line 12596 of file app_voicemail.c.

References ast_category_append(), ast_category_destroy(), ast_category_new(), ast_config_destroy(), ast_config_new(), ast_config_text_file_save(), ast_log(), ast_variable_append(), ast_variable_new(), and LOG_ERROR.

Referenced by vm_change_password().

12596                                                                               {
12597    struct ast_config *conf;
12598    struct ast_category *cat;
12599    struct ast_variable *var;
12600    int res = -1;
12601 
12602    if (!(conf = ast_config_new())) {
12603       ast_log(LOG_ERROR, "Error creating new config structure\n");
12604       return res;
12605    }
12606    if (!(cat = ast_category_new("general", "", 1))) {
12607       ast_log(LOG_ERROR, "Error creating new category structure\n");
12608       ast_config_destroy(conf);
12609       return res;
12610    }
12611    if (!(var = ast_variable_new("password", password, ""))) {
12612       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12613       ast_config_destroy(conf);
12614       ast_category_destroy(cat);
12615       return res;
12616    }
12617    ast_category_append(conf, cat);
12618    ast_variable_append(cat, var);
12619    if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12620       res = 0;
12621    } else {
12622       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12623    }
12624 
12625    ast_config_destroy(conf);
12626    return res;
12627 }


Variable Documentation

char* addesc = "Comedian Mail" [static]

Definition at line 776 of file app_voicemail.c.

Referenced by adsi_load_vmail().

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

Definition at line 903 of file app_voicemail.c.

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

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

Definition at line 904 of file app_voicemail.c.

Referenced by actual_load_config(), and adsi_load_vmail().

int adsiver = 1 [static]

Definition at line 905 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 779 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* app2 = "VoiceMailMain" [static]

Definition at line 782 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* app3 = "MailboxExists" [static]

Definition at line 784 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* app4 = "VMAuthenticate" [static]

Definition at line 785 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 889 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

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

Definition at line 892 of file app_voicemail.c.

Referenced by actual_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 11328 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char dialcontext[AST_MAX_CONTEXT] = "" [static]
char* emailbody = NULL [static]
char emaildateformat[32] = "%A, %B %d, %Y at %r" [static]

Definition at line 906 of file app_voicemail.c.

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

char* emailsubject = NULL [static]

Definition at line 896 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 890 of file app_voicemail.c.

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

char ext_pass_check_cmd[128] [static]

Definition at line 756 of file app_voicemail.c.

Referenced by actual_load_config(), and check_password().

char ext_pass_cmd[128] [static]
char externnotify[160] [static]

Definition at line 799 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

char fromstring[100] [static]

Definition at line 899 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

struct ast_flags globalflags = {0} [static]

Definition at line 928 of file app_voicemail.c.

Referenced by inprocess_count(), load_module(), and unload_module().

char listen_control_forward_key[12] [static]

Definition at line 857 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 859 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 860 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 858 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 861 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char locale[20] [static]

Definition at line 792 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

Initial value:
 {
   .name = "MAILBOX_EXISTS",
   .read = acf_mailbox_exists,
}

Definition at line 11084 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

const char* const mailbox_folders[] [static]

Definition at line 1718 of file app_voicemail.c.

Referenced by get_folder_by_name(), and mbox().

char mailcmd[160] [static]
int maxdeletedmsg [static]

Definition at line 795 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

int maxgreet [static]

Definition at line 805 of file app_voicemail.c.

Referenced by actual_load_config(), vm_newuser(), vm_options(), and vm_tempgreeting().

int maxlogins [static]

Definition at line 807 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_execmain().

int maxmsg [static]

Definition at line 794 of file app_voicemail.c.

Referenced by actual_load_config(), copy_message(), and populate_defaults().

int maxsilence [static]
int minpassword [static]

Definition at line 808 of file app_voicemail.c.

Referenced by actual_load_config(), and check_password().

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 826 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

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

Referenced by start_poll_thread(), and stop_poll_thread().

int my_umask [static]

Definition at line 758 of file app_voicemail.c.

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

char* pagerbody = NULL [static]

Definition at line 897 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

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

Definition at line 907 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 900 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 898 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

int passwordlocation [static]

Definition at line 809 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 821 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

unsigned int poll_freq [static]

Polling frequency

Definition at line 816 of file app_voicemail.c.

Referenced by actual_load_config(), and mb_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 813 of file app_voicemail.c.

Referenced by actual_load_config().

pthread_t poll_thread = AST_PTHREADT_NULL [static]
unsigned char poll_thread_run [static]

Definition at line 823 of file app_voicemail.c.

Referenced by mb_poll_thread(), start_poll_thread(), and stop_poll_thread().

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 762 of file app_voicemail.c.

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

int saydurationminfo [static]

Definition at line 886 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

char* sayname_app = "VMSayName" [static]

Definition at line 787 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char serveremail[80] [static]
int silencethreshold = 128 [static]
int skipms [static]
struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 800 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

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

Definition at line 774 of file app_voicemail.c.

Referenced by actual_load_config().

struct ast_data_entry vm_data_providers[] [static]
Initial value:
 {

}

Definition at line 11469 of file app_voicemail.c.

Referenced by load_module().

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

Definition at line 869 of file app_voicemail.c.

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

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

Definition at line 868 of file app_voicemail.c.

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

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

Definition at line 865 of file app_voicemail.c.

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

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

Definition at line 866 of file app_voicemail.c.

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

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

Definition at line 864 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_authenticate().

char vm_pls_try_again[80] = "vm-pls-try-again" [static]

Definition at line 870 of file app_voicemail.c.

Referenced by actual_load_config(), vm_forwardoptions(), vm_newuser(), and vm_options().

char vm_prepend_timeout[80] = "vm-then-pound" [static]

Definition at line 882 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_forwardoptions().

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

Definition at line 867 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]
Initial value:

Definition at line 11464 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 801 of file app_voicemail.c.

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

int vmmaxsecs [static]

Definition at line 804 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), and populate_defaults().

int vmminsecs [static]

Definition at line 803 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), and populate_defaults().

double volgain [static]

Definition at line 802 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

char zonetag[80] [static]

Definition at line 791 of file app_voicemail.c.

Referenced by actual_load_config(), build_peer(), and populate_defaults().


Generated on 29 Oct 2014 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1