Mon Mar 19 11:30:34 2012

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"

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  mwi_subs
struct  users
 list of users found in the config file More...
struct  vm_state
struct  vm_zone
struct  zones

Defines

#define ASTERISK_USERNAME   "asterisk"
#define BASELINELEN   72
#define BASEMAXINLINE   256
#define CHUNKSIZE   65536
#define COMMAND_TIMEOUT   5000
#define COPY(a, b, c, d, e, f, g, h)   (copy_plain_file(g,h));
#define 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 void __reg_module (void)
static void __unreg_module (void)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int 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_DATA_STRUCTURE (vm_zone, DATA_EXPORT_VM_ZONES)
 AST_DATA_STRUCTURE (ast_vm_user, DATA_EXPORT_VM_USERS)
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 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 struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", }
static char * addesc = "Comedian Mail"
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
static int adsiver = 1
static char * app = "VoiceMail"
static char * app2 = "VoiceMailMain"
static char * app3 = "MailboxExists"
static char * app4 = "VMAuthenticate"
static struct ast_module_infoast_module_info = &__mod_info
static char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char 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}
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 ast_mutex_t poll_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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_app_option vm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }}
static 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 430 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 453 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 454 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 427 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 423 of file app_voicemail.c.

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

Definition at line 741 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

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

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 435 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 437 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 438 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 436 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 439 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 811 of file app_voicemail.c.

Referenced by actual_load_config().

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

Definition at line 742 of file app_voicemail.c.

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

#define DISPOSE ( a,
 ) 

Definition at line 737 of file app_voicemail.c.

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

#define ENDL   "\n"

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

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

Definition at line 739 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"

Referenced by handle_voicemail_show_users().

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

Referenced by handle_voicemail_show_zones().

#define INTRO   "vm-intro"

Definition at line 446 of file app_voicemail.c.

Referenced by play_record_review(), and vm_forwardoptions().

#define MAX_DATETIME_FORMAT   512

Definition at line 461 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 462 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 448 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

#define MAXMSGLIMIT   9999

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

Referenced by actual_load_config().

#define OPERATOR_EXIT   300

Definition at line 484 of file app_voicemail.c.

Referenced by vm_exec(), and vm_execmain().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 754 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 753 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));

Definition at line 740 of file app_voicemail.c.

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

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 736 of file app_voicemail.c.

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

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

Definition at line 444 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 421 of file app_voicemail.c.

Referenced by run_externnotify().

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

Definition at line 738 of file app_voicemail.c.

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

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 763 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 440 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 477 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)

Attach message to voicemail notifications?

Definition at line 475 of file app_voicemail.c.

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

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 476 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 474 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 468 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 472 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 471 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 482 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 481 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 480 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 465 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 473 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 464 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 466 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 469 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 478 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 470 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 467 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 479 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 678 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 429 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 425 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 426 of file app_voicemail.c.

Referenced by add_email_attachment(), copy(), 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 487 of file app_voicemail.c.

00487             {
00488    NEW_FOLDER,
00489    OLD_FOLDER,
00490    WORK_FOLDER,
00491    FAMILY_FOLDER,
00492    FRIENDS_FOLDER,
00493    GREETINGS_FOLDER
00494 };

enum vm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 508 of file app_voicemail.c.

00508                     {
00509    OPT_ARG_RECORDGAIN = 0,
00510    OPT_ARG_PLAYFOLDER = 1,
00511    OPT_ARG_DTMFEXIT   = 2,
00512    /* This *must* be the last value in this enum! */
00513    OPT_ARG_ARRAY_SIZE = 3,
00514 };

enum vm_option_flags

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

00496                      {
00497    OPT_SILENT =           (1 << 0),
00498    OPT_BUSY_GREETING =    (1 << 1),
00499    OPT_UNAVAIL_GREETING = (1 << 2),
00500    OPT_RECORDGAIN =       (1 << 3),
00501    OPT_PREPEND_MAILBOX =  (1 << 4),
00502    OPT_AUTOPLAY =         (1 << 6),
00503    OPT_DTMFEXIT =         (1 << 7),
00504    OPT_MESSAGE_Urgent =   (1 << 8),
00505    OPT_MESSAGE_PRIORITY = (1 << 9)
00506 };

enum vm_passwordlocation

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 516 of file app_voicemail.c.

00516                          {
00517    OPT_PWLOC_VOICEMAILCONF = 0,
00518    OPT_PWLOC_SPOOLDIR      = 1,
00519    OPT_PWLOC_USERSCONF     = 2,
00520 };


Function Documentation

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

Definition at line 5372 of file app_voicemail.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

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

05373 {
05374    DIR *dir;
05375    struct dirent *de;
05376    char fn[256];
05377    int ret = 0;
05378 
05379    /* If no mailbox, return immediately */
05380    if (ast_strlen_zero(mailbox))
05381       return 0;
05382 
05383    if (ast_strlen_zero(folder))
05384       folder = "INBOX";
05385    if (ast_strlen_zero(context))
05386       context = "default";
05387 
05388    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05389 
05390    if (!(dir = opendir(fn)))
05391       return 0;
05392 
05393    while ((de = readdir(dir))) {
05394       if (!strncasecmp(de->d_name, "msg", 3)) {
05395          if (shortcircuit) {
05396             ret = 1;
05397             break;
05398          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05399             ret++;
05400          }
05401       }
05402    }
05403 
05404    closedir(dir);
05405 
05406    return ret;
05407 }

static void __reg_module ( void   )  [static]

Definition at line 13621 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

Definition at line 13621 of file app_voicemail.c.

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

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

11001 {
11002    struct ast_vm_user svm;
11003    AST_DECLARE_APP_ARGS(arg,
11004       AST_APP_ARG(mbox);
11005       AST_APP_ARG(context);
11006    );
11007 
11008    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11009 
11010    if (ast_strlen_zero(arg.mbox)) {
11011       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11012       return -1;
11013    }
11014 
11015    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11016    return 0;
11017 }

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

Definition at line 11821 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_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, 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(), vm_zone::list, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, locale, LOG_ERROR, mailcmd, MAX_NUM_CID_CONTEXTS, maxdeletedmsg, maxgreet, maxlogins, MAXMSG, maxmsg, MAXMSGLIMIT, maxsilence, MINPASSWORD, minpassword, vm_zone::msg_format, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, 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(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, userscontext, var, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_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().

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

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

04787 {
04788    char tmpdir[256], newtmp[256];
04789    char fname[256];
04790    char tmpcmd[256];
04791    int tmpfd = -1;
04792    int soxstatus = 0;
04793 
04794    /* Eww. We want formats to tell us their own MIME type */
04795    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04796 
04797    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04798       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04799       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04800       tmpfd = mkstemp(newtmp);
04801       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04802       ast_debug(3, "newtmp: %s\n", newtmp);
04803       if (tmpfd > -1) {
04804          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04805          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04806             attach = newtmp;
04807             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04808          } else {
04809             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04810                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04811             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04812          }
04813       }
04814    }
04815    fprintf(p, "--%s" ENDL, bound);
04816    if (msgnum > -1)
04817       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04818    else
04819       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04820    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04821    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04822    if (msgnum > -1)
04823       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04824    else
04825       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04826    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04827    base_encode(fname, p);
04828    if (last)
04829       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04830    if (tmpfd > -1) {
04831       if (soxstatus == 0) {
04832          unlink(fname);
04833       }
04834       close(tmpfd);
04835       unlink(newtmp);
04836    }
04837    return 0;
04838 }

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

Definition at line 6390 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

06391 {
06392    int x;
06393    if (!ast_adsi_available(chan))
06394       return;
06395    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06396    if (x < 0)
06397       return;
06398    if (!x) {
06399       if (adsi_load_vmail(chan, useadsi)) {
06400          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06401          return;
06402       }
06403    } else
06404       *useadsi = 1;
06405 }

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

Definition at line 6579 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available(), and vm_state::curmsg.

Referenced by vm_execmain().

06580 {
06581    int bytes = 0;
06582    unsigned char buf[256];
06583    unsigned char keys[8];
06584 
06585    int x;
06586 
06587    if (!ast_adsi_available(chan))
06588       return;
06589 
06590    /* New meaning for keys */
06591    for (x = 0; x < 5; x++)
06592       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06593 
06594    keys[6] = 0x0;
06595    keys[7] = 0x0;
06596 
06597    if (!vms->curmsg) {
06598       /* No prev key, provide "Folder" instead */
06599       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06600    }
06601    if (vms->curmsg >= vms->lastmsg) {
06602       /* If last message ... */
06603       if (vms->curmsg) {
06604          /* but not only message, provide "Folder" instead */
06605          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06606       } else {
06607          /* Otherwise if only message, leave blank */
06608          keys[3] = 1;
06609       }
06610    }
06611 
06612    /* If deleted, show "undeleted" */
06613    if (vms->deleted[vms->curmsg]) 
06614       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06615 
06616    /* Except "Exit" */
06617    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06618    bytes += ast_adsi_set_keys(buf + bytes, keys);
06619    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06620 
06621    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06622 }

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

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

06456 {
06457    unsigned char buf[256];
06458    int bytes = 0;
06459    unsigned char keys[8];
06460    int x, y;
06461 
06462    if (!ast_adsi_available(chan))
06463       return;
06464 
06465    for (x = 0; x < 5; x++) {
06466       y = ADSI_KEY_APPS + 12 + start + x;
06467       if (y > ADSI_KEY_APPS + 12 + 4)
06468          y = 0;
06469       keys[x] = ADSI_KEY_SKT | y;
06470    }
06471    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06472    keys[6] = 0;
06473    keys[7] = 0;
06474 
06475    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06476    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06477    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06478    bytes += ast_adsi_set_keys(buf + bytes, keys);
06479    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06480 
06481    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06482 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06728 {
06729    unsigned char buf[256];
06730    int bytes = 0;
06731 
06732    if (!ast_adsi_available(chan))
06733       return;
06734    bytes += adsi_logo(buf + bytes);
06735    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06736    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06737    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06738    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06739 
06740    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06741 }

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

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

06262 {
06263    unsigned char buf[256];
06264    int bytes = 0;
06265    int x;
06266    char num[5];
06267 
06268    *useadsi = 0;
06269    bytes += ast_adsi_data_mode(buf + bytes);
06270    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06271 
06272    bytes = 0;
06273    bytes += adsi_logo(buf);
06274    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06275 #ifdef DISPLAY
06276    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06277 #endif
06278    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06279    bytes += ast_adsi_data_mode(buf + bytes);
06280    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06281 
06282    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06283       bytes = 0;
06284       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06285       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06286       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06287       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06288       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06289       return 0;
06290    }
06291 
06292 #ifdef DISPLAY
06293    /* Add a dot */
06294    bytes = 0;
06295    bytes += ast_adsi_logo(buf);
06296    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06297    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06298    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06299    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06300 #endif
06301    bytes = 0;
06302    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06303    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06304    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06305    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06306    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06307    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06308    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06309 
06310 #ifdef DISPLAY
06311    /* Add another dot */
06312    bytes = 0;
06313    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06314    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06315 
06316    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06317    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06318 #endif
06319 
06320    bytes = 0;
06321    /* These buttons we load but don't use yet */
06322    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06323    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06324    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06325    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06326    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06327    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06328    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06329 
06330 #ifdef DISPLAY
06331    /* Add another dot */
06332    bytes = 0;
06333    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06334    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06335    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06336 #endif
06337 
06338    bytes = 0;
06339    for (x = 0; x < 5; x++) {
06340       snprintf(num, sizeof(num), "%d", x);
06341       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06342    }
06343    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06344    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06345 
06346 #ifdef DISPLAY
06347    /* Add another dot */
06348    bytes = 0;
06349    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06350    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06351    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06352 #endif
06353 
06354    if (ast_adsi_end_download(chan)) {
06355       bytes = 0;
06356       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06357       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06358       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06359       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06360       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06361       return 0;
06362    }
06363    bytes = 0;
06364    bytes += ast_adsi_download_disconnect(buf + bytes);
06365    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06366    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06367 
06368    ast_debug(1, "Done downloading scripts...\n");
06369 
06370 #ifdef DISPLAY
06371    /* Add last dot */
06372    bytes = 0;
06373    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06374    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06375 #endif
06376    ast_debug(1, "Restarting session...\n");
06377 
06378    bytes = 0;
06379    /* Load the session now */
06380    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06381       *useadsi = 1;
06382       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06383    } else
06384       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06385 
06386    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06387    return 0;
06388 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06408 {
06409    unsigned char buf[256];
06410    int bytes = 0;
06411    unsigned char keys[8];
06412    int x;
06413    if (!ast_adsi_available(chan))
06414       return;
06415 
06416    for (x = 0; x < 8; x++)
06417       keys[x] = 0;
06418    /* Set one key for next */
06419    keys[3] = ADSI_KEY_APPS + 3;
06420 
06421    bytes += adsi_logo(buf + bytes);
06422    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06423    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06424    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06425    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06426    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06427    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06428    bytes += ast_adsi_set_keys(buf + bytes, keys);
06429    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06430    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06431 }

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

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

06254 {
06255    int bytes = 0;
06256    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06257    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06258    return bytes;
06259 }

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

Definition at line 6484 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available(), ast_copy_string(), ast_strlen_zero(), buf1, buf2, vm_state::curmsg, vm_state::fn, name, and strsep().

Referenced by play_message(), and vm_execmain().

06485 {
06486    int bytes = 0;
06487    unsigned char buf[256]; 
06488    char buf1[256], buf2[256];
06489    char fn2[PATH_MAX];
06490 
06491    char cid[256] = "";
06492    char *val;
06493    char *name, *num;
06494    char datetime[21] = "";
06495    FILE *f;
06496 
06497    unsigned char keys[8];
06498 
06499    int x;
06500 
06501    if (!ast_adsi_available(chan))
06502       return;
06503 
06504    /* Retrieve important info */
06505    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06506    f = fopen(fn2, "r");
06507    if (f) {
06508       while (!feof(f)) {   
06509          if (!fgets((char *) buf, sizeof(buf), f)) {
06510             continue;
06511          }
06512          if (!feof(f)) {
06513             char *stringp = NULL;
06514             stringp = (char *) buf;
06515             strsep(&stringp, "=");
06516             val = strsep(&stringp, "=");
06517             if (!ast_strlen_zero(val)) {
06518                if (!strcmp((char *) buf, "callerid"))
06519                   ast_copy_string(cid, val, sizeof(cid));
06520                if (!strcmp((char *) buf, "origdate"))
06521                   ast_copy_string(datetime, val, sizeof(datetime));
06522             }
06523          }
06524       }
06525       fclose(f);
06526    }
06527    /* New meaning for keys */
06528    for (x = 0; x < 5; x++)
06529       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06530    keys[6] = 0x0;
06531    keys[7] = 0x0;
06532 
06533    if (!vms->curmsg) {
06534       /* No prev key, provide "Folder" instead */
06535       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06536    }
06537    if (vms->curmsg >= vms->lastmsg) {
06538       /* If last message ... */
06539       if (vms->curmsg) {
06540          /* but not only message, provide "Folder" instead */
06541          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06542          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06543 
06544       } else {
06545          /* Otherwise if only message, leave blank */
06546          keys[3] = 1;
06547       }
06548    }
06549 
06550    if (!ast_strlen_zero(cid)) {
06551       ast_callerid_parse(cid, &name, &num);
06552       if (!name)
06553          name = num;
06554    } else
06555       name = "Unknown Caller";
06556 
06557    /* If deleted, show "undeleted" */
06558 
06559    if (vms->deleted[vms->curmsg])
06560       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06561 
06562    /* Except "Exit" */
06563    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06564    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06565       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06566    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06567 
06568    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06569    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06570    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06571    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06572    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06573    bytes += ast_adsi_set_keys(buf + bytes, keys);
06574    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06575 
06576    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06577 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06434 {
06435    unsigned char buf[256];
06436    int bytes = 0;
06437    unsigned char keys[8];
06438    int x;
06439    if (!ast_adsi_available(chan))
06440       return;
06441 
06442    for (x = 0; x < 8; x++)
06443       keys[x] = 0;
06444    /* Set one key for next */
06445    keys[3] = ADSI_KEY_APPS + 3;
06446 
06447    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06448    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06449    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06450    bytes += ast_adsi_set_keys(buf + bytes, keys);
06451    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06452    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06453 }

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

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

06625 {
06626    unsigned char buf[256] = "";
06627    char buf1[256] = "", buf2[256] = "";
06628    int bytes = 0;
06629    unsigned char keys[8];
06630    int x;
06631 
06632    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06633    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06634    if (!ast_adsi_available(chan))
06635       return;
06636    if (vms->newmessages) {
06637       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06638       if (vms->oldmessages) {
06639          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06640          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06641       } else {
06642          snprintf(buf2, sizeof(buf2), "%s.", newm);
06643       }
06644    } else if (vms->oldmessages) {
06645       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06646       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06647    } else {
06648       strcpy(buf1, "You have no messages.");
06649       buf2[0] = ' ';
06650       buf2[1] = '\0';
06651    }
06652    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06653    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06654    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06655 
06656    for (x = 0; x < 6; x++)
06657       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06658    keys[6] = 0;
06659    keys[7] = 0;
06660 
06661    /* Don't let them listen if there are none */
06662    if (vms->lastmsg < 0)
06663       keys[0] = 1;
06664    bytes += ast_adsi_set_keys(buf + bytes, keys);
06665 
06666    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06667 
06668    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06669 }

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

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

06672 {
06673    unsigned char buf[256] = "";
06674    char buf1[256] = "", buf2[256] = "";
06675    int bytes = 0;
06676    unsigned char keys[8];
06677    int x;
06678 
06679    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06680 
06681    if (!ast_adsi_available(chan))
06682       return;
06683 
06684    /* Original command keys */
06685    for (x = 0; x < 6; x++)
06686       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06687 
06688    keys[6] = 0;
06689    keys[7] = 0;
06690 
06691    if ((vms->lastmsg + 1) < 1)
06692       keys[0] = 0;
06693 
06694    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06695       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06696 
06697    if (vms->lastmsg + 1)
06698       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06699    else
06700       strcpy(buf2, "no messages.");
06701    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06702    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06703    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06704    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06705    bytes += ast_adsi_set_keys(buf + bytes, keys);
06706 
06707    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06708 
06709    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06710    
06711 }

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

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_test_suite_event_notify, ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, config_flags, CONFIG_STATUS_FILEINVALID, 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(), RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

13184 {
13185    int res = 0;
13186    char filename[PATH_MAX];
13187    struct ast_config *msg_cfg = NULL;
13188    const char *origtime, *context;
13189    char *name, *num;
13190    int retries = 0;
13191    char *cid;
13192    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
13193 
13194    vms->starting = 0; 
13195 
13196    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13197 
13198    /* Retrieve info from VM attribute file */
13199    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
13200    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
13201    msg_cfg = ast_config_load(filename, config_flags);
13202    DISPOSE(vms->curdir, vms->curmsg);
13203    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
13204       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
13205       return 0;
13206    }
13207 
13208    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
13209       ast_config_destroy(msg_cfg);
13210       return 0;
13211    }
13212 
13213    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
13214 
13215    context = ast_variable_retrieve(msg_cfg, "message", "context");
13216    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
13217       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
13218    switch (option) {
13219    case 3: /* Play message envelope */
13220       if (!res)
13221          res = play_message_datetime(chan, vmu, origtime, filename);
13222       if (!res)
13223          res = play_message_callerid(chan, vms, cid, context, 0);
13224 
13225       res = 't';
13226       break;
13227 
13228    case 2:  /* Call back */
13229 
13230       if (ast_strlen_zero(cid))
13231          break;
13232 
13233       ast_callerid_parse(cid, &name, &num);
13234       while ((res > -1) && (res != 't')) {
13235          switch (res) {
13236          case '1':
13237             if (num) {
13238                /* Dial the CID number */
13239                res = dialout(chan, vmu, num, vmu->callback);
13240                if (res) {
13241                   ast_config_destroy(msg_cfg);
13242                   return 9;
13243                }
13244             } else {
13245                res = '2';
13246             }
13247             break;
13248 
13249          case '2':
13250             /* Want to enter a different number, can only do this if there's a dialout context for this user */
13251             if (!ast_strlen_zero(vmu->dialout)) {
13252                res = dialout(chan, vmu, NULL, vmu->dialout);
13253                if (res) {
13254                   ast_config_destroy(msg_cfg);
13255                   return 9;
13256                }
13257             } else {
13258                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
13259                res = ast_play_and_wait(chan, "vm-sorry");
13260             }
13261             ast_config_destroy(msg_cfg);
13262             return res;
13263          case '*':
13264             res = 't';
13265             break;
13266          case '3':
13267          case '4':
13268          case '5':
13269          case '6':
13270          case '7':
13271          case '8':
13272          case '9':
13273          case '0':
13274 
13275             res = ast_play_and_wait(chan, "vm-sorry");
13276             retries++;
13277             break;
13278          default:
13279             if (num) {
13280                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
13281                res = ast_play_and_wait(chan, "vm-num-i-have");
13282                if (!res)
13283                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
13284                if (!res)
13285                   res = ast_play_and_wait(chan, "vm-tocallnum");
13286                /* Only prompt for a caller-specified number if there is a dialout context specified */
13287                if (!ast_strlen_zero(vmu->dialout)) {
13288                   if (!res)
13289                      res = ast_play_and_wait(chan, "vm-calldiffnum");
13290                }
13291             } else {
13292                res = ast_play_and_wait(chan, "vm-nonumber");
13293                if (!ast_strlen_zero(vmu->dialout)) {
13294                   if (!res)
13295                      res = ast_play_and_wait(chan, "vm-toenternumber");
13296                }
13297             }
13298             if (!res) {
13299                res = ast_play_and_wait(chan, "vm-star-cancel");
13300             }
13301             if (!res) {
13302                res = ast_waitfordigit(chan, 6000);
13303             }
13304             if (!res) {
13305                retries++;
13306                if (retries > 3) {
13307                   res = 't';
13308                }
13309             }
13310             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
13311             break; 
13312             
13313          }
13314          if (res == 't')
13315             res = 0;
13316          else if (res == '*')
13317             res = -1;
13318       }
13319       break;
13320       
13321    case 1:  /* Reply */
13322       /* Send reply directly to sender */
13323       if (ast_strlen_zero(cid))
13324          break;
13325 
13326       ast_callerid_parse(cid, &name, &num);
13327       if (!num) {
13328          ast_verb(3, "No CID number available, no reply sent\n");
13329          if (!res)
13330             res = ast_play_and_wait(chan, "vm-nonumber");
13331          ast_config_destroy(msg_cfg);
13332          return res;
13333       } else {
13334          struct ast_vm_user vmu2;
13335          if (find_user(&vmu2, vmu->context, num)) {
13336             struct leave_vm_options leave_options;
13337             char mailbox[AST_MAX_EXTENSION * 2 + 2];
13338             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
13339 
13340             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
13341             
13342             memset(&leave_options, 0, sizeof(leave_options));
13343             leave_options.record_gain = record_gain;
13344             res = leave_voicemail(chan, mailbox, &leave_options);
13345             if (!res)
13346                res = 't';
13347             ast_config_destroy(msg_cfg);
13348             return res;
13349          } else {
13350             /* Sender has no mailbox, can't reply */
13351             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
13352             ast_play_and_wait(chan, "vm-nobox");
13353             res = 't';
13354             ast_config_destroy(msg_cfg);
13355             return res;
13356          }
13357       } 
13358       res = 0;
13359 
13360       break;
13361    }
13362 
13363 #ifndef IMAP_STORAGE
13364    ast_config_destroy(msg_cfg);
13365 
13366    if (!res) {
13367       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13368       vms->heard[msg] = 1;
13369       res = wait_file(chan, vms, vms->fn);
13370    }
13371 #endif
13372    return res;
13373 }

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

