Mon Oct 8 12:39:08 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 = "ac1f6a56484a8820659555499174e588" , .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 11333 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 11361 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 5377 of file app_voicemail.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

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

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

static void __reg_module ( void   )  [static]

Definition at line 13680 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

11036 {
11037    struct ast_vm_user svm;
11038    AST_DECLARE_APP_ARGS(arg,
11039       AST_APP_ARG(mbox);
11040       AST_APP_ARG(context);
11041    );
11042 
11043    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11044 
11045    if (ast_strlen_zero(arg.mbox)) {
11046       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11047       return -1;
11048    }
11049 
11050    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11051    return 0;
11052 }

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

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

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

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

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

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

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

06398 {
06399    int x;
06400    if (!ast_adsi_available(chan))
06401       return;
06402    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06403    if (x < 0)
06404       return;
06405    if (!x) {
06406       if (adsi_load_vmail(chan, useadsi)) {
06407          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06408          return;
06409       }
06410    } else
06411       *useadsi = 1;
06412 }

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

Definition at line 6592 of file app_voicemail.c.

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

Referenced by vm_execmain().

06593 {
06594    int bytes = 0;
06595    unsigned char buf[256];
06596    unsigned char keys[8];
06597 
06598    int x;
06599 
06600    if (!ast_adsi_available(chan))
06601       return;
06602 
06603    /* New meaning for keys */
06604    for (x = 0; x < 5; x++)
06605       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06606 
06607    keys[6] = 0x0;
06608    keys[7] = 0x0;
06609 
06610    if (!vms->curmsg) {
06611       /* No prev key, provide "Folder" instead */
06612       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06613    }
06614    if (vms->curmsg >= vms->lastmsg) {
06615       /* If last message ... */
06616       if (vms->curmsg) {
06617          /* but not only message, provide "Folder" instead */
06618          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06619       } else {
06620          /* Otherwise if only message, leave blank */
06621          keys[3] = 1;
06622       }
06623    }
06624 
06625    /* If deleted, show "undeleted" */
06626 #ifdef IMAP_STORAGE
06627    ast_mutex_lock(&vms->lock);
06628 #endif
06629    if (vms->deleted[vms->curmsg]) {
06630       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06631    }
06632 #ifdef IMAP_STORAGE
06633    ast_mutex_unlock(&vms->lock);
06634 #endif
06635 
06636    /* Except "Exit" */
06637    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06638    bytes += ast_adsi_set_keys(buf + bytes, keys);
06639    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06640 
06641    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06642 }

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

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

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

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06748 {
06749    unsigned char buf[256];
06750    int bytes = 0;
06751 
06752    if (!ast_adsi_available(chan))
06753       return;
06754    bytes += adsi_logo(buf + bytes);
06755    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06756    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06757    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06758    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06759 
06760    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06761 }

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

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

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

static void adsi_login ( struct ast_channel chan  )  [static]

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

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

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

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

06261 {
06262    int bytes = 0;
06263    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06264    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06265    return bytes;
06266 }

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

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

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

static void adsi_password ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 6644 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(), buf2, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_execmain().

06645 {
06646    unsigned char buf[256] = "";
06647    char buf1[256] = "", buf2[256] = "";
06648    int bytes = 0;
06649    unsigned char keys[8];
06650    int x;
06651 
06652    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06653    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06654    if (!ast_adsi_available(chan))
06655       return;
06656    if (vms->newmessages) {
06657       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06658       if (vms->oldmessages) {
06659          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06660          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06661       } else {
06662          snprintf(buf2, sizeof(buf2), "%s.", newm);
06663       }
06664    } else if (vms->oldmessages) {
06665       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06666       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06667    } else {
06668       strcpy(buf1, "You have no messages.");
06669       buf2[0] = ' ';
06670       buf2[1] = '\0';
06671    }
06672    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06673    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06674    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06675 
06676    for (x = 0; x < 6; x++)
06677       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06678    keys[6] = 0;
06679    keys[7] = 0;
06680 
06681    /* Don't let them listen if there are none */
06682    if (vms->lastmsg < 0)
06683       keys[0] = 1;
06684    bytes += ast_adsi_set_keys(buf + bytes, keys);
06685 
06686    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06687 
06688    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06689 }

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

Definition at line 6691 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(), buf2, vm_state::curbox, and vm_state::lastmsg.

Referenced by vm_execmain().

06692 {
06693    unsigned char buf[256] = "";
06694    char buf1[256] = "", buf2[256] = "";
06695    int bytes = 0;
06696    unsigned char keys[8];
06697    int x;
06698 
06699    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06700 
06701    if (!ast_adsi_available(chan))
06702       return;
06703 
06704    /* Original command keys */
06705    for (x = 0; x < 6; x++)
06706       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06707 
06708    keys[6] = 0;
06709    keys[7] = 0;
06710 
06711    if ((vms->lastmsg + 1) < 1)
06712       keys[0] = 0;
06713 
06714    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06715       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06716 
06717    if (vms->lastmsg + 1)
06718       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06719    else
06720       strcpy(buf2, "no messages.");
06721    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06722    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06723    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06724    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06725    bytes += ast_adsi_set_keys(buf + bytes, keys);
06726 
06727    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06728 
06729    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06730    
06731 }

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

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

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

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

10763 {
10764    /* Assumes lock is already held */
10765    char *tmp;
10766    char *stringp;
10767    char *s;
10768    struct ast_vm_user *vmu;
10769    char *mailbox_full;
10770    int new = 0, old = 0, urgent = 0;
10771    char secretfn[PATH_MAX] = "";
10772 
10773    tmp = ast_strdupa(data);
10774 
10775    if (!(vmu = find_or_create(context, box)))
10776       return -1;
10777 
10778    populate_defaults(vmu);
10779 
10780    stringp = tmp;
10781    if ((s = strsep(&stringp, ","))) {
10782       if (!ast_strlen_zero(s) && s[0] == '*') {
10783          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10784             "\n\tmust be reset in voicemail.conf.\n", box);
10785       }
10786       /* assign password regardless of validity to prevent NULL password from being assigned */
10787       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10788    }
10789    if (stringp && (s = strsep(&stringp, ","))) {
10790       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10791    }
10792    if (stringp && (s = strsep(&stringp, ","))) {
10793       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10794    }
10795    if (stringp && (s = strsep(&stringp, ","))) {
10796       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10797    }
10798    if (stringp && (s = strsep(&stringp, ","))) {
10799       apply_options(vmu, s);
10800    }
10801 
10802    switch (vmu->passwordlocation) {
10803    case OPT_PWLOC_SPOOLDIR:
10804       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10805       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10806    }
10807 
10808    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10809    strcpy(mailbox_full, box);
10810    strcat(mailbox_full, "@");
10811    strcat(mailbox_full, context);
10812 
10813    inboxcount2(mailbox_full, &urgent, &new, &old);
10814    queue_mwi_event(mailbox_full, urgent, new, old);
10815 
10816    return 0;
10817 }

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

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

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

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

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

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

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

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

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

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

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

04440 {
04441    for (; *str; str++) {
04442       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04443          return 1;
04444       }
04445    }
04446    return 0;
04447 }

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

07958 {
07959    int x = 0;
07960    int last_msg_idx = 0;
07961 
07962 #ifndef IMAP_STORAGE
07963    int res = 0, nummsg;
07964    char fn2[PATH_MAX];
07965 #endif
07966 
07967    if (vms->lastmsg <= -1) {
07968       goto done;
07969    }
07970 
07971    vms->curmsg = -1;
07972 #ifndef IMAP_STORAGE
07973    /* Get the deleted messages fixed */
07974    if (vm_lock_path(vms->curdir)) {
07975       return ERROR_LOCK_PATH;
07976    }
07977 
07978    /* update count as message may have arrived while we've got mailbox open */
07979    last_msg_idx = last_message_index(vmu, vms->curdir);
07980    if (last_msg_idx != vms->lastmsg) {
07981       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
07982    }
07983 
07984    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07985    for (x = 0; x < last_msg_idx + 1; x++) {
07986       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07987          /* Save this message.  It's not in INBOX or hasn't been heard */
07988          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07989          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07990             break;
07991          }
07992          vms->curmsg++;
07993          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07994          if (strcmp(vms->fn, fn2)) {
07995             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07996          }
07997       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07998          /* Move to old folder before deleting */
07999          res = save_to_folder(vmu, vms, x, 1);
08000          if (res == ERROR_LOCK_PATH) {
08001             /* If save failed do not delete the message */
08002             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08003             vms->deleted[x] = 0;
08004             vms->heard[x] = 0;
08005             --x;
08006          }
08007       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08008          /* Move to deleted folder */
08009          res = save_to_folder(vmu, vms, x, 10);
08010          if (res == ERROR_LOCK_PATH) {
08011             /* If save failed do not delete the message */
08012             vms->deleted[x] = 0;
08013             vms->heard[x] = 0;
08014             --x;
08015          }
08016       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08017          /* If realtime storage enabled - we should explicitly delete this message,
08018          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08019          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08020          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08021             DELETE(vms->curdir, x, vms->fn, vmu);
08022          }
08023       }
08024    }
08025 
08026    /* Delete ALL remaining messages */
08027    nummsg = x - 1;
08028    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08029       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08030       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08031          DELETE(vms->curdir, x, vms->fn, vmu);
08032       }
08033    }
08034    ast_unlock_path(vms->curdir);
08035 #else /* defined(IMAP_STORAGE) */
08036    ast_mutex_lock(&vms->lock);
08037    if (vms->deleted) {
08038       /* Since we now expunge after each delete, deleting in reverse order
08039        * ensures that no reordering occurs between each step. */
08040       last_msg_idx = vms->dh_arraysize;
08041       for (x = last_msg_idx - 1; x >= 0; x--) {
08042          if (vms->deleted[x]) {
08043             ast_debug(3, "IMAP delete of %d\n", x);
08044             DELETE(vms->curdir, x, vms->fn, vmu);
08045          }
08046       }
08047    }
08048 #endif
08049 
08050 done:
08051    if (vms->deleted) {
08052       ast_free(vms->deleted);
08053       vms->deleted = NULL;
08054    }
08055    if (vms->heard) {
08056       ast_free(vms->heard);
08057       vms->heard = NULL;
08058    }
08059    vms->dh_arraysize = 0;
08060 #ifdef IMAP_STORAGE
08061    ast_mutex_unlock(&vms->lock);
08062 #endif
08063 
08064    return 0;
08065 }

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

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

11140 {
11141    int which = 0;
11142    int wordlen;
11143    struct ast_vm_user *vmu;
11144    const char *context = "";
11145 
11146    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11147    if (pos > 4)
11148       return NULL;
11149    if (pos == 3)
11150       return (state == 0) ? ast_strdup("for") : NULL;
11151    wordlen = strlen(word);
11152    AST_LIST_TRAVERSE(&users, vmu, list) {
11153       if (!strncasecmp(word, vmu->context, wordlen)) {
11154          if (context && strcmp(context, vmu->context) && ++which > state)
11155             return ast_strdup(vmu->context);
11156          /* ignore repeated contexts ? */
11157          context = vmu->context;
11158       }
11159    }
11160    return NULL;
11161 }

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

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

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

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

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

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

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

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

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

13170 {
13171    int cmd = 0;
13172    char destination[80] = "";
13173    int retries = 0;
13174 
13175    if (!num) {
13176       ast_verb(3, "Destination number will be entered manually\n");
13177       while (retries < 3 && cmd != 't') {
13178          destination[1] = '\0';
13179          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13180          if (!cmd)
13181             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13182          if (!cmd)
13183             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13184          if (!cmd) {
13185             cmd = ast_waitfordigit(chan, 6000);
13186             if (cmd)
13187                destination[0] = cmd;
13188          }
13189          if (!cmd) {
13190             retries++;
13191          } else {
13192 
13193             if (cmd < 0)
13194                return 0;
13195             if (cmd == '*') {
13196                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13197                return 0;
13198             }
13199             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13200                retries++;
13201             else
13202                cmd = 't';
13203          }
13204          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13205       }
13206       if (retries >= 3) {
13207          return 0;
13208       }
13209       
13210    } else {
13211       if (option_verbose > 2)
13212          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13213       ast_copy_string(destination, num, sizeof(destination));
13214    }
13215 
13216    if (!ast_strlen_zero(destination)) {
13217       if (destination[strlen(destination) -1 ] == '*')
13218          return 0; 
13219       if (option_verbose > 2)
13220          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13221       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13222       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13223       chan->priority = 0;
13224       return 9;
13225    }
13226    return 0;
13227 }

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

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

