Wed Aug 7 17:15:50 2019

Asterisk developer's documentation


app_voicemail_odbcstorage.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 valid_config (const struct ast_config *cfg)
 Check if configuration file is valid.
static int vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
static int vm_box_exists (struct ast_channel *chan, const char *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_latin (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Common LATIN languages 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_odbcstorage.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 411 of file app_voicemail_odbcstorage.c.

#define BASELINELEN   72

Definition at line 434 of file app_voicemail_odbcstorage.c.

#define BASEMAXINLINE   256

Definition at line 435 of file app_voicemail_odbcstorage.c.

#define CHUNKSIZE   65536

Definition at line 408 of file app_voicemail_odbcstorage.c.

#define COMMAND_TIMEOUT   5000

Definition at line 404 of file app_voicemail_odbcstorage.c.

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

Definition at line 722 of file app_voicemail_odbcstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11277 of file app_voicemail_odbcstorage.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 11304 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 416 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 418 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 419 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 417 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 420 of file app_voicemail_odbcstorage.c.

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 792 of file app_voicemail_odbcstorage.c.

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

Definition at line 723 of file app_voicemail_odbcstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 718 of file app_voicemail_odbcstorage.c.

#define ENDL   "\n"

Definition at line 439 of file app_voicemail_odbcstorage.c.

#define ERROR_LOCK_PATH   -100

Definition at line 464 of file app_voicemail_odbcstorage.c.

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

Definition at line 720 of file app_voicemail_odbcstorage.c.

#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 427 of file app_voicemail_odbcstorage.c.

#define MAX_DATETIME_FORMAT   512

Definition at line 442 of file app_voicemail_odbcstorage.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 443 of file app_voicemail_odbcstorage.c.

#define MAXMSG   100

Definition at line 429 of file app_voicemail_odbcstorage.c.

#define MAXMSGLIMIT   9999

Definition at line 430 of file app_voicemail_odbcstorage.c.

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 432 of file app_voicemail_odbcstorage.c.

#define OPERATOR_EXIT   300

Definition at line 465 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 735 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 734 of file app_voicemail_odbcstorage.c.

#define RENAME ( a,
b,
c,
d,
e,
f,
g,
 )     (rename_file(g,h));

Definition at line 721 of file app_voicemail_odbcstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 717 of file app_voicemail_odbcstorage.c.

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

Definition at line 425 of file app_voicemail_odbcstorage.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 402 of file app_voicemail_odbcstorage.c.

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

Definition at line 719 of file app_voicemail_odbcstorage.c.

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 744 of file app_voicemail_odbcstorage.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 421 of file app_voicemail_odbcstorage.c.

#define VM_ALLOCED   (1 << 13)

Structure was malloc'ed, instead of placed in a return (usually static) buffer

Definition at line 458 of file app_voicemail_odbcstorage.c.

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 456 of file app_voicemail_odbcstorage.c.

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 457 of file app_voicemail_odbcstorage.c.

#define VM_DIRECFORWARD   (1 << 10)

Permit caller to use the Directory app for selecting to which mailbox to forward a VM

Definition at line 455 of file app_voicemail_odbcstorage.c.

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 449 of file app_voicemail_odbcstorage.c.

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 453 of file app_voicemail_odbcstorage.c.

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 452 of file app_voicemail_odbcstorage.c.

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 463 of file app_voicemail_odbcstorage.c.

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 462 of file app_voicemail_odbcstorage.c.

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 461 of file app_voicemail_odbcstorage.c.

#define VM_OPERATOR   (1 << 1)

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

Definition at line 446 of file app_voicemail_odbcstorage.c.

#define VM_PBXSKIP   (1 << 9)

Skip the [PBX] preamble in the Subject line of emails

Definition at line 454 of file app_voicemail_odbcstorage.c.

#define VM_REVIEW   (1 << 0)

After recording, permit the caller to review the recording before saving

Definition at line 445 of file app_voicemail_odbcstorage.c.

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 447 of file app_voicemail_odbcstorage.c.

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 450 of file app_voicemail_odbcstorage.c.

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 459 of file app_voicemail_odbcstorage.c.

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 451 of file app_voicemail_odbcstorage.c.

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 448 of file app_voicemail_odbcstorage.c.

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 460 of file app_voicemail_odbcstorage.c.

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 658 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 410 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 406 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 407 of file app_voicemail_odbcstorage.c.


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 468 of file app_voicemail_odbcstorage.c.

00468             {
00469    NEW_FOLDER,
00470    OLD_FOLDER,
00471    WORK_FOLDER,
00472    FAMILY_FOLDER,
00473    FRIENDS_FOLDER,
00474    GREETINGS_FOLDER
00475 };

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 489 of file app_voicemail_odbcstorage.c.

00489                     {
00490    OPT_ARG_RECORDGAIN = 0,
00491    OPT_ARG_PLAYFOLDER = 1,
00492    OPT_ARG_DTMFEXIT   = 2,
00493    /* This *must* be the last value in this enum! */
00494    OPT_ARG_ARRAY_SIZE = 3,
00495 };

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 477 of file app_voicemail_odbcstorage.c.

00477                      {
00478    OPT_SILENT =           (1 << 0),
00479    OPT_BUSY_GREETING =    (1 << 1),
00480    OPT_UNAVAIL_GREETING = (1 << 2),
00481    OPT_RECORDGAIN =       (1 << 3),
00482    OPT_PREPEND_MAILBOX =  (1 << 4),
00483    OPT_AUTOPLAY =         (1 << 6),
00484    OPT_DTMFEXIT =         (1 << 7),
00485    OPT_MESSAGE_Urgent =   (1 << 8),
00486    OPT_MESSAGE_PRIORITY = (1 << 9)
00487 };

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 497 of file app_voicemail_odbcstorage.c.

00497                          {
00498    OPT_PWLOC_VOICEMAILCONF = 0,
00499    OPT_PWLOC_SPOOLDIR      = 1,
00500    OPT_PWLOC_USERSCONF     = 2,
00501 };


Function Documentation

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

Definition at line 5403 of file app_voicemail_odbcstorage.c.

References ast_strlen_zero().

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

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

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

Definition at line 10980 of file app_voicemail_odbcstorage.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().

10981 {
10982    struct ast_vm_user svm;
10983    AST_DECLARE_APP_ARGS(arg,
10984       AST_APP_ARG(mbox);
10985       AST_APP_ARG(context);
10986    );
10987 
10988    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
10989 
10990    if (ast_strlen_zero(arg.mbox)) {
10991       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
10992       return -1;
10993    }
10994 
10995    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
10996    return 0;
10997 }

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

Definition at line 11814 of file app_voicemail_odbcstorage.c.

References 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, 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, find_or_create(), free_vm_users(), free_vm_zones(), is_valid_dtmf(), ast_variable::lineno, LOG_ERROR, ast_vm_user::mailbox, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, ast_variable::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), SENDMAIL, start_poll_thread(), stop_poll_thread(), substitute_escapes(), THRESHOLD_SILENCE, ast_variable::value, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_PBXSKIP, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, and VM_TEMPGREETWARN.

Referenced by load_config().

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

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 4817 of file app_voicemail_odbcstorage.c.

References ast_debug, ast_log(), ast_safe_system(), base_encode(), ast_vm_user::context, create_dirpath(), ENDL, LOG_WARNING, ast_vm_user::mailbox, VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

Referenced by make_email_file().

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

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

