Tue Aug 20 16:34:44 2013

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  vm_state
struct  vm_zone

Defines

#define ASTERISK_USERNAME   "asterisk"
#define BASELINELEN   72
#define BASEMAXINLINE   256
#define CHUNKSIZE   65536
#define COMMAND_TIMEOUT   5000
#define COPY(a, b, c, d, e, f, g, h)   (copy_plain_file(g,h));
#define DATA_EXPORT_VM_USERS(USER)
#define DATA_EXPORT_VM_ZONES(ZONE)
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"
#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"
#define DEFAULT_POLL_FREQ   30
#define DELETE(a, b, c, d)   (vm_delete(c))
#define DISPOSE(a, b)
#define ENDL   "\n"
#define ERROR_LOCK_PATH   -100
#define EXISTS(a, b, c, d)   (ast_fileexists(c,NULL,d) > 0)
#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"
#define MAX_DATETIME_FORMAT   512
#define MAX_NUM_CID_CONTEXTS   10
#define MAXMSG   100
#define MAXMSGLIMIT   9999
#define MINPASSWORD   0
#define OPERATOR_EXIT   300
#define PWDCHANGE_EXTERNAL   (1 << 2)
#define PWDCHANGE_INTERNAL   (1 << 1)
#define RENAME(a, b, c, d, e, f, g, h)   (rename_file(g,h));
#define RETRIEVE(a, b, c, d)
#define SENDMAIL   "/usr/sbin/sendmail -t"
#define SMDI_MWI_WAIT_TIMEOUT   1000
#define STORE(a, b, c, d, e, f, g, h, i, j)
#define tdesc   "Comedian Mail (Voicemail System)"
#define VALID_DTMF   "1234567890*#"
#define VM_ALLOCED   (1 << 13)
#define VM_ATTACH   (1 << 11)
#define VM_DELETE   (1 << 12)
#define VM_DIRECFORWARD   (1 << 10)
#define VM_ENVELOPE   (1 << 4)
#define VM_FORCEGREET   (1 << 8)
#define VM_FORCENAME   (1 << 7)
#define VM_FWDURGAUTO   (1 << 18)
#define VM_MESSAGEWRAP   (1 << 17)
#define VM_MOVEHEARD   (1 << 16)
#define VM_OPERATOR   (1 << 1)
#define VM_PBXSKIP   (1 << 9)
#define VM_REVIEW   (1 << 0)
#define VM_SAYCID   (1 << 2)
#define VM_SAYDURATION   (1 << 5)
#define VM_SEARCH   (1 << 14)
#define VM_SKIPAFTERCMD   (1 << 6)
#define VM_SVMAIL   (1 << 3)
#define VM_TEMPGREETWARN   (1 << 15)
#define VMSTATE_MAX_MSG_ARRAY   256
#define VOICEMAIL_CONFIG   "voicemail.conf"
#define VOICEMAIL_DIR_MODE   0777
#define VOICEMAIL_FILE_MODE   0666

Enumerations

enum  vm_box {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER, NEW_FOLDER, OLD_FOLDER,
  WORK_FOLDER, FAMILY_FOLDER, FRIENDS_FOLDER, GREETINGS_FOLDER,
  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,
  OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3,
  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), 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), 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, OPT_PWLOC_VOICEMAILCONF = 0,
  OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2, OPT_PWLOC_VOICEMAILCONF = 0, OPT_PWLOC_SPOOLDIR = 1,
  OPT_PWLOC_USERSCONF = 2
}

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int actual_load_config (int reload, struct ast_config *cfg, struct ast_config *ucfg)
static int add_email_attachment (FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
static void adsi_begin (struct ast_channel *chan, int *useadsi)
static void adsi_delete (struct ast_channel *chan, struct vm_state *vms)
static void adsi_folders (struct ast_channel *chan, int start, char *label)
static void adsi_goodbye (struct ast_channel *chan)
static int adsi_load_vmail (struct ast_channel *chan, int *useadsi)
static void adsi_login (struct ast_channel *chan)
static int adsi_logo (unsigned char *buf)
static void adsi_message (struct ast_channel *chan, struct vm_state *vms)
static void adsi_password (struct ast_channel *chan)
static void adsi_status (struct ast_channel *chan, struct vm_state *vms)
static void adsi_status2 (struct ast_channel *chan, struct vm_state *vms)
static int advanced_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
 The advanced options within a message.
static int append_mailbox (const char *context, const char *box, const char *data)
static void apply_option (struct ast_vm_user *vmu, const char *var, const char *value)
 Sets a a specific property value.
static void apply_options (struct ast_vm_user *vmu, const char *options)
 Destructively Parse options and apply.
static void apply_options_full (struct ast_vm_user *retval, struct ast_variable *var)
 Loads the options specific to a voicemail user.
 AST_APP_OPTIONS (vm_app_options,{AST_APP_OPTION('s', OPT_SILENT), AST_APP_OPTION('b', OPT_BUSY_GREETING), AST_APP_OPTION('u', OPT_UNAVAIL_GREETING), AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN), AST_APP_OPTION_ARG('d', OPT_DTMFEXIT, OPT_ARG_DTMFEXIT), AST_APP_OPTION('p', OPT_PREPEND_MAILBOX), AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER), AST_APP_OPTION('U', OPT_MESSAGE_Urgent),})
 AST_DATA_STRUCTURE (vm_zone, DATA_EXPORT_VM_ZONES)
 AST_DATA_STRUCTURE (ast_vm_user, DATA_EXPORT_VM_USERS)
static AST_LIST_HEAD_STATIC (zones, vm_zone)
static AST_LIST_HEAD_STATIC (users, ast_vm_user)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,.load=load_module,.unload=unload_module,.reload=reload,.nonoptreq="res_adsi,res_smdi",)
 AST_MUTEX_DEFINE_STATIC (poll_lock)
static AST_RWLIST_HEAD_STATIC (mwi_subs, mwi_sub)
static const char * ast_str_encode_mime (struct ast_str **end, ssize_t maxlen, const char *start, size_t preamble, size_t postamble)
 Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain control characters.
static const char * ast_str_quote (struct ast_str **buf, ssize_t maxlen, const char *from)
 Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
 AST_TEST_DEFINE (test_voicemail_vmuser)
static int base_encode (char *filename, FILE *so)
 Performs a base 64 encode algorithm on the contents of a File.
static int change_password_realtime (struct ast_vm_user *vmu, const char *password)
 Performs a change of the voicemail passowrd in the realtime engine.
static int check_mime (const char *str)
 Check if the string would need encoding within the MIME standard, to avoid confusing certain mail software that expects messages to be 7-bit clean.
static int check_password (struct ast_vm_user *vmu, char *password)
 Check that password meets minimum required length.
static int close_mailbox (struct vm_state *vms, struct ast_vm_user *vmu)
static char * complete_voicemail_show_users (const char *line, const char *word, int pos, int state)
static int copy (char *infile, char *outfile)
 Utility function to copy a file.
static int copy_message (struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt, char *dir, const char *flag)
 Copies a message from one mailbox to another.
static void copy_plain_file (char *frompath, char *topath)
 Copies a voicemail information (envelope) file.
static int count_messages (struct ast_vm_user *vmu, char *dir)
 Find all .txt files - even if they are not in sequence from 0000.
static int create_dirpath (char *dest, int len, const char *context, const char *ext, const char *folder)
 basically mkdir -p $dest/$context/$ext/$folder