10723 {
10724    struct ast_vm_user *vmu;
10725 
10726    if (!ast_strlen_zero(box) && box[0] == '*') {
10727       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10728             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10729             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10730             "\n\tand will be ignored.\n", box, context);
10731       return NULL;
10732    }
10733 
10734    AST_LIST_TRAVERSE(&users, vmu, list) {
10735       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10736          if (strcasecmp(vmu->context, context)) {
10737             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10738                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10739                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10740                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10741          }
10742          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10743          return NULL;
10744       }
10745       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10746          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10747          return NULL;
10748       }
10749    }
10750    
10751    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10752       return NULL;
10753    
10754    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10755    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10756 
10757    AST_LIST_INSERT_TAIL(&users, vmu, list);
10758    
10759    return vmu;
10760 }

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

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

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

11754 {
11755    struct ast_vm_user *current;
11756    AST_LIST_LOCK(&users);
11757    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11758       ast_set_flag(current, VM_ALLOCED);
11759       free_user(current);
11760    }
11761    AST_LIST_UNLOCK(&users);
11762 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

11766 {
11767    struct vm_zone *zcur;
11768    AST_LIST_LOCK(&zones);
11769    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11770       free_zone(zcur);
11771    AST_LIST_UNLOCK(&zones);
11772 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5079 of file app_voicemail.c.

References ast_free.

05080 {
05081    ast_free(z);
05082 }

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

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

05036 {
05037    struct ast_tm tm;
05038    struct timeval t = ast_tvnow();
05039    
05040    ast_localtime(&t, &tm, "UTC");
05041 
05042    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05043 }

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

06768 {
06769    int x;
06770    int d;
06771    char fn[PATH_MAX];
06772    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06773    if (d)
06774       return d;
06775    for (x = start; x < 5; x++) { /* For all folders */
06776       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06777          return d;
06778       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06779       if (d)
06780          return d;
06781       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06782 
06783       /* The inbox folder can have its name changed under certain conditions
06784        * so this checks if the sound file exists for the inbox folder name and
06785        * if it doesn't, plays the default name instead. */
06786       if (x == 0) {
06787          if (ast_fileexists(fn, NULL, NULL)) {
06788             d = vm_play_folder_name(chan, fn);
06789          } else {
06790             ast_verb(1, "failed to find %s\n", fn);
06791             d = vm_play_folder_name(chan, "vm-INBOX");
06792          }
06793       } else {
06794          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06795          d = vm_play_folder_name(chan, fn);
06796       }
06797 
06798       if (d)
06799          return d;
06800       d = ast_waitfordigit(chan, 500);
06801       if (d)
06802          return d;
06803    }
06804 
06805    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06806    if (d)
06807       return d;
06808    d = ast_waitfordigit(chan, 4000);
06809    return d;
06810 }

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

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

Referenced by vm_execmain().

06825 {
06826    int res = 0;
06827    int loops = 0;
06828 
06829    res = ast_play_and_wait(chan, fn);  /* Folder name */
06830    while (((res < '0') || (res > '9')) &&
06831          (res != '#') && (res >= 0) &&
06832          loops < 4) {
06833       res = get_folder(chan, 0);
06834       loops++;
06835    }
06836    if (loops == 4) { /* give up */
06837       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06838       return '#';
06839    }
06840    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06841    return res;
06842 }

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

11524 {
11525    unsigned int len;
11526    struct mwi_sub *mwi_sub;
11527    struct mwi_sub_task *p = datap;
11528 
11529    len = sizeof(*mwi_sub);
11530    if (!ast_strlen_zero(p->mailbox))
11531       len += strlen(p->mailbox);
11532 
11533    if (!ast_strlen_zero(p->context))
11534       len += strlen(p->context) + 1; /* Allow for seperator */
11535 
11536    if (!(mwi_sub = ast_calloc(1, len)))
11537       return -1;
11538 
11539    mwi_sub->uniqueid = p->uniqueid;
11540    if (!ast_strlen_zero(p->mailbox))
11541       strcpy(mwi_sub->mailbox, p->mailbox);
11542 
11543    if (!ast_strlen_zero(p->context)) {
11544       strcat(mwi_sub->mailbox, "@");
11545       strcat(mwi_sub->mailbox, p->context);
11546    }
11547 
11548    AST_RWLIST_WRLOCK(&mwi_subs);
11549    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11550    AST_RWLIST_UNLOCK(&mwi_subs);
11551    ast_free((void *) p->mailbox);
11552    ast_free((void *) p->context);
11553    ast_free(p);
11554    poll_subscribed_mailbox(mwi_sub);
11555    return 0;
11556 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

11502 {
11503    struct mwi_sub *mwi_sub;
11504    uint32_t *uniqueid = datap;
11505    
11506    AST_RWLIST_WRLOCK(&mwi_subs);
11507    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11508       if (mwi_sub->uniqueid == *uniqueid) {
11509          AST_LIST_REMOVE_CURRENT(entry);
11510          break;
11511       }
11512    }
11513    AST_RWLIST_TRAVERSE_SAFE_END
11514    AST_RWLIST_UNLOCK(&mwi_subs);
11515 
11516    if (mwi_sub)
11517       mwi_sub_destroy(mwi_sub);
11518 
11519    ast_free(uniqueid);  
11520    return 0;
11521 }

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

11277 {
11278    switch (cmd) {
11279    case CLI_INIT:
11280       e->command = "voicemail reload";
11281       e->usage =
11282          "Usage: voicemail reload\n"
11283          "       Reload voicemail configuration\n";
11284       return NULL;
11285    case CLI_GENERATE:
11286       return NULL;
11287    }
11288 
11289    if (a->argc != 2)
11290       return CLI_SHOWUSAGE;
11291 
11292    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11293    load_config(1);
11294    
11295    return CLI_SUCCESS;
11296 }

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

11165 {
11166    struct ast_vm_user *vmu;
11167 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11168    const char *context = NULL;
11169    int users_counter = 0;
11170 
11171    switch (cmd) {
11172    case CLI_INIT:
11173       e->command = "voicemail show users";
11174       e->usage =
11175          "Usage: voicemail show users [for <context>]\n"
11176          "       Lists all mailboxes currently set up\n";
11177       return NULL;
11178    case CLI_GENERATE:
11179       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11180    }  
11181 
11182    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11183       return CLI_SHOWUSAGE;
11184    if (a->argc == 5) {
11185       if (strcmp(a->argv[3],"for"))
11186          return CLI_SHOWUSAGE;
11187       context = a->argv[4];
11188    }
11189 
11190    if (ast_check_realtime("voicemail")) {
11191       if (!context) {
11192          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11193          return CLI_SHOWUSAGE;
11194       }
11195       return show_users_realtime(a->fd, context);
11196    }
11197 
11198    AST_LIST_LOCK(&users);
11199    if (AST_LIST_EMPTY(&users)) {
11200       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11201       AST_LIST_UNLOCK(&users);
11202       return CLI_FAILURE;
11203    }
11204    if (!context) {
11205       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11206    } else {
11207       int count = 0;
11208       AST_LIST_TRAVERSE(&users, vmu, list) {
11209          if (!strcmp(context, vmu->context)) {
11210             count++;
11211             break;
11212          }
11213       }
11214       if (count) {
11215          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11216       } else {
11217          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11218          AST_LIST_UNLOCK(&users);
11219          return CLI_FAILURE;
11220       }
11221    }
11222    AST_LIST_TRAVERSE(&users, vmu, list) {
11223       int newmsgs = 0, oldmsgs = 0;
11224       char count[12], tmp[256] = "";
11225 
11226       if (!context || !strcmp(context, vmu->context)) {
11227          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11228          inboxcount(tmp, &newmsgs, &oldmsgs);
11229          snprintf(count, sizeof(count), "%d", newmsgs);
11230          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11231          users_counter++;
11232       }
11233    }
11234    AST_LIST_UNLOCK(&users);
11235    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11236    return CLI_SUCCESS;
11237 }

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

11241 {
11242    struct vm_zone *zone;
11243 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11244    char *res = CLI_SUCCESS;
11245 
11246    switch (cmd) {
11247    case CLI_INIT:
11248       e->command = "voicemail show zones";
11249       e->usage =
11250          "Usage: voicemail show zones\n"
11251          "       Lists zone message formats\n";
11252       return NULL;
11253    case CLI_GENERATE:
11254       return NULL;
11255    }
11256 
11257    if (a->argc != 3)
11258       return CLI_SHOWUSAGE;
11259 
11260    AST_LIST_LOCK(&zones);
11261    if (!AST_LIST_EMPTY(&zones)) {
11262       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11263       AST_LIST_TRAVERSE(&zones, zone, list) {
11264          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11265       }
11266    } else {
11267       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11268       res = CLI_FAILURE;
11269    }
11270    AST_LIST_UNLOCK(&zones);
11271 
11272    return res;
11273 }

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

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

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

Definition at line 5505 of file app_voicemail.c.

References inboxcount2().

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

05506 {
05507    int urgentmsgs = 0;
05508    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05509    if (newmsgs) {
05510       *newmsgs += urgentmsgs;
05511    }
05512    return res;
05513 }

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

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

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

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

utility used by inchar(), for base_encode()

Definition at line 4205 of file app_voicemail.c.

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

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

04206 {
04207    int l;
04208 
04209    if (bio->ateof)
04210       return 0;
04211 
04212    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04213       if (ferror(fi))
04214          return -1;
04215 
04216       bio->ateof = 1;
04217       return 0;
04218    }
04219 
04220    bio->iolen = l;
04221    bio->iocp = 0;
04222 
04223    return 1;
04224 }

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

utility used by base_encode()

Definition at line 4229 of file app_voicemail.c.

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

Referenced by base_encode().

04230 {
04231    if (bio->iocp>=bio->iolen) {
04232       if (!inbuf(bio, fi))
04233          return EOF;
04234    }
04235 
04236    return bio->iobuf[bio->iocp++];
04237 }

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

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

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

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

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 5578 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, leave_vm_options::exitcontext, 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.

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

static int load_config ( int  reload  )  [static]

Definition at line 11821 of file app_voicemail.c.

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

11822 {
11823    struct ast_config *cfg, *ucfg;
11824    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11825    int res;
11826 
11827    ast_unload_realtime("voicemail");
11828    ast_unload_realtime("voicemail_data");
11829 
11830    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11831       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11832          return 0;
11833       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11834          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11835          ucfg = NULL;
11836       }
11837       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11838       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11839          ast_config_destroy(ucfg);
11840          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11841          return 0;
11842       }
11843    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11844       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11845       return 0;
11846    } else {
11847       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11848       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11849          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11850          ucfg = NULL;
11851       }
11852    }
11853 
11854    res = actual_load_config(reload, cfg, ucfg);
11855 
11856    ast_config_destroy(cfg);
11857    ast_config_destroy(ucfg);
11858 
11859    return res;
11860 }

static int load_module ( void   )  [static]

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

13122 {
13123    int res;
13124    my_umask = umask(0);
13125    umask(my_umask);
13126 
13127    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13128       return AST_MODULE_LOAD_DECLINE;
13129    }
13130 
13131    /* compute the location of the voicemail spool directory */
13132    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13133    
13134    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13135       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13136    }
13137 
13138    if ((res = load_config(0)))
13139       return res;
13140 
13141    res = ast_register_application_xml(app, vm_exec);
13142    res |= ast_register_application_xml(app2, vm_execmain);
13143    res |= ast_register_application_xml(app3, vm_box_exists);
13144    res |= ast_register_application_xml(app4, vmauthenticate);
13145    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13146    res |= ast_custom_function_register(&mailbox_exists_acf);
13147    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13148 #ifdef TEST_FRAMEWORK
13149    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13150    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13151    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13152    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13153    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13154 #endif
13155 
13156    if (res)
13157       return res;
13158 
13159    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13160    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13161 
13162    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13163    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13164    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13165 
13166    return res;
13167 }

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 4522 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(), ast_strftime_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, ast_channel::name, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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