Definition at line 10727 of file app_voicemail.c.

References apply_options(), 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(), strsep(), and VM_SPOOL_DIR.

Referenced by actual_load_config().

10728 {
10729    /* Assumes lock is already held */
10730    char *tmp;
10731    char *stringp;
10732    char *s;
10733    struct ast_vm_user *vmu;
10734    char *mailbox_full;
10735    int new = 0, old = 0, urgent = 0;
10736    char secretfn[PATH_MAX] = "";
10737 
10738    tmp = ast_strdupa(data);
10739 
10740    if (!(vmu = find_or_create(context, box)))
10741       return -1;
10742 
10743    populate_defaults(vmu);
10744 
10745    stringp = tmp;
10746    if ((s = strsep(&stringp, ","))) {
10747       if (!ast_strlen_zero(s) && s[0] == '*') {
10748          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10749             "\n\tmust be reset in voicemail.conf.\n", box);
10750       }
10751       /* assign password regardless of validity to prevent NULL password from being assigned */
10752       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10753    }
10754    if (stringp && (s = strsep(&stringp, ","))) {
10755       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10756    }
10757    if (stringp && (s = strsep(&stringp, ","))) {
10758       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10759    }
10760    if (stringp && (s = strsep(&stringp, ","))) {
10761       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10762    }
10763    if (stringp && (s = strsep(&stringp, ","))) {
10764       apply_options(vmu, s);
10765    }
10766 
10767    switch (vmu->passwordlocation) {
10768    case OPT_PWLOC_SPOOLDIR:
10769       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10770       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10771    }
10772 
10773    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10774    strcpy(mailbox_full, box);
10775    strcat(mailbox_full, "@");
10776    strcat(mailbox_full, context);
10777 
10778    inboxcount2(mailbox_full, &urgent, &new, &old);
10779    queue_mwi_event(mailbox_full, urgent, new, old);
10780 
10781    return 0;
10782 }

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 1056 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, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by apply_options().

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

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

Destructively Parse options and apply.

Definition at line 1297 of file app_voicemail.c.

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

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

01298 {  
01299    char *stringp;
01300    char *s;
01301    char *var, *value;
01302    stringp = ast_strdupa(options);
01303    while ((s = strsep(&stringp, "|"))) {
01304       value = s;
01305       if ((var = strsep(&value, "=")) && value) {
01306          apply_option(vmu, var, value);
01307       }
01308    }  
01309 }

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

References ast_copy_string(), ast_log(), ast_strlen_zero(), LOG_WARNING, ast_vm_user::mailbox, ast_vm_user::password, and var.

Referenced by actual_load_config(), and find_user_realtime().

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

AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)

AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)

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

04462 {
04463    struct ast_str *tmp = ast_str_alloca(80);
04464    int first_section = 1;
04465 
04466    ast_str_reset(*end);
04467    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04468    for (; *start; start++) {
04469       int need_encoding = 0;
04470       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04471          need_encoding = 1;
04472       }
04473       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04474          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04475          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04476          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04477          /* Start new line */
04478          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04479          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04480          first_section = 0;
04481       }
04482       if (need_encoding && *start == ' ') {
04483          ast_str_append(&tmp, -1, "_");
04484       } else if (need_encoding) {
04485          ast_str_append(&tmp, -1, "=%hhX", *start);
04486       } else {
04487          ast_str_append(&tmp, -1, "%c", *start);
04488       }
04489    }
04490    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04491    return ast_str_buffer(*end);
04492 }

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

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

04390 {
04391    const char *ptr;
04392 
04393    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04394    ast_str_set(buf, maxlen, "\"");
04395    for (ptr = from; *ptr; ptr++) {
04396       if (*ptr == '"' || *ptr == '\\') {
04397          ast_str_append(buf, maxlen, "\\%c", *ptr);
04398       } else {
04399          ast_str_append(buf, maxlen, "%c", *ptr);
04400       }
04401    }
04402    ast_str_append(buf, maxlen, "\"");
04403 
04404    return ast_str_buffer(*buf);
04405 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10784 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, free_user(), OPT_PWLOC_SPOOLDIR, populate_defaults(), 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, and VM_TEMPGREETWARN.

10785 {
10786    int res = 0;
10787    struct ast_vm_user *vmu;
10788    /* language parameter seems to only be used for display in manager action */
10789    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10790       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10791       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10792       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10793       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10794       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10795       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
10796       "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
10797       "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
10798 #ifdef IMAP_STORAGE
10799    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10800       "imapfolder=INBOX|imapvmshareid=6000";
10801 #endif
10802 
10803    switch (cmd) {
10804    case TEST_INIT:
10805       info->name = "vmuser";
10806       info->category = "/apps/app_voicemail/";
10807       info->summary = "Vmuser unit test";
10808       info->description =
10809          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10810       return AST_TEST_NOT_RUN;
10811    case TEST_EXECUTE:
10812       break;
10813    }
10814 
10815    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10816       return AST_TEST_NOT_RUN;
10817    }
10818    ast_set_flag(vmu, VM_ALLOCED);
10819    populate_defaults(vmu);
10820 
10821    apply_options(vmu, options_string);
10822 
10823    if (!ast_test_flag(vmu, VM_ATTACH)) {
10824       ast_test_status_update(test, "Parse failure for attach option\n");
10825       res = 1;
10826    }
10827    if (strcasecmp(vmu->attachfmt, "wav49")) {
10828       ast_test_status_update(test, "Parse failure for attachftm option\n");
10829       res = 1;
10830    }
10831    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10832       ast_test_status_update(test, "Parse failure for serveremail option\n");
10833       res = 1;
10834    }
10835    if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
10836       ast_test_status_update(test, "Parse failure for emailsubject option\n");
10837       res = 1;
10838    }
10839    if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
10840       ast_test_status_update(test, "Parse failure for emailbody option\n");
10841       res = 1;
10842    }
10843    if (strcasecmp(vmu->zonetag, "central")) {
10844       ast_test_status_update(test, "Parse failure for tz option\n");
10845       res = 1;
10846    }
10847    if (!ast_test_flag(vmu, VM_DELETE)) {
10848       ast_test_status_update(test, "Parse failure for delete option\n");
10849       res = 1;
10850    }
10851    if (!ast_test_flag(vmu, VM_SAYCID)) {
10852       ast_test_status_update(test, "Parse failure for saycid option\n");
10853       res = 1;
10854    }
10855    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10856       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10857       res = 1;
10858    }
10859    if (!ast_test_flag(vmu, VM_REVIEW)) {
10860       ast_test_status_update(test, "Parse failure for review option\n");
10861       res = 1;
10862    }
10863    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10864       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10865       res = 1;
10866    }
10867    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10868       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10869       res = 1;
10870    }
10871    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10872       ast_test_status_update(test, "Parse failure for operator option\n");
10873       res = 1;
10874    }
10875    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10876       ast_test_status_update(test, "Parse failure for envelope option\n");
10877       res = 1;
10878    }
10879    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10880       ast_test_status_update(test, "Parse failure for moveheard option\n");
10881       res = 1;
10882    }
10883    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10884       ast_test_status_update(test, "Parse failure for sayduration option\n");
10885       res = 1;
10886    }
10887    if (vmu->saydurationm != 5) {
10888       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10889       res = 1;
10890    }
10891    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10892       ast_test_status_update(test, "Parse failure for forcename option\n");
10893       res = 1;
10894    }
10895    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10896       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10897       res = 1;
10898    }
10899    if (strcasecmp(vmu->callback, "somecontext")) {
10900       ast_test_status_update(test, "Parse failure for callbacks option\n");
10901       res = 1;
10902    }
10903    if (strcasecmp(vmu->dialout, "somecontext2")) {
10904       ast_test_status_update(test, "Parse failure for dialout option\n");
10905       res = 1;
10906    }
10907    if (strcasecmp(vmu->exit, "somecontext3")) {
10908       ast_test_status_update(test, "Parse failure for exitcontext option\n");
10909       res = 1;
10910    }
10911    if (vmu->minsecs != 10) {
10912       ast_test_status_update(test, "Parse failure for minsecs option\n");
10913       res = 1;
10914    }
10915    if (vmu->maxsecs != 100) {
10916       ast_test_status_update(test, "Parse failure for maxsecs option\n");
10917       res = 1;
10918    }
10919    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10920       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10921       res = 1;
10922    }
10923    if (vmu->maxdeletedmsg != 50) {
10924       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10925       res = 1;
10926    }
10927    if (vmu->volgain != 1.3) {
10928       ast_test_status_update(test, "Parse failure for volgain option\n");
10929       res = 1;
10930    }
10931    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10932       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10933       res = 1;
10934    }
10935 #ifdef IMAP_STORAGE
10936    apply_options(vmu, option_string2);
10937 
10938    if (strcasecmp(vmu->imapuser, "imapuser")) {
10939       ast_test_status_update(test, "Parse failure for imapuser option\n");
10940       res = 1;
10941    }
10942    if (strcasecmp(vmu->imappassword, "imappasswd")) {
10943       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10944       res = 1;
10945    }
10946    if (strcasecmp(vmu->imapfolder, "INBOX")) {
10947       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10948       res = 1;
10949    }
10950    if (strcasecmp(vmu->imapvmshareid, "6000")) {
10951       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
10952       res = 1;
10953    }
10954 #endif
10955 
10956    free_user(vmu);
10957    return res ? AST_TEST_FAIL : AST_TEST_PASS;
10958 }

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

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

04266 {
04267    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04268       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04269       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04270       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04271    int i, hiteof = 0;
04272    FILE *fi;
04273    struct baseio bio;
04274 
04275    memset(&bio, 0, sizeof(bio));
04276    bio.iocp = BASEMAXINLINE;
04277 
04278    if (!(fi = fopen(filename, "rb"))) {
04279       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04280       return -1;
04281    }
04282 
04283    while (!hiteof){
04284       unsigned char igroup[3], ogroup[4];
04285       int c, n;
04286 
04287       memset(igroup, 0, sizeof(igroup));
04288 
04289       for (n = 0; n < 3; n++) {
04290          if ((c = inchar(&bio, fi)) == EOF) {
04291             hiteof = 1;
04292             break;
04293          }
04294 
04295          igroup[n] = (unsigned char) c;
04296       }
04297 
04298       if (n > 0) {
04299          ogroup[0]= dtable[igroup[0] >> 2];
04300          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04301          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04302          ogroup[3]= dtable[igroup[2] & 0x3F];
04303 
04304          if (n < 3) {
04305             ogroup[3] = '=';
04306 
04307             if (n < 2)
04308                ogroup[2] = '=';
04309          }
04310 
04311          for (i = 0; i < 4; i++)
04312             ochar(&bio, ogroup[i], so);
04313       }
04314    }
04315 
04316    fclose(fi);
04317    
04318    if (fputs(ENDL, so) == EOF) {
04319       return 0;
04320    }
04321 
04322    return 1;
04323 }

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

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

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

04435 {
04436    for (; *str; str++) {
04437       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04438          return 1;
04439       }
04440    }
04441    return 0;
04442 }

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 1234 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, ast_vm_user::mailbox, ast_vm_user::password, and vm_check_password_shell().

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

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

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

Definition at line 7930 of file app_voicemail.c.

References ast_check_realtime(), ast_log(), AST_LOG_NOTICE, ast_test_flag, ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, DELETE, vm_state::deleted, ERROR_LOCK_PATH, EXISTS, vm_state::fn, vm_state::heard, 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().

07931 {
07932    int x = 0;
07933 
07934 #ifndef IMAP_STORAGE
07935    int last_msg_idx;
07936    int res = 0, nummsg;
07937    char fn2[PATH_MAX];
07938 #endif
07939 
07940    if (vms->lastmsg <= -1) {
07941       goto done;
07942    }
07943 
07944    vms->curmsg = -1;
07945 #ifndef IMAP_STORAGE
07946    /* Get the deleted messages fixed */
07947    if (vm_lock_path(vms->curdir)) {
07948       return ERROR_LOCK_PATH;
07949    }
07950 
07951    /* update count as message may have arrived while we've got mailbox open */
07952    last_msg_idx = last_message_index(vmu, vms->curdir);
07953    if (last_msg_idx != vms->lastmsg) {
07954       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
07955    }
07956 
07957    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07958    for (x = 0; x < last_msg_idx + 1; x++) {
07959       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07960          /* Save this message.  It's not in INBOX or hasn't been heard */
07961          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07962          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07963             break;
07964          }
07965          vms->curmsg++;
07966          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07967          if (strcmp(vms->fn, fn2)) {
07968             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07969          }
07970       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07971          /* Move to old folder before deleting */
07972          res = save_to_folder(vmu, vms, x, 1);
07973          if (res == ERROR_LOCK_PATH) {
07974             /* If save failed do not delete the message */
07975             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07976             vms->deleted[x] = 0;
07977             vms->heard[x] = 0;
07978             --x;
07979          }
07980       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07981          /* Move to deleted folder */
07982          res = save_to_folder(vmu, vms, x, 10);
07983          if (res == ERROR_LOCK_PATH) {
07984             /* If save failed do not delete the message */
07985             vms->deleted[x] = 0;
07986             vms->heard[x] = 0;
07987             --x;
07988          }
07989       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07990          /* If realtime storage enabled - we should explicitly delete this message,
07991          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07992          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07993          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07994             DELETE(vms->curdir, x, vms->fn, vmu);
07995          }
07996       }
07997    }
07998 
07999    /* Delete ALL remaining messages */
08000    nummsg = x - 1;
08001    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08002       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08003       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08004          DELETE(vms->curdir, x, vms->fn, vmu);
08005       }
08006    }
08007    ast_unlock_path(vms->curdir);
08008 #else /* defined(IMAP_STORAGE) */
08009    if (vms->deleted) {
08010       /* Since we now expunge after each delete, deleting in reverse order
08011        * ensures that no reordering occurs between each step. */
08012       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
08013          if (vms->deleted[x]) {
08014             ast_debug(3, "IMAP delete of %d\n", x);
08015             DELETE(vms->curdir, x, vms->fn, vmu);
08016          }
08017       }
08018    }
08019 #endif
08020 
08021 done:
08022    if (vms->deleted && vmu->maxmsg) {
08023       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
08024    }
08025    if (vms->heard && vmu->maxmsg) {
08026       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
08027    }
08028 
08029    return 0;
08030 }

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

Definition at line 11104 of file app_voicemail.c.

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

Referenced by handle_voicemail_show_users().

11105 {
11106    int which = 0;
11107    int wordlen;
11108    struct ast_vm_user *vmu;
11109    const char *context = "";
11110 
11111    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11112    if (pos > 4)
11113       return NULL;
11114    if (pos == 3)
11115       return (state == 0) ? ast_strdup("for") : NULL;
11116    wordlen = strlen(word);
11117    AST_LIST_TRAVERSE(&users, vmu, list) {
11118       if (!strncasecmp(word, vmu->context, wordlen)) {
11119          if (context && strcmp(context, vmu->context) && ++which > state)
11120             return ast_strdup(vmu->context);
11121          /* ignore repeated contexts ? */
11122          context = vmu->context;
11123       }
11124    }
11125    return NULL;
11126 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

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

04070 {
04071    int ifd;
04072    int ofd;
04073    int res;
04074    int len;
04075    char buf[4096];
04076 
04077 #ifdef HARDLINK_WHEN_POSSIBLE
04078    /* Hard link if possible; saves disk space & is faster */
04079    if (link(infile, outfile)) {
04080 #endif
04081       if ((ifd = open(infile, O_RDONLY)) < 0) {
04082          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04083          return -1;
04084       }
04085       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04086          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04087          close(ifd);
04088          return -1;
04089       }
04090       do {
04091          len = read(ifd, buf, sizeof(buf));
04092          if (len < 0) {
04093             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04094             close(ifd);
04095             close(ofd);
04096             unlink(outfile);
04097          }
04098          if (len) {
04099             res = write(ofd, buf, len);
04100             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04101                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04102                close(ifd);
04103                close(ofd);
04104                unlink(outfile);
04105             }
04106          }
04107       } while (len);
04108       close(ifd);
04109       close(ofd);
04110       return 0;
04111 #ifdef HARDLINK_WHEN_POSSIBLE
04112    } else {
04113       /* Hard link succeeded */
04114       return 0;
04115    }
04116 #endif
04117 }

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 5306 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(), ast_channel::language, 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().

05307 {
05308    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05309    const char *frombox = mbox(vmu, imbox);
05310    const char *userfolder;
05311    int recipmsgnum;
05312    int res = 0;
05313 
05314    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05315 
05316    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05317       userfolder = "Urgent";
05318    } else {
05319       userfolder = "INBOX";
05320    }
05321 
05322    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05323 
05324    if (!dir)
05325       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05326    else
05327       ast_copy_string(fromdir, dir, sizeof(fromdir));
05328 
05329    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05330    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05331 
05332    if (vm_lock_path(todir))
05333       return ERROR_LOCK_PATH;
05334 
05335    recipmsgnum = last_message_index(recip, todir) + 1;
05336    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05337       make_file(topath, sizeof(topath), todir, recipmsgnum);
05338 #ifndef ODBC_STORAGE
05339       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05340          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05341       } else {
05342 #endif
05343          /* If we are prepending a message for ODBC, then the message already
05344           * exists in the database, but we want to force copying from the
05345           * filesystem (since only the FS contains the prepend). */
05346          copy_plain_file(frompath, topath);
05347          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05348          vm_delete(topath);
05349 #ifndef ODBC_STORAGE
05350       }
05351 #endif
05352    } else {
05353       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05354       res = -1;
05355    }
05356    ast_unlock_path(todir);
05357    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05358       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05359       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05360       flag);
05361    
05362    return res;
05363 }

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

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

Referenced by copy_message().

04129 {
04130    char frompath2[PATH_MAX], topath2[PATH_MAX];
04131    struct ast_variable *tmp,*var = NULL;
04132    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04133    ast_filecopy(frompath, topath, NULL);
04134    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04135    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04136    if (ast_check_realtime("voicemail_data")) {
04137       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04138       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04139       for (tmp = var; tmp; tmp = tmp->next) {
04140          if (!strcasecmp(tmp->name, "origmailbox")) {
04141             origmailbox = tmp->value;
04142          } else if (!strcasecmp(tmp->name, "context")) {
04143             context = tmp->value;
04144          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04145             macrocontext = tmp->value;
04146          } else if (!strcasecmp(tmp->name, "exten")) {
04147             exten = tmp->value;
04148          } else if (!strcasecmp(tmp->name, "priority")) {
04149             priority = tmp->value;
04150          } else if (!strcasecmp(tmp->name, "callerchan")) {
04151             callerchan = tmp->value;
04152          } else if (!strcasecmp(tmp->name, "callerid")) {
04153             callerid = tmp->value;
04154          } else if (!strcasecmp(tmp->name, "origdate")) {
04155             origdate = tmp->value;
04156          } else if (!strcasecmp(tmp->name, "origtime")) {
04157             origtime = tmp->value;
04158          } else if (!strcasecmp(tmp->name, "category")) {
04159             category = tmp->value;
04160          } else if (!strcasecmp(tmp->name, "duration")) {
04161             duration = tmp->value;
04162          }
04163       }
04164       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);
04165    }
04166    copy(frompath2, topath2);
04167    ast_variables_destroy(var);
04168 }

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

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

Referenced by manager_list_voicemail_users(), and open_mailbox().

03965 {
03966 
03967    int vmcount = 0;
03968    DIR *vmdir = NULL;
03969    struct dirent *vment = NULL;
03970 
03971    if (vm_lock_path(dir))
03972       return ERROR_LOCK_PATH;
03973 
03974    if ((vmdir = opendir(dir))) {
03975       while ((vment = readdir(vmdir))) {
03976          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03977             vmcount++;
03978          }
03979       }
03980       closedir(vmdir);
03981    }
03982    ast_unlock_path(dir);
03983    
03984    return vmcount;
03985 }

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

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

01682 {
01683    mode_t   mode = VOICEMAIL_DIR_MODE;
01684    int res;
01685 
01686    make_dir(dest, len, context, ext, folder);
01687    if ((res = ast_mkdir(dest, mode))) {
01688       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01689       return -1;
01690    }
01691    return 0;
01692 }

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

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

13111 {
13112    int cmd = 0;
13113    char destination[80] = "";
13114    int retries = 0;
13115 
13116    if (!num) {
13117       ast_verb(3, "Destination number will be entered manually\n");
13118       while (retries < 3 && cmd != 't') {
13119          destination[1] = '\0';
13120          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13121          if (!cmd)
13122             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13123          if (!cmd)
13124             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13125          if (!cmd) {
13126             cmd = ast_waitfordigit(chan, 6000);
13127             if (cmd)
13128                destination[0] = cmd;
13129          }
13130          if (!cmd) {
13131             retries++;
13132          } else {
13133 
13134             if (cmd < 0)
13135                return 0;
13136             if (cmd == '*') {
13137                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13138                return 0;
13139             }
13140             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13141                retries++;
13142             else
13143                cmd = 't';
13144          }
13145          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13146       }
13147       if (retries >= 3) {
13148          return 0;
13149       }
13150       
13151    } else {
13152       if (option_verbose > 2)
13153          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13154       ast_copy_string(destination, num, sizeof(destination));
13155    }
13156 
13157    if (!ast_strlen_zero(destination)) {
13158       if (destination[strlen(destination) -1 ] == '*')
13159          return 0; 
13160       if (option_verbose > 2)
13161          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13162       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13163       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13164       chan->priority = 0;
13165       return 9;
13166    }
13167    return 0;
13168 }

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

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