Definition at line 6426 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_authenticate(), and vm_execmain().

06427 {
06428    int x;
06429    if (!ast_adsi_available(chan))
06430       return;
06431    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06432    if (x < 0)
06433       return;
06434    if (!x) {
06435       if (adsi_load_vmail(chan, useadsi)) {
06436          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06437          return;
06438       }
06439    } else
06440       *useadsi = 1;
06441 }

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

Definition at line 6621 of file app_voicemail_odbcstorage.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().

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

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

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

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

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 6776 of file app_voicemail_odbcstorage.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().

06777 {
06778    unsigned char buf[256];
06779    int bytes = 0;
06780 
06781    if (!ast_adsi_available(chan))
06782       return;
06783    bytes += adsi_logo(buf + bytes);
06784    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06785    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06786    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06787    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06788 
06789    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06790 }

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

Definition at line 6297 of file app_voicemail_odbcstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ADSI_MSG_DOWNLOAD, 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().

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

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 6443 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 6289 of file app_voicemail_odbcstorage.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().

06290 {
06291    int bytes = 0;
06292    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06293    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06294    return bytes;
06295 }

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

Definition at line 6520 of file app_voicemail_odbcstorage.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, and vm_state::lastmsg.

Referenced by play_message(), and vm_execmain().

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

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 6469 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 6673 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 6720 of file app_voicemail_odbcstorage.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().

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

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 13186 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_execmain().

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

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

Definition at line 10707 of file app_voicemail_odbcstorage.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(), and read_password_from_file().

Referenced by actual_load_config().

10708 {
10709    /* Assumes lock is already held */
10710    char *tmp;
10711    char *stringp;
10712    char *s;
10713    struct ast_vm_user *vmu;
10714    char *mailbox_full;
10715    int new = 0, old = 0, urgent = 0;
10716    char secretfn[PATH_MAX] = "";
10717 
10718    tmp = ast_strdupa(data);
10719 
10720    if (!(vmu = find_or_create(context, box)))
10721       return -1;
10722 
10723    populate_defaults(vmu);
10724 
10725    stringp = tmp;
10726    if ((s = strsep(&stringp, ","))) {
10727       if (!ast_strlen_zero(s) && s[0] == '*') {
10728          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10729             "\n\tmust be reset in voicemail.conf.\n", box);
10730       }
10731       /* assign password regardless of validity to prevent NULL password from being assigned */
10732       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10733    }
10734    if (stringp && (s = strsep(&stringp, ","))) {
10735       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10736    }
10737    if (stringp && (s = strsep(&stringp, ","))) {
10738       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10739    }
10740    if (stringp && (s = strsep(&stringp, ","))) {
10741       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10742    }
10743    if (stringp && (s = strsep(&stringp, ","))) {
10744       apply_options(vmu, s);
10745    }
10746 
10747    switch (vmu->passwordlocation) {
10748    case OPT_PWLOC_SPOOLDIR:
10749       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10750       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10751    }
10752 
10753    mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
10754    strcpy(mailbox_full, box);
10755    strcat(mailbox_full, "@");
10756    strcat(mailbox_full, context);
10757 
10758    inboxcount2(mailbox_full, &urgent, &new, &old);
10759    queue_mwi_event(mailbox_full, urgent, new, old);
10760 
10761    return 0;
10762 }

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 1037 of file app_voicemail_odbcstorage.c.

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

Referenced by apply_options(), and apply_options_full().

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

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

Destructively Parse options and apply.

Definition at line 1278 of file app_voicemail_odbcstorage.c.

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

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

01279 {  
01280    char *stringp;
01281    char *s;
01282    char *var, *value;
01283    stringp = ast_strdupa(options);
01284    while ((s = strsep(&stringp, "|"))) {
01285       value = s;
01286       if ((var = strsep(&value, "=")) && value) {
01287          apply_option(vmu, var, value);
01288       }
01289    }  
01290 }

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 1297 of file app_voicemail_odbcstorage.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().

01298 {
01299    for (; var; var = var->next) {
01300       if (!strcasecmp(var->name, "vmsecret")) {
01301          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01302       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01303          if (ast_strlen_zero(retval->password)) {
01304             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01305                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01306                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01307             } else {
01308                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01309             }
01310          }
01311       } else if (!strcasecmp(var->name, "uniqueid")) {
01312          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01313       } else if (!strcasecmp(var->name, "pager")) {
01314          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01315       } else if (!strcasecmp(var->name, "email")) {
01316          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01317       } else if (!strcasecmp(var->name, "fullname")) {
01318          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01319       } else if (!strcasecmp(var->name, "context")) {
01320          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01321       } else if (!strcasecmp(var->name, "emailsubject")) {
01322          ast_free(retval->emailsubject);
01323          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01324       } else if (!strcasecmp(var->name, "emailbody")) {
01325          ast_free(retval->emailbody);
01326          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01327 #ifdef IMAP_STORAGE
01328       } else if (!strcasecmp(var->name, "imapuser")) {
01329          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01330          retval->imapversion = imapversion;
01331       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01332          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01333          retval->imapversion = imapversion;
01334       } else if (!strcasecmp(var->name, "imapfolder")) {
01335          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01336       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01337          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01338          retval->imapversion = imapversion;
01339 #endif
01340       } else
01341          apply_option(retval, var->name, var->value);
01342    }
01343 }

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 4492 of file app_voicemail_odbcstorage.c.

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

Referenced by make_email_file(), and sendpage().

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

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 4420 of file app_voicemail_odbcstorage.c.

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

Referenced by make_email_file(), and sendpage().

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

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10764 of file app_voicemail_odbcstorage.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.

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

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 4296 of file app_voicemail_odbcstorage.c.

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

Referenced by add_email_attachment().

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

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 1256 of file app_voicemail_odbcstorage.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().

01257 {
01258    int res = -1;
01259    if (!strcmp(vmu->password, password)) {
01260       /* No change (but an update would return 0 rows updated, so we opt out here) */
01261       return 0;
01262    }
01263 
01264    if (strlen(password) > 10) {
01265       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01266    }
01267    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01268       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01269       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01270       res = 0;
01271    }
01272    return res;
01273 }

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 4465 of file app_voicemail_odbcstorage.c.

Referenced by make_email_file(), and sendpage().

04466 {
04467    for (; *str; str++) {
04468       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04469          return 1;
04470       }
04471    }
04472    return 0;
04473 }

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 1215 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_newuser(), and vm_options().

01216 {
01217    /* check minimum length */
01218    if (strlen(password) < minpassword)
01219       return 1;
01220    /* check that password does not contain '*' character */
01221    if (!ast_strlen_zero(password) && password[0] == '*')
01222       return 1;
01223    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01224       char cmd[255], buf[255];
01225 
01226       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01227 
01228       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01229       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01230          ast_debug(5, "Result: %s\n", buf);
01231          if (!strncasecmp(buf, "VALID", 5)) {
01232             ast_debug(3, "Passed password check: '%s'\n", buf);
01233             return 0;
01234          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01235             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01236             return 0;
01237          } else {
01238             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01239             return 1;
01240          }
01241       }
01242    }
01243    return 0;
01244 }

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