11653 {
11654    struct ast_vm_user *vmu = NULL;
11655    const char *id = astman_get_header(m, "ActionID");
11656    char actionid[128] = "";
11657 
11658    if (!ast_strlen_zero(id))
11659       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11660 
11661    AST_LIST_LOCK(&users);
11662 
11663    if (AST_LIST_EMPTY(&users)) {
11664       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11665       AST_LIST_UNLOCK(&users);
11666       return RESULT_SUCCESS;
11667    }
11668    
11669    astman_send_ack(s, m, "Voicemail user list will follow");
11670    
11671    AST_LIST_TRAVERSE(&users, vmu, list) {
11672       char dirname[256];
11673 
11674 #ifdef IMAP_STORAGE
11675       int new, old;
11676       inboxcount(vmu->mailbox, &new, &old);
11677 #endif
11678       
11679       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11680       astman_append(s,
11681          "%s"
11682          "Event: VoicemailUserEntry\r\n"
11683          "VMContext: %s\r\n"
11684          "VoiceMailbox: %s\r\n"
11685          "Fullname: %s\r\n"
11686          "Email: %s\r\n"
11687          "Pager: %s\r\n"
11688          "ServerEmail: %s\r\n"
11689          "MailCommand: %s\r\n"
11690          "Language: %s\r\n"
11691          "TimeZone: %s\r\n"
11692          "Callback: %s\r\n"
11693          "Dialout: %s\r\n"
11694          "UniqueID: %s\r\n"
11695          "ExitContext: %s\r\n"
11696          "SayDurationMinimum: %d\r\n"
11697          "SayEnvelope: %s\r\n"
11698          "SayCID: %s\r\n"
11699          "AttachMessage: %s\r\n"
11700          "AttachmentFormat: %s\r\n"
11701          "DeleteMessage: %s\r\n"
11702          "VolumeGain: %.2f\r\n"
11703          "CanReview: %s\r\n"
11704          "CallOperator: %s\r\n"
11705          "MaxMessageCount: %d\r\n"
11706          "MaxMessageLength: %d\r\n"
11707          "NewMessageCount: %d\r\n"
11708 #ifdef IMAP_STORAGE
11709          "OldMessageCount: %d\r\n"
11710          "IMAPUser: %s\r\n"
11711 #endif
11712          "\r\n",
11713          actionid,
11714          vmu->context,
11715          vmu->mailbox,
11716          vmu->fullname,
11717          vmu->email,
11718          vmu->pager,
11719          vmu->serveremail,
11720          vmu->mailcmd,
11721          vmu->language,
11722          vmu->zonetag,
11723          vmu->callback,
11724          vmu->dialout,
11725          vmu->uniqueid,
11726          vmu->exit,
11727          vmu->saydurationm,
11728          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11729          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11730          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11731          vmu->attachfmt,
11732          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11733          vmu->volgain,
11734          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11735          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11736          vmu->maxmsg,
11737          vmu->maxsecs,
11738 #ifdef IMAP_STORAGE
11739          new, old, vmu->imapuser
11740 #else
11741          count_messages(vmu, dirname)
11742 #endif
11743          );
11744    }     
11745    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11746 
11747    AST_LIST_UNLOCK(&users);
11748 
11749    return RESULT_SUCCESS;
11750 }

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

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

11474 {
11475    while (poll_thread_run) {
11476       struct timespec ts = { 0, };
11477       struct timeval wait;
11478 
11479       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11480       ts.tv_sec = wait.tv_sec;
11481       ts.tv_nsec = wait.tv_usec * 1000;
11482 
11483       ast_mutex_lock(&poll_lock);
11484       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11485       ast_mutex_unlock(&poll_lock);
11486 
11487       if (!poll_thread_run)
11488          break;
11489 
11490       poll_subscribed_mailboxes();
11491    }
11492 
11493    return NULL;
11494 }

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

References __has_voicemail().

Referenced by load_module().

05373 {
05374    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05375 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11496 of file app_voicemail.c.

References ast_free, and mwi_sub.

Referenced by handle_unsubscribe().

11497 {
11498    ast_free(mwi_sub);
11499 }

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

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

11585 {
11586    struct mwi_sub_task *mwist;
11587    
11588    if (ast_event_get_type(event) != AST_EVENT_SUB)
11589       return;
11590 
11591    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11592       return;
11593 
11594    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11595       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11596       return;
11597    }
11598    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11599    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11600    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11601    
11602    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11603       ast_free(mwist);
11604    }
11605 }

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

Definition at line 11558 of file app_voicemail.c.

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

Referenced by start_poll_thread().

11559 {
11560    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11561 
11562    if (!uniqueid) {
11563       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11564       return;
11565    }
11566 
11567    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11568       ast_free(uniqueid);
11569       return;
11570    }
11571 
11572    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11573       ast_free(uniqueid);
11574       return;
11575    }
11576 
11577    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11578    *uniqueid = u;
11579    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11580       ast_free(uniqueid);
11581    }
11582 }

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

07056 {
07057    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07058    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07059    const char *category;
07060    char *myserveremail = serveremail;
07061 
07062    ast_channel_lock(chan);
07063    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07064       category = ast_strdupa(category);
07065    }
07066    ast_channel_unlock(chan);
07067 
07068 #ifndef IMAP_STORAGE
07069    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07070 #else
07071    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07072 #endif
07073    make_file(fn, sizeof(fn), todir, msgnum);
07074    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07075 
07076    if (!ast_strlen_zero(vmu->attachfmt)) {
07077       if (strstr(fmt, vmu->attachfmt))
07078          fmt = vmu->attachfmt;
07079       else
07080          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);
07081    }
07082 
07083    /* Attach only the first format */
07084    fmt = ast_strdupa(fmt);
07085    stringp = fmt;
07086    strsep(&stringp, "|");
07087 
07088    if (!ast_strlen_zero(vmu->serveremail))
07089       myserveremail = vmu->serveremail;
07090 
07091    if (!ast_strlen_zero(vmu->email)) {
07092       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07093 
07094       if (attach_user_voicemail)
07095          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07096 
07097       /* XXX possible imap issue, should category be NULL XXX */
07098       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07099 
07100       if (attach_user_voicemail)
07101          DISPOSE(todir, msgnum);
07102    }
07103 
07104    if (!ast_strlen_zero(vmu->pager)) {
07105       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07106    }
07107 
07108    if (ast_test_flag(vmu, VM_DELETE))
07109       DELETE(todir, msgnum, fn, vmu);
07110 
07111    /* Leave voicemail for someone */
07112    if (ast_app_has_voicemail(ext_context, NULL)) 
07113       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07114 
07115    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07116 
07117    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);
07118    run_externnotify(vmu->context, vmu->mailbox, flag);
07119 
07120 #ifdef IMAP_STORAGE
07121    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07122    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07123       vm_imap_delete(NULL, vms->curmsg, vmu);
07124       vms->newmessages--;  /* Fix new message count */
07125    }
07126 #endif
07127 
07128    return 0;
07129 }

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

utility used by base_encode()

Definition at line 4242 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04243 {
04244    if (bio->linelength >= BASELINELEN) {
04245       if (fputs(ENDL, so) == EOF) {
04246          return -1;
04247       }
04248 
04249       bio->linelength = 0;
04250    }
04251 
04252    if (putc(((unsigned char) c), so) == EOF) {
04253       return -1;
04254    }
04255 
04256    bio->linelength++;
04257 
04258    return 1;
04259 }

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

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

07905 {
07906    int count_msg, last_msg;
07907 
07908    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07909 
07910    /* Rename the member vmbox HERE so that we don't try to return before
07911     * we know what's going on.
07912     */
07913    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07914 
07915    /* Faster to make the directory than to check if it exists. */
07916    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07917 
07918    /* traverses directory using readdir (or select query for ODBC) */
07919    count_msg = count_messages(vmu, vms->curdir);
07920    if (count_msg < 0) {
07921       return count_msg;
07922    } else {
07923       vms->lastmsg = count_msg - 1;
07924    }
07925 
07926    if (vm_allocate_dh(vms, vmu, count_msg)) {
07927       return -1;
07928    }
07929 
07930    /*
07931    The following test is needed in case sequencing gets messed up.
07932    There appears to be more than one way to mess up sequence, so
07933    we will not try to find all of the root causes--just fix it when
07934    detected.
07935    */
07936 
07937    if (vm_lock_path(vms->curdir)) {
07938       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07939       return ERROR_LOCK_PATH;
07940    }
07941 
07942    /* for local storage, checks directory for messages up to maxmsg limit */
07943    last_msg = last_message_index(vmu, vms->curdir);
07944    ast_unlock_path(vms->curdir);
07945 
07946    if (last_msg < -1) {
07947       return last_msg;
07948    } else if (vms->lastmsg != last_msg) {
07949       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);
07950       resequence_mailbox(vmu, vms->curdir, count_msg);
07951    }
07952 
07953    return 0;
07954 }

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

Definition at line 7678 of file app_voicemail.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, 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().

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

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

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

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

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

Definition at line 7475 of file app_voicemail.c.

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

Referenced by play_message().

07476 {
07477    int res = 0;
07478 
07479    if (!ast_strlen_zero(category))
07480       res = ast_play_and_wait(chan, category);
07481 
07482    if (res) {
07483       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07484       res = 0;
07485    }
07486 
07487    return res;
07488 }

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

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

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

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

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

07629 {
07630    int res = 0;
07631    int durationm;
07632    int durations;
07633    /* Verify that we have a duration for the message */
07634    if (duration == NULL)
07635       return res;
07636 
07637    /* Convert from seconds to minutes */
07638    durations = atoi(duration);
07639    durationm = (durations / 60);
07640 
07641    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07642 
07643    if ((!res) && (durationm >= minduration)) {
07644       res = wait_file2(chan, vms, "vm-duration");
07645 
07646       /* POLISH syntax */
07647       if (!strncasecmp(chan->language, "pl", 2)) {
07648          div_t num = div(durationm, 10);
07649 
07650          if (durationm == 1) {
07651             res = ast_play_and_wait(chan, "digits/1z");
07652             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07653          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07654             if (num.rem == 2) {
07655                if (!num.quot) {
07656                   res = ast_play_and_wait(chan, "digits/2-ie");
07657                } else {
07658                   res = say_and_wait(chan, durationm - 2 , chan->language);
07659                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07660                }
07661             } else {
07662                res = say_and_wait(chan, durationm, chan->language);
07663             }
07664             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07665          } else {
07666             res = say_and_wait(chan, durationm, chan->language);
07667             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07668          }
07669       /* DEFAULT syntax */
07670       } else {
07671          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07672          res = wait_file2(chan, vms, "vm-minutes");
07673       }
07674    }
07675    return res;
07676 }

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11445 of file app_voicemail.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11446 {
11447    int new = 0, old = 0, urgent = 0;
11448 
11449    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11450 
11451    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11452       mwi_sub->old_urgent = urgent;
11453       mwi_sub->old_new = new;
11454       mwi_sub->old_old = old;
11455       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11456       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11457    }
11458 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11461 {
11462    struct mwi_sub *mwi_sub;
11463 
11464    AST_RWLIST_RDLOCK(&mwi_subs);
11465    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11466       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11467          poll_subscribed_mailbox(mwi_sub);
11468       }
11469    }
11470    AST_RWLIST_UNLOCK(&mwi_subs);
11471 }

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

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

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

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

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

07019 {
07020    struct ast_event *event;
07021    char *mailbox, *context;
07022 
07023    /* Strip off @default */
07024    context = mailbox = ast_strdupa(box);
07025    strsep(&context, "@");
07026    if (ast_strlen_zero(context))
07027       context = "default";
07028 
07029    if (!(event = ast_event_new(AST_EVENT_MWI,
07030          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07031          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07032          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07033          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07034          AST_EVENT_IE_END))) {
07035       return;
07036    }
07037 
07038    ast_event_queue_and_cache(event);
07039 }

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