Referenced by actual_load_config(), and append_mailbox().

10688 {
10689    struct ast_vm_user *vmu;
10690 
10691    if (!ast_strlen_zero(box) && box[0] == '*') {
10692       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10693             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10694             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10695             "\n\tand will be ignored.\n", box, context);
10696       return NULL;
10697    }
10698 
10699    AST_LIST_TRAVERSE(&users, vmu, list) {
10700       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10701          if (strcasecmp(vmu->context, context)) {
10702             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10703                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10704                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10705                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10706          }
10707          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10708          return NULL;
10709       }
10710       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10711          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10712          return NULL;
10713       }
10714    }
10715    
10716    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10717       return NULL;
10718    
10719    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10720    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10721 
10722    AST_LIST_INSERT_TAIL(&users, vmu, list);
10723    
10724    return vmu;
10725 }

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

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

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

Definition at line 1433 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, find_user_realtime(), globalflags, ast_vm_user::list, VM_ALLOCED, and VM_SEARCH.

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

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

Finds a voicemail user from the realtime engine.

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

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

01397 {
01398    struct ast_variable *var;
01399    struct ast_vm_user *retval;
01400 
01401    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01402       if (!ivm)
01403          ast_set_flag(retval, VM_ALLOCED);   
01404       else
01405          memset(retval, 0, sizeof(*retval));
01406       if (mailbox) 
01407          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01408       populate_defaults(retval);
01409       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01410          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01411       else
01412          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01413       if (var) {
01414          apply_options_full(retval, var);
01415          ast_variables_destroy(var);
01416       } else { 
01417          if (!ivm) 
01418             free_user(retval);
01419          retval = NULL;
01420       }  
01421    } 
01422    return retval;
01423 }

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

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

Returns:
zero on success, -1 on error.

Definition at line 7135 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_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(), free_user(), globalflags, ast_party_caller::id, inboxcount(), inprocess_count(), ast_channel::language, leave_voicemail(), ast_app::list, 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, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), serveremail, STORE, ast_party_name::str, ast_party_number::str, strsep(), 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().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1736 of file app_voicemail.c.

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

01737 {
01738    if (ast_test_flag(vmu, VM_ALLOCED)) {
01739 
01740       ast_free(vmu->emailbody);
01741       vmu->emailbody = NULL;
01742 
01743       ast_free(vmu->emailsubject);
01744       vmu->emailsubject = NULL;
01745 
01746       ast_free(vmu);
01747    }
01748 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11703 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11704 {
11705    struct ast_vm_user *current;
11706    AST_LIST_LOCK(&users);
11707    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11708       ast_set_flag(current, VM_ALLOCED);
11709       free_user(current);
11710    }
11711    AST_LIST_UNLOCK(&users);
11712 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11715 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11716 {
11717    struct vm_zone *zcur;
11718    AST_LIST_LOCK(&zones);
11719    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11720       free_zone(zcur);
11721    AST_LIST_UNLOCK(&zones);
11722 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5074 of file app_voicemail.c.

References ast_free.

05075 {
05076    ast_free(z);
05077 }

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

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

05031 {
05032    struct ast_tm tm;
05033    struct timeval t = ast_tvnow();
05034    
05035    ast_localtime(&t, &tm, "UTC");
05036 
05037    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05038 }

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 6747 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(), ast_channel::language, mbox(), and vm_play_folder_name().

Referenced by get_folder2().

06748 {
06749    int x;
06750    int d;
06751    char fn[PATH_MAX];
06752    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06753    if (d)
06754       return d;
06755    for (x = start; x < 5; x++) { /* For all folders */
06756       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06757          return d;
06758       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06759       if (d)
06760          return d;
06761       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06762 
06763       /* The inbox folder can have its name changed under certain conditions
06764        * so this checks if the sound file exists for the inbox folder name and
06765        * if it doesn't, plays the default name instead. */
06766       if (x == 0) {
06767          if (ast_fileexists(fn, NULL, NULL)) {
06768             d = vm_play_folder_name(chan, fn);
06769          } else {
06770             ast_verb(1, "failed to find %s\n", fn);
06771             d = vm_play_folder_name(chan, "vm-INBOX");
06772          }
06773       } else {
06774          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06775          d = vm_play_folder_name(chan, fn);
06776       }
06777 
06778       if (d)
06779          return d;
06780       d = ast_waitfordigit(chan, 500);
06781       if (d)
06782          return d;
06783    }
06784 
06785    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06786    if (d)
06787       return d;
06788    d = ast_waitfordigit(chan, 4000);
06789    return d;
06790 }

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

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

Referenced by vm_execmain().

06805 {
06806    int res = 0;
06807    int loops = 0;
06808 
06809    res = ast_play_and_wait(chan, fn);  /* Folder name */
06810    while (((res < '0') || (res > '9')) &&
06811          (res != '#') && (res >= 0) &&
06812          loops < 4) {
06813       res = get_folder(chan, 0);
06814       loops++;
06815    }
06816    if (loops == 4) { /* give up */
06817       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06818       return '#';
06819    }
06820    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06821    return res;
06822 }

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

Definition at line 1723 of file app_voicemail.c.

References ARRAY_LEN.

Referenced by vm_execmain().

01724 {
01725    size_t i;
01726 
01727    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01728       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01729          return i;
01730       }
01731    }
01732 
01733    return -1;
01734 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11486 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, mwi_sub, poll_subscribed_mailbox(), mwi_sub_task::uniqueid, and ast_event_sub::uniqueid.

Referenced by mwi_sub_event_cb().

11487 {
11488    unsigned int len;
11489    struct mwi_sub *mwi_sub;
11490    struct mwi_sub_task *p = datap;
11491 
11492    len = sizeof(*mwi_sub);
11493    if (!ast_strlen_zero(p->mailbox))
11494       len += strlen(p->mailbox);
11495 
11496    if (!ast_strlen_zero(p->context))
11497       len += strlen(p->context) + 1; /* Allow for seperator */
11498 
11499    if (!(mwi_sub = ast_calloc(1, len)))
11500       return -1;
11501 
11502    mwi_sub->uniqueid = p->uniqueid;
11503    if (!ast_strlen_zero(p->mailbox))
11504       strcpy(mwi_sub->mailbox, p->mailbox);
11505 
11506    if (!ast_strlen_zero(p->context)) {
11507       strcat(mwi_sub->mailbox, "@");
11508       strcat(mwi_sub->mailbox, p->context);
11509    }
11510 
11511    AST_RWLIST_WRLOCK(&mwi_subs);
11512    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11513    AST_RWLIST_UNLOCK(&mwi_subs);
11514    ast_free((void *) p->mailbox);
11515    ast_free((void *) p->context);
11516    ast_free(p);
11517    poll_subscribed_mailbox(mwi_sub);
11518    return 0;
11519 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11464 of file app_voicemail.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, mwi_sub::entry, mwi_sub, mwi_sub_destroy(), ast_event_sub::uniqueid, and mwi_sub::uniqueid.

Referenced by mwi_unsub_event_cb().

11465 {
11466    struct mwi_sub *mwi_sub;
11467    uint32_t *uniqueid = datap;
11468    
11469    AST_RWLIST_WRLOCK(&mwi_subs);
11470    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11471       if (mwi_sub->uniqueid == *uniqueid) {
11472          AST_LIST_REMOVE_CURRENT(entry);
11473          break;
11474       }
11475    }
11476    AST_RWLIST_TRAVERSE_SAFE_END
11477    AST_RWLIST_UNLOCK(&mwi_subs);
11478 
11479    if (mwi_sub)
11480       mwi_sub_destroy(mwi_sub);
11481 
11482    ast_free(uniqueid);  
11483    return 0;
11484 }

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

11240 {
11241    switch (cmd) {
11242    case CLI_INIT:
11243       e->command = "voicemail reload";
11244       e->usage =
11245          "Usage: voicemail reload\n"
11246          "       Reload voicemail configuration\n";
11247       return NULL;
11248    case CLI_GENERATE:
11249       return NULL;
11250    }
11251 
11252    if (a->argc != 2)
11253       return CLI_SHOWUSAGE;
11254 
11255    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11256    load_config(1);
11257    
11258    return CLI_SUCCESS;
11259 }

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

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

11130 {
11131    struct ast_vm_user *vmu;
11132 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11133    const char *context = NULL;
11134    int users_counter = 0;
11135 
11136    switch (cmd) {
11137    case CLI_INIT:
11138       e->command = "voicemail show users";
11139       e->usage =
11140          "Usage: voicemail show users [for <context>]\n"
11141          "       Lists all mailboxes currently set up\n";
11142       return NULL;
11143    case CLI_GENERATE:
11144       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11145    }  
11146 
11147    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11148       return CLI_SHOWUSAGE;
11149    if (a->argc == 5) {
11150       if (strcmp(a->argv[3],"for"))
11151          return CLI_SHOWUSAGE;
11152       context = a->argv[4];
11153    }
11154 
11155    if (ast_check_realtime("voicemail")) {
11156       if (!context) {
11157          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11158          return CLI_SHOWUSAGE;
11159       }
11160       return show_users_realtime(a->fd, context);
11161    }
11162 
11163    AST_LIST_LOCK(&users);
11164    if (AST_LIST_EMPTY(&users)) {
11165       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11166       AST_LIST_UNLOCK(&users);
11167       return CLI_FAILURE;
11168    }
11169    if (a->argc == 3)
11170       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11171    else {
11172       int count = 0;
11173       AST_LIST_TRAVERSE(&users, vmu, list) {
11174          if (!strcmp(context, vmu->context))
11175             count++;
11176       }
11177       if (count) {
11178          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11179       } else {
11180          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11181          AST_LIST_UNLOCK(&users);
11182          return CLI_FAILURE;
11183       }
11184    }
11185    AST_LIST_TRAVERSE(&users, vmu, list) {
11186       int newmsgs = 0, oldmsgs = 0;
11187       char count[12], tmp[256] = "";
11188 
11189       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
11190          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11191          inboxcount(tmp, &newmsgs, &oldmsgs);
11192          snprintf(count, sizeof(count), "%d", newmsgs);
11193          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11194          users_counter++;
11195       }
11196    }
11197    AST_LIST_UNLOCK(&users);
11198    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11199    return CLI_SUCCESS;
11200 }

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

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

11204 {
11205    struct vm_zone *zone;
11206 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11207    char *res = CLI_SUCCESS;
11208 
11209    switch (cmd) {
11210    case CLI_INIT:
11211       e->command = "voicemail show zones";
11212       e->usage =
11213          "Usage: voicemail show zones\n"
11214          "       Lists zone message formats\n";
11215       return NULL;
11216    case CLI_GENERATE:
11217       return NULL;
11218    }
11219 
11220    if (a->argc != 3)
11221       return CLI_SHOWUSAGE;
11222 
11223    AST_LIST_LOCK(&zones);
11224    if (!AST_LIST_EMPTY(&zones)) {
11225       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11226       AST_LIST_TRAVERSE(&zones, zone, list) {
11227          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11228       }
11229    } else {
11230       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11231       res = CLI_FAILURE;
11232    }
11233    AST_LIST_UNLOCK(&zones);
11234 
11235    return res;
11236 }

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

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

Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), mwi_send_init(), my_has_voicemail(), and vm_execmain().

05419 {
05420    char tmp[256], *tmp2 = tmp, *box, *context;
05421    ast_copy_string(tmp, mailbox, sizeof(tmp));
05422    if (ast_strlen_zero(folder)) {
05423       folder = "INBOX";
05424    }
05425    while ((box = strsep(&tmp2, ",&"))) {
05426       if ((context = strchr(box, '@')))
05427          *context++ = '\0';
05428       else
05429          context = "default";
05430       if (__has_voicemail(context, box, folder, 1))
05431          return 1;
05432       /* If we are checking INBOX, we should check Urgent as well */
05433       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05434          return 1;
05435       }
05436    }
05437    return 0;
05438 }

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

Definition at line 5500 of file app_voicemail.c.

References inboxcount2().

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

05501 {
05502    int urgentmsgs = 0;
05503    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05504    if (newmsgs) {
05505       *newmsgs += urgentmsgs;
05506    }
05507    return res;
05508 }

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

Definition at line 5441 of file app_voicemail.c.

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

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

05442 {
05443    char tmp[256];
05444    char *context;
05445 
05446    /* If no mailbox, return immediately */
05447    if (ast_strlen_zero(mailbox))
05448       return 0;
05449 
05450    if (newmsgs)
05451       *newmsgs = 0;
05452    if (oldmsgs)
05453       *oldmsgs = 0;
05454    if (urgentmsgs)
05455       *urgentmsgs = 0;
05456 
05457    if (strchr(mailbox, ',')) {
05458       int tmpnew, tmpold, tmpurgent;
05459       char *mb, *cur;
05460 
05461       ast_copy_string(tmp, mailbox, sizeof(tmp));
05462       mb = tmp;
05463       while ((cur = strsep(&mb, ", "))) {
05464          if (!ast_strlen_zero(cur)) {
05465             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05466                return -1;
05467             else {
05468                if (newmsgs)
05469                   *newmsgs += tmpnew; 
05470                if (oldmsgs)
05471                   *oldmsgs += tmpold;
05472                if (urgentmsgs)
05473                   *urgentmsgs += tmpurgent;
05474             }
05475          }
05476       }
05477       return 0;
05478    }
05479 
05480    ast_copy_string(tmp, mailbox, sizeof(tmp));
05481    
05482    if ((context = strchr(tmp, '@')))
05483       *context++ = '\0';
05484    else
05485       context = "default";
05486 
05487    if (newmsgs)
05488       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05489    if (oldmsgs)
05490       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05491    if (urgentmsgs)
05492       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05493 
05494    return 0;
05495 }

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

utility used by inchar(), for base_encode()

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

04201 {
04202    int l;
04203 
04204    if (bio->ateof)
04205       return 0;
04206 
04207    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04208       if (ferror(fi))
04209          return -1;
04210 
04211       bio->ateof = 1;
04212       return 0;
04213    }
04214 
04215    bio->iolen = l;
04216    bio->iocp = 0;
04217 
04218    return 1;
04219 }

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

utility used by base_encode()

Definition at line 4224 of file app_voicemail.c.

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

Referenced by base_encode().

04225 {
04226    if (bio->iocp>=bio->iolen) {
04227       if (!inbuf(bio, fi))
04228          return EOF;
04229    }
04230 
04231    return bio->iobuf[bio->iocp++];
04232 }

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

Definition at line 935 of file app_voicemail.c.

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

Referenced by load_module().

00936 {
00937    struct inprocess *i = obj, *j = arg;
00938    if (strcmp(i->mailbox, j->mailbox)) {
00939       return 0;
00940    }
00941    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00942 }

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

Definition at line 944 of file app_voicemail.c.

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

Referenced by copy_message(), and forward_message().

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

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

Definition at line 929 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

00930 {
00931    const struct inprocess *i = obj;
00932    return atoi(i->mailbox);
00933 }

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

Definition at line 5040 of file app_voicemail.c.

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

05041 {
05042    int res;
05043    char fn[PATH_MAX];
05044    char dest[PATH_MAX];
05045 
05046    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05047 
05048    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05049       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05050       return -1;
05051    }
05052 
05053    RETRIEVE(fn, -1, ext, context);
05054    if (ast_fileexists(fn, NULL, NULL) > 0) {
05055       res = ast_stream_and_wait(chan, fn, ecodes);
05056       if (res) {
05057          DISPOSE(fn, -1);
05058          return res;
05059       }
05060    } else {
05061       /* Dispose just in case */
05062       DISPOSE(fn, -1);
05063       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05064       if (res)
05065          return res;
05066       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05067       if (res)
05068          return res;
05069    }
05070    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05071    return res;
05072 }

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

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

Referenced by actual_load_config().

01372 {
01373    int i;
01374    char *local_key = ast_strdupa(key);
01375 
01376    for (i = 0; i < strlen(key); ++i) {
01377       if (!strchr(VALID_DTMF, *local_key)) {
01378          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01379          return 0;
01380       }
01381       local_key++;
01382    }
01383    return 1;
01384 }

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

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

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

04019 {
04020    int x;
04021    unsigned char map[MAXMSGLIMIT] = "";
04022    DIR *msgdir;
04023    struct dirent *msgdirent;
04024    int msgdirint;
04025    char extension[4];
04026    int stopcount = 0;
04027 
04028    /* Reading the entire directory into a file map scales better than
04029     * doing a stat repeatedly on a predicted sequence.  I suspect this
04030     * is partially due to stat(2) internally doing a readdir(2) itself to
04031     * find each file. */
04032    if (!(msgdir = opendir(dir))) {
04033       return -1;
04034    }
04035 
04036    while ((msgdirent = readdir(msgdir))) {
04037       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04038          map[msgdirint] = 1;
04039          stopcount++;
04040          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04041       }
04042    }
04043    closedir(msgdir);
04044 
04045    for (x = 0; x < vmu->maxmsg; x++) {
04046       if (map[x] == 1) {
04047          stopcount--;
04048       } else if (map[x] == 0 && !stopcount) {
04049          break;
04050       }
04051    }
04052 
04053    return x - 1;
04054 }

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

References ast_canmatch_extension(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_exists_extension(), ast_fileexists(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::caller, ast_channel::context, ast_vm_user::context, create_dirpath(), DISPOSE, errno, ast_vm_user::exit, find_user(), ast_party_caller::id, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, ast_party_id::number, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), RETRIEVE, S_COR, ast_party_number::str, ast_party_number::valid, VM_OPERATOR, VM_SPOOL_DIR, and VOICEMAIL_DIR_MODE.

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

static int load_config ( int  reload  )  [static]

Definition at line 11771 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_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, and VOICEMAIL_CONFIG.

11772 {
11773    struct ast_config *cfg, *ucfg;
11774    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11775    int res;
11776 
11777    ast_unload_realtime("voicemail");
11778    ast_unload_realtime("voicemail_data");
11779 
11780    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11781       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11782          return 0;
11783       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11784          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11785          ucfg = NULL;
11786       }
11787       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11788       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11789          ast_config_destroy(ucfg);
11790          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11791          return 0;
11792       }
11793    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11794       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11795       return 0;
11796    } else {
11797       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11798       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11799          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11800          ucfg = NULL;
11801       }
11802    }
11803 
11804    res = actual_load_config(reload, cfg, ucfg);
11805 
11806    ast_config_destroy(cfg);
11807    ast_config_destroy(ucfg);
11808 
11809    return res;
11810 }

static int load_module ( void   )  [static]

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

13063 {
13064    int res;
13065    my_umask = umask(0);
13066    umask(my_umask);
13067 
13068    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13069       return AST_MODULE_LOAD_DECLINE;
13070    }
13071 
13072    /* compute the location of the voicemail spool directory */
13073    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13074    
13075    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13076       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13077    }
13078 
13079    if ((res = load_config(0)))
13080       return res;
13081 
13082    res = ast_register_application_xml(app, vm_exec);
13083    res |= ast_register_application_xml(app2, vm_execmain);
13084    res |= ast_register_application_xml(app3, vm_box_exists);
13085    res |= ast_register_application_xml(app4, vmauthenticate);
13086    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13087    res |= ast_custom_function_register(&mailbox_exists_acf);
13088    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13089 #ifdef TEST_FRAMEWORK
13090    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13091    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13092    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13093    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13094    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13095 #endif
13096 
13097    if (res)
13098       return res;
13099 
13100    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13101    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13102 
13103    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13104    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13105    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13106 
13107    return res;
13108 }

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

References VM_SPOOL_DIR.

01636 {
01637    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01638 }

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 4517 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_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_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, config_flags, 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, ast_channel::name, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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

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

01653 {
01654    return snprintf(dest, len, "%s/msg%04d", dir, num);
01655 }

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

Manager list voicemail users command.

Definition at line 11602 of file app_voicemail.c.

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

Referenced by load_module().

11603 {
11604    struct ast_vm_user *vmu = NULL;
11605    const char *id = astman_get_header(m, "ActionID");
11606    char actionid[128] = "";
11607 
11608    if (!ast_strlen_zero(id))
11609       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11610 
11611    AST_LIST_LOCK(&users);
11612 
11613    if (AST_LIST_EMPTY(&users)) {
11614       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11615       AST_LIST_UNLOCK(&users);
11616       return RESULT_SUCCESS;
11617    }
11618    
11619    astman_send_ack(s, m, "Voicemail user list will follow");
11620    
11621    AST_LIST_TRAVERSE(&users, vmu, list) {
11622       char dirname[256];
11623 
11624 #ifdef IMAP_STORAGE
11625       int new, old;
11626       inboxcount(vmu->mailbox, &new, &old);
11627 #endif
11628       
11629       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11630       astman_append(s,
11631          "%s"
11632          "Event: VoicemailUserEntry\r\n"
11633          "VMContext: %s\r\n"
11634          "VoiceMailbox: %s\r\n"
11635          "Fullname: %s\r\n"
11636          "Email: %s\r\n"
11637          "Pager: %s\r\n"
11638          "ServerEmail: %s\r\n"
11639          "MailCommand: %s\r\n"
11640          "Language: %s\r\n"
11641          "TimeZone: %s\r\n"
11642          "Callback: %s\r\n"
11643          "Dialout: %s\r\n"
11644          "UniqueID: %s\r\n"
11645          "ExitContext: %s\r\n"
11646          "SayDurationMinimum: %d\r\n"
11647          "SayEnvelope: %s\r\n"
11648          "SayCID: %s\r\n"
11649          "AttachMessage: %s\r\n"
11650          "AttachmentFormat: %s\r\n"
11651          "DeleteMessage: %s\r\n"
11652          "VolumeGain: %.2f\r\n"
11653          "CanReview: %s\r\n"
11654          "CallOperator: %s\r\n"
11655          "MaxMessageCount: %d\r\n"
11656          "MaxMessageLength: %d\r\n"
11657          "NewMessageCount: %d\r\n"
11658 #ifdef IMAP_STORAGE
11659          "OldMessageCount: %d\r\n"
11660          "IMAPUser: %s\r\n"
11661 #endif
11662          "\r\n",
11663          actionid,
11664          vmu->context,
11665          vmu->mailbox,
11666          vmu->fullname,
11667          vmu->email,
11668          vmu->pager,
11669          vmu->serveremail,
11670          vmu->mailcmd,
11671          vmu->language,
11672          vmu->zonetag,
11673          vmu->callback,
11674          vmu->dialout,
11675          vmu->uniqueid,
11676          vmu->exit,
11677          vmu->saydurationm,
11678          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11679          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11680          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11681          vmu->attachfmt,
11682          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11683          vmu->volgain,
11684          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11685          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11686          vmu->maxmsg,
11687          vmu->maxsecs,
11688 #ifdef IMAP_STORAGE
11689          new, old, vmu->imapuser
11690 #else
11691          count_messages(vmu, dirname)
11692 #endif
11693          );
11694    }     
11695    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11696 
11697    AST_LIST_UNLOCK(&users);
11698 
11699    return RESULT_SUCCESS;
11700 }

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