Definition at line 7985 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 11084 of file app_voicemail_odbcstorage.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11085 {
11086    int which = 0;
11087    int wordlen;
11088    struct ast_vm_user *vmu;
11089    const char *context = "";
11090 
11091    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11092    if (pos > 4)
11093       return NULL;
11094    if (pos == 3)
11095       return (state == 0) ? ast_strdup("for") : NULL;
11096    wordlen = strlen(word);
11097    AST_LIST_TRAVERSE(&users, vmu, list) {
11098       if (!strncasecmp(word, vmu->context, wordlen)) {
11099          if (context && strcmp(context, vmu->context) && ++which > state)
11100             return ast_strdup(vmu->context);
11101          /* ignore repeated contexts ? */
11102          context = vmu->context;
11103       }
11104    }
11105    return NULL;
11106 }

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 4101 of file app_voicemail_odbcstorage.c.

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

Referenced by copy_plain_file(), and vm_forwardoptions().

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

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 5337 of file app_voicemail_odbcstorage.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(), 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().

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

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 4159 of file app_voicemail_odbcstorage.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().

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

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 3996 of file app_voicemail_odbcstorage.c.

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

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

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

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 1679 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 13113 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 10667 of file app_voicemail_odbcstorage.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, LOG_WARNING, ast_vm_user::mailbox, and VM_SEARCH.

Referenced by actual_load_config(), and append_mailbox().

10668 {
10669    struct ast_vm_user *vmu;
10670 
10671    if (!ast_strlen_zero(box) && box[0] == '*') {
10672       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10673             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10674             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10675             "\n\tand will be ignored.\n", box, context);
10676       return NULL;
10677    }
10678 
10679    AST_LIST_TRAVERSE(&users, vmu, list) {
10680       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10681          if (strcasecmp(vmu->context, context)) {
10682             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10683                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10684                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10685                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10686          }
10687          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10688          return NULL;
10689       }
10690       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10691          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10692          return NULL;
10693       }
10694    }
10695    
10696    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10697       return NULL;
10698    
10699    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10700    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10701 
10702    AST_LIST_INSERT_TAIL(&users, vmu, list);
10703    
10704    return vmu;
10705 }

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 1418 of file app_voicemail_odbcstorage.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(), VM_ALLOCED, and VM_SEARCH.

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

01419 {
01420    /* This function could be made to generate one from a database, too */
01421    struct ast_vm_user *vmu = NULL, *cur;
01422    AST_LIST_LOCK(&users);
01423 
01424    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01425       context = "default";
01426 
01427    AST_LIST_TRAVERSE(&users, cur, list) {
01428 #ifdef IMAP_STORAGE
01429       if (cur->imapversion != imapversion) {
01430          continue;
01431       }
01432 #endif
01433       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01434          break;
01435       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01436          break;
01437    }
01438    if (cur) {
01439       /* Make a copy, so that on a reload, we have no race */
01440       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01441          *vmu = *cur;
01442          if (!ivm) {
01443             vmu->emailbody = ast_strdup(cur->emailbody);
01444             vmu->emailsubject = ast_strdup(cur->emailsubject);
01445          }
01446          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01447          AST_LIST_NEXT(vmu, list) = NULL;
01448       }
01449    } else
01450       vmu = find_user_realtime(ivm, context, mailbox);
01451    AST_LIST_UNLOCK(&users);
01452    return vmu;
01453 }

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 1377 of file app_voicemail_odbcstorage.c.

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

Referenced by find_user().

01378 {
01379    struct ast_variable *var;
01380    struct ast_vm_user *retval;
01381 
01382    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01383       if (ivm) {
01384          memset(retval, 0, sizeof(*retval));
01385       }
01386       populate_defaults(retval);
01387       if (!ivm) {
01388          ast_set_flag(retval, VM_ALLOCED);
01389       }
01390       if (mailbox) {
01391          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01392       }
01393       if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
01394          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01395       } else {
01396          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01397       }
01398       if (var) {
01399          apply_options_full(retval, var);
01400          ast_variables_destroy(var);
01401       } else { 
01402          if (!ivm) 
01403             free_user(retval);
01404          retval = NULL;
01405       }  
01406    } 
01407    return retval;
01408 }

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 7187 of file app_voicemail_odbcstorage.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(), 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(), 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(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1734 of file app_voicemail_odbcstorage.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().

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

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11696 of file app_voicemail_odbcstorage.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().

11697 {
11698    struct ast_vm_user *current;
11699    AST_LIST_LOCK(&users);
11700    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11701       ast_set_flag(current, VM_ALLOCED);
11702       free_user(current);
11703    }
11704    AST_LIST_UNLOCK(&users);
11705 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11708 of file app_voicemail_odbcstorage.c.

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

Referenced by actual_load_config(), and unload_module().

11709 {
11710    struct vm_zone *zcur;
11711    AST_LIST_LOCK(&zones);
11712    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11713       free_zone(zcur);
11714    AST_LIST_UNLOCK(&zones);
11715 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5105 of file app_voicemail_odbcstorage.c.

References ast_free.

Referenced by free_vm_zones().

05106 {
05107    ast_free(z);
05108 }

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 5061 of file app_voicemail_odbcstorage.c.

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

Referenced by leave_voicemail().

05062 {
05063    struct ast_tm tm;
05064    struct timeval t = ast_tvnow();
05065    
05066    ast_localtime(&t, &tm, "UTC");
05067 
05068    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05069 }

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 6796 of file app_voicemail_odbcstorage.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().

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

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 6853 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_execmain().

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

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

Definition at line 1721 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

Referenced by vm_execmain().

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

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11466 of file app_voicemail_odbcstorage.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().

11467 {
11468    unsigned int len;
11469    struct mwi_sub *mwi_sub;
11470    struct mwi_sub_task *p = datap;
11471 
11472    len = sizeof(*mwi_sub);
11473    if (!ast_strlen_zero(p->mailbox))
11474       len += strlen(p->mailbox);
11475 
11476    if (!ast_strlen_zero(p->context))
11477       len += strlen(p->context) + 1; /* Allow for seperator */
11478 
11479    if (!(mwi_sub = ast_calloc(1, len)))
11480       return -1;
11481 
11482    mwi_sub->uniqueid = p->uniqueid;
11483    if (!ast_strlen_zero(p->mailbox))
11484       strcpy(mwi_sub->mailbox, p->mailbox);
11485 
11486    if (!ast_strlen_zero(p->context)) {
11487       strcat(mwi_sub->mailbox, "@");
11488       strcat(mwi_sub->mailbox, p->context);
11489    }
11490 
11491    AST_RWLIST_WRLOCK(&mwi_subs);
11492    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11493    AST_RWLIST_UNLOCK(&mwi_subs);
11494    ast_free((void *) p->mailbox);
11495    ast_free((void *) p->context);
11496    ast_free(p);
11497    poll_subscribed_mailbox(mwi_sub);
11498    return 0;
11499 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11444 of file app_voicemail_odbcstorage.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().

11445 {
11446    struct mwi_sub *mwi_sub;
11447    uint32_t *uniqueid = datap;
11448    
11449    AST_RWLIST_WRLOCK(&mwi_subs);
11450    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11451       if (mwi_sub->uniqueid == *uniqueid) {
11452          AST_LIST_REMOVE_CURRENT(entry);
11453          break;
11454       }
11455    }
11456    AST_RWLIST_TRAVERSE_SAFE_END
11457    AST_RWLIST_UNLOCK(&mwi_subs);
11458 
11459    if (mwi_sub)
11460       mwi_sub_destroy(mwi_sub);
11461 
11462    ast_free(uniqueid);  
11463    return 0;
11464 }

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 11221 of file app_voicemail_odbcstorage.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.

11222 {
11223    switch (cmd) {
11224    case CLI_INIT:
11225       e->command = "voicemail reload";
11226       e->usage =
11227          "Usage: voicemail reload\n"
11228          "       Reload voicemail configuration\n";
11229       return NULL;
11230    case CLI_GENERATE:
11231       return NULL;
11232    }
11233 
11234    if (a->argc != 2)
11235       return CLI_SHOWUSAGE;
11236 
11237    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11238    load_config(1);
11239    
11240    return CLI_SUCCESS;
11241 }

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 11109 of file app_voicemail_odbcstorage.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.

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

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 11185 of file app_voicemail_odbcstorage.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.

11186 {
11187    struct vm_zone *zone;
11188 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11189    char *res = CLI_SUCCESS;
11190 
11191    switch (cmd) {
11192    case CLI_INIT:
11193       e->command = "voicemail show zones";
11194       e->usage =
11195          "Usage: voicemail show zones\n"
11196          "       Lists zone message formats\n";
11197       return NULL;
11198    case CLI_GENERATE:
11199       return NULL;
11200    }
11201 
11202    if (a->argc != 3)
11203       return CLI_SHOWUSAGE;
11204 
11205    AST_LIST_LOCK(&zones);
11206    if (!AST_LIST_EMPTY(&zones)) {
11207       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11208       AST_LIST_TRAVERSE(&zones, zone, list) {
11209          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11210       }
11211    } else {
11212       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11213       res = CLI_FAILURE;
11214    }
11215    AST_LIST_UNLOCK(&zones);
11216 
11217    return res;
11218 }

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 5449 of file app_voicemail_odbcstorage.c.

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

Referenced by load_module(), and vm_execmain().

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

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

Definition at line 5531 of file app_voicemail_odbcstorage.c.

References inboxcount2().

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

05532 {
05533    int urgentmsgs = 0;
05534    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05535    if (newmsgs) {
05536       *newmsgs += urgentmsgs;
05537    }
05538    return res;
05539 }

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

Definition at line 5472 of file app_voicemail_odbcstorage.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().

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

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

utility used by inchar(), for base_encode()

Definition at line 4231 of file app_voicemail_odbcstorage.c.

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

Referenced by inchar().

04232 {
04233    int l;
04234 
04235    if (bio->ateof)
04236       return 0;
04237 
04238    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04239       if (ferror(fi))
04240          return -1;
04241 
04242       bio->ateof = 1;
04243       return 0;
04244    }
04245 
04246    bio->iolen = l;
04247    bio->iocp = 0;
04248 
04249    return 1;
04250 }

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

utility used by base_encode()

Definition at line 4255 of file app_voicemail_odbcstorage.c.

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

Referenced by base_encode().

04256 {
04257    if (bio->iocp>=bio->iolen) {
04258       if (!inbuf(bio, fi))
04259          return EOF;
04260    }
04261 
04262    return bio->iobuf[bio->iocp++];
04263 }

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

Definition at line 916 of file app_voicemail_odbcstorage.c.

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

Referenced by load_module().

00917 {
00918    struct inprocess *i = obj, *j = arg;
00919    if (strcmp(i->mailbox, j->mailbox)) {
00920       return 0;
00921    }
00922    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00923 }

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

Definition at line 925 of file app_voicemail_odbcstorage.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, LOG_WARNING, and inprocess::mailbox.

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

00926 {
00927    struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00928    arg->context = arg->mailbox + strlen(mailbox) + 1;
00929    strcpy(arg->mailbox, mailbox); /* SAFE */
00930    strcpy(arg->context, context); /* SAFE */
00931    ao2_lock(inprocess_container);
00932    if ((i = ao2_find(inprocess_container, arg, 0))) {
00933       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00934       ao2_unlock(inprocess_container);
00935       ao2_ref(i, -1);
00936       return ret;
00937    }
00938    if (delta < 0) {
00939       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00940    }
00941    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00942       ao2_unlock(inprocess_container);
00943       return 0;
00944    }
00945    i->context = i->mailbox + strlen(mailbox) + 1;
00946    strcpy(i->mailbox, mailbox); /* SAFE */
00947    strcpy(i->context, context); /* SAFE */
00948    i->count = delta;
00949    ao2_link(inprocess_container, i);
00950    ao2_unlock(inprocess_container);
00951    ao2_ref(i, -1);
00952    return 0;
00953 }

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