Definition at line 12551 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

12551                                                                                            {
12552    struct ast_config *pwconf;
12553    struct ast_flags config_flags = { 0 };
12554 
12555    pwconf = ast_config_load(secretfn, config_flags);
12556    if (pwconf) {
12557       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12558       if (val) {
12559          ast_copy_string(password, val, passwordlen);
12560          ast_config_destroy(pwconf);
12561          return;
12562       }
12563       ast_config_destroy(pwconf);
12564    }
12565    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12566 }

static int reload ( void   )  [static]

Definition at line 13081 of file app_voicemail.c.

References load_config().

13082 {
13083    return load_config(1);
13084 }

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

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

04001 {
04002    char stxt[PATH_MAX];
04003    char dtxt[PATH_MAX];
04004    ast_filerename(sfn, dfn, NULL);
04005    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04006    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04007    if (ast_check_realtime("voicemail_data")) {
04008       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04009    }
04010    rename(stxt, dtxt);
04011 }

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

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

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

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

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

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

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

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

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

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

06175 {
06176    int d;
06177    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06178    return d;
06179 }

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

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

12538 {
12539    int res = -1;
12540    char dir[PATH_MAX];
12541    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12542    ast_debug(2, "About to try retrieving name file %s\n", dir);
12543    RETRIEVE(dir, -1, mailbox, context);
12544    if (ast_fileexists(dir, NULL, NULL)) {
12545       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12546    }
12547    DISPOSE(dir, -1);
12548    return res;
12549 }

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

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

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

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

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

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

11101 {
11102    struct ast_config *cfg;
11103    const char *cat = NULL;
11104 
11105    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11106       "context", context, SENTINEL))) {
11107       return CLI_FAILURE;
11108    }
11109 
11110    ast_cli(fd,
11111       "\n"
11112       "=============================================================\n"
11113       "=== Configured Voicemail Users ==============================\n"
11114       "=============================================================\n"
11115       "===\n");
11116 
11117    while ((cat = ast_category_browse(cfg, cat))) {
11118       struct ast_variable *var = NULL;
11119       ast_cli(fd,
11120          "=== Mailbox ...\n"
11121          "===\n");
11122       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11123          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11124       ast_cli(fd,
11125          "===\n"
11126          "=== ---------------------------------------------------------\n"
11127          "===\n");
11128    }
11129 
11130    ast_cli(fd,
11131       "=============================================================\n"
11132       "\n");
11133 
11134    ast_config_destroy(cfg);
11135 
11136    return CLI_SUCCESS;
11137 }

static void start_poll_thread ( void   )  [static]

Definition at line 11607 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_log(), ast_pthread_create, LOG_ERROR, 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().

11608 {
11609    int errcode;
11610    mwi_sub_sub = ast_event_subscribe(AST_EVENT_SUB, mwi_sub_event_cb, "Voicemail MWI subscription", NULL,
11611       AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
11612       AST_EVENT_IE_END);
11613 
11614    mwi_unsub_sub = ast_event_subscribe(AST_EVENT_UNSUB, mwi_unsub_event_cb, "Voicemail MWI subscription", NULL,
11615       AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
11616       AST_EVENT_IE_END);
11617 
11618    if (mwi_sub_sub)
11619       ast_event_report_subs(mwi_sub_sub);
11620 
11621    poll_thread_run = 1;
11622 
11623    if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
11624       ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
11625    }
11626 }

static void stop_poll_thread ( void   )  [static]

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

11629 {
11630    poll_thread_run = 0;
11631 
11632    if (mwi_sub_sub) {
11633       ast_event_unsubscribe(mwi_sub_sub);
11634       mwi_sub_sub = NULL;
11635    }
11636 
11637    if (mwi_unsub_sub) {
11638       ast_event_unsubscribe(mwi_unsub_sub);
11639       mwi_unsub_sub = NULL;
11640    }
11641 
11642    ast_mutex_lock(&poll_lock);
11643    ast_cond_signal(&poll_cond);
11644    ast_mutex_unlock(&poll_lock);
11645 
11646    pthread_join(poll_thread, NULL);
11647 
11648    poll_thread = AST_PTHREADT_NULL;
11649 }

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

11775 {
11776    char *current;
11777 
11778    /* Add 16 for fudge factor */
11779    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11780 
11781    ast_str_reset(str);
11782    
11783    /* Substitute strings \r, \n, and \t into the appropriate characters */
11784    for (current = (char *) value; *current; current++) {
11785       if (*current == '\\') {
11786          current++;
11787          if (!*current) {
11788             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11789             break;
11790          }
11791          switch (*current) {
11792          case '\\':
11793             ast_str_append(&str, 0, "\\");
11794             break;
11795          case 'r':
11796             ast_str_append(&str, 0, "\r");
11797             break;
11798          case 'n':
11799 #ifdef IMAP_STORAGE
11800             if (!str->used || str->str[str->used - 1] != '\r') {
11801                ast_str_append(&str, 0, "\r");
11802             }
11803 #endif
11804             ast_str_append(&str, 0, "\n");
11805             break;
11806          case 't':
11807             ast_str_append(&str, 0, "\t");
11808             break;
11809          default:
11810             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11811             break;
11812          }
11813       } else {
11814          ast_str_append(&str, 0, "%c", *current);
11815       }
11816    }
11817 
11818    return ast_str_buffer(str);
11819 }

static int unload_module ( void   )  [static]

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

13087 {
13088    int res;
13089 
13090    res = ast_unregister_application(app);
13091    res |= ast_unregister_application(app2);
13092    res |= ast_unregister_application(app3);
13093    res |= ast_unregister_application(app4);
13094    res |= ast_unregister_application(sayname_app);
13095    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13096    res |= ast_manager_unregister("VoicemailUsersList");
13097    res |= ast_data_unregister(NULL);
13098 #ifdef TEST_FRAMEWORK
13099    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13100    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13101    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13102    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13103    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13104 #endif
13105    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13106    ast_uninstall_vm_functions();
13107    ao2_ref(inprocess_container, -1);
13108 
13109    if (poll_thread != AST_PTHREADT_NULL)
13110       stop_poll_thread();
13111 
13112    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13113    ast_unload_realtime("voicemail");
13114    ast_unload_realtime("voicemail_data");
13115 
13116    free_vm_users();
13117    free_vm_zones();
13118    return res;
13119 }

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_free, 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 
01754    /* remove old allocation */
01755    if (vms->deleted) {
01756       ast_free(vms->deleted);
01757       vms->deleted = NULL;
01758    }
01759    if (vms->heard) {
01760       ast_free(vms->heard);
01761       vms->heard = NULL;
01762    }
01763    vms->dh_arraysize = 0;
01764 
01765    if (arraysize > 0) {
01766       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01767          return -1;
01768       }
01769       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01770          ast_free(vms->deleted);
01771          vms->deleted = NULL;
01772          return -1;
01773       }
01774       vms->dh_arraysize = arraysize;
01775    }
01776 
01777    return 0;
01778 }

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

09779 {
09780    int useadsi = 0, valid = 0, logretries = 0;
09781    char password[AST_MAX_EXTENSION]="", *passptr;
09782    struct ast_vm_user vmus, *vmu = NULL;
09783 
09784    /* If ADSI is supported, setup login screen */
09785    adsi_begin(chan, &useadsi);
09786    if (!skipuser && useadsi)
09787       adsi_login(chan);
09788    ast_test_suite_event_notify("PLAYBACK", "Message: vm-login");
09789    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09790       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09791       return -1;
09792    }
09793 
09794    /* Authenticate them and get their mailbox/password */
09795 
09796    while (!valid && (logretries < max_logins)) {
09797       /* Prompt for, and read in the username */
09798       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09799          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09800          return -1;
09801       }
09802       if (ast_strlen_zero(mailbox)) {
09803          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09804             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09805          } else {
09806             ast_verb(3, "Username not entered\n"); 
09807             return -1;
09808          }
09809       } else if (mailbox[0] == '*') {
09810          /* user entered '*' */
09811          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09812          if (ast_exists_extension(chan, chan->context, "a", 1,
09813             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09814             return -1;
09815          }
09816          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09817          mailbox[0] = '\0';
09818       }
09819 
09820       if (useadsi)
09821          adsi_password(chan);
09822 
09823       if (!ast_strlen_zero(prefix)) {
09824          char fullusername[80] = "";
09825          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09826          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09827          ast_copy_string(mailbox, fullusername, mailbox_size);
09828       }
09829 
09830       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09831       vmu = find_user(&vmus, context, mailbox);
09832       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09833          /* saved password is blank, so don't bother asking */
09834          password[0] = '\0';
09835       } else {
09836          ast_test_suite_event_notify("PLAYBACK", "Message: %s", vm_password);
09837          if (ast_streamfile(chan, vm_password, chan->language)) {
09838             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09839             return -1;
09840          }
09841          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09842             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09843             return -1;
09844          } else if (password[0] == '*') {
09845             /* user entered '*' */
09846             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09847             if (ast_exists_extension(chan, chan->context, "a", 1,
09848                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09849                mailbox[0] = '*';
09850                return -1;
09851             }
09852             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09853             mailbox[0] = '\0';
09854             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09855             vmu = NULL;
09856          }
09857       }
09858 
09859       if (vmu) {
09860          passptr = vmu->password;
09861          if (passptr[0] == '-') passptr++;
09862       }
09863       if (vmu && !strcmp(passptr, password))
09864          valid++;
09865       else {
09866          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09867          if (!ast_strlen_zero(prefix))
09868             mailbox[0] = '\0';
09869       }
09870       logretries++;
09871       if (!valid) {
09872          if (skipuser || logretries >= max_logins) {
09873             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect");
09874             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09875                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09876                return -1;
09877             }
09878          } else {
09879             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect-mailbox");
09880             if (useadsi)
09881                adsi_login(chan);
09882             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09883                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09884                return -1;
09885             }
09886          }
09887          if (ast_waitstream(chan, "")) /* Channel is hung up */
09888             return -1;
09889       }
09890    }
09891    if (!valid && (logretries >= max_logins)) {
09892       ast_stopstream(chan);
09893       ast_play_and_wait(chan, "vm-goodbye");
09894       return -1;
09895    }
09896    if (vmu && !skipuser) {
09897       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09898    }
09899    return 0;
09900 }

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

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

10996 {
10997    struct ast_vm_user svm;
10998    char *context, *box;
10999    AST_DECLARE_APP_ARGS(args,
11000       AST_APP_ARG(mbox);
11001       AST_APP_ARG(options);
11002    );
11003    static int dep_warning = 0;
11004 
11005    if (ast_strlen_zero(data)) {
11006       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
11007       return -1;
11008    }
11009 
11010    if (!dep_warning) {
11011       dep_warning = 1;
11012       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
11013    }
11014 
11015    box = ast_strdupa(data);
11016 
11017    AST_STANDARD_APP_ARGS(args, box);
11018 
11019    if (args.options) {
11020    }
11021 
11022    if ((context = strchr(args.mbox, '@'))) {
11023       *context = '\0';
11024       context++;
11025    }
11026 
11027    if (find_user(&svm, context, args.mbox)) {
11028       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
11029    } else
11030       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
11031 
11032    return 0;
11033 }

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

09756 {
09757    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09758       return vm_browse_messages_es(chan, vms, vmu);
09759    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09760       return vm_browse_messages_gr(chan, vms, vmu);
09761    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09762       return vm_browse_messages_he(chan, vms, vmu);
09763    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09764       return vm_browse_messages_it(chan, vms, vmu);
09765    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09766       return vm_browse_messages_pt(chan, vms, vmu);
09767    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09768       return vm_browse_messages_vi(chan, vms, vmu);
09769    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09770       return vm_browse_messages_zh(chan, vms, vmu);
09771    } else {                                             /* Default to English syntax */
09772       return vm_browse_messages_en(chan, vms, vmu);
09773    }
09774 }

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