Definition at line 11436 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_lock, poll_subscribed_mailboxes(), and poll_thread_run.

Referenced by start_poll_thread().

11437 {
11438    while (poll_thread_run) {
11439       struct timespec ts = { 0, };
11440       struct timeval wait;
11441 
11442       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11443       ts.tv_sec = wait.tv_sec;
11444       ts.tv_nsec = wait.tv_usec * 1000;
11445 
11446       ast_mutex_lock(&poll_lock);
11447       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11448       ast_mutex_unlock(&poll_lock);
11449 
11450       if (!poll_thread_run)
11451          break;
11452 
11453       poll_subscribed_mailboxes();
11454    }
11455 
11456    return NULL;
11457 }

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

Definition at line 1713 of file app_voicemail.c.

References ARRAY_LEN.

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

01714 {
01715 #ifdef IMAP_STORAGE
01716    if (vmu && id == 0) {
01717       return vmu->imapfolder;
01718    }
01719 #endif
01720    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01721 }

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

Definition at line 5367 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

05368 {
05369    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05370 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11459 of file app_voicemail.c.

References ast_free, and mwi_sub.

Referenced by handle_unsubscribe().

11460 {
11461    ast_free(mwi_sub);
11462 }

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

Definition at line 11537 of file app_voicemail.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_SUB, ast_free, ast_log(), ast_strdup, ast_taskprocessor_push(), handle_subscribe(), LOG_ERROR, and mwi_subscription_tps.

Referenced by start_poll_thread().

11538 {
11539    struct mwi_sub_task *mwist;
11540    
11541    if (ast_event_get_type(event) != AST_EVENT_SUB)
11542       return;
11543 
11544    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11545       return;
11546 
11547    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11548       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11549       return;
11550    }
11551    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11552    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11553    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11554    
11555    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11556       ast_free(mwist);
11557    }
11558 }

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

Definition at line 11521 of file app_voicemail.c.

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

Referenced by start_poll_thread().

11522 {
11523    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11524    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11525       return;
11526 
11527    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11528       return;
11529 
11530    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11531    *uniqueid = u;
11532    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11533       ast_free(uniqueid);
11534    }
11535 }

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

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_unlock, ast_log(), 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, strsep(), VM_ATTACH, vm_delete(), VM_DELETE, and VM_SPOOL_DIR.

07033 {
07034    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07035    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07036    const char *category;
07037    char *myserveremail = serveremail;
07038 
07039    ast_channel_lock(chan);
07040    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07041       category = ast_strdupa(category);
07042    }
07043    ast_channel_unlock(chan);
07044 
07045 #ifndef IMAP_STORAGE
07046    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07047 #else
07048    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07049 #endif
07050    make_file(fn, sizeof(fn), todir, msgnum);
07051    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07052 
07053    if (!ast_strlen_zero(vmu->attachfmt)) {
07054       if (strstr(fmt, vmu->attachfmt))
07055          fmt = vmu->attachfmt;
07056       else
07057          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);
07058    }
07059 
07060    /* Attach only the first format */
07061    fmt = ast_strdupa(fmt);
07062    stringp = fmt;
07063    strsep(&stringp, "|");
07064 
07065    if (!ast_strlen_zero(vmu->serveremail))
07066       myserveremail = vmu->serveremail;
07067 
07068    if (!ast_strlen_zero(vmu->email)) {
07069       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07070 
07071       if (attach_user_voicemail)
07072          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07073 
07074       /* XXX possible imap issue, should category be NULL XXX */
07075       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07076 
07077       if (attach_user_voicemail)
07078          DISPOSE(todir, msgnum);
07079    }
07080 
07081    if (!ast_strlen_zero(vmu->pager)) {
07082       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07083    }
07084 
07085    if (ast_test_flag(vmu, VM_DELETE))
07086       DELETE(todir, msgnum, fn, vmu);
07087 
07088    /* Leave voicemail for someone */
07089    if (ast_app_has_voicemail(ext_context, NULL)) 
07090       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07091 
07092    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07093 
07094    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);
07095    run_externnotify(vmu->context, vmu->mailbox, flag);
07096 
07097 #ifdef IMAP_STORAGE
07098    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07099    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07100       vm_imap_delete(NULL, vms->curmsg, vmu);
07101       vms->newmessages--;  /* Fix new message count */
07102    }
07103 #endif
07104 
07105    return 0;
07106 }

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

utility used by base_encode()

Definition at line 4237 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04238 {
04239    if (bio->linelength >= BASELINELEN) {
04240       if (fputs(ENDL, so) == EOF) {
04241          return -1;
04242       }
04243 
04244       bio->linelength = 0;
04245    }
04246 
04247    if (putc(((unsigned char) c), so) == EOF) {
04248       return -1;
04249    }
04250 
04251    bio->linelength++;
04252 
04253    return 1;
04254 }

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

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

07878 {
07879    int count_msg, last_msg;
07880 
07881    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07882 
07883    /* Rename the member vmbox HERE so that we don't try to return before
07884     * we know what's going on.
07885     */
07886    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07887 
07888    /* Faster to make the directory than to check if it exists. */
07889    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07890 
07891    /* traverses directory using readdir (or select query for ODBC) */
07892    count_msg = count_messages(vmu, vms->curdir);
07893    if (count_msg < 0) {
07894       return count_msg;
07895    } else {
07896       vms->lastmsg = count_msg - 1;
07897    }
07898 
07899    if (vm_allocate_dh(vms, vmu, count_msg)) {
07900       return -1;
07901    }
07902 
07903    /*
07904    The following test is needed in case sequencing gets messed up.
07905    There appears to be more than one way to mess up sequence, so
07906    we will not try to find all of the root causes--just fix it when
07907    detected.
07908    */
07909 
07910    if (vm_lock_path(vms->curdir)) {
07911       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07912       return ERROR_LOCK_PATH;
07913    }
07914 
07915    /* for local storage, checks directory for messages up to maxmsg limit */
07916    last_msg = last_message_index(vmu, vms->curdir);
07917    ast_unlock_path(vms->curdir);
07918 
07919    if (last_msg < -1) {
07920       return last_msg;
07921    } else if (vms->lastmsg != last_msg) {
07922       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);
07923       resequence_mailbox(vmu, vms->curdir, count_msg);
07924    }
07925 
07926    return 0;
07927 }

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

Definition at line 7655 of file app_voicemail.c.

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

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

07656 {
07657    int res = 0;
07658    char filename[256], *cid;
07659    const char *origtime, *context, *category, *duration, *flag;
07660    struct ast_config *msg_cfg;
07661    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07662 
07663    vms->starting = 0;
07664    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07665    adsi_message(chan, vms);
07666    if (!vms->curmsg) {
07667       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07668    } else if (vms->curmsg == vms->lastmsg) {
07669       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07670    }
07671 
07672    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07673    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07674    msg_cfg = ast_config_load(filename, config_flags);
07675    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07676       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07677       return 0;
07678    }
07679    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07680 
07681    /* Play the word urgent if we are listening to urgent messages */
07682    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07683       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07684    }
07685 
07686    if (!res) {
07687       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07688       /* POLISH syntax */
07689       if (!strncasecmp(chan->language, "pl", 2)) {
07690          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07691             int ten, one;
07692             char nextmsg[256];
07693             ten = (vms->curmsg + 1) / 10;
07694             one = (vms->curmsg + 1) % 10;
07695 
07696             if (vms->curmsg < 20) {
07697                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07698                res = wait_file2(chan, vms, nextmsg);
07699             } else {
07700                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07701                res = wait_file2(chan, vms, nextmsg);
07702                if (one > 0) {
07703                   if (!res) {
07704                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07705                      res = wait_file2(chan, vms, nextmsg);
07706                   }
07707                }
07708             }
07709          }
07710          if (!res)
07711             res = wait_file2(chan, vms, "vm-message");
07712       /* HEBREW syntax */
07713       } else if (!strncasecmp(chan->language, "he", 2)) {
07714          if (!vms->curmsg) {
07715             res = wait_file2(chan, vms, "vm-message");
07716             res = wait_file2(chan, vms, "vm-first");
07717          } else if (vms->curmsg == vms->lastmsg) {
07718             res = wait_file2(chan, vms, "vm-message");
07719             res = wait_file2(chan, vms, "vm-last");
07720          } else {
07721             res = wait_file2(chan, vms, "vm-message");
07722             res = wait_file2(chan, vms, "vm-number");
07723             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07724          }
07725       /* VIETNAMESE syntax */
07726       } else if (!strncasecmp(chan->language, "vi", 2)) {
07727          if (!vms->curmsg) {
07728             res = wait_file2(chan, vms, "vm-message");
07729             res = wait_file2(chan, vms, "vm-first");
07730          } else if (vms->curmsg == vms->lastmsg) {
07731             res = wait_file2(chan, vms, "vm-message");
07732             res = wait_file2(chan, vms, "vm-last");
07733          } else {
07734             res = wait_file2(chan, vms, "vm-message");
07735             res = wait_file2(chan, vms, "vm-number");
07736             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07737          }
07738       } else {
07739          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07740             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07741          } else { /* DEFAULT syntax */
07742             res = wait_file2(chan, vms, "vm-message");
07743          }
07744          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07745             if (!res) {
07746                ast_test_suite_event_notify("PLAYBACK", "Message: message number");
07747                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07748             }
07749          }
07750       }
07751    }
07752 
07753    if (!msg_cfg) {
07754       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07755       return 0;
07756    }
07757 
07758    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07759       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07760       DISPOSE(vms->curdir, vms->curmsg);
07761       ast_config_destroy(msg_cfg);
07762       return 0;
07763    }
07764 
07765    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07766    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07767    category = ast_variable_retrieve(msg_cfg, "message", "category");
07768 
07769    context = ast_variable_retrieve(msg_cfg, "message", "context");
07770    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07771       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07772    if (!res) {
07773       res = play_message_category(chan, category);
07774    }
07775    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
07776       res = play_message_datetime(chan, vmu, origtime, filename);
07777    }
07778    if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
07779       res = play_message_callerid(chan, vms, cid, context, 0);
07780    }
07781    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
07782       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07783    }
07784    /* Allow pressing '1' to skip envelope / callerid */
07785    if (res == '1') {
07786       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07787       res = 0;
07788    }
07789    ast_config_destroy(msg_cfg);
07790 
07791    if (!res) {
07792       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07793       vms->heard[vms->curmsg] = 1;
07794 #ifdef IMAP_STORAGE
07795       /*IMAP storage stores any prepended message from a forward
07796        * as a separate file from the rest of the message
07797        */
07798       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07799          wait_file(chan, vms, vms->introfn);
07800       }
07801 #endif
07802       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07803          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07804          res = 0;
07805       }
07806       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07807    }
07808    DISPOSE(vms->curdir, vms->curmsg);
07809    return res;
07810 }

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

Definition at line 7541 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

07542 {
07543    int res = 0;
07544    int i;
07545    char *callerid, *name;
07546    char prefile[PATH_MAX] = "";
07547    
07548 
07549    /* If voicemail cid is not enabled, or we didn't get cid or context from
07550     * the attribute file, leave now.
07551     *
07552     * TODO Still need to change this so that if this function is called by the
07553     * message envelope (and someone is explicitly requesting to hear the CID),
07554     * it does not check to see if CID is enabled in the config file.
07555     */
07556    if ((cid == NULL)||(context == NULL))
07557       return res;
07558 
07559    /* Strip off caller ID number from name */
07560    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07561    ast_callerid_parse(cid, &name, &callerid);
07562    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07563       /* Check for internal contexts and only */
07564       /* say extension when the call didn't come from an internal context in the list */
07565       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07566          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07567          if ((strcmp(cidinternalcontexts[i], context) == 0))
07568             break;
07569       }
07570       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07571          if (!res) {
07572             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07573             if (!ast_strlen_zero(prefile)) {
07574             /* See if we can find a recorded name for this person instead of their extension number */
07575                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07576                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07577                   if (!callback)
07578                      res = wait_file2(chan, vms, "vm-from");
07579                   res = ast_stream_and_wait(chan, prefile, "");
07580                } else {
07581                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07582                   /* Say "from extension" as one saying to sound smoother */
07583                   if (!callback)
07584                      res = wait_file2(chan, vms, "vm-from-extension");
07585                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07586                }
07587             }
07588          }
07589       } else if (!res) {
07590          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07591          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07592          if (!callback)
07593             res = wait_file2(chan, vms, "vm-from-phonenumber");
07594          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07595       }
07596    } else {
07597       /* Number unknown */
07598       ast_debug(1, "VM-CID: From an unknown number\n");
07599       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07600       res = wait_file2(chan, vms, "vm-unknown-caller");
07601    }
07602    return res;
07603 }

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

Definition at line 7452 of file app_voicemail.c.

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

Referenced by play_message().

07453 {
07454    int res = 0;
07455 
07456    if (!ast_strlen_zero(category))
07457       res = ast_play_and_wait(chan, category);
07458 
07459    if (res) {
07460       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07461       res = 0;
07462    }
07463 
07464    return res;
07465 }

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

Definition at line 7467 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

07468 {
07469    int res = 0;
07470    struct vm_zone *the_zone = NULL;
07471    time_t t;
07472 
07473    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07474       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07475       return 0;
07476    }
07477 
07478    /* Does this user have a timezone specified? */
07479    if (!ast_strlen_zero(vmu->zonetag)) {
07480       /* Find the zone in the list */
07481       struct vm_zone *z;
07482       AST_LIST_LOCK(&zones);
07483       AST_LIST_TRAVERSE(&zones, z, list) {
07484          if (!strcmp(z->name, vmu->zonetag)) {
07485             the_zone = z;
07486             break;
07487          }
07488       }
07489       AST_LIST_UNLOCK(&zones);
07490    }
07491 
07492 /* No internal variable parsing for now, so we'll comment it out for the time being */
07493 #if 0
07494    /* Set the DIFF_* variables */
07495    ast_localtime(&t, &time_now, NULL);
07496    tv_now = ast_tvnow();
07497    ast_localtime(&tv_now, &time_then, NULL);
07498 
07499    /* Day difference */
07500    if (time_now.tm_year == time_then.tm_year)
07501       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07502    else
07503       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07504    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07505 
07506    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07507 #endif
07508    if (the_zone) {
07509       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07510    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07511       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07512    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07513       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07514    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07515       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);
07516    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07517       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07518    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07519       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07520    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07521       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07522    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07523       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);
07524    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07525       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07526    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07527       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07528    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07529       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);
07530    } else {
07531       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07532    }
07533 #if 0
07534    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07535 #endif
07536    return res;
07537 }

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

Definition at line 7605 of file app_voicemail.c.

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

Referenced by play_message().

07606 {
07607    int res = 0;
07608    int durationm;
07609    int durations;
07610    /* Verify that we have a duration for the message */
07611    if (duration == NULL)
07612       return res;
07613 
07614    /* Convert from seconds to minutes */
07615    durations = atoi(duration);
07616    durationm = (durations / 60);
07617 
07618    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07619 
07620    if ((!res) && (durationm >= minduration)) {
07621       res = wait_file2(chan, vms, "vm-duration");
07622 
07623       /* POLISH syntax */
07624       if (!strncasecmp(chan->language, "pl", 2)) {
07625          div_t num = div(durationm, 10);
07626 
07627          if (durationm == 1) {
07628             res = ast_play_and_wait(chan, "digits/1z");
07629             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07630          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07631             if (num.rem == 2) {
07632                if (!num.quot) {
07633                   res = ast_play_and_wait(chan, "digits/2-ie");
07634                } else {
07635                   res = say_and_wait(chan, durationm - 2 , chan->language);
07636                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07637                }
07638             } else {
07639                res = say_and_wait(chan, durationm, chan->language);
07640             }
07641             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07642          } else {
07643             res = say_and_wait(chan, durationm, chan->language);
07644             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07645          }
07646       /* DEFAULT syntax */
07647       } else {
07648          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07649          res = wait_file2(chan, vms, "vm-minutes");
07650       }
07651    }
07652    return res;
07653 }

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

References acceptdtmf, ast_channel_setoption(), ast_copy_string(), AST_DIGIT_ANY, ast_filedelete(), ast_filerename(), ast_log(), AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_stream_and_wait(), ast_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.

13378 {
13379    /* Record message & let caller review or re-record it, or set options if applicable */
13380    int res = 0;
13381    int cmd = 0;
13382    int max_attempts = 3;
13383    int attempts = 0;
13384    int recorded = 0;
13385    int msg_exists = 0;
13386    signed char zero_gain = 0;
13387    char tempfile[PATH_MAX];
13388    char *acceptdtmf = "#";
13389    char *canceldtmf = "";
13390    int canceleddtmf = 0;
13391 
13392    /* Note that urgent and private are for flagging messages as such in the future */
13393 
13394    /* barf if no pointer passed to store duration in */
13395    if (duration == NULL) {
13396       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13397       return -1;
13398    }
13399 
13400    if (!outsidecaller)
13401       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13402    else
13403       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13404 
13405    cmd = '3';  /* Want to start by recording */
13406 
13407    while ((cmd >= 0) && (cmd != 't')) {
13408       switch (cmd) {
13409       case '1':
13410          if (!msg_exists) {
13411             /* In this case, 1 is to record a message */
13412             cmd = '3';
13413             break;
13414          } else {
13415             /* Otherwise 1 is to save the existing message */
13416             ast_verb(3, "Saving message as is\n");
13417             if (!outsidecaller) 
13418                ast_filerename(tempfile, recordfile, NULL);
13419             ast_stream_and_wait(chan, "vm-msgsaved", "");
13420             if (!outsidecaller) {
13421                /* Saves to IMAP server only if imapgreeting=yes */
13422                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13423                DISPOSE(recordfile, -1);
13424             }
13425             cmd = 't';
13426             return res;
13427          }
13428       case '2':
13429          /* Review */
13430          ast_verb(3, "Reviewing the message\n");
13431          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13432          break;
13433       case '3':
13434          msg_exists = 0;
13435          /* Record */
13436          if (recorded == 1) 
13437             ast_verb(3, "Re-recording the message\n");
13438          else  
13439             ast_verb(3, "Recording the message\n");
13440          
13441          if (recorded && outsidecaller) {
13442             cmd = ast_play_and_wait(chan, INTRO);
13443             cmd = ast_play_and_wait(chan, "beep");
13444          }
13445          recorded = 1;
13446          /* 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 */
13447          if (record_gain)
13448             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13449          if (ast_test_flag(vmu, VM_OPERATOR))
13450             canceldtmf = "0";
13451          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13452          if (strchr(canceldtmf, cmd)) {
13453          /* need this flag here to distinguish between pressing '0' during message recording or after */
13454             canceleddtmf = 1;
13455          }
13456          if (record_gain)
13457             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13458          if (cmd == -1) {
13459             /* User has hung up, no options to give */
13460             if (!outsidecaller) {
13461                /* user was recording a greeting and they hung up, so let's delete the recording. */
13462                ast_filedelete(tempfile, NULL);
13463             }     
13464             return cmd;
13465          }
13466          if (cmd == '0') {
13467             break;
13468          } else if (cmd == '*') {
13469             break;
13470 #if 0
13471          } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13472             /* Message is too short */
13473             ast_verb(3, "Message too short\n");
13474             cmd = ast_play_and_wait(chan, "vm-tooshort");
13475             cmd = ast_filedelete(tempfile, NULL);
13476             break;
13477          } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13478             /* Message is all silence */
13479             ast_verb(3, "Nothing recorded\n");
13480             cmd = ast_filedelete(tempfile, NULL);
13481             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13482             if (!cmd)
13483                cmd = ast_play_and_wait(chan, "vm-speakup");
13484             break;
13485 #endif
13486          } else {
13487             /* If all is well, a message exists */
13488             msg_exists = 1;
13489             cmd = 0;
13490          }
13491          break;
13492       case '4':
13493          if (outsidecaller) {  /* only mark vm messages */
13494             /* Mark Urgent */
13495             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13496                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13497                res = ast_play_and_wait(chan, "vm-marked-urgent");
13498                strcpy(flag, "Urgent");
13499             } else if (flag) {
13500                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13501                res = ast_play_and_wait(chan, "vm-urgent-removed");
13502                strcpy(flag, "");
13503             } else {
13504                ast_play_and_wait(chan, "vm-sorry");
13505             }
13506             cmd = 0;
13507          } else {
13508             cmd = ast_play_and_wait(chan, "vm-sorry");
13509          }
13510          break;
13511       case '5':
13512       case '6':
13513       case '7':
13514       case '8':
13515       case '9':
13516       case '*':
13517       case '#':
13518          cmd = ast_play_and_wait(chan, "vm-sorry");
13519          break;
13520 #if 0 
13521 /*  XXX Commented out for the moment because of the dangers of deleting
13522     a message while recording (can put the message numbers out of sync) */
13523       case '*':
13524          /* Cancel recording, delete message, offer to take another message*/
13525          cmd = ast_play_and_wait(chan, "vm-deleted");
13526          cmd = ast_filedelete(tempfile, NULL);
13527          if (outsidecaller) {
13528             res = vm_exec(chan, NULL);
13529             return res;
13530          }
13531          else
13532             return 1;
13533 #endif
13534       case '0':
13535          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13536             cmd = ast_play_and_wait(chan, "vm-sorry");
13537             break;
13538          }
13539          if (msg_exists || recorded) {
13540             cmd = ast_play_and_wait(chan, "vm-saveoper");
13541             if (!cmd)
13542                cmd = ast_waitfordigit(chan, 3000);
13543             if (cmd == '1') {
13544                ast_filerename(tempfile, recordfile, NULL);
13545                ast_play_and_wait(chan, "vm-msgsaved");
13546                cmd = '0';
13547             } else if (cmd == '4') {
13548                if (flag) {
13549                   ast_play_and_wait(chan, "vm-marked-urgent");
13550                   strcpy(flag, "Urgent");
13551                }
13552                ast_play_and_wait(chan, "vm-msgsaved");
13553                cmd = '0';
13554             } else {
13555                ast_play_and_wait(chan, "vm-deleted");
13556                DELETE(tempfile, -1, tempfile, vmu);
13557                cmd = '0';
13558             }
13559          }
13560          return cmd;
13561       default:
13562          /* If the caller is an ouside caller, and the review option is enabled,
13563             allow them to review the message, but let the owner of the box review
13564             their OGM's */
13565          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13566             return cmd;
13567          if (msg_exists) {
13568             cmd = ast_play_and_wait(chan, "vm-review");
13569             if (!cmd && outsidecaller) {
13570                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13571                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13572                } else if (flag) {
13573                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13574                }
13575             }
13576          } else {
13577             cmd = ast_play_and_wait(chan, "vm-torerecord");
13578             if (!cmd)
13579                cmd = ast_waitfordigit(chan, 600);
13580          }
13581          
13582          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13583             cmd = ast_play_and_wait(chan, "vm-reachoper");
13584             if (!cmd)
13585                cmd = ast_waitfordigit(chan, 600);
13586          }
13587 #if 0
13588          if (!cmd)
13589             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13590 #endif
13591          if (!cmd)
13592             cmd = ast_waitfordigit(chan, 6000);
13593          if (!cmd) {
13594             attempts++;
13595          }
13596          if (attempts > max_attempts) {
13597             cmd = 't';
13598          }
13599       }
13600    }
13601    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13602       /* Hang up or timeout, so delete the recording. */
13603       ast_filedelete(tempfile, NULL);
13604    }
13605 
13606    if (cmd != 't' && outsidecaller)
13607       ast_play_and_wait(chan, "vm-goodbye");
13608 
13609    return cmd;
13610 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11408 of file app_voicemail.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11409 {
11410    int new = 0, old = 0, urgent = 0;
11411 
11412    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11413 
11414    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11415       mwi_sub->old_urgent = urgent;
11416       mwi_sub->old_new = new;
11417       mwi_sub->old_old = old;
11418       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11419       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11420    }
11421 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11423 of file app_voicemail.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), mwi_sub::entry, mwi_sub, and poll_subscribed_mailbox().