Definition at line 910 of file app_voicemail_odbcstorage.c.

References inprocess::mailbox.

Referenced by load_module().

00911 {
00912    const struct inprocess *i = obj;
00913    return atoi(i->mailbox);
00914 }

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

Definition at line 5071 of file app_voicemail_odbcstorage.c.

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

Referenced by leave_voicemail().

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

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 1352 of file app_voicemail_odbcstorage.c.

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

Referenced by actual_load_config().

01353 {
01354    int i;
01355    char *local_key = ast_strdupa(key);
01356 
01357    for (i = 0; i < strlen(key); ++i) {
01358       if (!strchr(VALID_DTMF, *local_key)) {
01359          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01360          return 0;
01361       }
01362       local_key++;
01363    }
01364    return 1;
01365 }

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 4050 of file app_voicemail_odbcstorage.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().

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

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 5607 of file app_voicemail_odbcstorage.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, 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, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

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

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

static int load_config ( int  reload  )  [static]

Definition at line 11764 of file app_voicemail_odbcstorage.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().

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

static int load_module ( void   )  [static]

Definition at line 13065 of file app_voicemail_odbcstorage.c.

References ao2_container_alloc, 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, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), inprocess_cmp_fn(), inprocess_hash_fn(), load_config(), manager_list_voicemail_users(), messagecount(), RQ_CHAR, RQ_UINTEGER3, sayname(), SENTINEL, vm_box_exists(), vm_exec(), vm_execmain(), vmauthenticate(), and vmsayname_exec().

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

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 1633 of file app_voicemail_odbcstorage.c.

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

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

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 4548 of file app_voicemail_odbcstorage.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(), check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, ENDL, ast_vm_user::fullname, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), valid_config(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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 1650 of file app_voicemail_odbcstorage.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().

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

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

Manager list voicemail users command.

Definition at line 11595 of file app_voicemail_odbcstorage.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, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, ast_vm_user::saydurationm, ast_vm_user::serveremail, ast_vm_user::uniqueid, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_OPERATOR, VM_REVIEW, VM_SAYCID, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by load_module().

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

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

Definition at line 11416 of file app_voicemail_odbcstorage.c.

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

Referenced by start_poll_thread().

11417 {
11418    while (poll_thread_run) {
11419       struct timespec ts = { 0, };
11420       struct timeval wait;
11421 
11422       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11423       ts.tv_sec = wait.tv_sec;
11424       ts.tv_nsec = wait.tv_usec * 1000;
11425 
11426       ast_mutex_lock(&poll_lock);
11427       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11428       ast_mutex_unlock(&poll_lock);
11429 
11430       if (!poll_thread_run)
11431          break;
11432 
11433       poll_subscribed_mailboxes();
11434    }
11435 
11436    return NULL;
11437 }

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

Definition at line 1711 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

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

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

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

Definition at line 5398 of file app_voicemail_odbcstorage.c.

References __has_voicemail().

Referenced by load_module().

05399 {
05400    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05401 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11439 of file app_voicemail_odbcstorage.c.

References ast_free.

Referenced by handle_unsubscribe().

11440 {
11441    ast_free(mwi_sub);
11442 }

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

Definition at line 11527 of file app_voicemail_odbcstorage.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, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

11528 {
11529    struct mwi_sub_task *mwist;
11530    
11531    if (ast_event_get_type(event) != AST_EVENT_SUB)
11532       return;
11533 
11534    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11535       return;
11536 
11537    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11538       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11539       return;
11540    }
11541    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11542    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11543    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11544    
11545    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11546       ast_free(mwist);
11547    }
11548 }

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