09595 {
09596    int cmd = 0;
09597 
09598    if (vms->lastmsg > -1) {
09599       cmd = play_message(chan, vmu, vms);
09600    } else {
09601       cmd = ast_play_and_wait(chan, "vm-youhave");
09602       if (!cmd) 
09603          cmd = ast_play_and_wait(chan, "vm-no");
09604       if (!cmd) {
09605          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09606          cmd = ast_play_and_wait(chan, vms->fn);
09607       }
09608       if (!cmd)
09609          cmd = ast_play_and_wait(chan, "vm-messages");
09610    }
09611    return cmd;
09612 }

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

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

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

09543 {
09544    int cmd = 0;
09545 
09546    if (vms->lastmsg > -1) {
09547       cmd = play_message(chan, vmu, vms);
09548    } else {
09549       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09550       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09551          if (!cmd) {
09552             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09553             cmd = ast_play_and_wait(chan, vms->fn);
09554          }
09555          if (!cmd)
09556             cmd = ast_play_and_wait(chan, "vm-messages");
09557       } else {
09558          if (!cmd)
09559             cmd = ast_play_and_wait(chan, "vm-messages");
09560          if (!cmd) {
09561             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09562             cmd = ast_play_and_wait(chan, vms->fn);
09563          }
09564       }
09565    } 
09566    return cmd;
09567 }

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

Definition at line 9570 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09571 {
09572    int cmd = 0;
09573 
09574    if (vms->lastmsg > -1) {
09575       cmd = play_message(chan, vmu, vms);
09576    } else {
09577       if (!strcasecmp(vms->fn, "INBOX")) {
09578          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09579       } else {
09580          cmd = ast_play_and_wait(chan, "vm-nomessages");
09581       }
09582    }
09583    return cmd;
09584 }

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

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

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

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

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

09729 {
09730    int cmd = 0;
09731 
09732    if (vms->lastmsg > -1) {
09733       cmd = play_message(chan, vmu, vms);
09734    } else {
09735       cmd = ast_play_and_wait(chan, "vm-no");
09736       if (!cmd) {
09737          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09738          cmd = ast_play_and_wait(chan, vms->fn);
09739       }
09740    }
09741    return cmd;
09742 }

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

09701 {
09702    int cmd;
09703 
09704    if (vms->lastmsg > -1) {
09705       cmd = play_message(chan, vmu, vms);
09706    } else {
09707       cmd = ast_play_and_wait(chan, "vm-you");
09708       if (!cmd) 
09709          cmd = ast_play_and_wait(chan, "vm-haveno");
09710       if (!cmd)
09711          cmd = ast_play_and_wait(chan, "vm-messages");
09712       if (!cmd) {
09713          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09714          cmd = ast_play_and_wait(chan, vms->fn);
09715       }
09716    }
09717    return cmd;
09718 }

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_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 (!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 4184 of file app_voicemail.c.

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

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

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

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

10655 {
10656    int res = 0;
10657    char *tmp;
10658    struct leave_vm_options leave_options;
10659    struct ast_flags flags = { 0 };
10660    char *opts[OPT_ARG_ARRAY_SIZE];
10661    AST_DECLARE_APP_ARGS(args,
10662       AST_APP_ARG(argv0);
10663       AST_APP_ARG(argv1);
10664    );
10665    
10666    memset(&leave_options, 0, sizeof(leave_options));
10667 
10668    if (chan->_state != AST_STATE_UP)
10669       ast_answer(chan);
10670 
10671    if (!ast_strlen_zero(data)) {
10672       tmp = ast_strdupa(data);
10673       AST_STANDARD_APP_ARGS(args, tmp);
10674       if (args.argc == 2) {
10675          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10676             return -1;
10677          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10678          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10679             int gain;
10680 
10681             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10682                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10683                return -1;
10684             } else {
10685                leave_options.record_gain = (signed char) gain;
10686             }
10687          }
10688          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10689             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10690                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10691          }
10692       }
10693    } else {
10694       char temp[256];
10695       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10696       if (res < 0)
10697          return res;
10698       if (ast_strlen_zero(temp))
10699          return 0;
10700       args.argv0 = ast_strdupa(temp);
10701    }
10702 
10703    res = leave_voicemail(chan, args.argv0, &leave_options);
10704    if (res == 't') {
10705       ast_play_and_wait(chan, "vm-goodbye");
10706       res = 0;
10707    }
10708 
10709    if (res == OPERATOR_EXIT) {
10710       res = 0;
10711    }
10712 
10713    if (res == ERROR_LOCK_PATH) {
10714       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10715       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10716       res = 0;
10717    }
10718 
10719    return res;
10720 }

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

Definition at line 9902 of file app_voicemail.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), ast_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().

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

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

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

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

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

Referenced by vm_execmain().

09218 {
09219    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09220       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09221    } else {             /* Default to ENGLISH */
09222       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09223    }
09224 }

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

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

Referenced by vm_instructions(), and vm_instructions_zh().

09106 {
09107    int res = 0;
09108    /* Play instructions and wait for new command */
09109    while (!res) {
09110       if (vms->starting) {
09111          if (vms->lastmsg > -1) {
09112             if (skipadvanced)
09113                res = ast_play_and_wait(chan, "vm-onefor-full");
09114             else
09115                res = ast_play_and_wait(chan, "vm-onefor");
09116             if (!res)
09117                res = vm_play_folder_name(chan, vms->vmbox);
09118          }
09119          if (!res) {
09120             if (skipadvanced)
09121                res = ast_play_and_wait(chan, "vm-opts-full");
09122             else
09123                res = ast_play_and_wait(chan, "vm-opts");
09124          }
09125       } else {
09126          /* Added for additional help */
09127          if (skipadvanced) {
09128             res = ast_play_and_wait(chan, "vm-onefor-full");
09129             if (!res)
09130                res = vm_play_folder_name(chan, vms->vmbox);
09131             res = ast_play_and_wait(chan, "vm-opts-full");
09132          }
09133          /* Logic:
09134           * If the current message is not the first OR
09135           * if we're listening to the first new message and there are
09136           * also urgent messages, then prompt for navigation to the
09137           * previous message
09138           */
09139          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09140             res = ast_play_and_wait(chan, "vm-prev");
09141          }
09142          if (!res && !skipadvanced)
09143             res = ast_play_and_wait(chan, "vm-advopts");
09144          if (!res)
09145             res = ast_play_and_wait(chan, "vm-repeat");
09146          /* Logic:
09147           * If we're not listening to the last message OR
09148           * we're listening to the last urgent message and there are
09149           * also new non-urgent messages, then prompt for navigation
09150           * to the next message
09151           */
09152          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09153             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09154             res = ast_play_and_wait(chan, "vm-next");
09155          }
09156          if (!res) {
09157             int curmsg_deleted;
09158 #ifdef IMAP_STORAGE
09159             ast_mutex_lock(&vms->lock);
09160 #endif
09161             curmsg_deleted = vms->deleted[vms->curmsg];
09162 #ifdef IMAP_STORAGE
09163             ast_mutex_unlock(&vms->lock);
09164 #endif
09165             if (!curmsg_deleted) {
09166                res = ast_play_and_wait(chan, "vm-delete");
09167             } else {
09168                res = ast_play_and_wait(chan, "vm-undelete");
09169             }
09170             if (!res) {
09171                res = ast_play_and_wait(chan, "vm-toforward");
09172             }
09173             if (!res) {
09174                res = ast_play_and_wait(chan, "vm-savemessage");
09175             }
09176          }
09177       }
09178       if (!res) {
09179          res = ast_play_and_wait(chan, "vm-helpexit");
09180       }
09181       if (!res)
09182          res = ast_waitfordigit(chan, 6000);
09183       if (!res) {
09184          vms->repeats++;
09185          if (vms->repeats > 2) {
09186             res = 't';
09187          }
09188       }
09189    }
09190    return res;
09191 }

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

09194 {
09195    int res = 0;
09196    /* Play instructions and wait for new command */
09197    while (!res) {
09198       if (vms->lastmsg > -1) {
09199          res = ast_play_and_wait(chan, "vm-listen");
09200          if (!res)
09201             res = vm_play_folder_name(chan, vms->vmbox);
09202          if (!res)
09203             res = ast_play_and_wait(chan, "press");
09204          if (!res)
09205             res = ast_play_and_wait(chan, "digits/1");
09206       }
09207       if (!res)
09208          res = ast_play_and_wait(chan, "vm-opts");
09209       if (!res) {
09210          vms->starting = 0;
09211          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09212       }
09213    }
09214    return res;
09215 }

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

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

09044 {
09045    char prefile[256];
09046    
09047    /* Notify the user that the temp greeting is set and give them the option to remove it */
09048    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09049    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09050       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09051       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09052          ast_play_and_wait(chan, "vm-tempgreetactive");
09053       }
09054       DISPOSE(prefile, -1);
09055    }
09056 
09057    /* Play voicemail intro - syntax is different for different languages */
09058    if (0) {
09059       return 0;
09060    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09061       return vm_intro_cs(chan, vms);
09062    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09063       static int deprecation_warning = 0;
09064       if (deprecation_warning++ % 10 == 0) {
09065          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09066       }
09067       return vm_intro_cs(chan, vms);
09068    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09069       return vm_intro_de(chan, vms);
09070    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09071       return vm_intro_es(chan, vms);
09072    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09073       return vm_intro_fr(chan, vms);
09074    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09075       return vm_intro_gr(chan, vms);
09076    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09077       return vm_intro_he(chan, vms);
09078    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09079       return vm_intro_it(chan, vms);
09080    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09081       return vm_intro_nl(chan, vms);
09082    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09083       return vm_intro_no(chan, vms);
09084    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09085       return vm_intro_pl(chan, vms);
09086    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09087       return vm_intro_pt_BR(chan, vms);
09088    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09089       return vm_intro_pt(chan, vms);
09090    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09091       return vm_intro_multilang(chan, vms, "n");
09092    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09093       return vm_intro_se(chan, vms);
09094    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09095       return vm_intro_multilang(chan, vms, "n");
09096    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09097       return vm_intro_vi(chan, vms);
09098    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09099       return vm_intro_zh(chan, vms);
09100    } else {                                             /* Default to ENGLISH */
09101       return vm_intro_en(chan, vms);
09102    }
09103 }

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

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

08914 {
08915    int res;
08916    res = ast_play_and_wait(chan, "vm-youhave");
08917    if (!res) {
08918       if (vms->newmessages) {
08919          if (vms->newmessages == 1) {
08920             res = ast_play_and_wait(chan, "digits/jednu");
08921          } else {
08922             res = say_and_wait(chan, vms->newmessages, chan->language);
08923          }
08924          if (!res) {
08925             if ((vms->newmessages == 1))
08926                res = ast_play_and_wait(chan, "vm-novou");
08927             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08928                res = ast_play_and_wait(chan, "vm-nove");
08929             if (vms->newmessages > 4)
08930                res = ast_play_and_wait(chan, "vm-novych");
08931          }
08932          if (vms->oldmessages && !res)
08933             res = ast_play_and_wait(chan, "vm-and");
08934          else if (!res) {
08935             if ((vms->newmessages == 1))
08936                res = ast_play_and_wait(chan, "vm-zpravu");
08937             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08938                res = ast_play_and_wait(chan, "vm-zpravy");
08939             if (vms->newmessages > 4)
08940                res = ast_play_and_wait(chan, "vm-zprav");
08941          }
08942       }
08943       if (!res && vms->oldmessages) {
08944          res = say_and_wait(chan, vms->oldmessages, chan->language);
08945          if (!res) {
08946             if ((vms->oldmessages == 1))
08947                res = ast_play_and_wait(chan, "vm-starou");
08948             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08949                res = ast_play_and_wait(chan, "vm-stare");
08950             if (vms->oldmessages > 4)
08951                res = ast_play_and_wait(chan, "vm-starych");
08952          }
08953          if (!res) {
08954             if ((vms->oldmessages == 1))
08955                res = ast_play_and_wait(chan, "vm-zpravu");
08956             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08957                res = ast_play_and_wait(chan, "vm-zpravy");
08958             if (vms->oldmessages > 4)
08959                res = ast_play_and_wait(chan, "vm-zprav");
08960          }
08961       }
08962       if (!res) {
08963          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08964             res = ast_play_and_wait(chan, "vm-no");
08965             if (!res)
08966                res = ast_play_and_wait(chan, "vm-zpravy");
08967          }
08968       }
08969    }
08970    return res;
08971 }

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

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