Referenced by mb_poll_thread().

11424 {
11425    struct mwi_sub *mwi_sub;
11426 
11427    AST_RWLIST_RDLOCK(&mwi_subs);
11428    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11429       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11430          poll_subscribed_mailbox(mwi_sub);
11431       }
11432    }
11433    AST_RWLIST_UNLOCK(&mwi_subs);
11434 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

Definition at line 1014 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, ast_vm_user::locale, ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, saydurationminfo, ast_vm_user::volgain, and ast_vm_user::zonetag.

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

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 4325 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, config_flags, 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(), and S_OR.

04326 {
04327    char callerid[256];
04328    char num[12];
04329    char fromdir[256], fromfile[256];
04330    struct ast_config *msg_cfg;
04331    const char *origcallerid, *origtime;
04332    char origcidname[80], origcidnum[80], origdate[80];
04333    int inttime;
04334    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04335 
04336    /* Prepare variables for substitution in email body and subject */
04337    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04338    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04339    snprintf(num, sizeof(num), "%d", msgnum);
04340    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04341    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04342    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04343    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04344       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04345    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04346    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04347    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04348    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04349    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04350 
04351    /* Retrieve info from VM attribute file */
04352    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04353    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04354    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04355       strcat(fromfile, ".txt");
04356    }
04357    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04358       if (option_debug > 0) {
04359          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04360       }
04361       return;
04362    }
04363 
04364    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04365       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04366       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04367       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04368       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04369    }
04370 
04371    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04372       struct timeval tv = { inttime, };
04373       struct ast_tm tm;
04374       ast_localtime(&tv, &tm, NULL);
04375       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04376       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04377    }
04378    ast_config_destroy(msg_cfg);
04379 }

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

Definition at line 6995 of file app_voicemail.c.

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

06996 {
06997    struct ast_event *event;
06998    char *mailbox, *context;
06999 
07000    /* Strip off @default */
07001    context = mailbox = ast_strdupa(box);
07002    strsep(&context, "@");
07003    if (ast_strlen_zero(context))
07004       context = "default";
07005 
07006    if (!(event = ast_event_new(AST_EVENT_MWI,
07007          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07008          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07009          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07010          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07011          AST_EVENT_IE_END))) {
07012       return;
07013    }
07014 
07015    ast_event_queue_and_cache(event);
07016 }

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

Definition at line 12501 of file app_voicemail.c.

References ast_config_load, ast_copy_string(), ast_log(), ast_variable_retrieve(), config_flags, and LOG_NOTICE.

Referenced by actual_load_config(), and append_mailbox().

12501                                                                                            {
12502    struct ast_config *pwconf;
12503    struct ast_flags config_flags = { 0 };
12504 
12505    pwconf = ast_config_load(secretfn, config_flags);
12506    if (pwconf) {
12507       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12508       if (val) {
12509          ast_copy_string(password, val, passwordlen);
12510          return;
12511       }
12512    }
12513    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12514 }

static int reload ( void   )  [static]

Definition at line 13022 of file app_voicemail.c.

References load_config().

13023 {
13024    return load_config(1);
13025 }

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

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

03995 {
03996    char stxt[PATH_MAX];
03997    char dtxt[PATH_MAX];
03998    ast_filerename(sfn, dfn, NULL);
03999    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04000    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04001    if (ast_check_realtime("voicemail_data")) {
04002       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04003    }
04004    rename(stxt, dtxt);
04005 }

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

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

06138 {
06139    /* we know the actual number of messages, so stop process when number is hit */
06140 
06141    int x, dest;
06142    char sfn[PATH_MAX];
06143    char dfn[PATH_MAX];
06144 
06145    if (vm_lock_path(dir)) {
06146       return ERROR_LOCK_PATH;
06147    }
06148 
06149    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06150       make_file(sfn, sizeof(sfn), dir, x);
06151       if (EXISTS(dir, x, sfn, NULL)) {
06152 
06153          if (x != dest) {
06154             make_file(dfn, sizeof(dfn), dir, dest);
06155             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06156          }
06157 
06158          dest++;
06159       }
06160    }
06161    ast_unlock_path(dir);
06162 
06163    return dest;
06164 }

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

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

Referenced by vm_change_password(), and vm_change_password_shell().

01481 {
01482    /* This function could be made to generate one from a database, too */
01483    struct ast_vm_user *cur;
01484    int res = -1;
01485    AST_LIST_LOCK(&users);
01486    AST_LIST_TRAVERSE(&users, cur, list) {
01487       if ((!context || !strcasecmp(context, cur->context)) &&
01488          (!strcasecmp(mailbox, cur->mailbox)))
01489             break;
01490    }
01491    if (cur) {
01492       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01493       res = 0;
01494    }
01495    AST_LIST_UNLOCK(&users);
01496    return res;
01497 }

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

Definition at line 5510 of file app_voicemail.c.

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

05511 {
05512    char arguments[255];
05513    char ext_context[256] = "";
05514    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05515    struct ast_smdi_mwi_message *mwi_msg;
05516 
05517    if (!ast_strlen_zero(context))
05518       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05519    else
05520       ast_copy_string(ext_context, extension, sizeof(ext_context));
05521 
05522    if (smdi_iface) {
05523       if (ast_app_has_voicemail(ext_context, NULL)) 
05524          ast_smdi_mwi_set(smdi_iface, extension);
05525       else
05526          ast_smdi_mwi_unset(smdi_iface, extension);
05527 
05528       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05529          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05530          if (!strncmp(mwi_msg->cause, "INV", 3))
05531             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05532          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05533             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05534          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05535          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05536       } else {
05537          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05538       }
05539    }
05540 
05541    if (!ast_strlen_zero(externnotify)) {
05542       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05543          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05544       } else {
05545          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05546          ast_debug(1, "Executing %s\n", arguments);
05547          ast_safe_system(arguments);
05548       }
05549    }
05550 }

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

Definition at line 6174 of file app_voicemail.c.

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

Referenced by close_mailbox(), and vm_execmain().

06175 {
06176 #ifdef IMAP_STORAGE
06177    /* we must use mbox(x) folder names, and copy the message there */
06178    /* simple. huh? */
06179    char sequence[10];
06180    char mailbox[256];
06181    int res;
06182 
06183    /* get the real IMAP message number for this message */
06184    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06185    
06186    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06187    ast_mutex_lock(&vms->lock);
06188    /* if save to Old folder, put in INBOX as read */
06189    if (box == OLD_FOLDER) {
06190       mail_setflag(vms->mailstream, sequence, "\\Seen");
06191       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06192    } else if (box == NEW_FOLDER) {
06193       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06194       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06195    }
06196    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06197       ast_mutex_unlock(&vms->lock);
06198       return 0;
06199    }
06200    /* Create the folder if it don't exist */
06201    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06202    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06203    if (mail_create(vms->mailstream, mailbox) == NIL) 
06204       ast_debug(5, "Folder exists.\n");
06205    else
06206       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06207    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06208    ast_mutex_unlock(&vms->lock);
06209    return res;
06210 #else
06211    char *dir = vms->curdir;
06212    char *username = vms->username;
06213    char *context = vmu->context;
06214    char sfn[PATH_MAX];
06215    char dfn[PATH_MAX];
06216    char ddir[PATH_MAX];
06217    const char *dbox = mbox(vmu, box);
06218    int x, i;
06219    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06220 
06221    if (vm_lock_path(ddir))
06222       return ERROR_LOCK_PATH;
06223 
06224    x = last_message_index(vmu, ddir) + 1;
06225 
06226    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06227       x--;
06228       for (i = 1; i <= x; i++) {
06229          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06230          make_file(sfn, sizeof(sfn), ddir, i);
06231          make_file(dfn, sizeof(dfn), ddir, i - 1);
06232          if (EXISTS(ddir, i, sfn, NULL)) {
06233             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06234          } else
06235             break;
06236       }
06237    } else {
06238       if (x >= vmu->maxmsg) {
06239          ast_unlock_path(ddir);
06240          return -1;
06241       }
06242    }
06243    make_file(sfn, sizeof(sfn), dir, msg);
06244    make_file(dfn, sizeof(dfn), ddir, x);
06245    if (strcmp(sfn, dfn)) {
06246       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06247    }
06248    ast_unlock_path(ddir);
06249 #endif
06250    return 0;
06251 }

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

Definition at line 6167 of file app_voicemail.c.

References AST_DIGIT_ANY, and ast_say_number().

Referenced by play_message_duration(), vm_execmain(), vm_intro_cs(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_it(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_se(), vm_intro_vi(), and vm_intro_zh().

06168 {
06169    int d;
06170    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06171    return d;
06172 }

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

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

12488 {
12489    int res = -1;
12490    char dir[PATH_MAX];
12491    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12492    ast_debug(2, "About to try retrieving name file %s\n", dir);
12493    RETRIEVE(dir, -1, mailbox, context);
12494    if (ast_fileexists(dir, NULL, NULL)) {
12495       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12496    }
12497    DISPOSE(dir, -1);
12498    return res;
12499 }

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

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

04841 {
04842    FILE *p = NULL;
04843    char tmp[80] = "/tmp/astmail-XXXXXX";
04844    char tmp2[256];
04845    char *stringp;
04846 
04847    if (vmu && ast_strlen_zero(vmu->email)) {
04848       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04849       return(0);
04850    }
04851 
04852    /* Mail only the first format */
04853    format = ast_strdupa(format);
04854    stringp = format;
04855    strsep(&stringp, "|");
04856 
04857    if (!strcmp(format, "wav49"))
04858       format = "WAV";
04859    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04860    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04861       command hangs */
04862    if ((p = vm_mkftemp(tmp)) == NULL) {
04863       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04864       return -1;
04865    } else {
04866       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04867       fclose(p);
04868       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04869       ast_safe_system(tmp2);
04870       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04871    }
04872    return 0;
04873 }

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

References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_log(), 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_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().

04876 {
04877    char enc_cidnum[256], enc_cidname[256];
04878    char date[256];
04879    char host[MAXHOSTNAMELEN] = "";
04880    char who[256];
04881    char dur[PATH_MAX];
04882    char tmp[80] = "/tmp/astmail-XXXXXX";
04883    char tmp2[PATH_MAX];
04884    struct ast_tm tm;
04885    FILE *p;
04886    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04887 
04888    if (!str1 || !str2) {
04889       ast_free(str1);
04890       ast_free(str2);
04891       return -1;
04892    }
04893 
04894    if (cidnum) {
04895       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04896    }
04897    if (cidname) {
04898       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04899    }
04900 
04901    if ((p = vm_mkftemp(tmp)) == NULL) {
04902       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04903       ast_free(str1);
04904       ast_free(str2);
04905       return -1;
04906    }
04907    gethostname(host, sizeof(host)-1);
04908    if (strchr(srcemail, '@')) {
04909       ast_copy_string(who, srcemail, sizeof(who));
04910    } else {
04911       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04912    }
04913    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04914    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04915    fprintf(p, "Date: %s\n", date);
04916 
04917    /* Reformat for custom pager format */
04918    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04919 
04920    if (!ast_strlen_zero(pagerfromstring)) {
04921       struct ast_channel *ast;
04922       if ((ast = ast_dummy_channel_alloc())) {
04923          char *ptr;
04924          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04925          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04926 
04927          if (check_mime(ast_str_buffer(str1))) {
04928             int first_line = 1;
04929             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04930             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04931                *ptr = '\0';
04932                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04933                first_line = 0;
04934                /* Substring is smaller, so this will never grow */
04935                ast_str_set(&str2, 0, "%s", ptr + 1);
04936             }
04937             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04938          } else {
04939             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04940          }
04941          ast = ast_channel_unref(ast);
04942       } else {
04943          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04944       }
04945    } else {
04946       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04947    }
04948 
04949    if (check_mime(vmu->fullname)) {
04950       int first_line = 1;
04951       char *ptr;
04952       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04953       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04954          *ptr = '\0';
04955          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04956          first_line = 0;
04957          /* Substring is smaller, so this will never grow */
04958          ast_str_set(&str2, 0, "%s", ptr + 1);
04959       }
04960       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04961    } else {
04962       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
04963    }
04964 
04965    if (!ast_strlen_zero(pagersubject)) {
04966       struct ast_channel *ast;
04967       if ((ast = ast_dummy_channel_alloc())) {
04968          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04969          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
04970          if (check_mime(ast_str_buffer(str1))) {
04971             int first_line = 1;
04972             char *ptr;
04973             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04974             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04975                *ptr = '\0';
04976                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04977                first_line = 0;
04978                /* Substring is smaller, so this will never grow */
04979                ast_str_set(&str2, 0, "%s", ptr + 1);
04980             }
04981             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04982          } else {
04983             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04984          }
04985          ast = ast_channel_unref(ast);
04986       } else {
04987          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04988       }
04989    } else {
04990       if (ast_strlen_zero(flag)) {
04991          fprintf(p, "Subject: New VM\n\n");
04992       } else {
04993          fprintf(p, "Subject: New %s VM\n\n", flag);
04994       }
04995    }
04996 
04997    if (pagerbody) {
04998       struct ast_channel *ast;
04999       if ((ast = ast_dummy_channel_alloc())) {
05000          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05001          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
05002          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
05003          ast = ast_channel_unref(ast);
05004       } else {
05005          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05006       }
05007    } else {
05008       fprintf(p, "New %s long %s msg in box %s\n"
05009             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
05010    }
05011 
05012    fclose(p);
05013    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
05014    ast_safe_system(tmp2);
05015    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
05016    ast_free(str1);
05017    ast_free(str2);
05018    return 0;
05019 }

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

Definition at line 11065 of file app_voicemail.c.

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

Referenced by handle_voicemail_show_users().

11066 {
11067    struct ast_config *cfg;
11068    const char *cat = NULL;
11069 
11070    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11071       "context", context, SENTINEL))) {
11072       return CLI_FAILURE;
11073    }
11074 
11075    ast_cli(fd,
11076       "\n"
11077       "=============================================================\n"
11078       "=== Configured Voicemail Users ==============================\n"
11079       "=============================================================\n"
11080       "===\n");
11081 
11082    while ((cat = ast_category_browse(cfg, cat))) {
11083       struct ast_variable *var = NULL;
11084       ast_cli(fd,
11085          "=== Mailbox ...\n"
11086          "===\n");
11087       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11088          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11089       ast_cli(fd,
11090          "===\n"
11091          "=== ---------------------------------------------------------\n"
11092          "===\n");
11093    }
11094 
11095    ast_cli(fd,
11096       "=============================================================\n"
11097       "\n");
11098 
11099    ast_config_destroy(cfg);
11100 
11101    return CLI_SUCCESS;
11102 }

static void start_poll_thread ( void   )  [static]

Definition at line 11560 of file app_voicemail.c.

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

Referenced by actual_load_config().

static void stop_poll_thread ( void   )  [static]

Definition at line 11578 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_lock, poll_thread, and poll_thread_run.

Referenced by actual_load_config(), and unload_module().

11579 {
11580    poll_thread_run = 0;
11581 
11582    if (mwi_sub_sub) {
11583       ast_event_unsubscribe(mwi_sub_sub);
11584       mwi_sub_sub = NULL;
11585    }
11586 
11587    if (mwi_unsub_sub) {
11588       ast_event_unsubscribe(mwi_unsub_sub);
11589       mwi_unsub_sub = NULL;
11590    }
11591 
11592    ast_mutex_lock(&poll_lock);
11593    ast_cond_signal(&poll_cond);
11594    ast_mutex_unlock(&poll_lock);
11595 
11596    pthread_join(poll_thread, NULL);
11597 
11598    poll_thread = AST_PTHREADT_NULL;
11599 }

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

Referenced by make_email_file(), and sendpage().

00985 {
00986    char *bufptr = buf;
00987    for (; *input; input++) {
00988       if (*input < 32) {
00989          continue;
00990       }
00991       *bufptr++ = *input;
00992       if (bufptr == buf + buflen - 1) {
00993          break;
00994       }
00995    }
00996    *bufptr = '\0';
00997    return buf;
00998 }

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

Definition at line 11724 of file app_voicemail.c.

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

Referenced by actual_load_config(), and apply_option().

11725 {
11726    char *current;
11727 
11728    /* Add 16 for fudge factor */
11729    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11730 
11731    ast_str_reset(str);
11732    
11733    /* Substitute strings \r, \n, and \t into the appropriate characters */
11734    for (current = (char *) value; *current; current++) {
11735       if (*current == '\\') {
11736          current++;
11737          if (!*current) {
11738             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11739             break;
11740          }
11741          switch (*current) {
11742          case '\\':
11743             ast_str_append(&str, 0, "\\");
11744             break;
11745          case 'r':
11746             ast_str_append(&str, 0, "\r");
11747             break;
11748          case 'n':
11749 #ifdef IMAP_STORAGE
11750             if (!str->used || str->str[str->used - 1] != '\r') {
11751                ast_str_append(&str, 0, "\r");
11752             }
11753 #endif
11754             ast_str_append(&str, 0, "\n");
11755             break;
11756          case 't':
11757             ast_str_append(&str, 0, "\t");
11758             break;
11759          default:
11760             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11761             break;
11762          }
11763       } else {
11764          ast_str_append(&str, 0, "%c", *current);
11765       }
11766    }
11767 
11768    return ast_str_buffer(str);
11769 }

static int unload_module ( void   )  [static]

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

13028 {
13029    int res;
13030 
13031    res = ast_unregister_application(app);
13032    res |= ast_unregister_application(app2);
13033    res |= ast_unregister_application(app3);
13034    res |= ast_unregister_application(app4);
13035    res |= ast_unregister_application(sayname_app);
13036    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13037    res |= ast_manager_unregister("VoicemailUsersList");
13038    res |= ast_data_unregister(NULL);
13039 #ifdef TEST_FRAMEWORK
13040    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13041    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13042    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13043    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13044    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13045 #endif
13046    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13047    ast_uninstall_vm_functions();
13048    ao2_ref(inprocess_container, -1);
13049 
13050    if (poll_thread != AST_PTHREADT_NULL)
13051       stop_poll_thread();
13052 
13053    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13054    ast_unload_realtime("voicemail");
13055    ast_unload_realtime("voicemail_data");
13056 
13057    free_vm_users();
13058    free_vm_zones();
13059    return res;
13060 }

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

Definition at line 1750 of file app_voicemail.c.

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

Referenced by open_mailbox().

01750                                                                                         {
01751 
01752    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01753    if (!vms->dh_arraysize) {
01754       /* initial allocation */
01755       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01756          return -1;
01757       }
01758       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01759          return -1;
01760       }
01761       vms->dh_arraysize = arraysize;
01762    } else if (vms->dh_arraysize < arraysize) {
01763       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01764          return -1;
01765       }
01766       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01767          return -1;
01768       }
01769       memset(vms->deleted, 0, arraysize * sizeof(int));
01770       memset(vms->heard, 0, arraysize * sizeof(int));
01771       vms->dh_arraysize = arraysize;
01772    }
01773 
01774    return 0;
01775 }

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

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

Referenced by vm_execmain(), and vmauthenticate().

09730 {
09731    int useadsi = 0, valid = 0, logretries = 0;
09732    char password[AST_MAX_EXTENSION]="", *passptr;
09733    struct ast_vm_user vmus, *vmu = NULL;
09734 
09735    /* If ADSI is supported, setup login screen */
09736    adsi_begin(chan, &useadsi);
09737    if (!skipuser && useadsi)
09738       adsi_login(chan);
09739    ast_test_suite_event_notify("PLAYBACK", "Message: vm-login");
09740    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09741       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09742       return -1;
09743    }
09744 
09745    /* Authenticate them and get their mailbox/password */
09746 
09747    while (!valid && (logretries < max_logins)) {
09748       /* Prompt for, and read in the username */
09749       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09750          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09751          return -1;
09752       }
09753       if (ast_strlen_zero(mailbox)) {
09754          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09755             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09756          } else {
09757             ast_verb(3, "Username not entered\n"); 
09758             return -1;
09759          }
09760       } else if (mailbox[0] == '*') {
09761          /* user entered '*' */
09762          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09763          if (ast_exists_extension(chan, chan->context, "a", 1,
09764             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09765             return -1;
09766          }
09767          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09768          mailbox[0] = '\0';
09769       }
09770 
09771       if (useadsi)
09772          adsi_password(chan);
09773 
09774       if (!ast_strlen_zero(prefix)) {
09775          char fullusername[80] = "";
09776          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09777          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09778          ast_copy_string(mailbox, fullusername, mailbox_size);
09779       }
09780 
09781       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09782       vmu = find_user(&vmus, context, mailbox);
09783       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09784          /* saved password is blank, so don't bother asking */
09785          password[0] = '\0';
09786       } else {
09787          ast_test_suite_event_notify("PLAYBACK", "Message: %s", vm_password);
09788          if (ast_streamfile(chan, vm_password, chan->language)) {
09789             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09790             return -1;
09791          }
09792          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09793             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09794             return -1;
09795          } else if (password[0] == '*') {
09796             /* user entered '*' */
09797             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09798             if (ast_exists_extension(chan, chan->context, "a", 1,
09799                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09800                mailbox[0] = '*';
09801                return -1;
09802             }
09803             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09804             mailbox[0] = '\0';
09805             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09806             vmu = NULL;
09807          }
09808       }
09809 
09810       if (vmu) {
09811          passptr = vmu->password;
09812          if (passptr[0] == '-') passptr++;
09813       }
09814       if (vmu && !strcmp(passptr, password))
09815          valid++;
09816       else {
09817          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09818          if (!ast_strlen_zero(prefix))
09819             mailbox[0] = '\0';
09820       }
09821       logretries++;
09822       if (!valid) {
09823          if (skipuser || logretries >= max_logins) {
09824             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect");
09825             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09826                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09827                return -1;
09828             }
09829          } else {
09830             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect-mailbox");
09831             if (useadsi)
09832                adsi_login(chan);
09833             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09834                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09835                return -1;
09836             }
09837          }
09838          if (ast_waitstream(chan, "")) /* Channel is hung up */
09839             return -1;
09840       }
09841    }
09842    if (!valid && (logretries >= max_logins)) {
09843       ast_stopstream(chan);
09844       ast_play_and_wait(chan, "vm-goodbye");
09845       return -1;
09846    }
09847    if (vmu && !skipuser) {
09848       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09849    }
09850    return 0;
09851 }

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