Definition at line 11501 of file app_voicemail_odbcstorage.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, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

11502 {
11503    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11504 
11505    if (!uniqueid) {
11506       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11507       return;
11508    }
11509 
11510    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11511       ast_free(uniqueid);
11512       return;
11513    }
11514 
11515    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11516       ast_free(uniqueid);
11517       return;
11518    }
11519 
11520    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11521    *uniqueid = u;
11522    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11523       ast_free(uniqueid);
11524    }
11525 }

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 7084 of file app_voicemail_odbcstorage.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, VM_ATTACH, vm_delete(), and VM_DELETE.

Referenced by copy_message(), and leave_voicemail().

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

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

utility used by base_encode()

Definition at line 4268 of file app_voicemail_odbcstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04269 {
04270    if (bio->linelength >= BASELINELEN) {
04271       if (fputs(ENDL, so) == EOF) {
04272          return -1;
04273       }
04274 
04275       bio->linelength = 0;
04276    }
04277 
04278    if (putc(((unsigned char) c), so) == EOF) {
04279       return -1;
04280    }
04281 
04282    bio->linelength++;
04283 
04284    return 1;
04285 }

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

Definition at line 7932 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 7706 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_browse_messages_vi(), vm_browse_messages_zh(), and vm_execmain().

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

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

Definition at line 7592 of file app_voicemail_odbcstorage.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, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

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

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

Definition at line 7503 of file app_voicemail_odbcstorage.c.

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

Referenced by play_message().

07504 {
07505    int res = 0;
07506 
07507    if (!ast_strlen_zero(category))
07508       res = ast_play_and_wait(chan, category);
07509 
07510    if (res) {
07511       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07512       res = 0;
07513    }
07514 
07515    return res;
07516 }

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

Definition at line 7518 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 7656 of file app_voicemail_odbcstorage.c.

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

Referenced by play_message().

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

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 13378 of file app_voicemail_odbcstorage.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, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11388 of file app_voicemail_odbcstorage.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11389 {
11390    int new = 0, old = 0, urgent = 0;
11391 
11392    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11393 
11394    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11395       mwi_sub->old_urgent = urgent;
11396       mwi_sub->old_new = new;
11397       mwi_sub->old_old = old;
11398       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11399       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11400    }
11401 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11403 of file app_voicemail_odbcstorage.c.

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

Referenced by mb_poll_thread().

11404 {
11405    struct mwi_sub *mwi_sub;
11406 
11407    AST_RWLIST_RDLOCK(&mwi_subs);
11408    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11409       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11410          poll_subscribed_mailbox(mwi_sub);
11411       }
11412    }
11413    AST_RWLIST_UNLOCK(&mwi_subs);
11414 }

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 995 of file app_voicemail_odbcstorage.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_free, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, ast_vm_user::locale, ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, ast_vm_user::volgain, and ast_vm_user::zonetag.

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

00996 {
00997    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
00998    vmu->passwordlocation = passwordlocation;
00999    if (saydurationminfo) {
01000       vmu->saydurationm = saydurationminfo;
01001    }
01002    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
01003    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
01004    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
01005    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
01006    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
01007    if (vmminsecs) {
01008       vmu->minsecs = vmminsecs;
01009    }
01010    if (vmmaxsecs) {
01011       vmu->maxsecs = vmmaxsecs;
01012    }
01013    if (maxmsg) {
01014       vmu->maxmsg = maxmsg;
01015    }
01016    if (maxdeletedmsg) {
01017       vmu->maxdeletedmsg = maxdeletedmsg;
01018    }
01019    vmu->volgain = volgain;
01020    ast_free(vmu->emailsubject);
01021    vmu->emailsubject = NULL;
01022    ast_free(vmu->emailbody);
01023    vmu->emailbody = NULL;
01024 #ifdef IMAP_STORAGE
01025    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
01026 #endif
01027 }

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 4356 of file app_voicemail_odbcstorage.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, ast_vm_user::fullname, ast_vm_user::locale, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, pbx_builtin_setvar_helper(), S_OR, and valid_config().

Referenced by make_email_file(), and sendpage().

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

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

Definition at line 7047 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 12494 of file app_voicemail_odbcstorage.c.

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

Referenced by actual_load_config(), and append_mailbox().

12494                                                                                            {
12495    struct ast_config *pwconf;
12496    struct ast_flags config_flags = { 0 };
12497 
12498    pwconf = ast_config_load(secretfn, config_flags);
12499    if (valid_config(pwconf)) {
12500       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12501       if (val) {
12502          ast_copy_string(password, val, passwordlen);
12503          ast_config_destroy(pwconf);
12504          return;
12505       }
12506       ast_config_destroy(pwconf);
12507    }
12508    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12509 }

static int reload ( void   )  [static]

Definition at line 13025 of file app_voicemail_odbcstorage.c.

References load_config().

13026 {
13027    return load_config(1);
13028 }

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 4026 of file app_voicemail_odbcstorage.c.

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

04027 {
04028    char stxt[PATH_MAX];
04029    char dtxt[PATH_MAX];
04030    ast_filerename(sfn, dfn, NULL);
04031    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04032    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04033    if (ast_check_realtime("voicemail_data")) {
04034       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04035    }
04036    rename(stxt, dtxt);
04037 }

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

Definition at line 6173 of file app_voicemail_odbcstorage.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().

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

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 1465 of file app_voicemail_odbcstorage.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().

01466 {
01467    /* This function could be made to generate one from a database, too */
01468    struct ast_vm_user *cur;
01469    int res = -1;
01470    AST_LIST_LOCK(&users);
01471    AST_LIST_TRAVERSE(&users, cur, list) {
01472       if ((!context || !strcasecmp(context, cur->context)) &&
01473          (!strcasecmp(mailbox, cur->mailbox)))
01474             break;
01475    }
01476    if (cur) {
01477       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01478       res = 0;
01479    }
01480    AST_LIST_UNLOCK(&users);
01481    return res;
01482 }

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

Definition at line 5541 of file app_voicemail_odbcstorage.c.

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

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

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

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

Definition at line 6210 of file app_voicemail_odbcstorage.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().

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

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 12480 of file app_voicemail_odbcstorage.c.

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

Referenced by load_module(), and vmsayname_exec().

12481 {
12482    int res = -1;
12483    char dir[PATH_MAX];
12484    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12485    ast_debug(2, "About to try retrieving name file %s\n", dir);
12486    RETRIEVE(dir, -1, mailbox, context);
12487    if (ast_fileexists(dir, NULL, NULL)) {
12488       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12489    }
12490    DISPOSE(dir, -1);
12491    return res;
12492 }

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 4871 of file app_voicemail_odbcstorage.c.

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