static int dialout (struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
static struct ast_vm_userfind_or_create (const char *context, const char *box)
static struct ast_vm_userfind_user (struct ast_vm_user *ivm, const char *context, const char *mailbox)
 Finds a voicemail user from the users file or the realtime engine.
static struct ast_vm_userfind_user_realtime (struct ast_vm_user *ivm, const char *context, const char *mailbox)
 Finds a voicemail user from the realtime engine.
static int forward_message (struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int is_new_message, signed char record_gain, int urgent)
 Sends a voicemail message to a mailbox recipient.
static void free_user (struct ast_vm_user *vmu)
static void free_vm_users (void)
 Free the users structure.
static void free_vm_zones (void)
 Free the zones structure.
static void free_zone (struct vm_zone *z)
static int get_date (char *s, int len)
 Gets the current date and time, as formatted string.
static int get_folder (struct ast_channel *chan, int start)
 get_folder: Folder menu Plays "press 1 for INBOX messages" etc. Should possibly be internationalized
static int get_folder2 (struct ast_channel *chan, char *fn, int start)
 plays a prompt and waits for a keypress.
static int get_folder_by_name (const char *name)
static int handle_subscribe (void *datap)
static int handle_unsubscribe (void *datap)
static char * handle_voicemail_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload voicemail configuration from the CLI.
static char * handle_voicemail_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail users in the CLI.
static char * handle_voicemail_show_zones (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail zones in the CLI.
static int has_voicemail (const char *mailbox, const char *folder)
 Determines if the given folder has messages.
static int inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
static int inboxcount2 (const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static int inbuf (struct baseio *bio, FILE *fi)
 utility used by inchar(), for base_encode()
static int inchar (struct baseio *bio, FILE *fi)
 utility used by base_encode()
static int inprocess_cmp_fn (void *obj, void *arg, int flags)
static int inprocess_count (const char *context, const char *mailbox, int delta)
static int inprocess_hash_fn (const void *obj, const int flags)
static int invent_message (struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
static int is_valid_dtmf (const char *key)
 Determines if a DTMF key entered is valid.
static int last_message_index (struct ast_vm_user *vmu, char *dir)
 Determines the highest message number in use for a given user and mailbox folder.
static int leave_voicemail (struct ast_channel *chan, char *ext, struct leave_vm_options *options)
 Prompts the user and records a voicemail to a mailbox.
static int load_config (int reload)
static int load_module (void)
static int make_dir (char *dest, int len, const char *context, const char *ext, const char *folder)
 Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.
static void make_email_file (FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag)
 Creates the email file to be sent to indicate a new voicemail exists for a user.
static int make_file (char *dest, const int len, const char *dir, const int num)
 Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.
static int manager_list_voicemail_users (struct mansession *s, const struct message *m)
 Manager list voicemail users command.
static void * mb_poll_thread (void *data)
static const char * mbox (struct ast_vm_user *vmu, int id)
static int messagecount (const char *context, const char *mailbox, const char *folder)
static void mwi_sub_destroy (struct mwi_sub *mwi_sub)
static void mwi_sub_event_cb (const struct ast_event *event, void *userdata)
static void mwi_unsub_event_cb (const struct ast_event *event, void *userdata)
static int notify_new_message (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname, const char *flag)
 Sends email notification that a user has a new voicemail waiting for them.
static int ochar (struct baseio *bio, int c, FILE *so)
 utility used by base_encode()
static int open_mailbox (struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int play_message (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int play_message_callerid (struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
static int play_message_category (struct ast_channel *chan, const char *category)
static int play_message_datetime (struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static int play_message_duration (struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static void poll_subscribed_mailbox (struct mwi_sub *mwi_sub)
static void poll_subscribed_mailboxes (void)
static void populate_defaults (struct ast_vm_user *vmu)
 Sets default voicemail system options to a voicemail user.
static void prep_email_sub_vars (struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
static void queue_mwi_event (const char *box, int urgent, int new, int old)
static void read_password_from_file (const char *secretfn, char *password, int passwordlen)
static int reload (void)
static void rename_file (char *sfn, char *dfn)
 Renames a message in a mailbox folder.
static int resequence_mailbox (struct ast_vm_user *vmu, char *dir, int stopcount)
static int reset_user_pw (const char *context, const char *mailbox, const char *newpass)
 Resets a user password to a specified password.
static void run_externnotify (char *context, char *extension, const char *flag)
static int save_to_folder (struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
static int say_and_wait (struct ast_channel *chan, int num, const char *language)
static int sayname (struct ast_channel *chan, const char *mailbox, const char *context)
static int sendmail (char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
static int sendpage (char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
static char * show_users_realtime (int fd, const char *context)
static void start_poll_thread (void)
static void stop_poll_thread (void)
static char * strip_control_and_high (const char *input, char *buf, size_t buflen)
 Strips control and non 7-bit clean characters from input string.
static const char * substitute_escapes (const char *value)
static int unload_module (void)
static int vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
static int vm_box_exists (struct ast_channel *chan, const char *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Spanish syntax for 'You have N messages' greeting.
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_it (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Italian syntax for 'You have N messages' greeting.
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Portuguese syntax for 'You have N messages' greeting.
static int vm_browse_messages_vi (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Vietnamese syntax for 'You have N messages' greeting.
static int vm_browse_messages_zh (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Chinese (Taiwan)syntax for 'You have N messages' greeting.
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
 The handler for the change password option.
static void vm_change_password_shell (struct ast_vm_user *vmu, char *newpassword)
static char * vm_check_password_shell (char *command, char *buf, size_t len)
static int vm_delete (char *file)
 Removes the voicemail sound and information file.
static int vm_exec (struct ast_channel *chan, const char *data)
static int vm_execmain (struct ast_channel *chan, const char *data)
static int vm_forwardoptions (struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
 presents the option to prepend to an existing message when forwarding it.
static int vm_instructions (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_en (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_zh (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_intro (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_cs (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_de (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_en (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_es (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_fr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_gr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_he (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_it (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_multilang (struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_intro_nl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_no (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt_BR (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_se (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_vi (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_zh (struct ast_channel *chan, struct vm_state *vms)
static int vm_lock_path (const char *path)
 Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.
static FILE * vm_mkftemp (char *template)
static int vm_newuser (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_play_folder_name (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_gr (struct ast_channel *chan, char *box)
static int vm_play_folder_name_pl (struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua (struct ast_channel *chan, char *box)
static int vm_tempgreeting (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
 The handler for 'record a temporary greeting'.
static int vm_users_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int vm_users_data_provider_get_helper (const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
static int vmauthenticate (struct ast_channel *chan, const char *data)
static int vmsayname_exec (struct ast_channel *chan, const char *data)
static struct ast_tmvmu_tm (const struct ast_vm_user *vmu, struct ast_tm *tm)
 fill in *tm for current time according to the proper timezone, if any.
static int wait_file (struct ast_channel *chan, struct vm_state *vms, char *file)
static int wait_file2 (struct ast_channel *chan, struct vm_state *vms, char *file)
static int write_password_to_file (const char *secretfn, const char *password)

Variables

static char * addesc = "Comedian Mail"
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
static int adsiver = 1
static char * app = "VoiceMail"
static char * app2 = "VoiceMailMain"
static char * app3 = "MailboxExists"
static char * app4 = "VMAuthenticate"
static char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_check_cmd [128]
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
struct ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char * sayname_app = "VMSayName"
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_data_entry vm_data_providers []
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_prepend_timeout [80] = "vm-then-pound"
static char vm_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
static struct ast_data_handler vm_users_data_provider
static char vmfmts [80]
static int vmmaxsecs
static int vmminsecs
static double volgain
static char zonetag [80]

Detailed Description

Comedian Mail - Voicemail System.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
unixODBC (http://www.unixodbc.org/)
ExtRef:
A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/)
See also
Note:
For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage
This module requires res_adsi to load. This needs to be optional during compilation.
This file is now almost impossible to work with, due to all #ifdefs. Feels like the database code before realtime. Someone - please come up with a plan to clean this up.

Definition in file app_voicemail.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

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

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11343 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 11370 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 810 of file app_voicemail.c.

Referenced by actual_load_config().

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

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

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

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

Definition at line 446 of file app_voicemail.c.

Referenced by leave_voicemail(), 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 leave_voicemail(), vm_exec(), and vm_execmain().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 753 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 752 of file app_voicemail.c.

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

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

Definition at line 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,
 ) 
#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 762 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)
#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 677 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(), leave_voicemail(), and vm_mkftemp().


Enumeration Type Documentation

enum vm_box
Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 
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 };

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 
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 };

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
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 };

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
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 5388 of file app_voicemail.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

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

05389 {
05390    DIR *dir;
05391    struct dirent *de;
05392    char fn[256];
05393    int ret = 0;
05394 
05395    /* If no mailbox, return immediately */
05396    if (ast_strlen_zero(mailbox))
05397       return 0;
05398 
05399    if (ast_strlen_zero(folder))
05400       folder = "INBOX";
05401    if (ast_strlen_zero(context))
05402       context = "default";
05403 
05404    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05405 
05406    if (!(dir = opendir(fn)))
05407       return 0;
05408 
05409    while ((de = readdir(dir))) {
05410       if (!strncasecmp(de->d_name, "msg", 3)) {
05411          if (shortcircuit) {
05412             ret = 1;
05413             break;
05414          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05415             ret++;
05416          }
05417       }
05418    }
05419 
05420    closedir(dir);
05421 
05422    return ret;
05423 }

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

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

11047 {
11048    struct ast_vm_user svm;
11049    AST_DECLARE_APP_ARGS(arg,
11050       AST_APP_ARG(mbox);
11051       AST_APP_ARG(context);
11052    );
11053 
11054    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11055 
11056    if (ast_strlen_zero(arg.mbox)) {
11057       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11058       return -1;
11059    }
11060 
11061    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11062    return 0;
11063 }

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

Definition at line 11880 of file app_voicemail.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, AST_LOG_WARNING, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, ast_vm_user::context, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, ext_pass_check_cmd, ext_pass_cmd, externnotify, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), ast_variable::lineno, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, locale, LOG_ERROR, ast_vm_user::mailbox, mailcmd, MAX_NUM_CID_CONTEXTS, maxdeletedmsg, maxgreet, maxlogins, MAXMSG, maxmsg, MAXMSGLIMIT, maxsilence, MINPASSWORD, minpassword, ast_variable::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, ast_vm_user::password, ast_vm_user::passwordlocation, passwordlocation, poll_freq, poll_mailboxes, poll_thread, populate_defaults(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, serveremail, silencethreshold, skipms, smdi_iface, start_poll_thread(), stop_poll_thread(), substitute_escapes(), THRESHOLD_SILENCE, userscontext, ast_variable::value, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_prepend_timeout, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SPOOL_DIR, VM_SVMAIL, VM_TEMPGREETWARN, vmfmts, vmmaxsecs, vmminsecs, volgain, and zonetag.

Referenced by load_config().

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

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

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

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

Definition at line 6408 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

06409 {
06410    int x;
06411    if (!ast_adsi_available(chan))
06412       return;
06413    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06414    if (x < 0)
06415       return;
06416    if (!x) {
06417       if (adsi_load_vmail(chan, useadsi)) {
06418          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06419          return;
06420       }
06421    } else
06422       *useadsi = 1;
06423 }

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

Definition at line 6603 of file app_voicemail.c.

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

Referenced by vm_execmain().

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

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

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

06474 {
06475    unsigned char buf[256];
06476    int bytes = 0;
06477    unsigned char keys[8];
06478    int x, y;
06479 
06480    if (!ast_adsi_available(chan))
06481       return;
06482 
06483    for (x = 0; x < 5; x++) {
06484       y = ADSI_KEY_APPS + 12 + start + x;
06485       if (y > ADSI_KEY_APPS + 12 + 4)
06486          y = 0;
06487       keys[x] = ADSI_KEY_SKT | y;
06488    }
06489    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06490    keys[6] = 0;
06491    keys[7] = 0;
06492 
06493    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06494    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06495    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06496    bytes += ast_adsi_set_keys(buf + bytes, keys);
06497    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06498 
06499    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06500 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06759 {
06760    unsigned char buf[256];
06761    int bytes = 0;
06762 
06763    if (!ast_adsi_available(chan))
06764       return;
06765    bytes += adsi_logo(buf + bytes);
06766    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06767    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06768    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06769    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06770 
06771    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06772 }

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

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

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

static void adsi_login ( struct ast_channel chan  )  [static]

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

06426 {
06427    unsigned char buf[256];
06428    int bytes = 0;
06429    unsigned char keys[8];
06430    int x;
06431    if (!ast_adsi_available(chan))
06432       return;
06433 
06434    for (x = 0; x < 8; x++)
06435       keys[x] = 0;
06436    /* Set one key for next */
06437    keys[3] = ADSI_KEY_APPS + 3;
06438 
06439    bytes += adsi_logo(buf + bytes);
06440    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06441    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06442    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06443    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06444    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06445    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06446    bytes += ast_adsi_set_keys(buf + bytes, keys);
06447    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06448    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06449 }

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

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

06272 {
06273    int bytes = 0;
06274    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06275    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06276    return bytes;
06277 }

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

Definition at line 6502 of file app_voicemail.c.

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

Referenced by play_message(), and vm_execmain().

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

static void adsi_password ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 6655 of file app_voicemail.c.

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

Referenced by vm_execmain().

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

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

Definition at line 6702 of file app_voicemail.c.

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

Referenced by vm_execmain().

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

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

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

Referenced by vm_execmain().

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

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

Definition at line 10773 of file app_voicemail.c.

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

Referenced by actual_load_config().

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

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

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

Referenced by apply_options(), and apply_options_full().

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

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

Destructively Parse options and apply.

Definition at line 1296 of file app_voicemail.c.

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

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

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

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

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

Referenced by actual_load_config(), and find_user_realtime().

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

AST_APP_OPTIONS ( vm_app_options   ) 
AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)
AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)
static AST_LIST_HEAD_STATIC ( zones  ,
vm_zone   
) [static]
static AST_LIST_HEAD_STATIC ( users  ,
ast_vm_user   
) [static]
AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
tdesc  ,
load = load_module,
unload = unload_module,
reload = reload,
nonoptreq = "res_adsi,res_smdi" 
)
AST_MUTEX_DEFINE_STATIC ( poll_lock   ) 
static AST_RWLIST_HEAD_STATIC ( mwi_subs  ,
mwi_sub   
) [static]
static const char* ast_str_encode_mime ( struct ast_str **  end,
ssize_t  maxlen,
const char *  start,
size_t  preamble,
size_t  postamble 
) [static]

Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain control characters.

Additionally, if the encoded string would exceed the MIME limit of 76 characters per line, then the encoding will be broken up into multiple sections, separated by a space character, in order to facilitate breaking up the associated header across multiple lines.

Parameters:
end An expandable buffer for holding the result
maxlen Always zero, but see
See also:
ast_str
Parameters:
start A string to be encoded
preamble The length of the first line already used for this string, to ensure that each line maintains a maximum length of 76 chars.
postamble the length of any additional characters appended to the line, used to ensure proper field wrapping.
Return values:
The encoded string.

Definition at line 4477 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

04478 {
04479    struct ast_str *tmp = ast_str_alloca(80);
04480    int first_section = 1;
04481 
04482    ast_str_reset(*end);
04483    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04484    for (; *start; start++) {
04485       int need_encoding = 0;
04486       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04487          need_encoding = 1;
04488       }
04489       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04490          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04491          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04492          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04493          /* Start new line */
04494          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04495          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04496          first_section = 0;
04497       }
04498       if (need_encoding && *start == ' ') {
04499          ast_str_append(&tmp, -1, "_");
04500       } else if (need_encoding) {
04501          ast_str_append(&tmp, -1, "=%hhX", *start);
04502       } else {
04503          ast_str_append(&tmp, -1, "%c", *start);
04504       }
04505    }
04506    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04507    return ast_str_buffer(*end);
04508 }

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

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

Referenced by make_email_file(), and sendpage().

04406 {
04407    const char *ptr;
04408 
04409    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04410    ast_str_set(buf, maxlen, "\"");
04411    for (ptr = from; *ptr; ptr++) {
04412       if (*ptr == '"' || *ptr == '\\') {
04413          ast_str_append(buf, maxlen, "\\%c", *ptr);
04414       } else {
04415          ast_str_append(buf, maxlen, "%c", *ptr);
04416       }
04417    }
04418    ast_str_append(buf, maxlen, "\"");
04419 
04420    return ast_str_buffer(*buf);
04421 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10830 of file app_voicemail.c.

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

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

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

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

Referenced by add_email_attachment().

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

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

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

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

Referenced by make_email_file(), and sendpage().

04451 {
04452    for (; *str; str++) {
04453       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04454          return 1;
04455       }
04456    }
04457    return 0;
04458 }

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

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

Referenced by vm_newuser(), and vm_options().

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

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

Definition at line 7968 of file app_voicemail.c.

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

Referenced by vm_execmain().

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

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

Definition at line 11150 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11151 {
11152    int which = 0;
11153    int wordlen;
11154    struct ast_vm_user *vmu;
11155    const char *context = "";
11156 
11157    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11158    if (pos > 4)
11159       return NULL;
11160    if (pos == 3)
11161       return (state == 0) ? ast_strdup("for") : NULL;
11162    wordlen = strlen(word);
11163    AST_LIST_TRAVERSE(&users, vmu, list) {
11164       if (!strncasecmp(word, vmu->context, wordlen)) {
11165          if (context && strcmp(context, vmu->context) && ++which > state)
11166             return ast_strdup(vmu->context);
11167          /* ignore repeated contexts ? */
11168          context = vmu->context;
11169       }
11170    }
11171    return NULL;
11172 }

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

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

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

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

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

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), ast_channel::caller, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), maxmsg, mbox(), ast_party_id::name, notify_new_message(), ast_party_id::number, S_COR, STORE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, ast_party_number::valid, vm_delete(), and vm_lock_path().

Referenced by forward_message(), and leave_voicemail().

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

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

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

Referenced by copy_message().

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

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

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

Referenced by leave_voicemail(), manager_list_voicemail_users(), and open_mailbox().

03982 {
03983 
03984    int vmcount = 0;
03985    DIR *vmdir = NULL;
03986    struct dirent *vment = NULL;
03987 
03988    if (vm_lock_path(dir))
03989       return ERROR_LOCK_PATH;
03990 
03991    if ((vmdir = opendir(dir))) {
03992       while ((vment = readdir(vmdir))) {
03993          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03994             vmcount++;
03995          }
03996       }
03997       closedir(vmdir);
03998    }
03999    ast_unlock_path(dir);
04000    
04001    return vmcount;
04002 }

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

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

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

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

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

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

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

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

Definition at line 10733 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

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

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

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

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

Definition at line 1436 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_malloc, ast_set2_flag, ast_strdup, ast_test_flag, ast_vm_user::emailbody, ast_vm_user::emailsubject, find_user_realtime(), globalflags, VM_ALLOCED, and VM_SEARCH.

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

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

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

Finds a voicemail user from the realtime engine.

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

Definition at line 1395 of file app_voicemail.c.

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

Referenced by find_user().

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

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

Sends a voicemail message to a mailbox recipient.

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

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

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

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

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

Definition at line 7169 of file app_voicemail.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_waitfordigit(), ast_channel::caller, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), vm_state::fn, free_user(), globalflags, ast_party_caller::id, inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), serveremail, STORE, ast_party_name::str, ast_party_number::str, vm_state::username, ast_party_name::valid, ast_party_number::valid, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), VM_FWDURGAUTO, VM_SPOOL_DIR, and vmfmts.

Referenced by vm_execmain().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1739 of file app_voicemail.c.

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

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

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

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11762 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11763 {
11764    struct ast_vm_user *current;
11765    AST_LIST_LOCK(&users);
11766    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11767       ast_set_flag(current, VM_ALLOCED);
11768       free_user(current);
11769    }
11770    AST_LIST_UNLOCK(&users);
11771 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11774 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11775 {
11776    struct vm_zone *zcur;
11777    AST_LIST_LOCK(&zones);
11778    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11779       free_zone(zcur);
11780    AST_LIST_UNLOCK(&zones);
11781 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5090 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

05091 {
05092    ast_free(z);
05093 }

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

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

Referenced by leave_voicemail().

05047 {
05048    struct ast_tm tm;
05049    struct timeval t = ast_tvnow();
05050    
05051    ast_localtime(&t, &tm, "UTC");
05052 
05053    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05054 }

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

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

Referenced by get_folder2().

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

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

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

Referenced by vm_execmain().

06836 {
06837    int res = 0;
06838    int loops = 0;
06839 
06840    res = ast_play_and_wait(chan, fn);  /* Folder name */
06841    while (((res < '0') || (res > '9')) &&
06842          (res != '#') && (res >= 0) &&
06843          loops < 4) {
06844       res = get_folder(chan, 0);
06845       loops++;
06846    }
06847    if (loops == 4) { /* give up */
06848       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06849       return '#';
06850    }
06851    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06852    return res;
06853 }

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

Definition at line 1726 of file app_voicemail.c.

References ARRAY_LEN, and mailbox_folders.

Referenced by vm_execmain().

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

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11532 of file app_voicemail.c.

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

Referenced by mwi_sub_event_cb().

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

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11510 of file app_voicemail.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and mwi_sub_destroy().

Referenced by mwi_unsub_event_cb().

11511 {
11512    struct mwi_sub *mwi_sub;
11513    uint32_t *uniqueid = datap;
11514    
11515    AST_RWLIST_WRLOCK(&mwi_subs);
11516    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11517       if (mwi_sub->uniqueid == *uniqueid) {
11518          AST_LIST_REMOVE_CURRENT(entry);
11519          break;
11520       }
11521    }
11522    AST_RWLIST_TRAVERSE_SAFE_END
11523    AST_RWLIST_UNLOCK(&mwi_subs);
11524 
11525    if (mwi_sub)
11526       mwi_sub_destroy(mwi_sub);
11527 
11528    ast_free(uniqueid);  
11529    return 0;
11530 }

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

11288 {
11289    switch (cmd) {
11290    case CLI_INIT:
11291       e->command = "voicemail reload";
11292       e->usage =
11293          "Usage: voicemail reload\n"
11294          "       Reload voicemail configuration\n";
11295       return NULL;
11296    case CLI_GENERATE:
11297       return NULL;
11298    }
11299 
11300    if (a->argc != 2)
11301       return CLI_SHOWUSAGE;
11302 
11303    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11304    load_config(1);
11305    
11306    return CLI_SUCCESS;
11307 }

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

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

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

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

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

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

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

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

Referenced by load_module(), and vm_execmain().

05435 {
05436    char tmp[256], *tmp2 = tmp, *box, *context;
05437    ast_copy_string(tmp, mailbox, sizeof(tmp));
05438    if (ast_strlen_zero(folder)) {
05439       folder = "INBOX";
05440    }
05441    while ((box = strsep(&tmp2, ",&"))) {
05442       if ((context = strchr(box, '@')))
05443          *context++ = '\0';
05444       else
05445          context = "default";
05446       if (__has_voicemail(context, box, folder, 1))
05447          return 1;
05448       /* If we are checking INBOX, we should check Urgent as well */
05449       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05450          return 1;
05451       }
05452    }
05453    return 0;
05454 }

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

Definition at line 5516 of file app_voicemail.c.

References inboxcount2().

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

05517 {
05518    int urgentmsgs = 0;
05519    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05520    if (newmsgs) {
05521       *newmsgs += urgentmsgs;
05522    }
05523    return res;
05524 }

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

Definition at line 5457 of file app_voicemail.c.

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

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

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

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

utility used by inchar(), for base_encode()

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

04217 {
04218    int l;
04219 
04220    if (bio->ateof)
04221       return 0;
04222 
04223    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04224       if (ferror(fi))
04225          return -1;
04226 
04227       bio->ateof = 1;
04228       return 0;
04229    }
04230 
04231    bio->iolen = l;
04232    bio->iocp = 0;
04233 
04234    return 1;
04235 }

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

utility used by base_encode()

Definition at line 4240 of file app_voicemail.c.

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

Referenced by base_encode().

04241 {
04242    if (bio->iocp>=bio->iolen) {
04243       if (!inbuf(bio, fi))
04244          return EOF;
04245    }
04246 
04247    return bio->iobuf[bio->iocp++];
04248 }

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

Definition at line 934 of file app_voicemail.c.

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

Referenced by load_module().

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

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

Definition at line 943 of file app_voicemail.c.

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

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

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

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

Definition at line 928 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

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

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

Definition at line 5056 of file app_voicemail.c.

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

Referenced by leave_voicemail().

05057 {
05058    int res;
05059    char fn[PATH_MAX];
05060    char dest[PATH_MAX];
05061 
05062    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05063 
05064    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05065       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05066       return -1;
05067    }
05068 
05069    RETRIEVE(fn, -1, ext, context);
05070    if (ast_fileexists(fn, NULL, NULL) > 0) {
05071       res = ast_stream_and_wait(chan, fn, ecodes);
05072       if (res) {
05073          DISPOSE(fn, -1);
05074          return res;
05075       }
05076    } else {
05077       /* Dispose just in case */
05078       DISPOSE(fn, -1);
05079       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05080       if (res)
05081          return res;
05082       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05083       if (res)
05084          return res;
05085    }
05086    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05087    return res;
05088 }

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

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

Referenced by actual_load_config().

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

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

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

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

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

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

References ast_callerid_merge(), ast_canmatch_extension(), ast_channel_lock, ast_channel_unlock, ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, ast_channel::exten, find_user(), free_user(), ast_party_redirecting::from, get_date(), ast_party_caller::id, inboxcount(), inprocess_count(), INTRO, invent_message(), last_message_index(), LOG_DEBUG, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, my_umask, ast_party_id::name, vm_state::newmessages, notify_new_message(), ast_party_id::number, OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, ast_channel::redirecting, RENAME, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, ast_party_name::str, ast_party_number::str, transfer, ast_party_name::valid, ast_party_number::valid, vm_lock_path(), VM_OPERATOR, VM_SPOOL_DIR, vmfmts, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

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

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

static int load_config ( int  reload  )  [static]

Definition at line 11830 of file app_voicemail.c.

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

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

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

static int load_module ( void   )  [static]

Definition at line 13130 of file app_voicemail.c.

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

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

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

References VM_SPOOL_DIR.

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

01639 {
01640    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01641 }

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

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

Referenced by sendmail().

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

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

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

01656 {
01657    return snprintf(dest, len, "%s/msg%04d", dir, num);
01658 }

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

Manager list voicemail users command.

Definition at line 11661 of file app_voicemail.c.

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

Referenced by load_module().

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

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

Definition at line 11482 of file app_voicemail.c.

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

Referenced by start_poll_thread().

11483 {
11484    while (poll_thread_run) {
11485       struct timespec ts = { 0, };
11486       struct timeval wait;
11487 
11488       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11489       ts.tv_sec = wait.tv_sec;
11490       ts.tv_nsec = wait.tv_usec * 1000;
11491 
11492       ast_mutex_lock(&poll_lock);
11493       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11494       ast_mutex_unlock(&poll_lock);
11495 
11496       if (!poll_thread_run)
11497          break;
11498 
11499       poll_subscribed_mailboxes();
11500    }
11501 
11502    return NULL;
11503 }

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

Definition at line 1716 of file app_voicemail.c.

References ARRAY_LEN, and mailbox_folders.

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

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

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

Definition at line 5383 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

05384 {
05385    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05386 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11505 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

11506 {
11507    ast_free(mwi_sub);
11508 }

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

Definition at line 11593 of file app_voicemail.c.

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

Referenced by start_poll_thread().

11594 {
11595    struct mwi_sub_task *mwist;
11596    
11597    if (ast_event_get_type(event) != AST_EVENT_SUB)
11598       return;
11599 
11600    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11601       return;
11602 
11603    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11604       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11605       return;
11606    }
11607    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11608    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11609    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11610    
11611    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11612       ast_free(mwist);
11613    }
11614 }

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

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

11568 {
11569    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11570 
11571    if (!uniqueid) {
11572       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11573       return;
11574    }
11575 
11576    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11577       ast_free(uniqueid);
11578       return;
11579    }
11580 
11581    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11582       ast_free(uniqueid);
11583       return;
11584    }
11585 
11586    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11587    *uniqueid = u;
11588    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11589       ast_free(uniqueid);
11590    }
11591 }

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

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

Referenced by copy_message(), and leave_voicemail().

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

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

utility used by base_encode()

Definition at line 4253 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04254 {
04255    if (bio->linelength >= BASELINELEN) {
04256       if (fputs(ENDL, so) == EOF) {
04257          return -1;
04258       }
04259 
04260       bio->linelength = 0;
04261    }
04262 
04263    if (putc(((unsigned char) c), so) == EOF) {
04264       return -1;
04265    }
04266 
04267    bio->linelength++;
04268 
04269    return 1;
04270 }

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

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

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

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

Definition at line 7689 of file app_voicemail.c.

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

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

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

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

Definition at line 7575 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

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

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

Definition at line 7486 of file app_voicemail.c.

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

Referenced by play_message().

07487 {
07488    int res = 0;
07489 
07490    if (!ast_strlen_zero(category))
07491       res = ast_play_and_wait(chan, category);
07492 
07493    if (res) {
07494       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07495       res = 0;
07496    }
07497 
07498    return res;
07499 }

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

Definition at line 7501 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_get_time_t(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), AST_LOG_WARNING, ast_say_date_with_format, ast_strlen_zero(), ast_tvnow(), pbx_builtin_setvar_helper(), and ast_vm_user::zonetag.

Referenced by advanced_options(), and play_message().

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

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

Definition at line 7639 of file app_voicemail.c.

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

Referenced by play_message().

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

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

References acceptdtmf, ast_channel_setoption(), ast_copy_string(), AST_DIGIT_ANY, ast_filedelete(), ast_filerename(), ast_log(), AST_LOG_WARNING, AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, INTRO, ast_vm_user::mailbox, maxsilence, silencethreshold, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11454 of file app_voicemail.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11455 {
11456    int new = 0, old = 0, urgent = 0;
11457 
11458    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11459 
11460    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11461       mwi_sub->old_urgent = urgent;
11462       mwi_sub->old_new = new;
11463       mwi_sub->old_old = old;
11464       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11465       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11466    }
11467 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11469 of file app_voicemail.c.

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

Referenced by mb_poll_thread().

11470 {
11471    struct mwi_sub *mwi_sub;
11472 
11473    AST_RWLIST_RDLOCK(&mwi_subs);
11474    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11475       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11476          poll_subscribed_mailbox(mwi_sub);
11477       }
11478    }
11479    AST_RWLIST_UNLOCK(&mwi_subs);
11480 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

  • all the globalflags
  • the saydurationminfo
  • the callcontext
  • the dialcontext
  • the exitcontext
  • vmmaxsecs, vmmaxmsg, maxdeletedmsg
  • volume gain
  • emailsubject, emailbody set to NULL

Definition at line 1013 of file app_voicemail.c.

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

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

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

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

Referenced by make_email_file(), and sendpage().

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

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

Definition at line 7029 of file app_voicemail.c.

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

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

07030 {
07031    struct ast_event *event;
07032    char *mailbox, *context;
07033 
07034    /* Strip off @default */
07035    context = mailbox = ast_strdupa(box);
07036    strsep(&context, "@");
07037    if (ast_strlen_zero(context))
07038       context = "default";
07039 
07040    if (!(event = ast_event_new(AST_EVENT_MWI,
07041          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07042          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07043          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07044          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07045          AST_EVENT_IE_END))) {
07046       return;
07047    }
07048 
07049    ast_event_queue_and_cache(event);
07050 }

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

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

12560                                                                                            {
12561    struct ast_config *pwconf;
12562    struct ast_flags config_flags = { 0 };
12563 
12564    pwconf = ast_config_load(secretfn, config_flags);
12565    if (pwconf) {
12566       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12567       if (val) {
12568          ast_copy_string(password, val, passwordlen);
12569          ast_config_destroy(pwconf);
12570          return;
12571       }
12572       ast_config_destroy(pwconf);
12573    }
12574    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12575 }

static int reload ( void   )  [static]

Definition at line 13090 of file app_voicemail.c.

References load_config().

13091 {
13092    return load_config(1);
13093 }

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

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

04012 {
04013    char stxt[PATH_MAX];
04014    char dtxt[PATH_MAX];
04015    ast_filerename(sfn, dfn, NULL);
04016    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04017    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04018    if (ast_check_realtime("voicemail_data")) {
04019       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04020    }
04021    rename(stxt, dtxt);
04022 }

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

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

06156 {
06157    /* we know the actual number of messages, so stop process when number is hit */
06158 
06159    int x, dest;
06160    char sfn[PATH_MAX];
06161    char dfn[PATH_MAX];
06162 
06163    if (vm_lock_path(dir)) {
06164       return ERROR_LOCK_PATH;
06165    }
06166 
06167    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06168       make_file(sfn, sizeof(sfn), dir, x);
06169       if (EXISTS(dir, x, sfn, NULL)) {
06170 
06171          if (x != dest) {
06172             make_file(dfn, sizeof(dfn), dir, dest);
06173             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06174          }
06175 
06176          dest++;
06177       }
06178    }
06179    ast_unlock_path(dir);
06180 
06181    return dest;
06182 }

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

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

Referenced by vm_change_password(), and vm_change_password_shell().

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

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

Definition at line 5526 of file app_voicemail.c.

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

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

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

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

Definition at line 6192 of file app_voicemail.c.

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

Referenced by close_mailbox(), and vm_execmain().

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

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

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

12547 {
12548    int res = -1;
12549    char dir[PATH_MAX];
12550    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12551    ast_debug(2, "About to try retrieving name file %s\n", dir);
12552    RETRIEVE(dir, -1, mailbox, context);
12553    if (ast_fileexists(dir, NULL, NULL)) {
12554       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12555    }
12556    DISPOSE(dir, -1);
12557    return res;
12558 }

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

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

Referenced by forward_message(), and notify_new_message().

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

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

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

Referenced by notify_new_message().

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

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

Definition at line 11111 of file app_voicemail.c.

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, ast_variable::name, ast_variable::next, SENTINEL, and ast_variable::value.

Referenced by handle_voicemail_show_users().

11112 {
11113    struct ast_config *cfg;
11114    const char *cat = NULL;
11115 
11116    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11117       "context", context, SENTINEL))) {
11118       return CLI_FAILURE;
11119    }
11120 
11121    ast_cli(fd,
11122       "\n"
11123       "=============================================================\n"
11124       "=== Configured Voicemail Users ==============================\n"
11125       "=============================================================\n"
11126       "===\n");
11127 
11128    while ((cat = ast_category_browse(cfg, cat))) {
11129       struct ast_variable *var = NULL;
11130       ast_cli(fd,
11131          "=== Mailbox ...\n"
11132          "===\n");
11133       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11134          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11135       ast_cli(fd,
11136          "===\n"
11137          "=== ---------------------------------------------------------\n"
11138          "===\n");
11139    }
11140 
11141    ast_cli(fd,
11142       "=============================================================\n"
11143       "\n");
11144 
11145    ast_config_destroy(cfg);
11146 
11147    return CLI_SUCCESS;
11148 }

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

Definition at line 11637 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11638 {
11639    poll_thread_run = 0;
11640 
11641    if (mwi_sub_sub) {
11642       ast_event_unsubscribe(mwi_sub_sub);
11643       mwi_sub_sub = NULL;
11644    }
11645 
11646    if (mwi_unsub_sub) {
11647       ast_event_unsubscribe(mwi_unsub_sub);
11648       mwi_unsub_sub = NULL;
11649    }
11650 
11651    ast_mutex_lock(&poll_lock);
11652    ast_cond_signal(&poll_cond);
11653    ast_mutex_unlock(&poll_lock);
11654 
11655    pthread_join(poll_thread, NULL);
11656 
11657    poll_thread = AST_PTHREADT_NULL;
11658 }

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

Referenced by make_email_file(), and sendpage().

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

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

Definition at line 11783 of file app_voicemail.c.

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

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

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

static int unload_module ( void   )  [static]

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

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

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

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

01753                                                                                         {
01754 
01755    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01756 
01757    /* remove old allocation */
01758    if (vms->deleted) {
01759       ast_free(vms->deleted);
01760       vms->deleted = NULL;
01761    }
01762    if (vms->heard) {
01763       ast_free(vms->heard);
01764       vms->heard = NULL;
01765    }
01766    vms->dh_arraysize = 0;
01767 
01768    if (arraysize > 0) {
01769       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01770          return -1;
01771       }
01772       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01773          ast_free(vms->deleted);
01774          vms->deleted = NULL;
01775          return -1;
01776       }
01777       vms->dh_arraysize = arraysize;
01778    }
01779 
01780    return 0;
01781 }

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

References adsi_begin(), adsi_login(), adsi_password(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, find_user(), ast_party_caller::id, ast_party_id::number, ast_vm_user::password, S_COR, ast_party_number::str, ast_party_number::valid, and vm_password.

Referenced by vm_execmain(), and vmauthenticate().

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

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

Definition at line 11006 of file app_voicemail.c.

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

Referenced by load_module().

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

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

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

Referenced by vm_execmain().

09767 {
09768    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09769       return vm_browse_messages_es(chan, vms, vmu);
09770    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09771       return vm_browse_messages_gr(chan, vms, vmu);
09772    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09773       return vm_browse_messages_he(chan, vms, vmu);
09774    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09775       return vm_browse_messages_it(chan, vms, vmu);
09776    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09777       return vm_browse_messages_pt(chan, vms, vmu);
09778    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09779       return vm_browse_messages_vi(chan, vms, vmu);
09780    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09781       return vm_browse_messages_zh(chan, vms, vmu);
09782    } else {                                             /* Default to English syntax */
09783       return vm_browse_messages_en(chan, vms, vmu);
09784    }
09785 }

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

09606 {
09607    int cmd = 0;
09608 
09609    if (vms->lastmsg > -1) {
09610       cmd = play_message(chan, vmu, vms);
09611    } else {
09612       cmd = ast_play_and_wait(chan, "vm-youhave");
09613       if (!cmd) 
09614          cmd = ast_play_and_wait(chan, "vm-no");
09615       if (!cmd) {
09616          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09617          cmd = ast_play_and_wait(chan, vms->fn);
09618       }
09619       if (!cmd)
09620          cmd = ast_play_and_wait(chan, "vm-messages");
09621    }
09622    return cmd;
09623 }

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

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

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

09554 {
09555    int cmd = 0;
09556 
09557    if (vms->lastmsg > -1) {
09558       cmd = play_message(chan, vmu, vms);
09559    } else {
09560       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09561       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09562          if (!cmd) {
09563             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09564             cmd = ast_play_and_wait(chan, vms->fn);
09565          }
09566          if (!cmd)
09567             cmd = ast_play_and_wait(chan, "vm-messages");
09568       } else {
09569          if (!cmd)
09570             cmd = ast_play_and_wait(chan, "vm-messages");
09571          if (!cmd) {
09572             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09573             cmd = ast_play_and_wait(chan, vms->fn);
09574          }
09575       }
09576    } 
09577    return cmd;
09578 }

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

Definition at line 9581 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09582 {
09583    int cmd = 0;
09584 
09585    if (vms->lastmsg > -1) {
09586       cmd = play_message(chan, vmu, vms);
09587    } else {
09588       if (!strcasecmp(vms->fn, "INBOX")) {
09589          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09590       } else {
09591          cmd = ast_play_and_wait(chan, "vm-nomessages");
09592       }
09593    }
09594    return cmd;
09595 }

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

09634 {
09635    int cmd;
09636 
09637    if (vms->lastmsg > -1) {
09638       cmd = play_message(chan, vmu, vms);
09639    } else {
09640       cmd = ast_play_and_wait(chan, "vm-no");
09641       if (!cmd)
09642          cmd = ast_play_and_wait(chan, "vm-message");
09643       if (!cmd) {
09644          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09645          cmd = ast_play_and_wait(chan, vms->fn);
09646       }
09647    }
09648    return cmd;
09649 }

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

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

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

09740 {
09741    int cmd = 0;
09742 
09743    if (vms->lastmsg > -1) {
09744       cmd = play_message(chan, vmu, vms);
09745    } else {
09746       cmd = ast_play_and_wait(chan, "vm-no");
09747       if (!cmd) {
09748          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09749          cmd = ast_play_and_wait(chan, vms->fn);
09750       }
09751    }
09752    return cmd;
09753 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by copy_message(), and notify_new_message().

04196 {
04197    char *txt;
04198    int txtsize = 0;
04199 
04200    txtsize = (strlen(file) + 5)*sizeof(char);
04201    txt = ast_alloca(txtsize);
04202    /* Sprintf here would safe because we alloca'd exactly the right length,
04203     * but trying to eliminate all sprintf's anyhow
04204     */
04205    if (ast_check_realtime("voicemail_data")) {
04206       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04207    }
04208    snprintf(txt, txtsize, "%s.txt", file);
04209    unlink(txt);
04210    return ast_filedelete(file, NULL);
04211 }

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

Definition at line 10665 of file app_voicemail.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), ast_copy_flags, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, ast_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_vm_options::exitcontext, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and leave_vm_options::record_gain.

Referenced by load_module(), and play_record_review().

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

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

Definition at line 9913 of file app_voicemail.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_LOG_WARNING, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_test_suite_assert, ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, vm_state::context, ast_channel::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), vm_state::fn, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, has_voicemail(), vm_state::heard, language, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), maxlogins, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, OLD_FOLDER, vm_state::oldmessages, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), vm_state::repeats, run_externnotify(), save_to_folder(), say_and_wait(), vm_state::starting, vm_state::urgentmessages, vm_state::username, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, VM_SVMAIL, vm_state::vmbox, and vmfmts.

Referenced by load_module().

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

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

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

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

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

Referenced by vm_execmain().

09229 {
09230    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09231       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09232    } else {             /* Default to ENGLISH */
09233       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09234    }
09235 }

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

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

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

09205 {
09206    int res = 0;
09207    /* Play instructions and wait for new command */
09208    while (!res) {
09209       if (vms->lastmsg > -1) {
09210          res = ast_play_and_wait(chan, "vm-listen");
09211          if (!res)
09212             res = vm_play_folder_name(chan, vms->vmbox);
09213          if (!res)
09214             res = ast_play_and_wait(chan, "press");
09215          if (!res)
09216             res = ast_play_and_wait(chan, "digits/1");
09217       }
09218       if (!res)
09219          res = ast_play_and_wait(chan, "vm-opts");
09220       if (!res) {
09221          vms->starting = 0;
09222          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09223       }
09224    }
09225    return res;
09226 }

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

Definition at line 9054 of file app_voicemail.c.

References ast_fileexists(), ast_log(), ast_play_and_wait(), ast_test_flag, ast_vm_user::context, DISPOSE, LOG_WARNING, ast_vm_user::mailbox, RETRIEVE, vm_state::username, vm_intro_cs(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_he(), vm_intro_it(), vm_intro_multilang(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_pt(), vm_intro_pt_BR(), vm_intro_se(), vm_intro_vi(), vm_intro_zh(), VM_SPOOL_DIR, and VM_TEMPGREETWARN.

Referenced by vm_execmain().

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

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

Definition at line 8924 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8620 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8369 of file app_voicemail.c.

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

Referenced by vm_intro().

08370 {
08371    int res;
08372 
08373    /* Introduce messages they have */
08374    res = ast_play_and_wait(chan, "vm-youhave");
08375    if (!res) {
08376       if (vms->urgentmessages) {
08377          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08378          if (!res)
08379             res = ast_play_and_wait(chan, "vm-Urgent");
08380          if ((vms->oldmessages || vms->newmessages) && !res) {
08381             res = ast_play_and_wait(chan, "vm-and");
08382          } else if (!res) {
08383             if ((vms->urgentmessages == 1))
08384                res = ast_play_and_wait(chan, "vm-message");
08385             else
08386                res = ast_play_and_wait(chan, "vm-messages");
08387          }
08388       }
08389       if (vms->newmessages) {
08390          res = say_and_wait(chan, vms->newmessages, chan->language);
08391          if (!res)
08392             res = ast_play_and_wait(chan, "vm-INBOX");
08393          if (vms->oldmessages && !res)
08394             res = ast_play_and_wait(chan, "vm-and");
08395          else if (!res) {
08396             if ((vms->newmessages == 1))
08397                res = ast_play_and_wait(chan, "vm-message");
08398             else
08399                res = ast_play_and_wait(chan, "vm-messages");
08400          }
08401             
08402       }
08403       if (!res && vms->oldmessages) {
08404          res = say_and_wait(chan, vms->oldmessages, chan->language);
08405          if (!res)
08406             res = ast_play_and_wait(chan, "vm-Old");
08407          if (!res) {
08408             if (vms->oldmessages == 1)
08409                res = ast_play_and_wait(chan, "vm-message");
08410             else
08411                res = ast_play_and_wait(chan, "vm-messages");
08412          }
08413       }
08414       if (!res) {
08415          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08416             res = ast_play_and_wait(chan, "vm-no");
08417             if (!res)
08418                res = ast_play_and_wait(chan, "vm-messages");
08419          }
08420       }
08421    }
08422    return res;
08423 }

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

Definition at line 8669 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8767 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8168 of file app_voicemail.c.

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

Referenced by vm_intro().

08169 {
08170    int res = 0;
08171 
08172    if (vms->newmessages) {
08173       res = ast_play_and_wait(chan, "vm-youhave");
08174       if (!res) 
08175          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08176       if (!res) {
08177          if ((vms->newmessages == 1)) {
08178             res = ast_play_and_wait(chan, "vm-INBOX");
08179             if (!res)
08180                res = ast_play_and_wait(chan, "vm-message");
08181          } else {
08182             res = ast_play_and_wait(chan, "vm-INBOXs");
08183             if (!res)
08184                res = ast_play_and_wait(chan, "vm-messages");
08185          }
08186       }
08187    } else if (vms->oldmessages){
08188       res = ast_play_and_wait(chan, "vm-youhave");
08189       if (!res)
08190          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08191       if ((vms->oldmessages == 1)){
08192          res = ast_play_and_wait(chan, "vm-Old");
08193          if (!res)
08194             res = ast_play_and_wait(chan, "vm-message");
08195       } else {
08196          res = ast_play_and_wait(chan, "vm-Olds");
08197          if (!res)
08198             res = ast_play_and_wait(chan, "vm-messages");
08199       }
08200    } else if (!vms->oldmessages && !vms->newmessages) 
08201       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08202    return res;
08203 }

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

Definition at line 8302 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8426 of file app_voicemail.c.

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

Referenced by vm_intro().

08427 {
08428    /* Introduce messages they have */
08429    int res;
08430    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08431       res = ast_play_and_wait(chan, "vm-no") ||
08432          ast_play_and_wait(chan, "vm-message");
08433    else
08434       res = ast_play_and_wait(chan, "vm-youhave");
08435    if (!res && vms->newmessages) {
08436       res = (vms->newmessages == 1) ?
08437          ast_play_and_wait(chan, "digits/un") ||
08438          ast_play_and_wait(chan, "vm-nuovo") ||
08439          ast_play_and_wait(chan, "vm-message") :
08440          /* 2 or more new messages */
08441          say_and_wait(chan, vms->newmessages, chan->language) ||
08442          ast_play_and_wait(chan, "vm-nuovi") ||
08443          ast_play_and_wait(chan, "vm-messages");
08444       if (!res && vms->oldmessages)
08445          res = ast_play_and_wait(chan, "vm-and");
08446    }
08447    if (!res && vms->oldmessages) {
08448       res = (vms->oldmessages == 1) ?
08449          ast_play_and_wait(chan, "digits/un") ||
08450          ast_play_and_wait(chan, "vm-vecchio") ||
08451          ast_play_and_wait(chan, "vm-message") :
08452          /* 2 or more old messages */
08453          say_and_wait(chan, vms->oldmessages, chan->language) ||
08454          ast_play_and_wait(chan, "vm-vecchi") ||
08455          ast_play_and_wait(chan, "vm-messages");
08456    }
08457    return res;
08458 }

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

Definition at line 8262 of file app_voicemail.c.

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

Referenced by vm_intro().

08263 {
08264    int res;
08265    int lastnum = 0;
08266 
08267    res = ast_play_and_wait(chan, "vm-youhave");
08268 
08269    if (!res && vms->newmessages) {
08270       lastnum = vms->newmessages;
08271 
08272       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08273          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08274       }
08275 
08276       if (!res && vms->oldmessages) {
08277          res = ast_play_and_wait(chan, "vm-and");
08278       }
08279    }
08280 
08281    if (!res && vms->oldmessages) {
08282       lastnum = vms->oldmessages;
08283 
08284       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08285          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08286       }
08287    }
08288 
08289    if (!res) {
08290       if (lastnum == 0) {
08291          res = ast_play_and_wait(chan, "vm-no");
08292       }
08293       if (!res) {
08294          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08295       }
08296    }
08297 
08298    return res;
08299 }

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

Definition at line 8810 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8576 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8461 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8861 of file app_voicemail.c.

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

Referenced by vm_intro().

08862 {
08863    /* Introduce messages they have */
08864    int res;
08865    res = ast_play_and_wait(chan, "vm-youhave");
08866    if (!res) {
08867       if (vms->newmessages) {
08868          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08869          if (!res) {
08870             if ((vms->newmessages == 1)) {
08871                res = ast_play_and_wait(chan, "vm-message");
08872                if (!res)
08873                   res = ast_play_and_wait(chan, "vm-INBOXs");
08874             } else {
08875                res = ast_play_and_wait(chan, "vm-messages");
08876                if (!res)
08877                   res = ast_play_and_wait(chan, "vm-INBOX");
08878             }
08879          }
08880          if (vms->oldmessages && !res)
08881             res = ast_play_and_wait(chan, "vm-and");
08882       }
08883       if (!res && vms->oldmessages) {
08884          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08885          if (!res) {
08886             if (vms->oldmessages == 1) {
08887                res = ast_play_and_wait(chan, "vm-message");
08888                if (!res)
08889                   res = ast_play_and_wait(chan, "vm-Olds");
08890             } else {
08891                res = ast_play_and_wait(chan, "vm-messages");
08892                if (!res)
08893                   res = ast_play_and_wait(chan, "vm-Old");
08894             }
08895          }
08896       }
08897       if (!res) {
08898          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08899             res = ast_play_and_wait(chan, "vm-no");
08900             if (!res)
08901                res = ast_play_and_wait(chan, "vm-messages");
08902          }
08903       }
08904    }
08905    return res;
08906 }

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

Definition at line 8722 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8532 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 9024 of file app_voicemail.c.

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

Referenced by vm_intro().

09025 {
09026    int res;
09027 
09028    /* Introduce messages they have */
09029    res = ast_play_and_wait(chan, "vm-youhave");
09030    if (!res) {
09031       if (vms->newmessages) {
09032          res = say_and_wait(chan, vms->newmessages, chan->language);
09033          if (!res)
09034             res = ast_play_and_wait(chan, "vm-INBOX");
09035          if (vms->oldmessages && !res)
09036             res = ast_play_and_wait(chan, "vm-and");
09037       }
09038       if (!res && vms->oldmessages) {
09039          res = say_and_wait(chan, vms->oldmessages, chan->language);
09040          if (!res)
09041             res = ast_play_and_wait(chan, "vm-Old");        
09042       }
09043       if (!res) {
09044          if (!vms->oldmessages && !vms->newmessages) {
09045             res = ast_play_and_wait(chan, "vm-no");
09046             if (!res)
09047                res = ast_play_and_wait(chan, "vm-message");
09048          }
09049       }
09050    }
09051    return res;
09052 }

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

Definition at line 8985 of file app_voicemail.c.

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

Referenced by vm_intro().

08986 {
08987    int res;
08988    /* Introduce messages they have */
08989    res = ast_play_and_wait(chan, "vm-you");
08990 
08991    if (!res && vms->newmessages) {
08992       res = ast_play_and_wait(chan, "vm-have");
08993       if (!res)
08994          res = say_and_wait(chan, vms->newmessages, chan->language);
08995       if (!res)
08996          res = ast_play_and_wait(chan, "vm-tong");
08997       if (!res)
08998          res = ast_play_and_wait(chan, "vm-INBOX");
08999       if (vms->oldmessages && !res)
09000          res = ast_play_and_wait(chan, "vm-and");
09001       else if (!res) 
09002          res = ast_play_and_wait(chan, "vm-messages");
09003    }
09004    if (!res && vms->oldmessages) {
09005       res = ast_play_and_wait(chan, "vm-have");
09006       if (!res)
09007          res = say_and_wait(chan, vms->oldmessages, chan->language);
09008       if (!res)
09009          res = ast_play_and_wait(chan, "vm-tong");
09010       if (!res)
09011          res = ast_play_and_wait(chan, "vm-Old");
09012       if (!res)
09013          res = ast_play_and_wait(chan, "vm-messages");
09014    }
09015    if (!res && !vms->oldmessages && !vms->newmessages) {
09016       res = ast_play_and_wait(chan, "vm-haveno");
09017       if (!res)
09018          res = ast_play_and_wait(chan, "vm-messages");
09019    }
09020    return res;
09021 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

03271 {
03272    switch (ast_lock_path(path)) {
03273    case AST_LOCK_TIMEOUT:
03274       return -1;
03275    default:
03276       return 0;
03277    }
03278 }

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

Definition at line 1661 of file app_voicemail.c.

References my_umask, and VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

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

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

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

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

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

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

Definition at line 8131 of file app_voicemail.c.

References ast_play_and_wait(), vm_play_folder_name_gr(), vm_play_folder_name_pl(), and vm_play_folder_name_ua().

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

08132 {
08133    int cmd;
08134 
08135    if (  !strncasecmp(chan->language, "it", 2) ||
08136         !strncasecmp(chan->language, "es", 2) ||
08137         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08138       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08139       return cmd ? cmd : ast_play_and_wait(chan, box);
08140    } else if (!strncasecmp(chan->language, "gr", 2)) {
08141       return vm_play_folder_name_gr(chan, box);
08142    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08143       return ast_play_and_wait(chan, box);
08144    } else if (!strncasecmp(chan->language, "pl", 2)) {
08145       return vm_play_folder_name_pl(chan, box);
08146    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08147       return vm_play_folder_name_ua(chan, box);
08148    } else if (!strncasecmp(chan->language, "vi", 2)) {
08149       return ast_play_and_wait(chan, box);
08150    } else {  /* Default English */
08151       cmd = ast_play_and_wait(chan, box);
08152       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08153    }
08154 }

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

Definition at line 8084 of file app_voicemail.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

08085 {
08086    int cmd;
08087    char *buf;
08088 
08089    buf = ast_alloca(strlen(box) + 2);
08090    strcpy(buf, box);
08091    strcat(buf, "s");
08092 
08093    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08094       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08095       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08096    } else {
08097       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08098       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08099    }
08100 }

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

Definition at line 8102 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08103 {
08104    int cmd;
08105 
08106    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08107       if (!strcasecmp(box, "vm-INBOX"))
08108          cmd = ast_play_and_wait(chan, "vm-new-e");
08109       else
08110          cmd = ast_play_and_wait(chan, "vm-old-e");
08111       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08112    } else {
08113       cmd = ast_play_and_wait(chan, "vm-messages");
08114       return cmd ? cmd : ast_play_and_wait(chan, box);
08115    }
08116 }

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

Definition at line 8118 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08119 {
08120    int cmd;
08121 
08122    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08123       cmd = ast_play_and_wait(chan, "vm-messages");
08124       return cmd ? cmd : ast_play_and_wait(chan, box);
08125    } else {
08126       cmd = ast_play_and_wait(chan, box);
08127       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08128    }
08129 }

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

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

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

Definition at line 11431 of file app_voicemail.c.

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

11433 {
11434    struct ast_vm_user *user;
11435 
11436    AST_LIST_LOCK(&users);
11437    AST_LIST_TRAVERSE(&users, user, list) {
11438       vm_users_data_provider_get_helper(search, data_root, user);
11439    }
11440    AST_LIST_UNLOCK(&users);
11441 
11442    return 0;
11443 }

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

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

Referenced by vm_users_data_provider_get().

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

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

Definition at line 11070 of file app_voicemail.c.

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

Referenced by load_module().

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

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

Definition at line 12610 of file app_voicemail.c.

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

Referenced by load_module().

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

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

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

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

Definition at line 4427 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

04428 {
04429    const struct vm_zone *z = NULL;
04430    struct timeval t = ast_tvnow();
04431 
04432    /* Does this user have a timezone specified? */
04433    if (!ast_strlen_zero(vmu->zonetag)) {
04434       /* Find the zone in the list */
04435       AST_LIST_LOCK(&zones);
04436       AST_LIST_TRAVERSE(&zones, z, list) {
04437          if (!strcmp(z->name, vmu->zonetag))
04438             break;
04439       }
04440       AST_LIST_UNLOCK(&zones);
04441    }
04442    ast_localtime(&t, tm, z ? z->timezone : NULL);
04443    return tm;
04444 }

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

Definition at line 7472 of file app_voicemail.c.

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

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

07473 {
07474    int res;
07475    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07476       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07477    return res;
07478 }

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

Definition at line 12577 of file app_voicemail.c.

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

Referenced by vm_change_password().

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


Variable Documentation

char* addesc = "Comedian Mail" [static]

Definition at line 768 of file app_voicemail.c.

Referenced by adsi_load_vmail().

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

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

Referenced by actual_load_config(), and adsi_load_vmail().

int adsiver = 1 [static]

Definition at line 897 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 771 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* app2 = "VoiceMailMain" [static]

Definition at line 774 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* app3 = "MailboxExists" [static]

Definition at line 776 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* app4 = "VMAuthenticate" [static]

Definition at line 777 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 881 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

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

Definition at line 884 of file app_voicemail.c.

Referenced by actual_load_config(), and play_message_callerid().

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

Definition at line 11309 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

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

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

Referenced by actual_load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

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

Referenced by actual_load_config(), and check_password().

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

Definition at line 791 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

char fromstring[100] [static]

Definition at line 891 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

struct ast_flags globalflags = {0} [static]

Definition at line 920 of file app_voicemail.c.

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

char listen_control_forward_key[12] [static]

Definition at line 849 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 851 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 852 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 850 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 853 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char locale[20] [static]

Definition at line 784 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

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

Definition at line 11065 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

const char* const mailbox_folders[] [static]

Definition at line 1697 of file app_voicemail.c.

Referenced by get_folder_by_name(), and mbox().

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

Definition at line 787 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

int maxgreet [static]

Definition at line 797 of file app_voicemail.c.

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

int maxlogins [static]

Definition at line 799 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_execmain().

int maxmsg [static]

Definition at line 786 of file app_voicemail.c.

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

int maxsilence [static]
int minpassword [static]

Definition at line 800 of file app_voicemail.c.

Referenced by actual_load_config(), and check_password().

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 818 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

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

Referenced by start_poll_thread(), and stop_poll_thread().

int my_umask [static]

Definition at line 750 of file app_voicemail.c.

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

char* pagerbody = NULL [static]

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

Referenced by actual_load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 892 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 890 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

int passwordlocation [static]

Definition at line 801 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 813 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

unsigned int poll_freq [static]

Polling frequency

Definition at line 808 of file app_voicemail.c.

Referenced by actual_load_config(), and mb_poll_thread().

unsigned int poll_mailboxes [static]

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

Definition at line 805 of file app_voicemail.c.

Referenced by actual_load_config().

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

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

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

int saydurationminfo [static]

Definition at line 878 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

char* sayname_app = "VMSayName" [static]

Definition at line 779 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

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

Definition at line 792 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

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

Definition at line 766 of file app_voicemail.c.

Referenced by actual_load_config().

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

}

Definition at line 11450 of file app_voicemail.c.

Referenced by load_module().

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

Definition at line 861 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 860 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 857 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 858 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 856 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 862 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 874 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_forwardoptions().

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

Definition at line 859 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]
Initial value:

Definition at line 11445 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 793 of file app_voicemail.c.

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

int vmmaxsecs [static]

Definition at line 796 of file app_voicemail.c.

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

int vmminsecs [static]

Definition at line 795 of file app_voicemail.c.

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

double volgain [static]

Definition at line 794 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

char zonetag[80] [static]

Definition at line 783 of file app_voicemail.c.

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


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1