Definition at line 10960 of file app_voicemail.c.

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

Referenced by load_module().

10961 {
10962    struct ast_vm_user svm;
10963    char *context, *box;
10964    AST_DECLARE_APP_ARGS(args,
10965       AST_APP_ARG(mbox);
10966       AST_APP_ARG(options);
10967    );
10968    static int dep_warning = 0;
10969 
10970    if (ast_strlen_zero(data)) {
10971       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10972       return -1;
10973    }
10974 
10975    if (!dep_warning) {
10976       dep_warning = 1;
10977       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10978    }
10979 
10980    box = ast_strdupa(data);
10981 
10982    AST_STANDARD_APP_ARGS(args, box);
10983 
10984    if (args.options) {
10985    }
10986 
10987    if ((context = strchr(args.mbox, '@'))) {
10988       *context = '\0';
10989       context++;
10990    }
10991 
10992    if (find_user(&svm, context, args.mbox)) {
10993       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10994    } else
10995       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10996 
10997    return 0;
10998 }

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

References ast_channel::language, vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

09707 {
09708    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09709       return vm_browse_messages_es(chan, vms, vmu);
09710    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09711       return vm_browse_messages_gr(chan, vms, vmu);
09712    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09713       return vm_browse_messages_he(chan, vms, vmu);
09714    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09715       return vm_browse_messages_it(chan, vms, vmu);
09716    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09717       return vm_browse_messages_pt(chan, vms, vmu);
09718    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09719       return vm_browse_messages_vi(chan, vms, vmu);
09720    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09721       return vm_browse_messages_zh(chan, vms, vmu);
09722    } else {                                             /* Default to English syntax */
09723       return vm_browse_messages_en(chan, vms, vmu);
09724    }
09725 }

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

09546 {
09547    int cmd = 0;
09548 
09549    if (vms->lastmsg > -1) {
09550       cmd = play_message(chan, vmu, vms);
09551    } else {
09552       cmd = ast_play_and_wait(chan, "vm-youhave");
09553       if (!cmd) 
09554          cmd = ast_play_and_wait(chan, "vm-no");
09555       if (!cmd) {
09556          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09557          cmd = ast_play_and_wait(chan, vms->fn);
09558       }
09559       if (!cmd)
09560          cmd = ast_play_and_wait(chan, "vm-messages");
09561    }
09562    return cmd;
09563 }

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

09600 {
09601    int cmd;
09602 
09603    if (vms->lastmsg > -1) {
09604       cmd = play_message(chan, vmu, vms);
09605    } else {
09606       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09607       if (!cmd)
09608          cmd = ast_play_and_wait(chan, "vm-messages");
09609       if (!cmd) {
09610          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09611          cmd = ast_play_and_wait(chan, vms->fn);
09612       }
09613    }
09614    return cmd;
09615 }

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

09494 {
09495    int cmd = 0;
09496 
09497    if (vms->lastmsg > -1) {
09498       cmd = play_message(chan, vmu, vms);
09499    } else {
09500       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09501       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09502          if (!cmd) {
09503             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09504             cmd = ast_play_and_wait(chan, vms->fn);
09505          }
09506          if (!cmd)
09507             cmd = ast_play_and_wait(chan, "vm-messages");
09508       } else {
09509          if (!cmd)
09510             cmd = ast_play_and_wait(chan, "vm-messages");
09511          if (!cmd) {
09512             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09513             cmd = ast_play_and_wait(chan, vms->fn);
09514          }
09515       }
09516    } 
09517    return cmd;
09518 }

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

Definition at line 9521 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09522 {
09523    int cmd = 0;
09524 
09525    if (vms->lastmsg > -1) {
09526       cmd = play_message(chan, vmu, vms);
09527    } else {
09528       if (!strcasecmp(vms->fn, "INBOX")) {
09529          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09530       } else {
09531          cmd = ast_play_and_wait(chan, "vm-nomessages");
09532       }
09533    }
09534    return cmd;
09535 }

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

09574 {
09575    int cmd;
09576 
09577    if (vms->lastmsg > -1) {
09578       cmd = play_message(chan, vmu, vms);
09579    } else {
09580       cmd = ast_play_and_wait(chan, "vm-no");
09581       if (!cmd)
09582          cmd = ast_play_and_wait(chan, "vm-message");
09583       if (!cmd) {
09584          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09585          cmd = ast_play_and_wait(chan, vms->fn);
09586       }
09587    }
09588    return cmd;
09589 }

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

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

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

09680 {
09681    int cmd = 0;
09682 
09683    if (vms->lastmsg > -1) {
09684       cmd = play_message(chan, vmu, vms);
09685    } else {
09686       cmd = ast_play_and_wait(chan, "vm-no");
09687       if (!cmd) {
09688          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09689          cmd = ast_play_and_wait(chan, vms->fn);
09690       }
09691    }
09692    return cmd;
09693 }

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

09652 {
09653    int cmd;
09654 
09655    if (vms->lastmsg > -1) {
09656       cmd = play_message(chan, vmu, vms);
09657    } else {
09658       cmd = ast_play_and_wait(chan, "vm-you");
09659       if (!cmd) 
09660          cmd = ast_play_and_wait(chan, "vm-haveno");
09661       if (!cmd)
09662          cmd = ast_play_and_wait(chan, "vm-messages");
09663       if (!cmd) {
09664          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09665          cmd = ast_play_and_wait(chan, vms->fn);
09666       }
09667    }
09668    return cmd;
09669 }

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

References ast_category_browse(), ast_category_get(), 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, config_flags, CONFIG_STATUS_FILEINVALID, 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(), value, var, VM_SPOOL_DIR, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser(), and vm_options().

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

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

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

01610 {
01611    char buf[255];
01612    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01613    ast_debug(1, "External password: %s\n",buf);
01614    if (!ast_safe_system(buf)) {
01615       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01616       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01617       /* Reset the password in memory, too */
01618       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01619    }
01620 }

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

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

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

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

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

04180 {
04181    char *txt;
04182    int txtsize = 0;
04183 
04184    txtsize = (strlen(file) + 5)*sizeof(char);
04185    txt = alloca(txtsize);
04186    /* Sprintf here would safe because we alloca'd exactly the right length,
04187     * but trying to eliminate all sprintf's anyhow
04188     */
04189    if (ast_check_realtime("voicemail_data")) {
04190       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04191    }
04192    snprintf(txt, txtsize, "%s.txt", file);
04193    unlink(txt);
04194    return ast_filedelete(file, NULL);
04195 }

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

Definition at line 10619 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_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, ast_flags::flags, 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 vm_app_options.

Referenced by load_module(), and play_record_review().

10620 {
10621    int res = 0;
10622    char *tmp;
10623    struct leave_vm_options leave_options;
10624    struct ast_flags flags = { 0 };
10625    char *opts[OPT_ARG_ARRAY_SIZE];
10626    AST_DECLARE_APP_ARGS(args,
10627       AST_APP_ARG(argv0);
10628       AST_APP_ARG(argv1);
10629    );
10630    
10631    memset(&leave_options, 0, sizeof(leave_options));
10632 
10633    if (chan->_state != AST_STATE_UP)
10634       ast_answer(chan);
10635 
10636    if (!ast_strlen_zero(data)) {
10637       tmp = ast_strdupa(data);
10638       AST_STANDARD_APP_ARGS(args, tmp);
10639       if (args.argc == 2) {
10640          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10641             return -1;
10642          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10643          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10644             int gain;
10645 
10646             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10647                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10648                return -1;
10649             } else {
10650                leave_options.record_gain = (signed char) gain;
10651             }
10652          }
10653          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10654             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10655                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10656          }
10657       }
10658    } else {
10659       char temp[256];
10660       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10661       if (res < 0)
10662          return res;
10663       if (ast_strlen_zero(temp))
10664          return 0;
10665       args.argv0 = ast_strdupa(temp);
10666    }
10667 
10668    res = leave_voicemail(chan, args.argv0, &leave_options);
10669    if (res == 't') {
10670       ast_play_and_wait(chan, "vm-goodbye");
10671       res = 0;
10672    }
10673 
10674    if (res == OPERATOR_EXIT) {
10675       res = 0;
10676    }
10677 
10678    if (res == ERROR_LOCK_PATH) {
10679       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10680       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10681       res = 0;
10682    }
10683 
10684    return res;
10685 }

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

Definition at line 9853 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_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_goto_if_exists(), ast_log(), AST_LOG_ERROR, 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, ast_channel::context, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), ast_flags::flags, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, has_voicemail(), language, ast_vm_user::language, ast_vm_user::mailbox, make_file(), maxlogins, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, 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(), run_externnotify(), save_to_folder(), say_and_wait(), vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, VM_SVMAIL, and vmfmts.

Referenced by load_module().

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

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 6842 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, config_flags, CONFIG_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, maxsilence, play_record_review(), silencethreshold, vm_pls_try_again, and vm_prepend_timeout.

Referenced by forward_message().

06844 {
06845    int cmd = 0;
06846    int retries = 0, prepend_duration = 0, already_recorded = 0;
06847    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06848    char textfile[PATH_MAX];
06849    struct ast_config *msg_cfg;
06850    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06851 #ifndef IMAP_STORAGE
06852    signed char zero_gain = 0;
06853 #endif
06854    const char *duration_str;
06855 
06856    /* Must always populate duration correctly */
06857    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06858    strcpy(textfile, msgfile);
06859    strcpy(backup, msgfile);
06860    strcpy(backup_textfile, msgfile);
06861    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06862    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06863    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06864 
06865    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06866       *duration = atoi(duration_str);
06867    } else {
06868       *duration = 0;
06869    }
06870 
06871    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06872       if (cmd)
06873          retries = 0;
06874       switch (cmd) {
06875       case '1': 
06876 
06877 #ifdef IMAP_STORAGE
06878          /* Record new intro file */
06879          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06880          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06881          ast_play_and_wait(chan, INTRO);
06882          ast_play_and_wait(chan, "beep");
06883          play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag);
06884          cmd = 't';
06885 #else
06886 
06887          /* prepend a message to the current message, update the metadata and return */
06888 
06889          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06890          strcpy(textfile, msgfile);
06891          strncat(textfile, ".txt", sizeof(textfile) - 1);
06892          *duration = 0;
06893 
06894          /* if we can't read the message metadata, stop now */
06895          if (!msg_cfg) {
06896             cmd = 0;
06897             break;
06898          }
06899 
06900          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06901 #ifndef IMAP_STORAGE
06902          if (already_recorded) {
06903             ast_filecopy(backup, msgfile, NULL);
06904             copy(backup_textfile, textfile);
06905          }
06906          else {
06907             ast_filecopy(msgfile, backup, NULL);
06908             copy(textfile, backup_textfile);
06909          }
06910 #endif
06911          already_recorded = 1;
06912 
06913          if (record_gain)
06914             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06915 
06916          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
06917 
06918          if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
06919             ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
06920             ast_stream_and_wait(chan, vm_prepend_timeout, "");
06921             ast_filerename(backup, msgfile, NULL);
06922          }
06923 
06924          if (record_gain)
06925             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06926 
06927          
06928          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06929             *duration = atoi(duration_str);
06930 
06931          if (prepend_duration) {
06932             struct ast_category *msg_cat;
06933             /* need enough space for a maximum-length message duration */
06934             char duration_buf[12];
06935 
06936             *duration += prepend_duration;
06937             msg_cat = ast_category_get(msg_cfg, "message");
06938             snprintf(duration_buf, 11, "%ld", *duration);
06939             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06940                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06941             }
06942          }
06943 
06944 #endif
06945          break;
06946       case '2': 
06947          /* NULL out introfile so we know there is no intro! */
06948 #ifdef IMAP_STORAGE
06949          *vms->introfn = '\0';
06950 #endif
06951          cmd = 't';
06952          break;
06953       case '*':
06954          cmd = '*';
06955          break;
06956       default: 
06957          /* If time_out and return to menu, reset already_recorded */
06958          already_recorded = 0;
06959 
06960          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
06961             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06962          if (!cmd) {
06963             cmd = ast_play_and_wait(chan, "vm-starmain");
06964             /* "press star to return to the main menu" */
06965          }
06966          if (!cmd) {
06967             cmd = ast_waitfordigit(chan, 6000);
06968          }
06969          if (!cmd) {
06970             retries++;
06971          }
06972          if (retries > 3) {
06973             cmd = '*'; /* Let's cancel this beast */
06974          }
06975          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
06976       }
06977    }
06978 
06979    if (msg_cfg)
06980       ast_config_destroy(msg_cfg);
06981    if (prepend_duration)
06982       *duration = prepend_duration;
06983 
06984    if (already_recorded && cmd == -1) {
06985       /* restore original message if prepention cancelled */
06986       ast_filerename(backup, msgfile, NULL);
06987       rename(backup_textfile, textfile);
06988    }
06989 
06990    if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */
06991       cmd = 0;
06992    return cmd;
06993 }

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

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

Referenced by vm_execmain().

09172 {
09173    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09174       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09175    } else {             /* Default to ENGLISH */
09176       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09177    }
09178 }

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

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

Referenced by vm_instructions(), and vm_instructions_zh().

09071 {
09072    int res = 0;
09073    /* Play instructions and wait for new command */
09074    while (!res) {
09075       if (vms->starting) {
09076          if (vms->lastmsg > -1) {
09077             if (skipadvanced)
09078                res = ast_play_and_wait(chan, "vm-onefor-full");
09079             else
09080                res = ast_play_and_wait(chan, "vm-onefor");
09081             if (!res)
09082                res = vm_play_folder_name(chan, vms->vmbox);
09083          }
09084          if (!res) {
09085             if (skipadvanced)
09086                res = ast_play_and_wait(chan, "vm-opts-full");
09087             else
09088                res = ast_play_and_wait(chan, "vm-opts");
09089          }
09090       } else {
09091          /* Added for additional help */
09092          if (skipadvanced) {
09093             res = ast_play_and_wait(chan, "vm-onefor-full");
09094             if (!res)
09095                res = vm_play_folder_name(chan, vms->vmbox);
09096             res = ast_play_and_wait(chan, "vm-opts-full");
09097          }
09098          /* Logic:
09099           * If the current message is not the first OR
09100           * if we're listening to the first new message and there are
09101           * also urgent messages, then prompt for navigation to the
09102           * previous message
09103           */
09104          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09105             res = ast_play_and_wait(chan, "vm-prev");
09106          }
09107          if (!res && !skipadvanced)
09108             res = ast_play_and_wait(chan, "vm-advopts");
09109          if (!res)
09110             res = ast_play_and_wait(chan, "vm-repeat");
09111          /* Logic:
09112           * If we're not listening to the last message OR
09113           * we're listening to the last urgent message and there are
09114           * also new non-urgent messages, then prompt for navigation
09115           * to the next message
09116           */
09117          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09118             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09119             res = ast_play_and_wait(chan, "vm-next");
09120          }
09121          if (!res) {
09122             if (!vms->deleted[vms->curmsg])
09123                res = ast_play_and_wait(chan, "vm-delete");
09124             else
09125                res = ast_play_and_wait(chan, "vm-undelete");
09126             if (!res)
09127                res = ast_play_and_wait(chan, "vm-toforward");
09128             if (!res)
09129                res = ast_play_and_wait(chan, "vm-savemessage");
09130          }
09131       }
09132       if (!res) {
09133          res = ast_play_and_wait(chan, "vm-helpexit");
09134       }
09135       if (!res)
09136          res = ast_waitfordigit(chan, 6000);
09137       if (!res) {
09138          vms->repeats++;
09139          if (vms->repeats > 2) {
09140             res = 't';
09141          }
09142       }
09143    }
09144    return res;
09145 }

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

09148 {
09149    int res = 0;
09150    /* Play instructions and wait for new command */
09151    while (!res) {
09152       if (vms->lastmsg > -1) {
09153          res = ast_play_and_wait(chan, "vm-listen");
09154          if (!res)
09155             res = vm_play_folder_name(chan, vms->vmbox);
09156          if (!res)
09157             res = ast_play_and_wait(chan, "press");
09158          if (!res)
09159             res = ast_play_and_wait(chan, "digits/1");
09160       }
09161       if (!res)
09162          res = ast_play_and_wait(chan, "vm-opts");
09163       if (!res) {
09164          vms->starting = 0;
09165          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09166       }
09167    }
09168    return res;
09169 }

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

Definition at line 9008 of file app_voicemail.c.

References ast_fileexists(), ast_log(), ast_play_and_wait(), ast_test_flag, ast_vm_user::context, DISPOSE, ast_channel::language, 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().

09009 {
09010    char prefile[256];
09011    
09012    /* Notify the user that the temp greeting is set and give them the option to remove it */
09013    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09014    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09015       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09016       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09017          ast_play_and_wait(chan, "vm-tempgreetactive");
09018       }
09019       DISPOSE(prefile, -1);
09020    }
09021 
09022    /* Play voicemail intro - syntax is different for different languages */
09023    if (0) {
09024       return 0;
09025    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09026       return vm_intro_cs(chan, vms);
09027    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09028       static int deprecation_warning = 0;
09029       if (deprecation_warning++ % 10 == 0) {
09030          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09031       }
09032       return vm_intro_cs(chan, vms);
09033    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09034       return vm_intro_de(chan, vms);
09035    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09036       return vm_intro_es(chan, vms);
09037    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09038       return vm_intro_fr(chan, vms);
09039    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09040       return vm_intro_gr(chan, vms);
09041    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09042       return vm_intro_he(chan, vms);
09043    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09044       return vm_intro_it(chan, vms);
09045    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09046       return vm_intro_nl(chan, vms);
09047    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09048       return vm_intro_no(chan, vms);
09049    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09050       return vm_intro_pl(chan, vms);
09051    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09052       return vm_intro_pt_BR(chan, vms);
09053    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09054       return vm_intro_pt(chan, vms);
09055    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09056       return vm_intro_multilang(chan, vms, "n");
09057    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09058       return vm_intro_se(chan, vms);
09059    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09060       return vm_intro_multilang(chan, vms, "n");
09061    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09062       return vm_intro_vi(chan, vms);
09063    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09064       return vm_intro_zh(chan, vms);
09065    } else {                                             /* Default to ENGLISH */
09066       return vm_intro_en(chan, vms);
09067    }
09068 }

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

Definition at line 8878 of file app_voicemail.c.

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

Referenced by vm_intro().

08879 {
08880    int res;
08881    res = ast_play_and_wait(chan, "vm-youhave");
08882    if (!res) {
08883       if (vms->newmessages) {
08884          if (vms->newmessages == 1) {
08885             res = ast_play_and_wait(chan, "digits/jednu");
08886          } else {
08887             res = say_and_wait(chan, vms->newmessages, chan->language);
08888          }
08889          if (!res) {
08890             if ((vms->newmessages == 1))
08891                res = ast_play_and_wait(chan, "vm-novou");
08892             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08893                res = ast_play_and_wait(chan, "vm-nove");
08894             if (vms->newmessages > 4)
08895                res = ast_play_and_wait(chan, "vm-novych");
08896          }
08897          if (vms->oldmessages && !res)
08898             res = ast_play_and_wait(chan, "vm-and");
08899          else if (!res) {
08900             if ((vms->newmessages == 1))
08901                res = ast_play_and_wait(chan, "vm-zpravu");
08902             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08903                res = ast_play_and_wait(chan, "vm-zpravy");
08904             if (vms->newmessages > 4)
08905                res = ast_play_and_wait(chan, "vm-zprav");
08906          }
08907       }
08908       if (!res && vms->oldmessages) {
08909          res = say_and_wait(chan, vms->oldmessages, chan->language);
08910          if (!res) {
08911             if ((vms->oldmessages == 1))
08912                res = ast_play_and_wait(chan, "vm-starou");
08913             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08914                res = ast_play_and_wait(chan, "vm-stare");
08915             if (vms->oldmessages > 4)
08916                res = ast_play_and_wait(chan, "vm-starych");
08917          }
08918          if (!res) {
08919             if ((vms->oldmessages == 1))
08920                res = ast_play_and_wait(chan, "vm-zpravu");
08921             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08922                res = ast_play_and_wait(chan, "vm-zpravy");
08923             if (vms->oldmessages > 4)
08924                res = ast_play_and_wait(chan, "vm-zprav");
08925          }
08926       }
08927       if (!res) {
08928          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08929             res = ast_play_and_wait(chan, "vm-no");
08930             if (!res)
08931                res = ast_play_and_wait(chan, "vm-zpravy");
08932          }
08933       }
08934    }
08935    return res;
08936 }

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

Definition at line 8574 of file app_voicemail.c.

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

Referenced by vm_intro().

08575 {
08576    /* Introduce messages they have */
08577    int res;
08578    res = ast_play_and_wait(chan, "vm-youhave");
08579    if (!res) {
08580       if (vms->newmessages) {
08581          if ((vms->newmessages == 1))
08582             res = ast_play_and_wait(chan, "digits/1F");
08583          else
08584             res = say_and_wait(chan, vms->newmessages, chan->language);
08585          if (!res)
08586             res = ast_play_and_wait(chan, "vm-INBOX");
08587          if (vms->oldmessages && !res)
08588             res = ast_play_and_wait(chan, "vm-and");
08589          else if (!res) {
08590             if ((vms->newmessages == 1))
08591                res = ast_play_and_wait(chan, "vm-message");
08592             else
08593                res = ast_play_and_wait(chan, "vm-messages");
08594          }
08595             
08596       }
08597       if (!res && vms->oldmessages) {
08598          if (vms->oldmessages == 1)
08599             res = ast_play_and_wait(chan, "digits/1F");
08600          else
08601             res = say_and_wait(chan, vms->oldmessages, chan->language);
08602          if (!res)
08603             res = ast_play_and_wait(chan, "vm-Old");
08604          if (!res) {
08605             if (vms->oldmessages == 1)
08606                res = ast_play_and_wait(chan, "vm-message");
08607             else
08608                res = ast_play_and_wait(chan, "vm-messages");
08609          }
08610       }
08611       if (!res) {
08612          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08613             res = ast_play_and_wait(chan, "vm-no");
08614             if (!res)
08615                res = ast_play_and_wait(chan, "vm-messages");
08616          }
08617       }
08618    }
08619    return res;
08620 }

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