08610 {
08611    /* Introduce messages they have */
08612    int res;
08613    res = ast_play_and_wait(chan, "vm-youhave");
08614    if (!res) {
08615       if (vms->newmessages) {
08616          if ((vms->newmessages == 1))
08617             res = ast_play_and_wait(chan, "digits/1F");
08618          else
08619             res = say_and_wait(chan, vms->newmessages, chan->language);
08620          if (!res)
08621             res = ast_play_and_wait(chan, "vm-INBOX");
08622          if (vms->oldmessages && !res)
08623             res = ast_play_and_wait(chan, "vm-and");
08624          else if (!res) {
08625             if ((vms->newmessages == 1))
08626                res = ast_play_and_wait(chan, "vm-message");
08627             else
08628                res = ast_play_and_wait(chan, "vm-messages");
08629          }
08630             
08631       }
08632       if (!res && vms->oldmessages) {
08633          if (vms->oldmessages == 1)
08634             res = ast_play_and_wait(chan, "digits/1F");
08635          else
08636             res = say_and_wait(chan, vms->oldmessages, chan->language);
08637          if (!res)
08638             res = ast_play_and_wait(chan, "vm-Old");
08639          if (!res) {
08640             if (vms->oldmessages == 1)
08641                res = ast_play_and_wait(chan, "vm-message");
08642             else
08643                res = ast_play_and_wait(chan, "vm-messages");
08644          }
08645       }
08646       if (!res) {
08647          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08648             res = ast_play_and_wait(chan, "vm-no");
08649             if (!res)
08650                res = ast_play_and_wait(chan, "vm-messages");
08651          }
08652       }
08653    }
08654    return res;
08655 }

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

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

08359 {
08360    int res;
08361 
08362    /* Introduce messages they have */
08363    res = ast_play_and_wait(chan, "vm-youhave");
08364    if (!res) {
08365       if (vms->urgentmessages) {
08366          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08367          if (!res)
08368             res = ast_play_and_wait(chan, "vm-Urgent");
08369          if ((vms->oldmessages || vms->newmessages) && !res) {
08370             res = ast_play_and_wait(chan, "vm-and");
08371          } else if (!res) {
08372             if ((vms->urgentmessages == 1))
08373                res = ast_play_and_wait(chan, "vm-message");
08374             else
08375                res = ast_play_and_wait(chan, "vm-messages");
08376          }
08377       }
08378       if (vms->newmessages) {
08379          res = say_and_wait(chan, vms->newmessages, chan->language);
08380          if (!res)
08381             res = ast_play_and_wait(chan, "vm-INBOX");
08382          if (vms->oldmessages && !res)
08383             res = ast_play_and_wait(chan, "vm-and");
08384          else if (!res) {
08385             if ((vms->newmessages == 1))
08386                res = ast_play_and_wait(chan, "vm-message");
08387             else
08388                res = ast_play_and_wait(chan, "vm-messages");
08389          }
08390             
08391       }
08392       if (!res && vms->oldmessages) {
08393          res = say_and_wait(chan, vms->oldmessages, chan->language);
08394          if (!res)
08395             res = ast_play_and_wait(chan, "vm-Old");
08396          if (!res) {
08397             if (vms->oldmessages == 1)
08398                res = ast_play_and_wait(chan, "vm-message");
08399             else
08400                res = ast_play_and_wait(chan, "vm-messages");
08401          }
08402       }
08403       if (!res) {
08404          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08405             res = ast_play_and_wait(chan, "vm-no");
08406             if (!res)
08407                res = ast_play_and_wait(chan, "vm-messages");
08408          }
08409       }
08410    }
08411    return res;
08412 }

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

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

08659 {
08660    /* Introduce messages they have */
08661    int res;
08662    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08663       res = ast_play_and_wait(chan, "vm-youhaveno");
08664       if (!res)
08665          res = ast_play_and_wait(chan, "vm-messages");
08666    } else {
08667       res = ast_play_and_wait(chan, "vm-youhave");
08668    }
08669    if (!res) {
08670       if (vms->newmessages) {
08671          if (!res) {
08672             if ((vms->newmessages == 1)) {
08673                res = ast_play_and_wait(chan, "digits/1M");
08674                if (!res)
08675                   res = ast_play_and_wait(chan, "vm-message");
08676                if (!res)
08677                   res = ast_play_and_wait(chan, "vm-INBOXs");
08678             } else {
08679                res = say_and_wait(chan, vms->newmessages, chan->language);
08680                if (!res)
08681                   res = ast_play_and_wait(chan, "vm-messages");
08682                if (!res)
08683                   res = ast_play_and_wait(chan, "vm-INBOX");
08684             }
08685          }
08686          if (vms->oldmessages && !res)
08687             res = ast_play_and_wait(chan, "vm-and");
08688       }
08689       if (vms->oldmessages) {
08690          if (!res) {
08691             if (vms->oldmessages == 1) {
08692                res = ast_play_and_wait(chan, "digits/1M");
08693                if (!res)
08694                   res = ast_play_and_wait(chan, "vm-message");
08695                if (!res)
08696                   res = ast_play_and_wait(chan, "vm-Olds");
08697             } else {
08698                res = say_and_wait(chan, vms->oldmessages, chan->language);
08699                if (!res)
08700                   res = ast_play_and_wait(chan, "vm-messages");
08701                if (!res)
08702                   res = ast_play_and_wait(chan, "vm-Old");
08703             }
08704          }
08705       }
08706    }
08707 return res;
08708 }

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

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

08757 {
08758    /* Introduce messages they have */
08759    int res;
08760    res = ast_play_and_wait(chan, "vm-youhave");
08761    if (!res) {
08762       if (vms->newmessages) {
08763          res = say_and_wait(chan, vms->newmessages, chan->language);
08764          if (!res)
08765             res = ast_play_and_wait(chan, "vm-INBOX");
08766          if (vms->oldmessages && !res)
08767             res = ast_play_and_wait(chan, "vm-and");
08768          else if (!res) {
08769             if ((vms->newmessages == 1))
08770                res = ast_play_and_wait(chan, "vm-message");
08771             else
08772                res = ast_play_and_wait(chan, "vm-messages");
08773          }
08774             
08775       }
08776       if (!res && vms->oldmessages) {
08777          res = say_and_wait(chan, vms->oldmessages, chan->language);
08778          if (!res)
08779             res = ast_play_and_wait(chan, "vm-Old");
08780          if (!res) {
08781             if (vms->oldmessages == 1)
08782                res = ast_play_and_wait(chan, "vm-message");
08783             else
08784                res = ast_play_and_wait(chan, "vm-messages");
08785          }
08786       }
08787       if (!res) {
08788          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08789             res = ast_play_and_wait(chan, "vm-no");
08790             if (!res)
08791                res = ast_play_and_wait(chan, "vm-messages");
08792          }
08793       }
08794    }
08795    return res;
08796 }

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

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

08158 {
08159    int res = 0;
08160 
08161    if (vms->newmessages) {
08162       res = ast_play_and_wait(chan, "vm-youhave");
08163       if (!res) 
08164          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08165       if (!res) {
08166          if ((vms->newmessages == 1)) {
08167             res = ast_play_and_wait(chan, "vm-INBOX");
08168             if (!res)
08169                res = ast_play_and_wait(chan, "vm-message");
08170          } else {
08171             res = ast_play_and_wait(chan, "vm-INBOXs");
08172             if (!res)
08173                res = ast_play_and_wait(chan, "vm-messages");
08174          }
08175       }
08176    } else if (vms->oldmessages){
08177       res = ast_play_and_wait(chan, "vm-youhave");
08178       if (!res)
08179          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08180       if ((vms->oldmessages == 1)){
08181          res = ast_play_and_wait(chan, "vm-Old");
08182          if (!res)
08183             res = ast_play_and_wait(chan, "vm-message");
08184       } else {
08185          res = ast_play_and_wait(chan, "vm-Olds");
08186          if (!res)
08187             res = ast_play_and_wait(chan, "vm-messages");
08188       }
08189    } else if (!vms->oldmessages && !vms->newmessages) 
08190       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08191    return res;
08192 }

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

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

08292 {
08293    int res = 0;
08294 
08295    /* Introduce messages they have */
08296    if (!res) {
08297       if ((vms->newmessages) || (vms->oldmessages)) {
08298          res = ast_play_and_wait(chan, "vm-youhave");
08299       }
08300       /*
08301        * The word "shtei" refers to the number 2 in hebrew when performing a count
08302        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08303        * an element, this is one of them.
08304        */
08305       if (vms->newmessages) {
08306          if (!res) {
08307             if (vms->newmessages == 1) {
08308                res = ast_play_and_wait(chan, "vm-INBOX1");
08309             } else {
08310                if (vms->newmessages == 2) {
08311                   res = ast_play_and_wait(chan, "vm-shtei");
08312                } else {
08313                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08314                }
08315                res = ast_play_and_wait(chan, "vm-INBOX");
08316             }
08317          }
08318          if (vms->oldmessages && !res) {
08319             res = ast_play_and_wait(chan, "vm-and");
08320             if (vms->oldmessages == 1) {
08321                res = ast_play_and_wait(chan, "vm-Old1");
08322             } else {
08323                if (vms->oldmessages == 2) {
08324                   res = ast_play_and_wait(chan, "vm-shtei");
08325                } else {
08326                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08327                }
08328                res = ast_play_and_wait(chan, "vm-Old");
08329             }
08330          }
08331       }
08332       if (!res && vms->oldmessages && !vms->newmessages) {
08333          if (!res) {
08334             if (vms->oldmessages == 1) {
08335                res = ast_play_and_wait(chan, "vm-Old1");
08336             } else {
08337                if (vms->oldmessages == 2) {
08338                   res = ast_play_and_wait(chan, "vm-shtei");
08339                } else {
08340                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08341                }
08342                res = ast_play_and_wait(chan, "vm-Old");
08343             }
08344          }
08345       }
08346       if (!res) {
08347          if (!vms->oldmessages && !vms->newmessages) {
08348             if (!res) {
08349                res = ast_play_and_wait(chan, "vm-nomessages");
08350             }
08351          }
08352       }
08353    }
08354    return res;
08355 }

static int vm_intro_it ( 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, say_and_wait(), and vm_state::urgentmessages.

Referenced by vm_intro().

08416 {
08417    /* Introduce messages they have */
08418    int res;
08419    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08420       res = ast_play_and_wait(chan, "vm-no") ||
08421          ast_play_and_wait(chan, "vm-message");
08422    else
08423       res = ast_play_and_wait(chan, "vm-youhave");
08424    if (!res && vms->newmessages) {
08425       res = (vms->newmessages == 1) ?
08426          ast_play_and_wait(chan, "digits/un") ||
08427          ast_play_and_wait(chan, "vm-nuovo") ||
08428          ast_play_and_wait(chan, "vm-message") :
08429          /* 2 or more new messages */
08430          say_and_wait(chan, vms->newmessages, chan->language) ||
08431          ast_play_and_wait(chan, "vm-nuovi") ||
08432          ast_play_and_wait(chan, "vm-messages");
08433       if (!res && vms->oldmessages)
08434          res = ast_play_and_wait(chan, "vm-and");
08435    }
08436    if (!res && vms->oldmessages) {
08437       res = (vms->oldmessages == 1) ?
08438          ast_play_and_wait(chan, "digits/un") ||
08439          ast_play_and_wait(chan, "vm-vecchio") ||
08440          ast_play_and_wait(chan, "vm-message") :
08441          /* 2 or more old messages */
08442          say_and_wait(chan, vms->oldmessages, chan->language) ||
08443          ast_play_and_wait(chan, "vm-vecchi") ||
08444          ast_play_and_wait(chan, "vm-messages");
08445    }
08446    return res;
08447 }

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

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

08252 {
08253    int res;
08254    int lastnum = 0;
08255 
08256    res = ast_play_and_wait(chan, "vm-youhave");
08257 
08258    if (!res && vms->newmessages) {
08259       lastnum = vms->newmessages;
08260 
08261       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08262          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08263       }
08264 
08265       if (!res && vms->oldmessages) {
08266          res = ast_play_and_wait(chan, "vm-and");
08267       }
08268    }
08269 
08270    if (!res && vms->oldmessages) {
08271       lastnum = vms->oldmessages;
08272 
08273       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08274          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08275       }
08276    }
08277 
08278    if (!res) {
08279       if (lastnum == 0) {
08280          res = ast_play_and_wait(chan, "vm-no");
08281       }
08282       if (!res) {
08283          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08284       }
08285    }
08286 
08287    return res;
08288 }

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

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