Referenced by forward_message(), and notify_new_message().

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

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 4906 of file app_voicemail_odbcstorage.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, MAXHOSTNAMELEN, prep_email_sub_vars(), S_OR, strip_control_and_high(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

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

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

Definition at line 11045 of file app_voicemail_odbcstorage.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().

11046 {
11047    struct ast_config *cfg;
11048    const char *cat = NULL;
11049 
11050    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11051       "context", context, SENTINEL))) {
11052       return CLI_FAILURE;
11053    }
11054 
11055    ast_cli(fd,
11056       "\n"
11057       "=============================================================\n"
11058       "=== Configured Voicemail Users ==============================\n"
11059       "=============================================================\n"
11060       "===\n");
11061 
11062    while ((cat = ast_category_browse(cfg, cat))) {
11063       struct ast_variable *var = NULL;
11064       ast_cli(fd,
11065          "=== Mailbox ...\n"
11066          "===\n");
11067       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11068          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11069       ast_cli(fd,
11070          "===\n"
11071          "=== ---------------------------------------------------------\n"
11072          "===\n");
11073    }
11074 
11075    ast_cli(fd,
11076       "=============================================================\n"
11077       "\n");
11078 
11079    ast_config_destroy(cfg);
11080 
11081    return CLI_SUCCESS;
11082 }

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

Definition at line 11571 of file app_voicemail_odbcstorage.c.

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

Referenced by actual_load_config(), and unload_module().

11572 {
11573    poll_thread_run = 0;
11574 
11575    if (mwi_sub_sub) {
11576       ast_event_unsubscribe(mwi_sub_sub);
11577       mwi_sub_sub = NULL;
11578    }
11579 
11580    if (mwi_unsub_sub) {
11581       ast_event_unsubscribe(mwi_unsub_sub);
11582       mwi_unsub_sub = NULL;
11583    }
11584 
11585    ast_mutex_lock(&poll_lock);
11586    ast_cond_signal(&poll_cond);
11587    ast_mutex_unlock(&poll_lock);
11588 
11589    pthread_join(poll_thread, NULL);
11590 
11591    poll_thread = AST_PTHREADT_NULL;
11592 }

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 965 of file app_voicemail_odbcstorage.c.

Referenced by make_email_file(), and sendpage().

00966 {
00967    char *bufptr = buf;
00968    for (; *input; input++) {
00969       if (*input < 32) {
00970          continue;
00971       }
00972       *bufptr++ = *input;
00973       if (bufptr == buf + buflen - 1) {
00974          break;
00975       }
00976    }
00977    *bufptr = '\0';
00978    return buf;
00979 }

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

Definition at line 11717 of file app_voicemail_odbcstorage.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().

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

static int unload_module ( void   )  [static]

Definition at line 13030 of file app_voicemail_odbcstorage.c.

References ao2_ref, 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(), free_vm_users(), free_vm_zones(), and stop_poll_thread().

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

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

Check if configuration file is valid.

Definition at line 1487 of file app_voicemail_odbcstorage.c.

References CONFIG_STATUS_FILEINVALID.

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

01488 {
01489    return cfg && cfg != CONFIG_STATUS_FILEINVALID;
01490 }

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

Definition at line 1748 of file app_voicemail_odbcstorage.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().

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

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 9725 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_execmain(), and vmauthenticate().

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

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

Definition at line 10940 of file app_voicemail_odbcstorage.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().

10941 {
10942    struct ast_vm_user svm;
10943    char *context, *box;
10944    AST_DECLARE_APP_ARGS(args,
10945       AST_APP_ARG(mbox);
10946       AST_APP_ARG(options);
10947    );
10948    static int dep_warning = 0;
10949 
10950    if (ast_strlen_zero(data)) {
10951       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10952       return -1;
10953    }
10954 
10955    if (!dep_warning) {
10956       dep_warning = 1;
10957       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10958    }
10959 
10960    box = ast_strdupa(data);
10961 
10962    AST_STANDARD_APP_ARGS(args, box);
10963 
10964    if (args.options) {
10965    }
10966 
10967    if ((context = strchr(args.mbox, '@'))) {
10968       *context = '\0';
10969       context++;
10970    }
10971 
10972    if (find_user(&svm, context, args.mbox)) {
10973       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10974    } else
10975       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10976 
10977    return 0;
10978 }

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 9707 of file app_voicemail_odbcstorage.c.

References vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

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

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 9588 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_browse_messages().

09589 {
09590    int cmd = 0;
09591 
09592    if (vms->lastmsg > -1) {
09593       cmd = play_message(chan, vmu, vms);
09594    } else {
09595       cmd = ast_play_and_wait(chan, "vm-youhave");
09596       if (!cmd) 
09597          cmd = ast_play_and_wait(chan, "vm-no");
09598       if (!cmd) {
09599          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09600          cmd = ast_play_and_wait(chan, vms->fn);
09601       }
09602       if (!cmd)
09603          cmd = ast_play_and_wait(chan, "vm-messages");
09604    }
09605    return cmd;
09606 }

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

Definition at line 9564 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_browse_messages().

09565 {
09566    int cmd = 0;
09567 
09568    if (vms->lastmsg > -1) {
09569       cmd = play_message(chan, vmu, vms);
09570    } else {
09571       if (!strcasecmp(vms->fn, "INBOX")) {
09572          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09573       } else {
09574          cmd = ast_play_and_wait(chan, "vm-nomessages");
09575       }
09576    }
09577    return cmd;
09578 }

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

Common LATIN languages syntax for 'You have N messages' greeting.

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

Definition at line 9617 of file app_voicemail_odbcstorage.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().

09618 {
09619    int cmd;
09620 
09621    if (vms->lastmsg > -1) {
09622       cmd = play_message(chan, vmu, vms);
09623    } else {
09624       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09625       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09626          if (!cmd) {
09627             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09628             cmd = ast_play_and_wait(chan, vms->fn);
09629          }
09630          if (!cmd)
09631             cmd = ast_play_and_wait(chan, "vm-messages");
09632       } else {
09633          if (!cmd)
09634             cmd = ast_play_and_wait(chan, "vm-messages");
09635          if (!cmd) {
09636             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09637             cmd = ast_play_and_wait(chan, vms->fn);
09638          }
09639       }
09640    }
09641    return cmd;
09642 }

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 9680 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_browse_messages().

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

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 9652 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_browse_messages().

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

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 1499 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_newuser(), and vm_options().

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

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

Definition at line 1607 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_newuser(), and vm_options().

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

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

Definition at line 1162 of file app_voicemail_odbcstorage.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().

01163 {
01164    int fds[2], pid = 0;
01165 
01166    memset(buf, 0, len);
01167 
01168    if (pipe(fds)) {
01169       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01170    } else {
01171       /* good to go*/
01172       pid = ast_safe_fork(0);
01173 
01174       if (pid < 0) {
01175          /* ok maybe not */
01176          close(fds[0]);
01177          close(fds[1]);
01178          snprintf(buf, len, "FAILURE: Fork failed");
01179       } else if (pid) {
01180          /* parent */
01181          close(fds[1]);
01182          if (read(fds[0], buf, len) < 0) {
01183             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01184          }
01185          close(fds[0]);
01186       } else {
01187          /*  child */
01188          AST_DECLARE_APP_ARGS(arg,
01189             AST_APP_ARG(v)[20];
01190          );
01191          char *mycmd = ast_strdupa(command);
01192 
01193          close(fds[0]);
01194          dup2(fds[1], STDOUT_FILENO);
01195          close(fds[1]);
01196          ast_close_fds_above_n(STDOUT_FILENO);
01197 
01198          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01199 
01200          execv(arg.v[0], arg.v); 
01201          printf("FAILURE: %s", strerror(errno));
01202          _exit(0);
01203       }
01204    }
01205    return buf;
01206 }

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 4210 of file app_voicemail_odbcstorage.c.

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