Definition at line 8323 of file app_voicemail.c.

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

Referenced by vm_intro().

08324 {
08325    int res;
08326 
08327    /* Introduce messages they have */
08328    res = ast_play_and_wait(chan, "vm-youhave");
08329    if (!res) {
08330       if (vms->urgentmessages) {
08331          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08332          if (!res)
08333             res = ast_play_and_wait(chan, "vm-Urgent");
08334          if ((vms->oldmessages || vms->newmessages) && !res) {
08335             res = ast_play_and_wait(chan, "vm-and");
08336          } else if (!res) {
08337             if ((vms->urgentmessages == 1))
08338                res = ast_play_and_wait(chan, "vm-message");
08339             else
08340                res = ast_play_and_wait(chan, "vm-messages");
08341          }
08342       }
08343       if (vms->newmessages) {
08344          res = say_and_wait(chan, vms->newmessages, chan->language);
08345          if (!res)
08346             res = ast_play_and_wait(chan, "vm-INBOX");
08347          if (vms->oldmessages && !res)
08348             res = ast_play_and_wait(chan, "vm-and");
08349          else if (!res) {
08350             if ((vms->newmessages == 1))
08351                res = ast_play_and_wait(chan, "vm-message");
08352             else
08353                res = ast_play_and_wait(chan, "vm-messages");
08354          }
08355             
08356       }
08357       if (!res && vms->oldmessages) {
08358          res = say_and_wait(chan, vms->oldmessages, chan->language);
08359          if (!res)
08360             res = ast_play_and_wait(chan, "vm-Old");
08361          if (!res) {
08362             if (vms->oldmessages == 1)
08363                res = ast_play_and_wait(chan, "vm-message");
08364             else
08365                res = ast_play_and_wait(chan, "vm-messages");
08366          }
08367       }
08368       if (!res) {
08369          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08370             res = ast_play_and_wait(chan, "vm-no");
08371             if (!res)
08372                res = ast_play_and_wait(chan, "vm-messages");
08373          }
08374       }
08375    }
08376    return res;
08377 }

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

Definition at line 8623 of file app_voicemail.c.

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

Referenced by vm_intro().

08624 {
08625    /* Introduce messages they have */
08626    int res;
08627    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08628       res = ast_play_and_wait(chan, "vm-youhaveno");
08629       if (!res)
08630          res = ast_play_and_wait(chan, "vm-messages");
08631    } else {
08632       res = ast_play_and_wait(chan, "vm-youhave");
08633    }
08634    if (!res) {
08635       if (vms->newmessages) {
08636          if (!res) {
08637             if ((vms->newmessages == 1)) {
08638                res = ast_play_and_wait(chan, "digits/1M");
08639                if (!res)
08640                   res = ast_play_and_wait(chan, "vm-message");
08641                if (!res)
08642                   res = ast_play_and_wait(chan, "vm-INBOXs");
08643             } else {
08644                res = say_and_wait(chan, vms->newmessages, chan->language);
08645                if (!res)
08646                   res = ast_play_and_wait(chan, "vm-messages");
08647                if (!res)
08648                   res = ast_play_and_wait(chan, "vm-INBOX");
08649             }
08650          }
08651          if (vms->oldmessages && !res)
08652             res = ast_play_and_wait(chan, "vm-and");
08653       }
08654       if (vms->oldmessages) {
08655          if (!res) {
08656             if (vms->oldmessages == 1) {
08657                res = ast_play_and_wait(chan, "digits/1M");
08658                if (!res)
08659                   res = ast_play_and_wait(chan, "vm-message");
08660                if (!res)
08661                   res = ast_play_and_wait(chan, "vm-Olds");
08662             } else {
08663                res = say_and_wait(chan, vms->oldmessages, chan->language);
08664                if (!res)
08665                   res = ast_play_and_wait(chan, "vm-messages");
08666                if (!res)
08667                   res = ast_play_and_wait(chan, "vm-Old");
08668             }
08669          }
08670       }
08671    }
08672 return res;
08673 }

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

Definition at line 8721 of file app_voicemail.c.

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

Referenced by vm_intro().

08722 {
08723    /* Introduce messages they have */
08724    int res;
08725    res = ast_play_and_wait(chan, "vm-youhave");
08726    if (!res) {
08727       if (vms->newmessages) {
08728          res = say_and_wait(chan, vms->newmessages, chan->language);
08729          if (!res)
08730             res = ast_play_and_wait(chan, "vm-INBOX");
08731          if (vms->oldmessages && !res)
08732             res = ast_play_and_wait(chan, "vm-and");
08733          else if (!res) {
08734             if ((vms->newmessages == 1))
08735                res = ast_play_and_wait(chan, "vm-message");
08736             else
08737                res = ast_play_and_wait(chan, "vm-messages");
08738          }
08739             
08740       }
08741       if (!res && vms->oldmessages) {
08742          res = say_and_wait(chan, vms->oldmessages, chan->language);
08743          if (!res)
08744             res = ast_play_and_wait(chan, "vm-Old");
08745          if (!res) {
08746             if (vms->oldmessages == 1)
08747                res = ast_play_and_wait(chan, "vm-message");
08748             else
08749                res = ast_play_and_wait(chan, "vm-messages");
08750          }
08751       }
08752       if (!res) {
08753          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08754             res = ast_play_and_wait(chan, "vm-no");
08755             if (!res)
08756                res = ast_play_and_wait(chan, "vm-messages");
08757          }
08758       }
08759    }
08760    return res;
08761 }

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

Definition at line 8122 of file app_voicemail.c.

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

Referenced by vm_intro().

08123 {
08124    int res = 0;
08125 
08126    if (vms->newmessages) {
08127       res = ast_play_and_wait(chan, "vm-youhave");
08128       if (!res) 
08129          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08130       if (!res) {
08131          if ((vms->newmessages == 1)) {
08132             res = ast_play_and_wait(chan, "vm-INBOX");
08133             if (!res)
08134                res = ast_play_and_wait(chan, "vm-message");
08135          } else {
08136             res = ast_play_and_wait(chan, "vm-INBOXs");
08137             if (!res)
08138                res = ast_play_and_wait(chan, "vm-messages");
08139          }
08140       }
08141    } else if (vms->oldmessages){
08142       res = ast_play_and_wait(chan, "vm-youhave");
08143       if (!res)
08144          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08145       if ((vms->oldmessages == 1)){
08146          res = ast_play_and_wait(chan, "vm-Old");
08147          if (!res)
08148             res = ast_play_and_wait(chan, "vm-message");
08149       } else {
08150          res = ast_play_and_wait(chan, "vm-Olds");
08151          if (!res)
08152             res = ast_play_and_wait(chan, "vm-messages");
08153       }
08154    } else if (!vms->oldmessages && !vms->newmessages) 
08155       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08156    return res;
08157 }

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

Definition at line 8256 of file app_voicemail.c.

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

Referenced by vm_intro().

08257 {
08258    int res = 0;
08259 
08260    /* Introduce messages they have */
08261    if (!res) {
08262       if ((vms->newmessages) || (vms->oldmessages)) {
08263          res = ast_play_and_wait(chan, "vm-youhave");
08264       }
08265       /*
08266        * The word "shtei" refers to the number 2 in hebrew when performing a count
08267        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08268        * an element, this is one of them.
08269        */
08270       if (vms->newmessages) {
08271          if (!res) {
08272             if (vms->newmessages == 1) {
08273                res = ast_play_and_wait(chan, "vm-INBOX1");
08274             } else {
08275                if (vms->newmessages == 2) {
08276                   res = ast_play_and_wait(chan, "vm-shtei");
08277                } else {
08278                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08279                }
08280                res = ast_play_and_wait(chan, "vm-INBOX");
08281             }
08282          }
08283          if (vms->oldmessages && !res) {
08284             res = ast_play_and_wait(chan, "vm-and");
08285             if (vms->oldmessages == 1) {
08286                res = ast_play_and_wait(chan, "vm-Old1");
08287             } else {
08288                if (vms->oldmessages == 2) {
08289                   res = ast_play_and_wait(chan, "vm-shtei");
08290                } else {
08291                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08292                }
08293                res = ast_play_and_wait(chan, "vm-Old");
08294             }
08295          }
08296       }
08297       if (!res && vms->oldmessages && !vms->newmessages) {
08298          if (!res) {
08299             if (vms->oldmessages == 1) {
08300                res = ast_play_and_wait(chan, "vm-Old1");
08301             } else {
08302                if (vms->oldmessages == 2) {
08303                   res = ast_play_and_wait(chan, "vm-shtei");
08304                } else {
08305                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08306                }
08307                res = ast_play_and_wait(chan, "vm-Old");
08308             }
08309          }
08310       }
08311       if (!res) {
08312          if (!vms->oldmessages && !vms->newmessages) {
08313             if (!res) {
08314                res = ast_play_and_wait(chan, "vm-nomessages");
08315             }
08316          }
08317       }
08318    }
08319    return res;
08320 }

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

Definition at line 8380 of file app_voicemail.c.

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

Referenced by vm_intro().

08381 {
08382    /* Introduce messages they have */
08383    int res;
08384    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08385       res = ast_play_and_wait(chan, "vm-no") ||
08386          ast_play_and_wait(chan, "vm-message");
08387    else
08388       res = ast_play_and_wait(chan, "vm-youhave");
08389    if (!res && vms->newmessages) {
08390       res = (vms->newmessages == 1) ?
08391          ast_play_and_wait(chan, "digits/un") ||
08392          ast_play_and_wait(chan, "vm-nuovo") ||
08393          ast_play_and_wait(chan, "vm-message") :
08394          /* 2 or more new messages */
08395          say_and_wait(chan, vms->newmessages, chan->language) ||
08396          ast_play_and_wait(chan, "vm-nuovi") ||
08397          ast_play_and_wait(chan, "vm-messages");
08398       if (!res && vms->oldmessages)
08399          res = ast_play_and_wait(chan, "vm-and");
08400    }
08401    if (!res && vms->oldmessages) {
08402       res = (vms->oldmessages == 1) ?
08403          ast_play_and_wait(chan, "digits/un") ||
08404          ast_play_and_wait(chan, "vm-vecchio") ||
08405          ast_play_and_wait(chan, "vm-message") :
08406          /* 2 or more old messages */
08407          say_and_wait(chan, vms->oldmessages, chan->language) ||
08408          ast_play_and_wait(chan, "vm-vecchi") ||
08409          ast_play_and_wait(chan, "vm-messages");
08410    }
08411    return res;
08412 }

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

Definition at line 8216 of file app_voicemail.c.

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

Referenced by vm_intro().

08217 {
08218    int res;
08219    int lastnum = 0;
08220 
08221    res = ast_play_and_wait(chan, "vm-youhave");
08222 
08223    if (!res && vms->newmessages) {
08224       lastnum = vms->newmessages;
08225 
08226       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08227          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08228       }
08229 
08230       if (!res && vms->oldmessages) {
08231          res = ast_play_and_wait(chan, "vm-and");
08232       }
08233    }
08234 
08235    if (!res && vms->oldmessages) {
08236       lastnum = vms->oldmessages;
08237 
08238       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08239          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08240       }
08241    }
08242 
08243    if (!res) {
08244       if (lastnum == 0) {
08245          res = ast_play_and_wait(chan, "vm-no");
08246       }
08247       if (!res) {
08248          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08249       }
08250    }
08251 
08252    return res;
08253 }

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

Definition at line 8764 of file app_voicemail.c.

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

Referenced by vm_intro().

08765 {
08766    /* Introduce messages they have */
08767    int res;
08768    res = ast_play_and_wait(chan, "vm-youhave");
08769    if (!res) {
08770       if (vms->newmessages) {
08771          res = say_and_wait(chan, vms->newmessages, chan->language);
08772          if (!res) {
08773             if (vms->newmessages == 1)
08774                res = ast_play_and_wait(chan, "vm-INBOXs");
08775             else
08776                res = ast_play_and_wait(chan, "vm-INBOX");
08777          }
08778          if (vms->oldmessages && !res)
08779             res = ast_play_and_wait(chan, "vm-and");
08780          else if (!res) {
08781             if ((vms->newmessages == 1))
08782                res = ast_play_and_wait(chan, "vm-message");
08783             else
08784                res = ast_play_and_wait(chan, "vm-messages");
08785          }
08786             
08787       }
08788       if (!res && vms->oldmessages) {
08789          res = say_and_wait(chan, vms->oldmessages, chan->language);
08790          if (!res) {
08791             if (vms->oldmessages == 1)
08792                res = ast_play_and_wait(chan, "vm-Olds");
08793             else
08794                res = ast_play_and_wait(chan, "vm-Old");
08795          }
08796          if (!res) {
08797             if (vms->oldmessages == 1)
08798                res = ast_play_and_wait(chan, "vm-message");
08799             else
08800                res = ast_play_and_wait(chan, "vm-messages");
08801          }
08802       }
08803       if (!res) {
08804          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08805             res = ast_play_and_wait(chan, "vm-no");
08806             if (!res)
08807                res = ast_play_and_wait(chan, "vm-messages");
08808          }
08809       }
08810    }
08811    return res;
08812 }

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

Definition at line 8530 of file app_voicemail.c.

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

Referenced by vm_intro().

08531 {
08532    /* Introduce messages they have */
08533    int res;
08534 
08535    res = ast_play_and_wait(chan, "vm-youhave");
08536    if (res)
08537       return res;
08538 
08539    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08540       res = ast_play_and_wait(chan, "vm-no");
08541       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08542       return res;
08543    }
08544 
08545    if (vms->newmessages) {
08546       if ((vms->newmessages == 1)) {
08547          res = ast_play_and_wait(chan, "digits/1");
08548          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08549          res = res ? res : ast_play_and_wait(chan, "vm-message");
08550       } else {
08551          res = say_and_wait(chan, vms->newmessages, chan->language);
08552          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08553          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08554       }
08555       if (!res && vms->oldmessages)
08556          res = ast_play_and_wait(chan, "vm-and");
08557    }
08558    if (!res && vms->oldmessages) {
08559       if (vms->oldmessages == 1) {
08560          res = ast_play_and_wait(chan, "digits/1");
08561          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08562          res = res ? res : ast_play_and_wait(chan, "vm-message");
08563       } else {
08564          res = say_and_wait(chan, vms->oldmessages, chan->language);
08565          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08566          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08567       }
08568    }
08569 
08570    return res;
08571 }

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

Definition at line 8415 of file app_voicemail.c.

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

Referenced by vm_intro().

08416 {
08417    /* Introduce messages they have */
08418    int res;
08419    div_t num;
08420 
08421    if (!vms->oldmessages && !vms->newmessages) {
08422       res = ast_play_and_wait(chan, "vm-no");
08423       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08424       return res;
08425    } else {
08426       res = ast_play_and_wait(chan, "vm-youhave");
08427    }
08428 
08429    if (vms->newmessages) {
08430       num = div(vms->newmessages, 10);
08431       if (vms->newmessages == 1) {
08432          res = ast_play_and_wait(chan, "digits/1-a");
08433          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08434          res = res ? res : ast_play_and_wait(chan, "vm-message");
08435       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08436          if (num.rem == 2) {
08437             if (!num.quot) {
08438                res = ast_play_and_wait(chan, "digits/2-ie");
08439             } else {
08440                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08441                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08442             }
08443          } else {
08444             res = say_and_wait(chan, vms->newmessages, chan->language);
08445          }
08446          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08447          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08448       } else {
08449          res = say_and_wait(chan, vms->newmessages, chan->language);
08450          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08451          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08452       }
08453       if (!res && vms->oldmessages)
08454          res = ast_play_and_wait(chan, "vm-and");
08455    }
08456    if (!res && vms->oldmessages) {
08457       num = div(vms->oldmessages, 10);
08458       if (vms->oldmessages == 1) {
08459          res = ast_play_and_wait(chan, "digits/1-a");
08460          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08461          res = res ? res : ast_play_and_wait(chan, "vm-message");
08462       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08463          if (num.rem == 2) {
08464             if (!num.quot) {
08465                res = ast_play_and_wait(chan, "digits/2-ie");
08466             } else {
08467                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08468                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08469             }
08470          } else {
08471             res = say_and_wait(chan, vms->oldmessages, chan->language);
08472          }
08473          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08474          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08475       } else {
08476          res = say_and_wait(chan, vms->oldmessages, chan->language);
08477          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08478          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08479       }
08480    }
08481 
08482    return res;
08483 }

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

Definition at line 8815 of file app_voicemail.c.

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

Referenced by vm_intro().

08816 {
08817    /* Introduce messages they have */
08818    int res;
08819    res = ast_play_and_wait(chan, "vm-youhave");
08820    if (!res) {
08821       if (vms->newmessages) {
08822          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08823          if (!res) {
08824             if ((vms->newmessages == 1)) {
08825                res = ast_play_and_wait(chan, "vm-message");
08826                if (!res)
08827                   res = ast_play_and_wait(chan, "vm-INBOXs");
08828             } else {
08829                res = ast_play_and_wait(chan, "vm-messages");
08830                if (!res)
08831                   res = ast_play_and_wait(chan, "vm-INBOX");
08832             }
08833          }
08834          if (vms->oldmessages && !res)
08835             res = ast_play_and_wait(chan, "vm-and");
08836       }
08837       if (!res && vms->oldmessages) {
08838          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08839          if (!res) {
08840             if (vms->oldmessages == 1) {
08841                res = ast_play_and_wait(chan, "vm-message");
08842                if (!res)
08843                   res = ast_play_and_wait(chan, "vm-Olds");
08844             } else {
08845                res = ast_play_and_wait(chan, "vm-messages");
08846                if (!res)
08847                   res = ast_play_and_wait(chan, "vm-Old");
08848             }
08849          }
08850       }
08851       if (!res) {
08852          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08853             res = ast_play_and_wait(chan, "vm-no");
08854             if (!res)
08855                res = ast_play_and_wait(chan, "vm-messages");
08856          }
08857       }
08858    }
08859    return res;
08860 }

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

Definition at line 8676 of file app_voicemail.c.

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

Referenced by vm_intro().

08676                                                                           {
08677    /* Introduce messages they have */
08678    int res;
08679    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08680       res = ast_play_and_wait(chan, "vm-nomessages");
08681       return res;
08682    } else {
08683       res = ast_play_and_wait(chan, "vm-youhave");
08684    }
08685    if (vms->newmessages) {
08686       if (!res)
08687          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08688       if ((vms->newmessages == 1)) {
08689          if (!res)
08690             res = ast_play_and_wait(chan, "vm-message");
08691          if (!res)
08692             res = ast_play_and_wait(chan, "vm-INBOXs");
08693       } else {
08694          if (!res)
08695             res = ast_play_and_wait(chan, "vm-messages");
08696          if (!res)
08697             res = ast_play_and_wait(chan, "vm-INBOX");
08698       }
08699       if (vms->oldmessages && !res)
08700          res = ast_play_and_wait(chan, "vm-and");
08701    }
08702    if (vms->oldmessages) {
08703       if (!res)
08704          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08705       if (vms->oldmessages == 1) {
08706          if (!res)
08707             res = ast_play_and_wait(chan, "vm-message");
08708          if (!res)
08709             res = ast_play_and_wait(chan, "vm-Olds");
08710       } else {
08711          if (!res)
08712             res = ast_play_and_wait(chan, "vm-messages");
08713          if (!res)
08714             res = ast_play_and_wait(chan, "vm-Old");
08715       }
08716    }
08717    return res;
08718 }

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

Definition at line 8486 of file app_voicemail.c.

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

Referenced by vm_intro().

08487 {
08488    /* Introduce messages they have */
08489    int res;
08490 
08491    res = ast_play_and_wait(chan, "vm-youhave");
08492    if (res)
08493       return res;
08494 
08495    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08496       res = ast_play_and_wait(chan, "vm-no");
08497       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08498       return res;
08499    }
08500 
08501    if (vms->newmessages) {
08502       if ((vms->newmessages == 1)) {
08503          res = ast_play_and_wait(chan, "digits/ett");
08504          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08505          res = res ? res : ast_play_and_wait(chan, "vm-message");
08506       } else {
08507          res = say_and_wait(chan, vms->newmessages, chan->language);
08508          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08509          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08510       }
08511       if (!res && vms->oldmessages)
08512          res = ast_play_and_wait(chan, "vm-and");
08513    }
08514    if (!res && vms->oldmessages) {
08515       if (vms->oldmessages == 1) {
08516          res = ast_play_and_wait(chan, "digits/ett");
08517          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08518          res = res ? res : ast_play_and_wait(chan, "vm-message");
08519       } else {
08520          res = say_and_wait(chan, vms->oldmessages, chan->language);
08521          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08522          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08523       }
08524    }
08525 
08526    return res;
08527 }

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

Definition at line 8978 of file app_voicemail.c.

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

Referenced by vm_intro().

08979 {
08980    int res;
08981 
08982    /* Introduce messages they have */
08983    res = ast_play_and_wait(chan, "vm-youhave");
08984    if (!res) {
08985       if (vms->newmessages) {
08986          res = say_and_wait(chan, vms->newmessages, chan->language);
08987          if (!res)
08988             res = ast_play_and_wait(chan, "vm-INBOX");
08989          if (vms->oldmessages && !res)
08990             res = ast_play_and_wait(chan, "vm-and");
08991       }
08992       if (!res && vms->oldmessages) {
08993          res = say_and_wait(chan, vms->oldmessages, chan->language);
08994          if (!res)
08995             res = ast_play_and_wait(chan, "vm-Old");        
08996       }
08997       if (!res) {
08998          if (!vms->oldmessages && !vms->newmessages) {
08999             res = ast_play_and_wait(chan, "vm-no");
09000             if (!res)
09001                res = ast_play_and_wait(chan, "vm-message");
09002          }
09003       }
09004    }
09005    return res;
09006 }

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

Definition at line 8939 of file app_voicemail.c.

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

Referenced by vm_intro().