08800 {
08801    /* Introduce messages they have */
08802    int res;
08803    res = ast_play_and_wait(chan, "vm-youhave");
08804    if (!res) {
08805       if (vms->newmessages) {
08806          res = say_and_wait(chan, vms->newmessages, chan->language);
08807          if (!res) {
08808             if (vms->newmessages == 1)
08809                res = ast_play_and_wait(chan, "vm-INBOXs");
08810             else
08811                res = ast_play_and_wait(chan, "vm-INBOX");
08812          }
08813          if (vms->oldmessages && !res)
08814             res = ast_play_and_wait(chan, "vm-and");
08815          else if (!res) {
08816             if ((vms->newmessages == 1))
08817                res = ast_play_and_wait(chan, "vm-message");
08818             else
08819                res = ast_play_and_wait(chan, "vm-messages");
08820          }
08821             
08822       }
08823       if (!res && vms->oldmessages) {
08824          res = say_and_wait(chan, vms->oldmessages, chan->language);
08825          if (!res) {
08826             if (vms->oldmessages == 1)
08827                res = ast_play_and_wait(chan, "vm-Olds");
08828             else
08829                res = ast_play_and_wait(chan, "vm-Old");
08830          }
08831          if (!res) {
08832             if (vms->oldmessages == 1)
08833                res = ast_play_and_wait(chan, "vm-message");
08834             else
08835                res = ast_play_and_wait(chan, "vm-messages");
08836          }
08837       }
08838       if (!res) {
08839          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08840             res = ast_play_and_wait(chan, "vm-no");
08841             if (!res)
08842                res = ast_play_and_wait(chan, "vm-messages");
08843          }
08844       }
08845    }
08846    return res;
08847 }

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

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

08566 {
08567    /* Introduce messages they have */
08568    int res;
08569 
08570    res = ast_play_and_wait(chan, "vm-youhave");
08571    if (res)
08572       return res;
08573 
08574    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08575       res = ast_play_and_wait(chan, "vm-no");
08576       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08577       return res;
08578    }
08579 
08580    if (vms->newmessages) {
08581       if ((vms->newmessages == 1)) {
08582          res = ast_play_and_wait(chan, "digits/1");
08583          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08584          res = res ? res : ast_play_and_wait(chan, "vm-message");
08585       } else {
08586          res = say_and_wait(chan, vms->newmessages, chan->language);
08587          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08588          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08589       }
08590       if (!res && vms->oldmessages)
08591          res = ast_play_and_wait(chan, "vm-and");
08592    }
08593    if (!res && vms->oldmessages) {
08594       if (vms->oldmessages == 1) {
08595          res = ast_play_and_wait(chan, "digits/1");
08596          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08597          res = res ? res : ast_play_and_wait(chan, "vm-message");
08598       } else {
08599          res = say_and_wait(chan, vms->oldmessages, chan->language);
08600          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08601          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08602       }
08603    }
08604 
08605    return res;
08606 }

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

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

08451 {
08452    /* Introduce messages they have */
08453    int res;
08454    div_t num;
08455 
08456    if (!vms->oldmessages && !vms->newmessages) {
08457       res = ast_play_and_wait(chan, "vm-no");
08458       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08459       return res;
08460    } else {
08461       res = ast_play_and_wait(chan, "vm-youhave");
08462    }
08463 
08464    if (vms->newmessages) {
08465       num = div(vms->newmessages, 10);
08466       if (vms->newmessages == 1) {
08467          res = ast_play_and_wait(chan, "digits/1-a");
08468          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08469          res = res ? res : ast_play_and_wait(chan, "vm-message");
08470       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08471          if (num.rem == 2) {
08472             if (!num.quot) {
08473                res = ast_play_and_wait(chan, "digits/2-ie");
08474             } else {
08475                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08476                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08477             }
08478          } else {
08479             res = say_and_wait(chan, vms->newmessages, chan->language);
08480          }
08481          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08482          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08483       } else {
08484          res = say_and_wait(chan, vms->newmessages, chan->language);
08485          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08486          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08487       }
08488       if (!res && vms->oldmessages)
08489          res = ast_play_and_wait(chan, "vm-and");
08490    }
08491    if (!res && vms->oldmessages) {
08492       num = div(vms->oldmessages, 10);
08493       if (vms->oldmessages == 1) {
08494          res = ast_play_and_wait(chan, "digits/1-a");
08495          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08496          res = res ? res : ast_play_and_wait(chan, "vm-message");
08497       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08498          if (num.rem == 2) {
08499             if (!num.quot) {
08500                res = ast_play_and_wait(chan, "digits/2-ie");
08501             } else {
08502                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08503                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08504             }
08505          } else {
08506             res = say_and_wait(chan, vms->oldmessages, chan->language);
08507          }
08508          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08509          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08510       } else {
08511          res = say_and_wait(chan, vms->oldmessages, chan->language);
08512          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08513          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08514       }
08515    }
08516 
08517    return res;
08518 }

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

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

08851 {
08852    /* Introduce messages they have */
08853    int res;
08854    res = ast_play_and_wait(chan, "vm-youhave");
08855    if (!res) {
08856       if (vms->newmessages) {
08857          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08858          if (!res) {
08859             if ((vms->newmessages == 1)) {
08860                res = ast_play_and_wait(chan, "vm-message");
08861                if (!res)
08862                   res = ast_play_and_wait(chan, "vm-INBOXs");
08863             } else {
08864                res = ast_play_and_wait(chan, "vm-messages");
08865                if (!res)
08866                   res = ast_play_and_wait(chan, "vm-INBOX");
08867             }
08868          }
08869          if (vms->oldmessages && !res)
08870             res = ast_play_and_wait(chan, "vm-and");
08871       }
08872       if (!res && vms->oldmessages) {
08873          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08874          if (!res) {
08875             if (vms->oldmessages == 1) {
08876                res = ast_play_and_wait(chan, "vm-message");
08877                if (!res)
08878                   res = ast_play_and_wait(chan, "vm-Olds");
08879             } else {
08880                res = ast_play_and_wait(chan, "vm-messages");
08881                if (!res)
08882                   res = ast_play_and_wait(chan, "vm-Old");
08883             }
08884          }
08885       }
08886       if (!res) {
08887          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08888             res = ast_play_and_wait(chan, "vm-no");
08889             if (!res)
08890                res = ast_play_and_wait(chan, "vm-messages");
08891          }
08892       }
08893    }
08894    return res;
08895 }

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

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

08711                                                                           {
08712    /* Introduce messages they have */
08713    int res;
08714    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08715       res = ast_play_and_wait(chan, "vm-nomessages");
08716       return res;
08717    } else {
08718       res = ast_play_and_wait(chan, "vm-youhave");
08719    }
08720    if (vms->newmessages) {
08721       if (!res)
08722          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08723       if ((vms->newmessages == 1)) {
08724          if (!res)
08725             res = ast_play_and_wait(chan, "vm-message");
08726          if (!res)
08727             res = ast_play_and_wait(chan, "vm-INBOXs");
08728       } else {
08729          if (!res)
08730             res = ast_play_and_wait(chan, "vm-messages");
08731          if (!res)
08732             res = ast_play_and_wait(chan, "vm-INBOX");
08733       }
08734       if (vms->oldmessages && !res)
08735          res = ast_play_and_wait(chan, "vm-and");
08736    }
08737    if (vms->oldmessages) {
08738       if (!res)
08739          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08740       if (vms->oldmessages == 1) {
08741          if (!res)
08742             res = ast_play_and_wait(chan, "vm-message");
08743          if (!res)
08744             res = ast_play_and_wait(chan, "vm-Olds");
08745       } else {
08746          if (!res)
08747             res = ast_play_and_wait(chan, "vm-messages");
08748          if (!res)
08749             res = ast_play_and_wait(chan, "vm-Old");
08750       }
08751    }
08752    return res;
08753 }

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

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

08522 {
08523    /* Introduce messages they have */
08524    int res;
08525 
08526    res = ast_play_and_wait(chan, "vm-youhave");
08527    if (res)
08528       return res;
08529 
08530    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08531       res = ast_play_and_wait(chan, "vm-no");
08532       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08533       return res;
08534    }
08535 
08536    if (vms->newmessages) {
08537       if ((vms->newmessages == 1)) {
08538          res = ast_play_and_wait(chan, "digits/ett");
08539          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08540          res = res ? res : ast_play_and_wait(chan, "vm-message");
08541       } else {
08542          res = say_and_wait(chan, vms->newmessages, chan->language);
08543          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08544          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08545       }
08546       if (!res && vms->oldmessages)
08547          res = ast_play_and_wait(chan, "vm-and");
08548    }
08549    if (!res && vms->oldmessages) {
08550       if (vms->oldmessages == 1) {
08551          res = ast_play_and_wait(chan, "digits/ett");
08552          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08553          res = res ? res : ast_play_and_wait(chan, "vm-message");
08554       } else {
08555          res = say_and_wait(chan, vms->oldmessages, chan->language);
08556          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08557          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08558       }
08559    }
08560 
08561    return res;
08562 }

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

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

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

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

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

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

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03260 {
03261    switch (ast_lock_path(path)) {
03262    case AST_LOCK_TIMEOUT:
03263       return -1;
03264    default:
03265       return 0;
03266    }
03267 }

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

09228 {
09229    int cmd = 0;
09230    int duration = 0;
09231    int tries = 0;
09232    char newpassword[80] = "";
09233    char newpassword2[80] = "";
09234    char prefile[PATH_MAX] = "";
09235    unsigned char buf[256];
09236    int bytes = 0;
09237 
09238    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09239    if (ast_adsi_available(chan)) {
09240       bytes += adsi_logo(buf + bytes);
09241       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09242       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09243       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09244       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09245       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09246    }
09247 
09248    /* If forcename is set, have the user record their name */
09249    if (ast_test_flag(vmu, VM_FORCENAME)) {
09250       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09251       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09252          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09253          if (cmd < 0 || cmd == 't' || cmd == '#')
09254             return cmd;
09255       }
09256    }
09257 
09258    /* If forcegreetings is set, have the user record their greetings */
09259    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09260       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09261       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09262          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09263          if (cmd < 0 || cmd == 't' || cmd == '#')
09264             return cmd;
09265       }
09266 
09267       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09268       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09269          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09270          if (cmd < 0 || cmd == 't' || cmd == '#')
09271             return cmd;
09272       }
09273    }
09274 
09275    /*
09276     * Change the password last since new users will be able to skip over any steps this one comes before
09277     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09278     */
09279    for (;;) {
09280       newpassword[1] = '\0';
09281       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09282       if (cmd == '#')
09283          newpassword[0] = '\0';
09284       if (cmd < 0 || cmd == 't' || cmd == '#')
09285          return cmd;
09286       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09287       if (cmd < 0 || cmd == 't' || cmd == '#')
09288          return cmd;
09289       cmd = check_password(vmu, newpassword); /* perform password validation */
09290       if (cmd != 0) {
09291          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09292          cmd = ast_play_and_wait(chan, vm_invalid_password);
09293       } else {
09294          newpassword2[1] = '\0';
09295          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09296          if (cmd == '#')
09297             newpassword2[0] = '\0';
09298          if (cmd < 0 || cmd == 't' || cmd == '#')
09299             return cmd;
09300          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09301          if (cmd < 0 || cmd == 't' || cmd == '#')
09302             return cmd;
09303          if (!strcmp(newpassword, newpassword2))
09304             break;
09305          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09306          cmd = ast_play_and_wait(chan, vm_mismatch);
09307       }
09308       if (++tries == 3)
09309          return -1;
09310       if (cmd != 0) {
09311          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09312       }
09313    }
09314    if (pwdchange & PWDCHANGE_INTERNAL)
09315       vm_change_password(vmu, newpassword);
09316    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09317       vm_change_password_shell(vmu, newpassword);
09318 
09319    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09320    cmd = ast_play_and_wait(chan, vm_passchanged);
09321 
09322    return cmd;
09323 }

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