Referenced by copy_message(), and notify_new_message().

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

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

Definition at line 10599 of file app_voicemail_odbcstorage.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().

10600 {
10601    int res = 0;
10602    char *tmp;
10603    struct leave_vm_options leave_options;
10604    struct ast_flags flags = { 0 };
10605    char *opts[OPT_ARG_ARRAY_SIZE];
10606    AST_DECLARE_APP_ARGS(args,
10607       AST_APP_ARG(argv0);
10608       AST_APP_ARG(argv1);
10609    );
10610    
10611    memset(&leave_options, 0, sizeof(leave_options));
10612 
10613    if (chan->_state != AST_STATE_UP)
10614       ast_answer(chan);
10615 
10616    if (!ast_strlen_zero(data)) {
10617       tmp = ast_strdupa(data);
10618       AST_STANDARD_APP_ARGS(args, tmp);
10619       if (args.argc == 2) {
10620          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10621             return -1;
10622          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10623          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10624             int gain;
10625 
10626             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10627                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10628                return -1;
10629             } else {
10630                leave_options.record_gain = (signed char) gain;
10631             }
10632          }
10633          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10634             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10635                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10636          }
10637       }
10638    } else {
10639       char temp[256];
10640       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10641       if (res < 0)
10642          return res;
10643       if (ast_strlen_zero(temp))
10644          return 0;
10645       args.argv0 = ast_strdupa(temp);
10646    }
10647 
10648    res = leave_voicemail(chan, args.argv0, &leave_options);
10649    if (res == 't') {
10650       ast_play_and_wait(chan, "vm-goodbye");
10651       res = 0;
10652    }
10653 
10654    if (res == OPERATOR_EXIT) {
10655       res = 0;
10656    }
10657 
10658    if (res == ERROR_LOCK_PATH) {
10659       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10660       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10661       res = 0;
10662    }
10663 
10664    return res;
10665 }

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

Definition at line 9847 of file app_voicemail_odbcstorage.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(), has_voicemail(), vm_state::heard, language, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), 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, and vm_state::vmbox.

Referenced by load_module().

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

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 6891 of file app_voicemail_odbcstorage.c.

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

Referenced by forward_message().

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

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 9245 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_execmain().

09246 {
09247    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09248       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09249    } else {             /* Default to ENGLISH */
09250       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09251    }
09252 }

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 9133 of file app_voicemail_odbcstorage.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().

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

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 9221 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 9071 of file app_voicemail_odbcstorage.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(), and VM_TEMPGREETWARN.

Referenced by vm_execmain().

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

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

Definition at line 8941 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8637 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8386 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8686 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8784 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8185 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8319 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8443 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8279 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 8827 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8593 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8478 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 8878 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 8739 of file app_voicemail_odbcstorage.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().

08739                                                                           {
08740    /* Introduce messages they have */
08741    int res;
08742    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08743       res = ast_play_and_wait(chan, "vm-nomessages");
08744       return res;
08745    } else {
08746       res = ast_play_and_wait(chan, "vm-youhave");
08747    }
08748    if (vms->newmessages) {
08749       if (!res)
08750          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08751       if ((vms->newmessages == 1)) {
08752          if (!res)
08753             res = ast_play_and_wait(chan, "vm-message");
08754          if (!res)
08755             res = ast_play_and_wait(chan, "vm-INBOXs");
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-INBOX");
08761       }
08762       if (vms->oldmessages && !res)
08763          res = ast_play_and_wait(chan, "vm-and");
08764    }
08765    if (vms->oldmessages) {
08766       if (!res)
08767          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08768       if (vms->oldmessages == 1) {
08769          if (!res)
08770             res = ast_play_and_wait(chan, "vm-message");
08771          if (!res)
08772             res = ast_play_and_wait(chan, "vm-Olds");
08773       } else {
08774          if (!res)
08775             res = ast_play_and_wait(chan, "vm-messages");
08776          if (!res)
08777             res = ast_play_and_wait(chan, "vm-Old");
08778       }
08779    }
08780    return res;
08781 }

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

Definition at line 8549 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 9041 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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

Definition at line 9002 of file app_voicemail_odbcstorage.c.

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

Referenced by vm_intro().

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

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 3285 of file app_voicemail_odbcstorage.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().

03286 {
03287    switch (ast_lock_path(path)) {
03288    case AST_LOCK_TIMEOUT:
03289       return -1;
03290    default:
03291       return 0;
03292    }
03293 }

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

Definition at line 1656 of file app_voicemail_odbcstorage.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

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

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 9255 of file app_voicemail_odbcstorage.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, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, and VM_FORCENAME.

Referenced by vm_execmain().

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

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 9353 of file app_voicemail_odbcstorage.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, ast_vm_user::mailbox, ast_vm_user::password, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), and vm_tempgreeting().

Referenced by vm_execmain().

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

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

Definition at line 8148 of file app_voicemail_odbcstorage.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().

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

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

Definition at line 8101 of file app_voicemail_odbcstorage.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

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

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

Definition at line 8119 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08120 {
08121    int cmd;
08122 
08123    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08124       if (!strcasecmp(box, "vm-INBOX"))
08125          cmd = ast_play_and_wait(chan, "vm-new-e");
08126       else
08127          cmd = ast_play_and_wait(chan, "vm-old-e");
08128       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08129    } else {
08130       cmd = ast_play_and_wait(chan, "vm-messages");
08131       return cmd ? cmd : ast_play_and_wait(chan, box);
08132    }
08133 }

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

Definition at line 8135 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08136 {
08137    int cmd;
08138 
08139    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08140       cmd = ast_play_and_wait(chan, "vm-messages");
08141       return cmd ? cmd : ast_play_and_wait(chan, box);
08142    } else {
08143       cmd = ast_play_and_wait(chan, box);
08144       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08145    }
08146 }

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 9496 of file app_voicemail_odbcstorage.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, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

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

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

Definition at line 11365 of file app_voicemail_odbcstorage.c.

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

11367 {
11368    struct ast_vm_user *user;
11369 
11370    AST_LIST_LOCK(&users);
11371    AST_LIST_TRAVERSE(&users, user, list) {
11372       vm_users_data_provider_get_helper(search, data_root, user);
11373    }
11374    AST_LIST_UNLOCK(&users);
11375 
11376    return 0;
11377 }

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 11318 of file app_voicemail_odbcstorage.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().

11320 {
11321    struct ast_data *data_user, *data_zone;
11322    struct ast_data *data_state;
11323    struct vm_zone *zone = NULL;
11324    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11325    char ext_context[256] = "";
11326 
11327    data_user = ast_data_add_node(data_root, "user");
11328    if (!data_user) {
11329       return -1;
11330    }
11331 
11332    ast_data_add_structure(ast_vm_user, data_user, user);
11333 
11334    AST_LIST_LOCK(&zones);
11335    AST_LIST_TRAVERSE(&zones, zone, list) {
11336       if (!strcmp(zone->name, user->zonetag)) {
11337          break;
11338       }
11339    }
11340    AST_LIST_UNLOCK(&zones);
11341 
11342    /* state */
11343    data_state = ast_data_add_node(data_user, "state");
11344    if (!data_state) {
11345       return -1;
11346    }
11347    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11348    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11349    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11350    ast_data_add_int(data_state, "newmsg", newmsg);
11351    ast_data_add_int(data_state, "oldmsg", oldmsg);
11352 
11353    if (zone) {
11354       data_zone = ast_data_add_node(data_user, "zone");
11355       ast_data_add_structure(vm_zone, data_zone, zone);
11356    }
11357 
11358    if (!ast_data_search_match(search, data_user)) {
11359       ast_data_remove_node(data_root, data_user);
11360    }
11361 
11362    return 0;
11363 }

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

