Tue Aug 20 16:34:46 2013

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 vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
static int vm_box_exists (struct ast_channel *chan, const char *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Spanish syntax for 'You have N messages' greeting.
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_it (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Italian syntax for 'You have N messages' greeting.
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Portuguese syntax for 'You have N messages' greeting.
static int vm_browse_messages_vi (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Vietnamese syntax for 'You have N messages' greeting.
static int vm_browse_messages_zh (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Chinese (Taiwan)syntax for 'You have N messages' greeting.
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
 The handler for the change password option.
static void vm_change_password_shell (struct ast_vm_user *vmu, char *newpassword)
static char * vm_check_password_shell (char *command, char *buf, size_t len)
static int vm_delete (char *file)
 Removes the voicemail sound and information file.
static int vm_exec (struct ast_channel *chan, const char *data)
static int vm_execmain (struct ast_channel *chan, const char *data)
static int vm_forwardoptions (struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
 presents the option to prepend to an existing message when forwarding it.
static int vm_instructions (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_en (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_zh (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_intro (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_cs (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_de (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_en (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_es (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_fr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_gr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_he (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_it (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_multilang (struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_intro_nl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_no (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt_BR (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_se (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_vi (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_zh (struct ast_channel *chan, struct vm_state *vms)
static int vm_lock_path (const char *path)
 Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.
static FILE * vm_mkftemp (char *template)
static int vm_newuser (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_play_folder_name (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_gr (struct ast_channel *chan, char *box)
static int vm_play_folder_name_pl (struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua (struct ast_channel *chan, char *box)
static int vm_tempgreeting (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
 The handler for 'record a temporary greeting'.
static int vm_users_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int vm_users_data_provider_get_helper (const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
static int vmauthenticate (struct ast_channel *chan, const char *data)
static int vmsayname_exec (struct ast_channel *chan, const char *data)
static struct ast_tmvmu_tm (const struct ast_vm_user *vmu, struct ast_tm *tm)
 fill in *tm for current time according to the proper timezone, if any.
static int wait_file (struct ast_channel *chan, struct vm_state *vms, char *file)
static int wait_file2 (struct ast_channel *chan, struct vm_state *vms, char *file)
static int write_password_to_file (const char *secretfn, const char *password)

Variables

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

Detailed Description

Comedian Mail - Voicemail System.

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

Definition in file app_voicemail_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 721 of file app_voicemail_odbcstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11324 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 11351 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 791 of file app_voicemail_odbcstorage.c.

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

Definition at line 722 of file app_voicemail_odbcstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 717 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 719 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 734 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 733 of file app_voicemail_odbcstorage.c.

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

Definition at line 720 of file app_voicemail_odbcstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

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

#define tdesc   "Comedian Mail (Voicemail System)"

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

References ast_strlen_zero().

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

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

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

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

11028 {
11029    struct ast_vm_user svm;
11030    AST_DECLARE_APP_ARGS(arg,
11031       AST_APP_ARG(mbox);
11032       AST_APP_ARG(context);
11033    );
11034 
11035    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11036 
11037    if (ast_strlen_zero(arg.mbox)) {
11038       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11039       return -1;
11040    }
11041 
11042    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11043    return 0;
11044 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06740 {
06741    unsigned char buf[256];
06742    int bytes = 0;
06743 
06744    if (!ast_adsi_available(chan))
06745       return;
06746    bytes += adsi_logo(buf + bytes);
06747    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06748    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06749    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06750    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06751 
06752    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06753 }

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

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

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

static void adsi_login ( struct ast_channel chan  )  [static]

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

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

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

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

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

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

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

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

static void adsi_password ( struct ast_channel chan  )  [static]

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

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

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

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

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

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

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

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

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 13232 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, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

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

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

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

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

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

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

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

Destructively Parse options and apply.

Definition at line 1277 of file app_voicemail_odbcstorage.c.

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

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

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

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

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

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

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

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

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

Referenced by make_email_file(), and sendpage().

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

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

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

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

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

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

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

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

Referenced by make_email_file(), and sendpage().

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

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

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

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

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

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

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

Definition at line 11131 of file app_voicemail_odbcstorage.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

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

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

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

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

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

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

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

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

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

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

01666 {
01667    mode_t   mode = VOICEMAIL_DIR_MODE;
01668    int res;
01669 
01670    make_dir(dest, len, context, ext, folder);
01671    if ((res = ast_mkdir(dest, mode))) {
01672       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01673       return -1;
01674    }
01675    return 0;
01676 }

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

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

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

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

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

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

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

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

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

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

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

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

static void free_user ( struct ast_vm_user vmu  )  [static]

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

01721 {
01722    if (ast_test_flag(vmu, VM_ALLOCED)) {
01723 
01724       ast_free(vmu->emailbody);
01725       vmu->emailbody = NULL;
01726 
01727       ast_free(vmu->emailsubject);
01728       vmu->emailsubject = NULL;
01729 
01730       ast_free(vmu);
01731    }
01732 }

static void free_vm_users ( void   )  [static]

Free the users structure.

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

11744 {
11745    struct ast_vm_user *current;
11746    AST_LIST_LOCK(&users);
11747    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11748       ast_set_flag(current, VM_ALLOCED);
11749       free_user(current);
11750    }
11751    AST_LIST_UNLOCK(&users);
11752 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

11756 {
11757    struct vm_zone *zcur;
11758    AST_LIST_LOCK(&zones);
11759    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11760       free_zone(zcur);
11761    AST_LIST_UNLOCK(&zones);
11762 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5071 of file app_voicemail_odbcstorage.c.

References ast_free.

Referenced by free_vm_zones().

05072 {
05073    ast_free(z);
05074 }

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

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

Referenced by leave_voicemail().

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

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

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

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

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

Referenced by vm_execmain().

06817 {
06818    int res = 0;
06819    int loops = 0;
06820 
06821    res = ast_play_and_wait(chan, fn);  /* Folder name */
06822    while (((res < '0') || (res > '9')) &&
06823          (res != '#') && (res >= 0) &&
06824          loops < 4) {
06825       res = get_folder(chan, 0);
06826       loops++;
06827    }
06828    if (loops == 4) { /* give up */
06829       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06830       return '#';
06831    }
06832    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06833    return res;
06834 }

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

Definition at line 1707 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

Referenced by vm_execmain().

01708 {
01709    size_t i;
01710 
01711    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01712       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01713          return i;
01714       }
01715    }
01716 
01717    return -1;
01718 }

static int handle_subscribe ( void *  datap  )  [static]

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

11514 {
11515    unsigned int len;
11516    struct mwi_sub *mwi_sub;
11517    struct mwi_sub_task *p = datap;
11518 
11519    len = sizeof(*mwi_sub);
11520    if (!ast_strlen_zero(p->mailbox))
11521       len += strlen(p->mailbox);
11522 
11523    if (!ast_strlen_zero(p->context))
11524       len += strlen(p->context) + 1; /* Allow for seperator */
11525 
11526    if (!(mwi_sub = ast_calloc(1, len)))
11527       return -1;
11528 
11529    mwi_sub->uniqueid = p->uniqueid;
11530    if (!ast_strlen_zero(p->mailbox))
11531       strcpy(mwi_sub->mailbox, p->mailbox);
11532 
11533    if (!ast_strlen_zero(p->context)) {
11534       strcat(mwi_sub->mailbox, "@");
11535       strcat(mwi_sub->mailbox, p->context);
11536    }
11537 
11538    AST_RWLIST_WRLOCK(&mwi_subs);
11539    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11540    AST_RWLIST_UNLOCK(&mwi_subs);
11541    ast_free((void *) p->mailbox);
11542    ast_free((void *) p->context);
11543    ast_free(p);
11544    poll_subscribed_mailbox(mwi_sub);
11545    return 0;
11546 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

11492 {
11493    struct mwi_sub *mwi_sub;
11494    uint32_t *uniqueid = datap;
11495    
11496    AST_RWLIST_WRLOCK(&mwi_subs);
11497    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11498       if (mwi_sub->uniqueid == *uniqueid) {
11499          AST_LIST_REMOVE_CURRENT(entry);
11500          break;
11501       }
11502    }
11503    AST_RWLIST_TRAVERSE_SAFE_END
11504    AST_RWLIST_UNLOCK(&mwi_subs);
11505 
11506    if (mwi_sub)
11507       mwi_sub_destroy(mwi_sub);
11508 
11509    ast_free(uniqueid);  
11510    return 0;
11511 }

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

11269 {
11270    switch (cmd) {
11271    case CLI_INIT:
11272       e->command = "voicemail reload";
11273       e->usage =
11274          "Usage: voicemail reload\n"
11275          "       Reload voicemail configuration\n";
11276       return NULL;
11277    case CLI_GENERATE:
11278       return NULL;
11279    }
11280 
11281    if (a->argc != 2)
11282       return CLI_SHOWUSAGE;
11283 
11284    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11285    load_config(1);
11286    
11287    return CLI_SUCCESS;
11288 }

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

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

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

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

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

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

Referenced by load_module(), and vm_execmain().

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

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

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

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

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

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

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

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

utility used by inchar(), for base_encode()

Definition at line 4197 of file app_voicemail_odbcstorage.c.

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

Referenced by inchar().

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

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

utility used by base_encode()

Definition at line 4221 of file app_voicemail_odbcstorage.c.

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

Referenced by base_encode().

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

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

Definition at line 915 of file app_voicemail_odbcstorage.c.

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

Referenced by load_module().

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

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

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

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

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

Definition at line 909 of file app_voicemail_odbcstorage.c.

References inprocess::mailbox.

Referenced by load_module().

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

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

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

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

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

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

Referenced by actual_load_config().

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

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

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

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

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

static int load_config ( int  reload  )  [static]

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

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

static int load_module ( void   )  [static]

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

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

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

01620 {
01621    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01622 }

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 4514 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(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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

01637 {
01638    return snprintf(dest, len, "%s/msg%04d", dir, num);
01639 }

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

Manager list voicemail users command.

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

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

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

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

11464 {
11465    while (poll_thread_run) {
11466       struct timespec ts = { 0, };
11467       struct timeval wait;
11468 
11469       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11470       ts.tv_sec = wait.tv_sec;
11471       ts.tv_nsec = wait.tv_usec * 1000;
11472 
11473       ast_mutex_lock(&poll_lock);
11474       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11475       ast_mutex_unlock(&poll_lock);
11476 
11477       if (!poll_thread_run)
11478          break;
11479 
11480       poll_subscribed_mailboxes();
11481    }
11482 
11483    return NULL;
11484 }

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

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

01698 {
01699 #ifdef IMAP_STORAGE
01700    if (vmu && id == 0) {
01701       return vmu->imapfolder;
01702    }
01703 #endif
01704    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01705 }

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

Definition at line 5364 of file app_voicemail_odbcstorage.c.

References __has_voicemail().

Referenced by load_module().

05365 {
05366    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05367 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11486 of file app_voicemail_odbcstorage.c.

References ast_free.

Referenced by handle_unsubscribe().

11487 {
11488    ast_free(mwi_sub);
11489 }

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

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

11575 {
11576    struct mwi_sub_task *mwist;
11577    
11578    if (ast_event_get_type(event) != AST_EVENT_SUB)
11579       return;
11580 
11581    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11582       return;
11583 
11584    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11585       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11586       return;
11587    }
11588    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11589    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11590    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11591    
11592    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11593       ast_free(mwist);
11594    }
11595 }

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

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

11549 {
11550    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11551 
11552    if (!uniqueid) {
11553       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11554       return;
11555    }
11556 
11557    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11558       ast_free(uniqueid);
11559       return;
11560    }
11561 
11562    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11563       ast_free(uniqueid);
11564       return;
11565    }
11566 
11567    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11568    *uniqueid = u;
11569    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11570       ast_free(uniqueid);
11571    }
11572 }

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

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

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

utility used by base_encode()

Definition at line 4234 of file app_voicemail_odbcstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

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

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

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

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

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

Definition at line 7670 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, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

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

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

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

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

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

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

Definition at line 7467 of file app_voicemail_odbcstorage.c.

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

Referenced by play_message().

07468 {
07469    int res = 0;
07470 
07471    if (!ast_strlen_zero(category))
07472       res = ast_play_and_wait(chan, category);
07473 
07474    if (res) {
07475       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07476       res = 0;
07477    }
07478 
07479    return res;
07480 }

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

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

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

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

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

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

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11435 of file app_voicemail_odbcstorage.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11436 {
11437    int new = 0, old = 0, urgent = 0;
11438 
11439    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11440 
11441    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11442       mwi_sub->old_urgent = urgent;
11443       mwi_sub->old_new = new;
11444       mwi_sub->old_old = old;
11445       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11446       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11447    }
11448 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11451 {
11452    struct mwi_sub *mwi_sub;
11453 
11454    AST_RWLIST_RDLOCK(&mwi_subs);
11455    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11456       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11457          poll_subscribed_mailbox(mwi_sub);
11458       }
11459    }
11460    AST_RWLIST_UNLOCK(&mwi_subs);
11461 }

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

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

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

Referenced by make_email_file(), and sendpage().

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

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

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

07011 {
07012    struct ast_event *event;
07013    char *mailbox, *context;
07014 
07015    /* Strip off @default */
07016    context = mailbox = ast_strdupa(box);
07017    strsep(&context, "@");
07018    if (ast_strlen_zero(context))
07019       context = "default";
07020 
07021    if (!(event = ast_event_new(AST_EVENT_MWI,
07022          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07023          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07024          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07025          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07026          AST_EVENT_IE_END))) {
07027       return;
07028    }
07029 
07030    ast_event_queue_and_cache(event);
07031 }

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

Definition at line 12541 of file app_voicemail_odbcstorage.c.

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

Referenced by actual_load_config(), and append_mailbox().

12541                                                                                            {
12542    struct ast_config *pwconf;
12543    struct ast_flags config_flags = { 0 };
12544 
12545    pwconf = ast_config_load(secretfn, config_flags);
12546    if (pwconf) {
12547       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12548       if (val) {
12549          ast_copy_string(password, val, passwordlen);
12550          ast_config_destroy(pwconf);
12551          return;
12552       }
12553       ast_config_destroy(pwconf);
12554    }
12555    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12556 }

static int reload ( void   )  [static]

Definition at line 13071 of file app_voicemail_odbcstorage.c.

References load_config().

13072 {
13073    return load_config(1);
13074 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

12528 {
12529    int res = -1;
12530    char dir[PATH_MAX];
12531    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12532    ast_debug(2, "About to try retrieving name file %s\n", dir);
12533    RETRIEVE(dir, -1, mailbox, context);
12534    if (ast_fileexists(dir, NULL, NULL)) {
12535       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12536    }
12537    DISPOSE(dir, -1);
12538    return res;
12539 }

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

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

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

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

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

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

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

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

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

11619 {
11620    poll_thread_run = 0;
11621 
11622    if (mwi_sub_sub) {
11623       ast_event_unsubscribe(mwi_sub_sub);
11624       mwi_sub_sub = NULL;
11625    }
11626 
11627    if (mwi_unsub_sub) {
11628       ast_event_unsubscribe(mwi_unsub_sub);
11629       mwi_unsub_sub = NULL;
11630    }
11631 
11632    ast_mutex_lock(&poll_lock);
11633    ast_cond_signal(&poll_cond);
11634    ast_mutex_unlock(&poll_lock);
11635 
11636    pthread_join(poll_thread, NULL);
11637 
11638    poll_thread = AST_PTHREADT_NULL;
11639 }

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

Referenced by make_email_file(), and sendpage().

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

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

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

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

static int unload_module ( void   )  [static]

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

13077 {
13078    int res;
13079 
13080    res = ast_unregister_application(app);
13081    res |= ast_unregister_application(app2);
13082    res |= ast_unregister_application(app3);
13083    res |= ast_unregister_application(app4);
13084    res |= ast_unregister_application(sayname_app);
13085    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13086    res |= ast_manager_unregister("VoicemailUsersList");
13087    res |= ast_data_unregister(NULL);
13088 #ifdef TEST_FRAMEWORK
13089    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13090    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13091    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13092    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13093    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13094 #endif
13095    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13096    ast_uninstall_vm_functions();
13097    ao2_ref(inprocess_container, -1);
13098 
13099    if (poll_thread != AST_PTHREADT_NULL)
13100       stop_poll_thread();
13101 
13102    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13103    ast_unload_realtime("voicemail");
13104    ast_unload_realtime("voicemail_data");
13105 
13106    free_vm_users();
13107    free_vm_zones();
13108    return res;
13109 }

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

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

01734                                                                                         {
01735 
01736    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01737 
01738    /* remove old allocation */
01739    if (vms->deleted) {
01740       ast_free(vms->deleted);
01741       vms->deleted = NULL;
01742    }
01743    if (vms->heard) {
01744       ast_free(vms->heard);
01745       vms->heard = NULL;
01746    }
01747    vms->dh_arraysize = 0;
01748 
01749    if (arraysize > 0) {
01750       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01751          return -1;
01752       }
01753       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01754          ast_free(vms->deleted);
01755          vms->deleted = NULL;
01756          return -1;
01757       }
01758       vms->dh_arraysize = arraysize;
01759    }
01760 
01761    return 0;
01762 }

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 9768 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_test_suite_event_notify, ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, find_user(), ast_party_caller::id, ast_party_id::number, ast_vm_user::password, S_COR, ast_party_number::str, and ast_party_number::valid.

Referenced by vm_execmain(), and vmauthenticate().

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

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

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

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

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

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

Referenced by vm_execmain().

09748 {
09749    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09750       return vm_browse_messages_es(chan, vms, vmu);
09751    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09752       return vm_browse_messages_gr(chan, vms, vmu);
09753    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09754       return vm_browse_messages_he(chan, vms, vmu);
09755    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09756       return vm_browse_messages_it(chan, vms, vmu);
09757    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09758       return vm_browse_messages_pt(chan, vms, vmu);
09759    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09760       return vm_browse_messages_vi(chan, vms, vmu);
09761    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09762       return vm_browse_messages_zh(chan, vms, vmu);
09763    } else {                                             /* Default to English syntax */
09764       return vm_browse_messages_en(chan, vms, vmu);
09765    }
09766 }

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

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

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

Spanish syntax for 'You have N messages' greeting.

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

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

09641 {
09642    int cmd;
09643 
09644    if (vms->lastmsg > -1) {
09645       cmd = play_message(chan, vmu, vms);
09646    } else {
09647       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09648       if (!cmd)
09649          cmd = ast_play_and_wait(chan, "vm-messages");
09650       if (!cmd) {
09651          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09652          cmd = ast_play_and_wait(chan, vms->fn);
09653       }
09654    }
09655    return cmd;
09656 }

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

Greek syntax for 'You have N messages' greeting.

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

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

09535 {
09536    int cmd = 0;
09537 
09538    if (vms->lastmsg > -1) {
09539       cmd = play_message(chan, vmu, vms);
09540    } else {
09541       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09542       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09543          if (!cmd) {
09544             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09545             cmd = ast_play_and_wait(chan, vms->fn);
09546          }
09547          if (!cmd)
09548             cmd = ast_play_and_wait(chan, "vm-messages");
09549       } else {
09550          if (!cmd)
09551             cmd = ast_play_and_wait(chan, "vm-messages");
09552          if (!cmd) {
09553             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09554             cmd = ast_play_and_wait(chan, vms->fn);
09555          }
09556       }
09557    } 
09558    return cmd;
09559 }

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

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

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

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

Italian syntax for 'You have N messages' greeting.

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

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

09615 {
09616    int cmd;
09617 
09618    if (vms->lastmsg > -1) {
09619       cmd = play_message(chan, vmu, vms);
09620    } else {
09621       cmd = ast_play_and_wait(chan, "vm-no");
09622       if (!cmd)
09623          cmd = ast_play_and_wait(chan, "vm-message");
09624       if (!cmd) {
09625          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09626          cmd = ast_play_and_wait(chan, vms->fn);
09627       }
09628    }
09629    return cmd;
09630 }

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

Portuguese syntax for 'You have N messages' greeting.

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

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

09667 {
09668    int cmd;
09669 
09670    if (vms->lastmsg > -1) {
09671       cmd = play_message(chan, vmu, vms);
09672    } else {
09673       cmd = ast_play_and_wait(chan, "vm-no");
09674       if (!cmd) {
09675          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09676          cmd = ast_play_and_wait(chan, vms->fn);
09677       }
09678       if (!cmd)
09679          cmd = ast_play_and_wait(chan, "vm-messages");
09680    }
09681    return cmd;
09682 }

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

09721 {
09722    int cmd = 0;
09723 
09724    if (vms->lastmsg > -1) {
09725       cmd = play_message(chan, vmu, vms);
09726    } else {
09727       cmd = ast_play_and_wait(chan, "vm-no");
09728       if (!cmd) {
09729          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09730          cmd = ast_play_and_wait(chan, vms->fn);
09731       }
09732    }
09733    return cmd;
09734 }

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

09693 {
09694    int cmd;
09695 
09696    if (vms->lastmsg > -1) {
09697       cmd = play_message(chan, vmu, vms);
09698    } else {
09699       cmd = ast_play_and_wait(chan, "vm-you");
09700       if (!cmd) 
09701          cmd = ast_play_and_wait(chan, "vm-haveno");
09702       if (!cmd)
09703          cmd = ast_play_and_wait(chan, "vm-messages");
09704       if (!cmd) {
09705          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09706          cmd = ast_play_and_wait(chan, vms->fn);
09707       }
09708    }
09709    return cmd;
09710 }

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

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

Referenced by vm_newuser(), and vm_options().

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

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

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

01594 {
01595    char buf[255];
01596    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01597    ast_debug(1, "External password: %s\n",buf);
01598    if (!ast_safe_system(buf)) {
01599       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01600       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01601       /* Reset the password in memory, too */
01602       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01603    }
01604 }

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

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

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

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

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

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

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

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

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

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

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

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 6854 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, CONFIG_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

Referenced by forward_message().

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

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

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

Referenced by vm_execmain().

09210 {
09211    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09212       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09213    } else {             /* Default to ENGLISH */
09214       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09215    }
09216 }

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

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

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

09186 {
09187    int res = 0;
09188    /* Play instructions and wait for new command */
09189    while (!res) {
09190       if (vms->lastmsg > -1) {
09191          res = ast_play_and_wait(chan, "vm-listen");
09192          if (!res)
09193             res = vm_play_folder_name(chan, vms->vmbox);
09194          if (!res)
09195             res = ast_play_and_wait(chan, "press");
09196          if (!res)
09197             res = ast_play_and_wait(chan, "digits/1");
09198       }
09199       if (!res)
09200          res = ast_play_and_wait(chan, "vm-opts");
09201       if (!res) {
09202          vms->starting = 0;
09203          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09204       }
09205    }
09206    return res;
09207 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

09006 {
09007    int res;
09008 
09009    /* Introduce messages they have */
09010    res = ast_play_and_wait(chan, "vm-youhave");
09011    if (!res) {
09012       if (vms->newmessages) {
09013          res = say_and_wait(chan, vms->newmessages, chan->language);
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       }
09019       if (!res && vms->oldmessages) {
09020          res = say_and_wait(chan, vms->oldmessages, chan->language);
09021          if (!res)
09022             res = ast_play_and_wait(chan, "vm-Old");        
09023       }
09024       if (!res) {
09025          if (!vms->oldmessages && !vms->newmessages) {
09026             res = ast_play_and_wait(chan, "vm-no");
09027             if (!res)
09028                res = ast_play_and_wait(chan, "vm-message");
09029          }
09030       }
09031    }
09032    return res;
09033 }

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

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

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

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

03252 {
03253    switch (ast_lock_path(path)) {
03254    case AST_LOCK_TIMEOUT:
03255       return -1;
03256    default:
03257       return 0;
03258    }
03259 }

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

Definition at line 1642 of file app_voicemail_odbcstorage.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01643 {
01644    FILE *p = NULL;
01645    int pfd = mkstemp(template);
01646    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01647    if (pfd > -1) {
01648       p = fdopen(pfd, "w+");
01649       if (!p) {
01650          close(pfd);
01651          pfd = -1;
01652       }
01653    }
01654    return p;
01655 }

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

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

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

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

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

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

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

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

Definition at line 8065 of file app_voicemail_odbcstorage.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

08066 {
08067    int cmd;
08068    char *buf;
08069 
08070    buf = ast_alloca(strlen(box) + 2);
08071    strcpy(buf, box);
08072    strcat(buf, "s");
08073 
08074    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08075       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08076       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08077    } else {
08078       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08079       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08080    }
08081 }

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

Definition at line 8083 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08084 {
08085    int cmd;
08086 
08087    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08088       if (!strcasecmp(box, "vm-INBOX"))
08089          cmd = ast_play_and_wait(chan, "vm-new-e");
08090       else
08091          cmd = ast_play_and_wait(chan, "vm-old-e");
08092       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08093    } else {
08094       cmd = ast_play_and_wait(chan, "vm-messages");
08095       return cmd ? cmd : ast_play_and_wait(chan, box);
08096    }
08097 }

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

Definition at line 8099 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08100 {
08101    int cmd;
08102 
08103    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08104       cmd = ast_play_and_wait(chan, "vm-messages");
08105       return cmd ? cmd : ast_play_and_wait(chan, box);
08106    } else {
08107       cmd = ast_play_and_wait(chan, box);
08108       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08109    }
08110 }

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

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

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

Definition at line 11412 of file app_voicemail_odbcstorage.c.

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

11414 {
11415    struct ast_vm_user *user;
11416 
11417    AST_LIST_LOCK(&users);
11418    AST_LIST_TRAVERSE(&users, user, list) {
11419       vm_users_data_provider_get_helper(search, data_root, user);
11420    }
11421    AST_LIST_UNLOCK(&users);
11422 
11423    return 0;
11424 }

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

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

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

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

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

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

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

12592 {
12593    char *context;
12594    char *args_copy;
12595    int res;
12596 
12597    if (ast_strlen_zero(data)) {
12598       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12599       return -1;
12600    }
12601 
12602    args_copy = ast_strdupa(data);
12603    if ((context = strchr(args_copy, '@'))) {
12604       *context++ = '\0';
12605    } else {
12606       context = "default";
12607    }
12608 
12609    if ((res = sayname(chan, args_copy, context) < 0)) {
12610       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12611       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12612       if (!res) {
12613          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12614       }
12615    }
12616 
12617    return res;
12618 }

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

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

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

07454 {
07455    int res;
07456    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07457       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07458    return res;
07459 }

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

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

12558                                                                               {
12559    struct ast_config *conf;
12560    struct ast_category *cat;
12561    struct ast_variable *var;
12562    int res = -1;
12563 
12564    if (!(conf = ast_config_new())) {
12565       ast_log(LOG_ERROR, "Error creating new config structure\n");
12566       return res;
12567    }
12568    if (!(cat = ast_category_new("general", "", 1))) {
12569       ast_log(LOG_ERROR, "Error creating new category structure\n");
12570       ast_config_destroy(conf);
12571       return res;
12572    }
12573    if (!(var = ast_variable_new("password", password, ""))) {
12574       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12575       ast_config_destroy(conf);
12576       ast_category_destroy(cat);
12577       return res;
12578    }
12579    ast_category_append(conf, cat);
12580    ast_variable_append(cat, var);
12581    if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12582       res = 0;
12583    } else {
12584       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12585    }
12586 
12587    ast_config_destroy(conf);
12588    return res;
12589 }


Variable Documentation

char* addesc = "Comedian Mail" [static]

Definition at line 749 of file app_voicemail_odbcstorage.c.

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

Definition at line 876 of file app_voicemail_odbcstorage.c.

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

Definition at line 877 of file app_voicemail_odbcstorage.c.

int adsiver = 1 [static]

Definition at line 878 of file app_voicemail_odbcstorage.c.

char* app = "VoiceMail" [static]

Definition at line 752 of file app_voicemail_odbcstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 755 of file app_voicemail_odbcstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 757 of file app_voicemail_odbcstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 758 of file app_voicemail_odbcstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 862 of file app_voicemail_odbcstorage.c.

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

Definition at line 874 of file app_voicemail_odbcstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

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

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 861 of file app_voicemail_odbcstorage.c.

char* emailbody = NULL [static]

Definition at line 868 of file app_voicemail_odbcstorage.c.

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

Definition at line 879 of file app_voicemail_odbcstorage.c.

char* emailsubject = NULL [static]

Definition at line 869 of file app_voicemail_odbcstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 863 of file app_voicemail_odbcstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 729 of file app_voicemail_odbcstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 728 of file app_voicemail_odbcstorage.c.

char externnotify[160] [static]

Definition at line 772 of file app_voicemail_odbcstorage.c.

char fromstring[100] [static]

Definition at line 872 of file app_voicemail_odbcstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 857 of file app_voicemail_odbcstorage.c.

Definition at line 901 of file app_voicemail_odbcstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 830 of file app_voicemail_odbcstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 832 of file app_voicemail_odbcstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 833 of file app_voicemail_odbcstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 831 of file app_voicemail_odbcstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 834 of file app_voicemail_odbcstorage.c.

char locale[20] [static]

Definition at line 765 of file app_voicemail_odbcstorage.c.

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

Definition at line 11046 of file app_voicemail_odbcstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1678 of file app_voicemail_odbcstorage.c.

char mailcmd[160] [static]

Definition at line 771 of file app_voicemail_odbcstorage.c.

int maxdeletedmsg [static]

Definition at line 768 of file app_voicemail_odbcstorage.c.

int maxgreet [static]

Definition at line 778 of file app_voicemail_odbcstorage.c.

int maxlogins [static]

Definition at line 780 of file app_voicemail_odbcstorage.c.

int maxmsg [static]

Definition at line 767 of file app_voicemail_odbcstorage.c.

int maxsilence [static]

Definition at line 766 of file app_voicemail_odbcstorage.c.

int minpassword [static]

Definition at line 781 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 799 of file app_voicemail_odbcstorage.c.

Definition at line 825 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 801 of file app_voicemail_odbcstorage.c.

int my_umask [static]

Definition at line 731 of file app_voicemail_odbcstorage.c.

char* pagerbody = NULL [static]

Definition at line 870 of file app_voicemail_odbcstorage.c.

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

Definition at line 880 of file app_voicemail_odbcstorage.c.

char pagerfromstring[100] [static]

Definition at line 873 of file app_voicemail_odbcstorage.c.

char* pagersubject = NULL [static]

Definition at line 871 of file app_voicemail_odbcstorage.c.

int passwordlocation [static]

Definition at line 782 of file app_voicemail_odbcstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 794 of file app_voicemail_odbcstorage.c.

unsigned int poll_freq [static]

Polling frequency

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 795 of file app_voicemail_odbcstorage.c.

unsigned char poll_thread_run [static]

Definition at line 796 of file app_voicemail_odbcstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 735 of file app_voicemail_odbcstorage.c.

int saydurationminfo [static]

Definition at line 859 of file app_voicemail_odbcstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 760 of file app_voicemail_odbcstorage.c.

char serveremail[80] [static]

Definition at line 770 of file app_voicemail_odbcstorage.c.

int silencethreshold = 128 [static]

Definition at line 769 of file app_voicemail_odbcstorage.c.

int skipms [static]

Definition at line 779 of file app_voicemail_odbcstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 773 of file app_voicemail_odbcstorage.c.

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

Definition at line 747 of file app_voicemail_odbcstorage.c.

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

}

Definition at line 11431 of file app_voicemail_odbcstorage.c.

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

Definition at line 842 of file app_voicemail_odbcstorage.c.

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

Definition at line 841 of file app_voicemail_odbcstorage.c.

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

Definition at line 838 of file app_voicemail_odbcstorage.c.

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

Definition at line 839 of file app_voicemail_odbcstorage.c.

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

Definition at line 837 of file app_voicemail_odbcstorage.c.

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

Definition at line 843 of file app_voicemail_odbcstorage.c.

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

Definition at line 855 of file app_voicemail_odbcstorage.c.

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

Definition at line 840 of file app_voicemail_odbcstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 726 of file app_voicemail_odbcstorage.c.

Initial value:

Definition at line 11426 of file app_voicemail_odbcstorage.c.

char vmfmts[80] [static]

Definition at line 774 of file app_voicemail_odbcstorage.c.

int vmmaxsecs [static]

Definition at line 777 of file app_voicemail_odbcstorage.c.

int vmminsecs [static]

Definition at line 776 of file app_voicemail_odbcstorage.c.

double volgain [static]

Definition at line 775 of file app_voicemail_odbcstorage.c.

char zonetag[80] [static]

Definition at line 764 of file app_voicemail_odbcstorage.c.


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