09326 {
09327    int cmd = 0;
09328    int retries = 0;
09329    int duration = 0;
09330    char newpassword[80] = "";
09331    char newpassword2[80] = "";
09332    char prefile[PATH_MAX] = "";
09333    unsigned char buf[256];
09334    int bytes = 0;
09335 
09336    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09337    if (ast_adsi_available(chan)) {
09338       bytes += adsi_logo(buf + bytes);
09339       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09340       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09341       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09342       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09343       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09344    }
09345    while ((cmd >= 0) && (cmd != 't')) {
09346       if (cmd)
09347          retries = 0;
09348       switch (cmd) {
09349       case '1': /* Record your unavailable message */
09350          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09351          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09352          break;
09353       case '2':  /* Record your busy message */
09354          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09355          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09356          break;
09357       case '3': /* Record greeting */
09358          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09359          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09360          break;
09361       case '4':  /* manage the temporary greeting */
09362          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09363          break;
09364       case '5': /* change password */
09365          if (vmu->password[0] == '-') {
09366             cmd = ast_play_and_wait(chan, "vm-no");
09367             break;
09368          }
09369          newpassword[1] = '\0';
09370          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09371          if (cmd == '#')
09372             newpassword[0] = '\0';
09373          else {
09374             if (cmd < 0)
09375                break;
09376             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09377                break;
09378             }
09379          }
09380          cmd = check_password(vmu, newpassword); /* perform password validation */
09381          if (cmd != 0) {
09382             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09383             cmd = ast_play_and_wait(chan, vm_invalid_password);
09384             if (!cmd) {
09385                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09386             }
09387             break;
09388          }
09389          newpassword2[1] = '\0';
09390          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09391          if (cmd == '#')
09392             newpassword2[0] = '\0';
09393          else {
09394             if (cmd < 0)
09395                break;
09396 
09397             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09398                break;
09399             }
09400          }
09401          if (strcmp(newpassword, newpassword2)) {
09402             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09403             cmd = ast_play_and_wait(chan, vm_mismatch);
09404             if (!cmd) {
09405                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09406             }
09407             break;
09408          }
09409 
09410          if (pwdchange & PWDCHANGE_INTERNAL) {
09411             vm_change_password(vmu, newpassword);
09412          }
09413          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09414             vm_change_password_shell(vmu, newpassword);
09415          }
09416 
09417          ast_debug(1, "User %s set password to %s of length %d\n",
09418             vms->username, newpassword, (int) strlen(newpassword));
09419          cmd = ast_play_and_wait(chan, vm_passchanged);
09420          break;
09421       case '*': 
09422          cmd = 't';
09423          break;
09424       default: 
09425          cmd = 0;
09426          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09427          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09428          if (ast_fileexists(prefile, NULL, NULL)) {
09429             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09430          }
09431          DISPOSE(prefile, -1);
09432          if (!cmd) {
09433             cmd = ast_play_and_wait(chan, "vm-options");
09434          }
09435          if (!cmd) {
09436             cmd = ast_waitfordigit(chan, 6000);
09437          }
09438          if (!cmd) {
09439             retries++;
09440          }
09441          if (retries > 3) {
09442             cmd = 't';
09443          }
09444          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09445       }
09446    }
09447    if (cmd == 't')
09448       cmd = 0;
09449    return cmd;
09450 }

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

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

08121 {
08122    int cmd;
08123 
08124    if (  !strncasecmp(chan->language, "it", 2) ||
08125         !strncasecmp(chan->language, "es", 2) ||
08126         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08127       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08128       return cmd ? cmd : ast_play_and_wait(chan, box);
08129    } else if (!strncasecmp(chan->language, "gr", 2)) {
08130       return vm_play_folder_name_gr(chan, box);
08131    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08132       return ast_play_and_wait(chan, box);
08133    } else if (!strncasecmp(chan->language, "pl", 2)) {
08134       return vm_play_folder_name_pl(chan, box);
08135    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08136       return vm_play_folder_name_ua(chan, box);
08137    } else if (!strncasecmp(chan->language, "vi", 2)) {
08138       return ast_play_and_wait(chan, box);
08139    } else {  /* Default English */
08140       cmd = ast_play_and_wait(chan, box);
08141       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08142    }
08143 }

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

Definition at line 8073 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08074 {
08075    int cmd;
08076    char *buf;
08077 
08078    buf = alloca(strlen(box) + 2);
08079    strcpy(buf, box);
08080    strcat(buf, "s");
08081 
08082    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08083       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08084       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08085    } else {
08086       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08087       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08088    }
08089 }

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

Definition at line 8091 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08092 {
08093    int cmd;
08094 
08095    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08096       if (!strcasecmp(box, "vm-INBOX"))
08097          cmd = ast_play_and_wait(chan, "vm-new-e");
08098       else
08099          cmd = ast_play_and_wait(chan, "vm-old-e");
08100       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08101    } else {
08102       cmd = ast_play_and_wait(chan, "vm-messages");
08103       return cmd ? cmd : ast_play_and_wait(chan, box);
08104    }
08105 }

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

Definition at line 8107 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08108 {
08109    int cmd;
08110 
08111    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08112       cmd = ast_play_and_wait(chan, "vm-messages");
08113       return cmd ? cmd : ast_play_and_wait(chan, box);
08114    } else {
08115       cmd = ast_play_and_wait(chan, box);
08116       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08117    }
08118 }

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

09469 {
09470    int cmd = 0;
09471    int retries = 0;
09472    int duration = 0;
09473    char prefile[PATH_MAX] = "";
09474    unsigned char buf[256];
09475    int bytes = 0;
09476 
09477    if (ast_adsi_available(chan)) {
09478       bytes += adsi_logo(buf + bytes);
09479       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09480       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09481       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09482       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09483       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09484    }
09485 
09486    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09487    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09488    while ((cmd >= 0) && (cmd != 't')) {
09489       if (cmd)
09490          retries = 0;
09491       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09492       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09493          cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09494          if (cmd == -1) {
09495             break;
09496          }
09497          cmd = 't';  
09498       } else {
09499          switch (cmd) {
09500          case '1':
09501             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09502             break;
09503          case '2':
09504             DELETE(prefile, -1, prefile, vmu);
09505             ast_play_and_wait(chan, "vm-tempremoved");
09506             cmd = 't';  
09507             break;
09508          case '*': 
09509             cmd = 't';
09510             break;
09511          default:
09512             cmd = ast_play_and_wait(chan,
09513                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09514                   "vm-tempgreeting2" : "vm-tempgreeting");
09515             if (!cmd) {
09516                cmd = ast_waitfordigit(chan, 6000);
09517             }
09518             if (!cmd) {
09519                retries++;
09520             }
09521             if (retries > 3) {
09522                cmd = 't';
09523             }
09524             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09525          }
09526       }
09527       DISPOSE(prefile, -1);
09528    }
09529    if (cmd == 't')
09530       cmd = 0;
09531    return cmd;
09532 }

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

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

11424 {
11425    struct ast_vm_user *user;
11426 
11427    AST_LIST_LOCK(&users);
11428    AST_LIST_TRAVERSE(&users, user, list) {
11429       vm_users_data_provider_get_helper(search, data_root, user);
11430    }
11431    AST_LIST_UNLOCK(&users);
11432 
11433    return 0;
11434 }

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

11377 {
11378    struct ast_data *data_user, *data_zone;
11379    struct ast_data *data_state;
11380    struct vm_zone *zone = NULL;
11381    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11382    char ext_context[256] = "";
11383 
11384    data_user = ast_data_add_node(data_root, "user");
11385    if (!data_user) {
11386       return -1;
11387    }
11388 
11389    ast_data_add_structure(ast_vm_user, data_user, user);
11390 
11391    AST_LIST_LOCK(&zones);
11392    AST_LIST_TRAVERSE(&zones, zone, list) {
11393       if (!strcmp(zone->name, user->zonetag)) {
11394          break;
11395       }
11396    }
11397    AST_LIST_UNLOCK(&zones);
11398 
11399    /* state */
11400    data_state = ast_data_add_node(data_user, "state");
11401    if (!data_state) {
11402       return -1;
11403    }
11404    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11405    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11406    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11407    ast_data_add_int(data_state, "newmsg", newmsg);
11408    ast_data_add_int(data_state, "oldmsg", oldmsg);
11409 
11410    if (zone) {
11411       data_zone = ast_data_add_node(data_user, "zone");
11412       ast_data_add_structure(vm_zone, data_zone, zone);
11413    }
11414 
11415    if (!ast_data_search_match(search, data_user)) {
11416       ast_data_remove_node(data_root, data_user);
11417    }
11418 
11419    return 0;
11420 }

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

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

11060 {
11061    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11062    struct ast_vm_user vmus;
11063    char *options = NULL;
11064    int silent = 0, skipuser = 0;
11065    int res = -1;
11066    
11067    if (data) {
11068       s = ast_strdupa(data);
11069       user = strsep(&s, ",");
11070       options = strsep(&s, ",");
11071       if (user) {
11072          s = user;
11073          user = strsep(&s, "@");
11074          context = strsep(&s, "");
11075          if (!ast_strlen_zero(user))
11076             skipuser++;
11077          ast_copy_string(mailbox, user, sizeof(mailbox));
11078       }
11079    }
11080 
11081    if (options) {
11082       silent = (strchr(options, 's')) != NULL;
11083    }
11084 
11085    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11086       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11087       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11088       ast_play_and_wait(chan, "auth-thankyou");
11089       res = 0;
11090    } else if (mailbox[0] == '*') {
11091       /* user entered '*' */
11092       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11093          res = 0; /* prevent hangup */
11094       }
11095    }
11096 
11097    return res;
11098 }

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

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

12602 {
12603    char *context;
12604    char *args_copy;
12605    int res;
12606 
12607    if (ast_strlen_zero(data)) {
12608       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12609       return -1;
12610    }
12611 
12612    args_copy = ast_strdupa(data);
12613    if ((context = strchr(args_copy, '@'))) {
12614       *context++ = '\0';
12615    } else {
12616       context = "default";
12617    }
12618 
12619    if ((res = sayname(chan, args_copy, context) < 0)) {
12620       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12621       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12622       if (!res) {
12623          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12624       }
12625    }
12626 
12627    return res;
12628 }

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

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

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

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

07462 {
07463    int res;
07464    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07465       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07466    return res;
07467 }

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

Definition at line 12568 of file app_voicemail.c.

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

Referenced by vm_change_password().

12568                                                                               {
12569    struct ast_config *conf;
12570    struct ast_category *cat;
12571    struct ast_variable *var;
12572    int res = -1;
12573 
12574    if (!(conf = ast_config_new())) {
12575       ast_log(LOG_ERROR, "Error creating new config structure\n");
12576       return res;
12577    }
12578    if (!(cat = ast_category_new("general", "", 1))) {
12579       ast_log(LOG_ERROR, "Error creating new category structure\n");
12580       ast_config_destroy(conf);
12581       return res;
12582    }
12583    if (!(var = ast_variable_new("password", password, ""))) {
12584       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12585       ast_config_destroy(conf);
12586       ast_category_destroy(cat);
12587       return res;
12588    }
12589    ast_category_append(conf, cat);
12590    ast_variable_append(cat, var);
12591    if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12592       res = 0;
12593    } else {
12594       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12595    }
12596 
12597    ast_config_destroy(conf);
12598    return res;
12599 }


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

Definition at line 13680 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 13680 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 11298 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 11054 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 11441 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 11436 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 Oct 8 12:39:09 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7