Definition at line 11004 of file app_voicemail_odbcstorage.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().

11005 {
11006    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11007    struct ast_vm_user vmus;
11008    char *options = NULL;
11009    int silent = 0, skipuser = 0;
11010    int res = -1;
11011    
11012    if (data) {
11013       s = ast_strdupa(data);
11014       user = strsep(&s, ",");
11015       options = strsep(&s, ",");
11016       if (user) {
11017          s = user;
11018          user = strsep(&s, "@");
11019          context = strsep(&s, "");
11020          if (!ast_strlen_zero(user))
11021             skipuser++;
11022          ast_copy_string(mailbox, user, sizeof(mailbox));
11023       }
11024    }
11025 
11026    if (options) {
11027       silent = (strchr(options, 's')) != NULL;
11028    }
11029 
11030    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11031       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11032       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11033       ast_play_and_wait(chan, "auth-thankyou");
11034       res = 0;
11035    } else if (mailbox[0] == '*') {
11036       /* user entered '*' */
11037       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11038          res = 0; /* prevent hangup */
11039       }
11040    }
11041 
11042    return res;
11043 }

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

Definition at line 12544 of file app_voicemail_odbcstorage.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().

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

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 4442 of file app_voicemail_odbcstorage.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().

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

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 7489 of file app_voicemail_odbcstorage.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().

07490 {
07491    int res;
07492    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07493       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07494    return res;
07495 }

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

Definition at line 12511 of file app_voicemail_odbcstorage.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().

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


Variable Documentation

char* addesc = "Comedian Mail" [static]

Definition at line 750 of file app_voicemail_odbcstorage.c.

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

Definition at line 877 of file app_voicemail_odbcstorage.c.

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

Definition at line 878 of file app_voicemail_odbcstorage.c.

int adsiver = 1 [static]

Definition at line 879 of file app_voicemail_odbcstorage.c.

char* app = "VoiceMail" [static]

Definition at line 753 of file app_voicemail_odbcstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 756 of file app_voicemail_odbcstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 758 of file app_voicemail_odbcstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 759 of file app_voicemail_odbcstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 863 of file app_voicemail_odbcstorage.c.

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

Definition at line 875 of file app_voicemail_odbcstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 866 of file app_voicemail_odbcstorage.c.

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 11243 of file app_voicemail_odbcstorage.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 862 of file app_voicemail_odbcstorage.c.

char* emailbody = NULL [static]

Definition at line 869 of file app_voicemail_odbcstorage.c.

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

Definition at line 880 of file app_voicemail_odbcstorage.c.

char* emailsubject = NULL [static]

Definition at line 870 of file app_voicemail_odbcstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 864 of file app_voicemail_odbcstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 730 of file app_voicemail_odbcstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 729 of file app_voicemail_odbcstorage.c.

char externnotify[160] [static]

Definition at line 773 of file app_voicemail_odbcstorage.c.

char fromstring[100] [static]

Definition at line 873 of file app_voicemail_odbcstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 858 of file app_voicemail_odbcstorage.c.

Definition at line 902 of file app_voicemail_odbcstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 831 of file app_voicemail_odbcstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 833 of file app_voicemail_odbcstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 834 of file app_voicemail_odbcstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 832 of file app_voicemail_odbcstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 835 of file app_voicemail_odbcstorage.c.

char locale[20] [static]

Definition at line 766 of file app_voicemail_odbcstorage.c.

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

Definition at line 10999 of file app_voicemail_odbcstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1692 of file app_voicemail_odbcstorage.c.

char mailcmd[160] [static]

Definition at line 772 of file app_voicemail_odbcstorage.c.

int maxdeletedmsg [static]

Definition at line 769 of file app_voicemail_odbcstorage.c.

int maxgreet [static]

Definition at line 779 of file app_voicemail_odbcstorage.c.

int maxlogins [static]

Definition at line 781 of file app_voicemail_odbcstorage.c.

int maxmsg [static]

Definition at line 768 of file app_voicemail_odbcstorage.c.

int maxsilence [static]

Definition at line 767 of file app_voicemail_odbcstorage.c.

int minpassword [static]

Definition at line 782 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 800 of file app_voicemail_odbcstorage.c.

Definition at line 826 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 802 of file app_voicemail_odbcstorage.c.

int my_umask [static]

Definition at line 732 of file app_voicemail_odbcstorage.c.

char* pagerbody = NULL [static]

Definition at line 871 of file app_voicemail_odbcstorage.c.

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

Definition at line 881 of file app_voicemail_odbcstorage.c.

char pagerfromstring[100] [static]

Definition at line 874 of file app_voicemail_odbcstorage.c.

char* pagersubject = NULL [static]

Definition at line 872 of file app_voicemail_odbcstorage.c.

int passwordlocation [static]

Definition at line 783 of file app_voicemail_odbcstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 795 of file app_voicemail_odbcstorage.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 790 of file app_voicemail_odbcstorage.c.

unsigned int poll_mailboxes [static]

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

Definition at line 787 of file app_voicemail_odbcstorage.c.

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 796 of file app_voicemail_odbcstorage.c.

unsigned char poll_thread_run [static]

Definition at line 797 of file app_voicemail_odbcstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 736 of file app_voicemail_odbcstorage.c.

int saydurationminfo [static]

Definition at line 860 of file app_voicemail_odbcstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 761 of file app_voicemail_odbcstorage.c.

char serveremail[80] [static]

Definition at line 771 of file app_voicemail_odbcstorage.c.

int silencethreshold = 128 [static]

Definition at line 770 of file app_voicemail_odbcstorage.c.

int skipms [static]

Definition at line 780 of file app_voicemail_odbcstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 774 of file app_voicemail_odbcstorage.c.

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

Definition at line 748 of file app_voicemail_odbcstorage.c.

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

}

Definition at line 11384 of file app_voicemail_odbcstorage.c.

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

Definition at line 843 of file app_voicemail_odbcstorage.c.

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

Definition at line 842 of file app_voicemail_odbcstorage.c.

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

Definition at line 839 of file app_voicemail_odbcstorage.c.

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

Definition at line 840 of file app_voicemail_odbcstorage.c.

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

Definition at line 838 of file app_voicemail_odbcstorage.c.

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

Definition at line 844 of file app_voicemail_odbcstorage.c.

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

Definition at line 856 of file app_voicemail_odbcstorage.c.

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

Definition at line 841 of file app_voicemail_odbcstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 727 of file app_voicemail_odbcstorage.c.

Initial value:

Definition at line 11379 of file app_voicemail_odbcstorage.c.

char vmfmts[80] [static]

Definition at line 775 of file app_voicemail_odbcstorage.c.

int vmmaxsecs [static]

Definition at line 778 of file app_voicemail_odbcstorage.c.

int vmminsecs [static]

Definition at line 777 of file app_voicemail_odbcstorage.c.

double volgain [static]

Definition at line 776 of file app_voicemail_odbcstorage.c.

char zonetag[80] [static]

Definition at line 765 of file app_voicemail_odbcstorage.c.


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1