08940 {
08941    int res;
08942    /* Introduce messages they have */
08943    res = ast_play_and_wait(chan, "vm-you");
08944 
08945    if (!res && vms->newmessages) {
08946       res = ast_play_and_wait(chan, "vm-have");
08947       if (!res)
08948          res = say_and_wait(chan, vms->newmessages, chan->language);
08949       if (!res)
08950          res = ast_play_and_wait(chan, "vm-tong");
08951       if (!res)
08952          res = ast_play_and_wait(chan, "vm-INBOX");
08953       if (vms->oldmessages && !res)
08954          res = ast_play_and_wait(chan, "vm-and");
08955       else if (!res) 
08956          res = ast_play_and_wait(chan, "vm-messages");
08957    }
08958    if (!res && vms->oldmessages) {
08959       res = ast_play_and_wait(chan, "vm-have");
08960       if (!res)
08961          res = say_and_wait(chan, vms->oldmessages, chan->language);
08962       if (!res)
08963          res = ast_play_and_wait(chan, "vm-tong");
08964       if (!res)
08965          res = ast_play_and_wait(chan, "vm-Old");
08966       if (!res)
08967          res = ast_play_and_wait(chan, "vm-messages");
08968    }
08969    if (!res && !vms->oldmessages && !vms->newmessages) {
08970       res = ast_play_and_wait(chan, "vm-haveno");
08971       if (!res)
08972          res = ast_play_and_wait(chan, "vm-messages");
08973    }
08974    return res;
08975 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03257 {
03258    switch (ast_lock_path(path)) {
03259    case AST_LOCK_TIMEOUT:
03260       return -1;
03261    default:
03262       return 0;
03263    }
03264 }

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

Definition at line 1658 of file app_voicemail.c.

References my_umask, and VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01659 {
01660    FILE *p = NULL;
01661    int pfd = mkstemp(template);
01662    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01663    if (pfd > -1) {
01664       p = fdopen(pfd, "w+");
01665       if (!p) {
01666          close(pfd);
01667          pfd = -1;
01668       }
01669    }
01670    return p;
01671 }

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

09182 {
09183    int cmd = 0;
09184    int duration = 0;
09185    int tries = 0;
09186    char newpassword[80] = "";
09187    char newpassword2[80] = "";
09188    char prefile[PATH_MAX] = "";
09189    unsigned char buf[256];
09190    int bytes = 0;
09191 
09192    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09193    if (ast_adsi_available(chan)) {
09194       bytes += adsi_logo(buf + bytes);
09195       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09196       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09197       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09198       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09199       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09200    }
09201 
09202    /* If forcename is set, have the user record their name */
09203    if (ast_test_flag(vmu, VM_FORCENAME)) {
09204       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09205       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09206          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09207          if (cmd < 0 || cmd == 't' || cmd == '#')
09208             return cmd;
09209       }
09210    }
09211 
09212    /* If forcegreetings is set, have the user record their greetings */
09213    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09214       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09215       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09216          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09217          if (cmd < 0 || cmd == 't' || cmd == '#')
09218             return cmd;
09219       }
09220 
09221       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09222       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09223          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09224          if (cmd < 0 || cmd == 't' || cmd == '#')
09225             return cmd;
09226       }
09227    }
09228 
09229    /*
09230     * Change the password last since new users will be able to skip over any steps this one comes before
09231     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09232     */
09233    for (;;) {
09234       newpassword[1] = '\0';
09235       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09236       if (cmd == '#')
09237          newpassword[0] = '\0';
09238       if (cmd < 0 || cmd == 't' || cmd == '#')
09239          return cmd;
09240       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09241       if (cmd < 0 || cmd == 't' || cmd == '#')
09242          return cmd;
09243       cmd = check_password(vmu, newpassword); /* perform password validation */
09244       if (cmd != 0) {
09245          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09246          cmd = ast_play_and_wait(chan, vm_invalid_password);
09247       } else {
09248          newpassword2[1] = '\0';
09249          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09250          if (cmd == '#')
09251             newpassword2[0] = '\0';
09252          if (cmd < 0 || cmd == 't' || cmd == '#')
09253             return cmd;
09254          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09255          if (cmd < 0 || cmd == 't' || cmd == '#')
09256             return cmd;
09257          if (!strcmp(newpassword, newpassword2))
09258             break;
09259          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09260          cmd = ast_play_and_wait(chan, vm_mismatch);
09261       }
09262       if (++tries == 3)
09263          return -1;
09264       if (cmd != 0) {
09265          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09266       }
09267    }
09268    if (pwdchange & PWDCHANGE_INTERNAL)
09269       vm_change_password(vmu, newpassword);
09270    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09271       vm_change_password_shell(vmu, newpassword);
09272 
09273    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09274    cmd = ast_play_and_wait(chan, vm_passchanged);
09275 
09276    return cmd;
09277 }

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

09280 {
09281    int cmd = 0;
09282    int retries = 0;
09283    int duration = 0;
09284    char newpassword[80] = "";
09285    char newpassword2[80] = "";
09286    char prefile[PATH_MAX] = "";
09287    unsigned char buf[256];
09288    int bytes = 0;
09289 
09290    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09291    if (ast_adsi_available(chan)) {
09292       bytes += adsi_logo(buf + bytes);
09293       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09294       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09295       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09296       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09297       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09298    }
09299    while ((cmd >= 0) && (cmd != 't')) {
09300       if (cmd)
09301          retries = 0;
09302       switch (cmd) {
09303       case '1': /* Record your unavailable message */
09304          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09305          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09306          break;
09307       case '2':  /* Record your busy message */
09308          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09309          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09310          break;
09311       case '3': /* Record greeting */
09312          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09313          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09314          break;
09315       case '4':  /* manage the temporary greeting */
09316          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09317          break;
09318       case '5': /* change password */
09319          if (vmu->password[0] == '-') {
09320             cmd = ast_play_and_wait(chan, "vm-no");
09321             break;
09322          }
09323          newpassword[1] = '\0';
09324          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09325          if (cmd == '#')
09326             newpassword[0] = '\0';
09327          else {
09328             if (cmd < 0)
09329                break;
09330             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09331                break;
09332             }
09333          }
09334          cmd = check_password(vmu, newpassword); /* perform password validation */
09335          if (cmd != 0) {
09336             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09337             cmd = ast_play_and_wait(chan, vm_invalid_password);
09338             if (!cmd) {
09339                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09340             }
09341             break;
09342          }
09343          newpassword2[1] = '\0';
09344          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09345          if (cmd == '#')
09346             newpassword2[0] = '\0';
09347          else {
09348             if (cmd < 0)
09349                break;
09350 
09351             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09352                break;
09353             }
09354          }
09355          if (strcmp(newpassword, newpassword2)) {
09356             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09357             cmd = ast_play_and_wait(chan, vm_mismatch);
09358             if (!cmd) {
09359                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09360             }
09361             break;
09362          }
09363 
09364          if (pwdchange & PWDCHANGE_INTERNAL) {
09365             vm_change_password(vmu, newpassword);
09366          }
09367          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09368             vm_change_password_shell(vmu, newpassword);
09369          }
09370 
09371          ast_debug(1, "User %s set password to %s of length %d\n",
09372             vms->username, newpassword, (int) strlen(newpassword));
09373          cmd = ast_play_and_wait(chan, vm_passchanged);
09374          break;
09375       case '*': 
09376          cmd = 't';
09377          break;
09378       default: 
09379          cmd = 0;
09380          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09381          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09382          if (ast_fileexists(prefile, NULL, NULL)) {
09383             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09384          }
09385          DISPOSE(prefile, -1);
09386          if (!cmd) {
09387             cmd = ast_play_and_wait(chan, "vm-options");
09388          }
09389          if (!cmd) {
09390             cmd = ast_waitfordigit(chan, 6000);
09391          }
09392          if (!cmd) {
09393             retries++;
09394          }
09395          if (retries > 3) {
09396             cmd = 't';
09397          }
09398          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09399       }
09400    }
09401    if (cmd == 't')
09402       cmd = 0;
09403    return cmd;
09404 }

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

Definition at line 8085 of file app_voicemail.c.

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

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

08086 {
08087    int cmd;
08088 
08089    if (  !strncasecmp(chan->language, "it", 2) ||
08090         !strncasecmp(chan->language, "es", 2) ||
08091         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08092       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08093       return cmd ? cmd : ast_play_and_wait(chan, box);
08094    } else if (!strncasecmp(chan->language, "gr", 2)) {
08095       return vm_play_folder_name_gr(chan, box);
08096    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08097       return ast_play_and_wait(chan, box);
08098    } else if (!strncasecmp(chan->language, "pl", 2)) {
08099       return vm_play_folder_name_pl(chan, box);
08100    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08101       return vm_play_folder_name_ua(chan, box);
08102    } else if (!strncasecmp(chan->language, "vi", 2)) {
08103       return ast_play_and_wait(chan, box);
08104    } else {  /* Default English */
08105       cmd = ast_play_and_wait(chan, box);
08106       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08107    }
08108 }

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

Definition at line 8038 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08039 {
08040    int cmd;
08041    char *buf;
08042 
08043    buf = alloca(strlen(box) + 2);
08044    strcpy(buf, box);
08045    strcat(buf, "s");
08046 
08047    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08048       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08049       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08050    } else {
08051       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08052       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08053    }
08054 }

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

Definition at line 8056 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08057 {
08058    int cmd;
08059 
08060    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08061       if (!strcasecmp(box, "vm-INBOX"))
08062          cmd = ast_play_and_wait(chan, "vm-new-e");
08063       else
08064          cmd = ast_play_and_wait(chan, "vm-old-e");
08065       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08066    } else {
08067       cmd = ast_play_and_wait(chan, "vm-messages");
08068       return cmd ? cmd : ast_play_and_wait(chan, box);
08069    }
08070 }

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

Definition at line 8072 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08073 {
08074    int cmd;
08075 
08076    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08077       cmd = ast_play_and_wait(chan, "vm-messages");
08078       return cmd ? cmd : ast_play_and_wait(chan, box);
08079    } else {
08080       cmd = ast_play_and_wait(chan, box);
08081       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08082    }
08083 }

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

09423 {
09424    int cmd = 0;
09425    int retries = 0;
09426    int duration = 0;
09427    char prefile[PATH_MAX] = "";
09428    unsigned char buf[256];
09429    int bytes = 0;
09430 
09431    if (ast_adsi_available(chan)) {
09432       bytes += adsi_logo(buf + bytes);
09433       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09434       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09435       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09436       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09437       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09438    }
09439 
09440    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09441    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09442    while ((cmd >= 0) && (cmd != 't')) {
09443       if (cmd)
09444          retries = 0;
09445       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09446       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09447          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09448          cmd = 't';  
09449       } else {
09450          switch (cmd) {
09451          case '1':
09452             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09453             break;
09454          case '2':
09455             DELETE(prefile, -1, prefile, vmu);
09456             ast_play_and_wait(chan, "vm-tempremoved");
09457             cmd = 't';  
09458             break;
09459          case '*': 
09460             cmd = 't';
09461             break;
09462          default:
09463             cmd = ast_play_and_wait(chan,
09464                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09465                   "vm-tempgreeting2" : "vm-tempgreeting");
09466             if (!cmd) {
09467                cmd = ast_waitfordigit(chan, 6000);
09468             }
09469             if (!cmd) {
09470                retries++;
09471             }
09472             if (retries > 3) {
09473                cmd = 't';
09474             }
09475             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09476          }
09477       }
09478       DISPOSE(prefile, -1);
09479    }
09480    if (cmd == 't')
09481       cmd = 0;
09482    return cmd;
09483 }

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

Definition at line 11385 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::list, user, and vm_users_data_provider_get_helper().

11387 {
11388    struct ast_vm_user *user;
11389 
11390    AST_LIST_LOCK(&users);
11391    AST_LIST_TRAVERSE(&users, user, list) {
11392       vm_users_data_provider_get_helper(search, data_root, user);
11393    }
11394    AST_LIST_UNLOCK(&users);
11395 
11396    return 0;
11397 }

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 11338 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, inboxcount2(), vm_zone::list, vm_zone::name, and user.

Referenced by vm_users_data_provider_get().

11340 {
11341    struct ast_data *data_user, *data_zone;
11342    struct ast_data *data_state;
11343    struct vm_zone *zone = NULL;
11344    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11345    char ext_context[256] = "";
11346 
11347    data_user = ast_data_add_node(data_root, "user");
11348    if (!data_user) {
11349       return -1;
11350    }
11351 
11352    ast_data_add_structure(ast_vm_user, data_user, user);
11353 
11354    AST_LIST_LOCK(&zones);
11355    AST_LIST_TRAVERSE(&zones, zone, list) {
11356       if (!strcmp(zone->name, user->zonetag)) {
11357          break;
11358       }
11359    }
11360    AST_LIST_UNLOCK(&zones);
11361 
11362    /* state */
11363    data_state = ast_data_add_node(data_user, "state");
11364    if (!data_state) {
11365       return -1;
11366    }
11367    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11368    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11369    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11370    ast_data_add_int(data_state, "newmsg", newmsg);
11371    ast_data_add_int(data_state, "oldmsg", oldmsg);
11372 
11373    if (zone) {
11374       data_zone = ast_data_add_node(data_user, "zone");
11375       ast_data_add_structure(vm_zone, data_zone, zone);
11376    }
11377 
11378    if (!ast_data_search_match(search, data_user)) {
11379       ast_data_remove_node(data_root, data_user);
11380    }
11381 
11382    return 0;
11383 }

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

Definition at line 11024 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(), strsep(), and vm_authenticate().

Referenced by load_module().

11025 {
11026    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11027    struct ast_vm_user vmus;
11028    char *options = NULL;
11029    int silent = 0, skipuser = 0;
11030    int res = -1;
11031    
11032    if (data) {
11033       s = ast_strdupa(data);
11034       user = strsep(&s, ",");
11035       options = strsep(&s, ",");
11036       if (user) {
11037          s = user;
11038          user = strsep(&s, "@");
11039          context = strsep(&s, "");
11040          if (!ast_strlen_zero(user))
11041             skipuser++;
11042          ast_copy_string(mailbox, user, sizeof(mailbox));
11043       }
11044    }
11045 
11046    if (options) {
11047       silent = (strchr(options, 's')) != NULL;
11048    }
11049 
11050    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11051       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11052       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11053       ast_play_and_wait(chan, "auth-thankyou");
11054       res = 0;
11055    } else if (mailbox[0] == '*') {
11056       /* user entered '*' */
11057       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11058          res = 0; /* prevent hangup */
11059       }
11060    }
11061 
11062    return res;
11063 }

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

Definition at line 12542 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(), ast_channel::language, LOG_WARNING, and sayname().

Referenced by load_module().

12543 {
12544    char *context;
12545    char *args_copy;
12546    int res;
12547 
12548    if (ast_strlen_zero(data)) {
12549       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12550       return -1;
12551    }
12552 
12553    args_copy = ast_strdupa(data);
12554    if ((context = strchr(args_copy, '@'))) {
12555       *context++ = '\0';
12556    } else {
12557       context = "default";
12558    }
12559 
12560    if ((res = sayname(chan, args_copy, context) < 0)) {
12561       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12562       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12563       if (!res) {
12564          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12565       }
12566    }
12567 
12568    return res;
12569 }

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

fill in *tm for current time according to the proper timezone, if any.

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

Definition at line 4411 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

04412 {
04413    const struct vm_zone *z = NULL;
04414    struct timeval t = ast_tvnow();
04415 
04416    /* Does this user have a timezone specified? */
04417    if (!ast_strlen_zero(vmu->zonetag)) {
04418       /* Find the zone in the list */
04419       AST_LIST_LOCK(&zones);
04420       AST_LIST_TRAVERSE(&zones, z, list) {
04421          if (!strcmp(z->name, vmu->zonetag))
04422             break;
04423       }
04424       AST_LIST_UNLOCK(&zones);
04425    }
04426    ast_localtime(&t, tm, z ? z->timezone : NULL);
04427    return tm;
04428 }

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

Definition at line 7446 of file app_voicemail.c.

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

Referenced by advanced_options(), ast_say_date_da(), ast_say_date_de(), ast_say_date_pt(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_th(), ast_say_date_with_format_vi(), ast_say_date_with_format_zh(), ast_say_datetime_from_now_pt(), ast_say_number_full_pt(), ast_say_time_pt(), ast_say_time_pt_BR(), gr_say_number_female(), and play_message().

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

Definition at line 7438 of file app_voicemail.c.

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

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

07439 {
07440    int res;
07441    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07442       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07443    return res;
07444 }

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

Definition at line 12516 of file app_voicemail.c.

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

Referenced by vm_change_password().

12516                                                                               {
12517    struct ast_config *conf;
12518    struct ast_category *cat;
12519    struct ast_variable *var;
12520 
12521    if (!(conf=ast_config_new())) {
12522       ast_log(LOG_ERROR, "Error creating new config structure\n");
12523       return -1;
12524    }
12525    if (!(cat=ast_category_new("general","",1))) {
12526       ast_log(LOG_ERROR, "Error creating new category structure\n");
12527       return -1;
12528    }
12529    if (!(var=ast_variable_new("password",password,""))) {
12530       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12531       return -1;
12532    }
12533    ast_category_append(conf,cat);
12534    ast_variable_append(cat,var);
12535    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12536       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12537       return -1;
12538    }
12539    return 0;
12540 }


Variable Documentation

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

Definition at line 13621 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 769 of file app_voicemail.c.

Referenced by adsi_load_vmail().

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

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

Referenced by actual_load_config(), and adsi_load_vmail().

int adsiver = 1 [static]

Definition at line 898 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 772 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 775 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 777 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 778 of file app_voicemail.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 13621 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 882 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

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

Definition at line 894 of file app_voicemail.c.

Referenced by actual_load_config(), ast_str_encode_mime(), make_email_file(), and tds_load_module().

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 885 of file app_voicemail.c.

Referenced by actual_load_config(), and play_message_callerid().

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

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

Definition at line 11261 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 881 of file app_voicemail.c.

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

char* emailbody = NULL [static]

Definition at line 888 of file app_voicemail.c.

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

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

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

Referenced by actual_load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

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

Referenced by actual_load_config().

char ext_pass_cmd[128] [static]

Definition at line 748 of file app_voicemail.c.

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

char externnotify[160] [static]

Definition at line 792 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

char fromstring[100] [static]

Definition at line 892 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

struct ast_flags globalflags = {0} [static]

Definition at line 877 of file app_voicemail.c.

struct ao2_container* inprocess_container

Definition at line 921 of file app_voicemail.c.

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

char listen_control_forward_key[12] [static]

Definition at line 850 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 852 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 853 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 851 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 854 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char locale[20] [static]

Definition at line 785 of file app_voicemail.c.

Referenced by actual_load_config().

struct ast_custom_function mailbox_exists_acf [static]

Initial value:

 {
   .name = "MAILBOX_EXISTS",
   .read = acf_mailbox_exists,
}

Definition at line 11019 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

const char* const mailbox_folders[] [static]

Definition at line 1694 of file app_voicemail.c.

char mailcmd[160] [static]

Definition at line 791 of file app_voicemail.c.

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

int maxdeletedmsg [static]

Definition at line 788 of file app_voicemail.c.

Referenced by actual_load_config().

int maxgreet [static]

Definition at line 798 of file app_voicemail.c.

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

int maxlogins [static]

Definition at line 800 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_execmain().

int maxmsg [static]

Definition at line 787 of file app_voicemail.c.

Referenced by actual_load_config(), and copy_message().

int maxsilence [static]

Definition at line 786 of file app_voicemail.c.

Referenced by actual_load_config(), ast_record_review(), play_record_review(), and vm_forwardoptions().

int minpassword [static]

Definition at line 801 of file app_voicemail.c.

Referenced by actual_load_config().

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 819 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

struct ast_taskprocessor* mwi_subscription_tps [static]

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

Referenced by start_poll_thread(), and stop_poll_thread().

int my_umask [static]

Definition at line 751 of file app_voicemail.c.

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

char* pagerbody = NULL [static]

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

Referenced by actual_load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 893 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 891 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

int passwordlocation [static]

Definition at line 802 of file app_voicemail.c.

Referenced by actual_load_config().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 814 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

unsigned int poll_freq [static]

Polling frequency

Definition at line 809 of file app_voicemail.c.

Referenced by actual_load_config(), and mb_poll_thread().

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

Definition at line 813 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

unsigned int poll_mailboxes [static]

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

Definition at line 806 of file app_voicemail.c.

Referenced by actual_load_config().

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 815 of file app_voicemail.c.

Referenced by actual_load_config(), start_poll_thread(), stop_poll_thread(), and unload_module().

unsigned char poll_thread_run [static]

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

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

int saydurationminfo [static]

Definition at line 879 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

char* sayname_app = "VMSayName" [static]

Definition at line 780 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char serveremail[80] [static]

Definition at line 790 of file app_voicemail.c.

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

int silencethreshold = 128 [static]

Definition at line 789 of file app_voicemail.c.

Referenced by actual_load_config(), ast_record_review(), play_record_review(), setup_privacy_args(), and vm_forwardoptions().

int skipms [static]

Definition at line 799 of file app_voicemail.c.

Referenced by actual_load_config(), controlplayback_exec(), handle_controlstreamfile(), and wait_file().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 793 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

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

Definition at line 767 of file app_voicemail.c.

Referenced by actual_load_config().

struct ast_app_option vm_app_options[128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }} [static]

Definition at line 532 of file app_voicemail.c.

Referenced by vm_exec(), and vm_execmain().

struct ast_data_entry vm_data_providers[] [static]

Initial value:

 {

}

Definition at line 11404 of file app_voicemail.c.

Referenced by load_module().

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

Definition at line 862 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 861 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 858 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 859 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 857 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 863 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 875 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_forwardoptions().

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

Definition at line 860 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 746 of file app_voicemail.c.

Referenced by __has_voicemail(), actual_load_config(), append_mailbox(), forward_message(), invent_message(), leave_voicemail(), load_module(), make_dir(), notify_new_message(), play_message_callerid(), sayname(), vm_change_password(), vm_intro(), vm_newuser(), vm_options(), and vm_tempgreeting().

struct ast_data_handler vm_users_data_provider [static]

Initial value:

Definition at line 11399 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 794 of file app_voicemail.c.

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

int vmmaxsecs [static]

Definition at line 797 of file app_voicemail.c.

Referenced by actual_load_config().

int vmminsecs [static]

Definition at line 796 of file app_voicemail.c.

Referenced by actual_load_config().

double volgain [static]

Definition at line 795 of file app_voicemail.c.

Referenced by actual_load_config().

char zonetag[80] [static]

Definition at line 784 of file app_voicemail.c.

Referenced by actual_load_config(), and build_peer().


Generated on Mon Mar 19 11:30:34 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7