Wed Apr 6 11:29:52 2011

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

Defines

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

Enumerations

enum  vm_box {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER
}
enum  vm_option_args { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }
enum  vm_option_flags {
  OPT_SILENT = (1 << 0), OPT_BUSY_GREETING = (1 << 1), OPT_UNAVAIL_GREETING = (1 << 2), OPT_RECORDGAIN = (1 << 3),
  OPT_PREPEND_MAILBOX = (1 << 4), OPT_AUTOPLAY = (1 << 6), OPT_DTMFEXIT = (1 << 7), OPT_MESSAGE_Urgent = (1 << 8),
  OPT_MESSAGE_PRIORITY = (1 << 9)
}
enum  vm_passwordlocation { OPT_PWLOC_VOICEMAILCONF = 0, OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2 }

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", }
static char * addesc = "Comedian Mail"
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
static int adsiver = 1
static char * app = "VoiceMail"
static char * app2 = "VoiceMailMain"
static char * app3 = "MailboxExists"
static char * app4 = "VMAuthenticate"
static struct ast_module_infoast_module_info = &__mod_info
static char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_check_cmd [128]
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char * sayname_app = "VMSayName"
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_app_option vm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }}
static struct ast_data_entry vm_data_providers []
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_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, read doc/imapstorage.txt

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

#define BASELINELEN   72

Definition at line 427 of file app_voicemail_odbcstorage.c.

#define BASEMAXINLINE   256

Definition at line 428 of file app_voicemail_odbcstorage.c.

#define CHUNKSIZE   65536

Definition at line 401 of file app_voicemail_odbcstorage.c.

#define COMMAND_TIMEOUT   5000

Definition at line 397 of file app_voicemail_odbcstorage.c.

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

Definition at line 711 of file app_voicemail_odbcstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

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

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 409 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 411 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 412 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 410 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 413 of file app_voicemail_odbcstorage.c.

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 781 of file app_voicemail_odbcstorage.c.

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

Definition at line 712 of file app_voicemail_odbcstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 707 of file app_voicemail_odbcstorage.c.

#define ENDL   "\n"

Definition at line 432 of file app_voicemail_odbcstorage.c.

#define ERROR_LOCK_PATH   -100

Definition at line 457 of file app_voicemail_odbcstorage.c.

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

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

#define MAX_DATETIME_FORMAT   512

Definition at line 435 of file app_voicemail_odbcstorage.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 436 of file app_voicemail_odbcstorage.c.

#define MAXMSG   100

Definition at line 422 of file app_voicemail_odbcstorage.c.

#define MAXMSGLIMIT   9999

Definition at line 423 of file app_voicemail_odbcstorage.c.

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 425 of file app_voicemail_odbcstorage.c.

#define OPERATOR_EXIT   300

Definition at line 458 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 724 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 723 of file app_voicemail_odbcstorage.c.

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

Definition at line 710 of file app_voicemail_odbcstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 706 of file app_voicemail_odbcstorage.c.

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

Definition at line 418 of file app_voicemail_odbcstorage.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 395 of file app_voicemail_odbcstorage.c.

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

Definition at line 708 of file app_voicemail_odbcstorage.c.

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 733 of file app_voicemail_odbcstorage.c.

#define VALID_DTMF   "1234567890*#"

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

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 449 of file app_voicemail_odbcstorage.c.

#define VM_DELETE   (1 << 12)

Delete message after sending notification

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

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 442 of file app_voicemail_odbcstorage.c.

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 446 of file app_voicemail_odbcstorage.c.

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 445 of file app_voicemail_odbcstorage.c.

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

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

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 454 of file app_voicemail_odbcstorage.c.

#define VM_OPERATOR   (1 << 1)

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

Definition at line 439 of file app_voicemail_odbcstorage.c.

#define VM_PBXSKIP   (1 << 9)

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

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

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 440 of file app_voicemail_odbcstorage.c.

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 443 of file app_voicemail_odbcstorage.c.

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 452 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 444 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 441 of file app_voicemail_odbcstorage.c.

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 453 of file app_voicemail_odbcstorage.c.

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 648 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 403 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 399 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 400 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 

Definition at line 461 of file app_voicemail_odbcstorage.c.

00461             {
00462    NEW_FOLDER,
00463    OLD_FOLDER,
00464    WORK_FOLDER,
00465    FAMILY_FOLDER,
00466    FRIENDS_FOLDER,
00467    GREETINGS_FOLDER
00468 };

enum vm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 482 of file app_voicemail_odbcstorage.c.

00482                     {
00483    OPT_ARG_RECORDGAIN = 0,
00484    OPT_ARG_PLAYFOLDER = 1,
00485    OPT_ARG_DTMFEXIT   = 2,
00486    /* This *must* be the last value in this enum! */
00487    OPT_ARG_ARRAY_SIZE = 3,
00488 };

enum vm_option_flags

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 

Definition at line 470 of file app_voicemail_odbcstorage.c.

00470                      {
00471    OPT_SILENT =           (1 << 0),
00472    OPT_BUSY_GREETING =    (1 << 1),
00473    OPT_UNAVAIL_GREETING = (1 << 2),
00474    OPT_RECORDGAIN =       (1 << 3),
00475    OPT_PREPEND_MAILBOX =  (1 << 4),
00476    OPT_AUTOPLAY =         (1 << 6),
00477    OPT_DTMFEXIT =         (1 << 7),
00478    OPT_MESSAGE_Urgent =   (1 << 8),
00479    OPT_MESSAGE_PRIORITY = (1 << 9)
00480 };

enum vm_passwordlocation

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 490 of file app_voicemail_odbcstorage.c.

00490                          {
00491    OPT_PWLOC_VOICEMAILCONF = 0,
00492    OPT_PWLOC_SPOOLDIR      = 1,
00493    OPT_PWLOC_USERSCONF     = 2,
00494 };


Function Documentation

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

Definition at line 5237 of file app_voicemail_odbcstorage.c.

References ast_strlen_zero().

05238 {
05239    DIR *dir;
05240    struct dirent *de;
05241    char fn[256];
05242    int ret = 0;
05243 
05244    /* If no mailbox, return immediately */
05245    if (ast_strlen_zero(mailbox))
05246       return 0;
05247 
05248    if (ast_strlen_zero(folder))
05249       folder = "INBOX";
05250    if (ast_strlen_zero(context))
05251       context = "default";
05252 
05253    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05254 
05255    if (!(dir = opendir(fn)))
05256       return 0;
05257 
05258    while ((de = readdir(dir))) {
05259       if (!strncasecmp(de->d_name, "msg", 3)) {
05260          if (shortcircuit) {
05261             ret = 1;
05262             break;
05263          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05264             ret++;
05265          }
05266       }
05267    }
05268 
05269    closedir(dir);
05270 
05271    return ret;
05272 }

static void __reg_module ( void   )  [static]

Definition at line 13197 of file app_voicemail_odbcstorage.c.

static void __unreg_module ( void   )  [static]

Definition at line 13197 of file app_voicemail_odbcstorage.c.

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

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

10702 {
10703    struct ast_vm_user svm;
10704    AST_DECLARE_APP_ARGS(arg,
10705       AST_APP_ARG(mbox);
10706       AST_APP_ARG(context);
10707    );
10708 
10709    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
10710 
10711    if (ast_strlen_zero(arg.mbox)) {
10712       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
10713       return -1;
10714    }
10715 
10716    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
10717    return 0;
10718 }

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

04656 {
04657    char tmpdir[256], newtmp[256];
04658    char fname[256];
04659    char tmpcmd[256];
04660    int tmpfd = -1;
04661 
04662    /* Eww. We want formats to tell us their own MIME type */
04663    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04664 
04665    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04666       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04667       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04668       tmpfd = mkstemp(newtmp);
04669       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04670       ast_debug(3, "newtmp: %s\n", newtmp);
04671       if (tmpfd > -1) {
04672          int soxstatus;
04673          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04674          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04675             attach = newtmp;
04676             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04677          } else {
04678             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04679                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04680             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04681          }
04682       }
04683    }
04684    fprintf(p, "--%s" ENDL, bound);
04685    if (msgnum > -1)
04686       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04687    else
04688       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04689    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04690    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04691    if (msgnum > -1)
04692       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04693    else
04694       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04695    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04696    base_encode(fname, p);
04697    if (last)
04698       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04699    if (tmpfd > -1) {
04700       unlink(fname);
04701       close(tmpfd);
04702       unlink(newtmp);
04703    }
04704    return 0;
04705 }

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

Definition at line 6223 of file app_voicemail_odbcstorage.c.

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

06224 {
06225    int x;
06226    if (!ast_adsi_available(chan))
06227       return;
06228    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06229    if (x < 0)
06230       return;
06231    if (!x) {
06232       if (adsi_load_vmail(chan, useadsi)) {
06233          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06234          return;
06235       }
06236    } else
06237       *useadsi = 1;
06238 }

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

Definition at line 6412 of file app_voicemail_odbcstorage.c.

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

06413 {
06414    int bytes = 0;
06415    unsigned char buf[256];
06416    unsigned char keys[8];
06417 
06418    int x;
06419 
06420    if (!ast_adsi_available(chan))
06421       return;
06422 
06423    /* New meaning for keys */
06424    for (x = 0; x < 5; x++)
06425       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06426 
06427    keys[6] = 0x0;
06428    keys[7] = 0x0;
06429 
06430    if (!vms->curmsg) {
06431       /* No prev key, provide "Folder" instead */
06432       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06433    }
06434    if (vms->curmsg >= vms->lastmsg) {
06435       /* If last message ... */
06436       if (vms->curmsg) {
06437          /* but not only message, provide "Folder" instead */
06438          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06439       } else {
06440          /* Otherwise if only message, leave blank */
06441          keys[3] = 1;
06442       }
06443    }
06444 
06445    /* If deleted, show "undeleted" */
06446    if (vms->deleted[vms->curmsg]) 
06447       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06448 
06449    /* Except "Exit" */
06450    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06451    bytes += ast_adsi_set_keys(buf + bytes, keys);
06452    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06453 
06454    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06455 }

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

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

06289 {
06290    unsigned char buf[256];
06291    int bytes = 0;
06292    unsigned char keys[8];
06293    int x, y;
06294 
06295    if (!ast_adsi_available(chan))
06296       return;
06297 
06298    for (x = 0; x < 5; x++) {
06299       y = ADSI_KEY_APPS + 12 + start + x;
06300       if (y > ADSI_KEY_APPS + 12 + 4)
06301          y = 0;
06302       keys[x] = ADSI_KEY_SKT | y;
06303    }
06304    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06305    keys[6] = 0;
06306    keys[7] = 0;
06307 
06308    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06309    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06310    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06311    bytes += ast_adsi_set_keys(buf + bytes, keys);
06312    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06313 
06314    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06315 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06561 {
06562    unsigned char buf[256];
06563    int bytes = 0;
06564 
06565    if (!ast_adsi_available(chan))
06566       return;
06567    bytes += adsi_logo(buf + bytes);
06568    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06569    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06570    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06571    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06572 
06573    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06574 }

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

Definition at line 6094 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, adsifdn, adsisec, adsiver, ast_adsi_begin_download(), ast_adsi_data_mode(), ast_adsi_display(), ast_adsi_download_disconnect(), ast_adsi_end_download(), ast_adsi_load_session(), ast_adsi_load_soft_key(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, and mbox().

06095 {
06096    unsigned char buf[256];
06097    int bytes = 0;
06098    int x;
06099    char num[5];
06100 
06101    *useadsi = 0;
06102    bytes += ast_adsi_data_mode(buf + bytes);
06103    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06104 
06105    bytes = 0;
06106    bytes += adsi_logo(buf);
06107    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06108 #ifdef DISPLAY
06109    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06110 #endif
06111    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06112    bytes += ast_adsi_data_mode(buf + bytes);
06113    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06114 
06115    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06116       bytes = 0;
06117       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06118       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06119       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06120       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06121       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06122       return 0;
06123    }
06124 
06125 #ifdef DISPLAY
06126    /* Add a dot */
06127    bytes = 0;
06128    bytes += ast_adsi_logo(buf);
06129    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06130    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06131    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06132    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06133 #endif
06134    bytes = 0;
06135    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06136    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06137    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06138    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06139    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06140    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06141    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06142 
06143 #ifdef DISPLAY
06144    /* Add another dot */
06145    bytes = 0;
06146    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06147    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06148 
06149    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06150    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06151 #endif
06152 
06153    bytes = 0;
06154    /* These buttons we load but don't use yet */
06155    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06156    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06157    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06158    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06159    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06160    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06161    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06162 
06163 #ifdef DISPLAY
06164    /* Add another dot */
06165    bytes = 0;
06166    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06167    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06168    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06169 #endif
06170 
06171    bytes = 0;
06172    for (x = 0; x < 5; x++) {
06173       snprintf(num, sizeof(num), "%d", x);
06174       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06175    }
06176    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06177    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06178 
06179 #ifdef DISPLAY
06180    /* Add another dot */
06181    bytes = 0;
06182    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06183    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06184    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06185 #endif
06186 
06187    if (ast_adsi_end_download(chan)) {
06188       bytes = 0;
06189       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06190       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06191       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06192       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06193       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06194       return 0;
06195    }
06196    bytes = 0;
06197    bytes += ast_adsi_download_disconnect(buf + bytes);
06198    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06199    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06200 
06201    ast_debug(1, "Done downloading scripts...\n");
06202 
06203 #ifdef DISPLAY
06204    /* Add last dot */
06205    bytes = 0;
06206    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06207    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06208 #endif
06209    ast_debug(1, "Restarting session...\n");
06210 
06211    bytes = 0;
06212    /* Load the session now */
06213    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06214       *useadsi = 1;
06215       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06216    } else
06217       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06218 
06219    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06220    return 0;
06221 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06241 {
06242    unsigned char buf[256];
06243    int bytes = 0;
06244    unsigned char keys[8];
06245    int x;
06246    if (!ast_adsi_available(chan))
06247       return;
06248 
06249    for (x = 0; x < 8; x++)
06250       keys[x] = 0;
06251    /* Set one key for next */
06252    keys[3] = ADSI_KEY_APPS + 3;
06253 
06254    bytes += adsi_logo(buf + bytes);
06255    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06256    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06257    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06258    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06259    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06260    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06261    bytes += ast_adsi_set_keys(buf + bytes, keys);
06262    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06263    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06264 }

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

Definition at line 6086 of file app_voicemail_odbcstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

06087 {
06088    int bytes = 0;
06089    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06090    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06091    return bytes;
06092 }

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

Definition at line 6317 of file app_voicemail_odbcstorage.c.

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

06318 {
06319    int bytes = 0;
06320    unsigned char buf[256]; 
06321    char buf1[256], buf2[256];
06322    char fn2[PATH_MAX];
06323 
06324    char cid[256] = "";
06325    char *val;
06326    char *name, *num;
06327    char datetime[21] = "";
06328    FILE *f;
06329 
06330    unsigned char keys[8];
06331 
06332    int x;
06333 
06334    if (!ast_adsi_available(chan))
06335       return;
06336 
06337    /* Retrieve important info */
06338    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06339    f = fopen(fn2, "r");
06340    if (f) {
06341       while (!feof(f)) {   
06342          if (!fgets((char *) buf, sizeof(buf), f)) {
06343             continue;
06344          }
06345          if (!feof(f)) {
06346             char *stringp = NULL;
06347             stringp = (char *) buf;
06348             strsep(&stringp, "=");
06349             val = strsep(&stringp, "=");
06350             if (!ast_strlen_zero(val)) {
06351                if (!strcmp((char *) buf, "callerid"))
06352                   ast_copy_string(cid, val, sizeof(cid));
06353                if (!strcmp((char *) buf, "origdate"))
06354                   ast_copy_string(datetime, val, sizeof(datetime));
06355             }
06356          }
06357       }
06358       fclose(f);
06359    }
06360    /* New meaning for keys */
06361    for (x = 0; x < 5; x++)
06362       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06363    keys[6] = 0x0;
06364    keys[7] = 0x0;
06365 
06366    if (!vms->curmsg) {
06367       /* No prev key, provide "Folder" instead */
06368       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06369    }
06370    if (vms->curmsg >= vms->lastmsg) {
06371       /* If last message ... */
06372       if (vms->curmsg) {
06373          /* but not only message, provide "Folder" instead */
06374          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06375          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06376 
06377       } else {
06378          /* Otherwise if only message, leave blank */
06379          keys[3] = 1;
06380       }
06381    }
06382 
06383    if (!ast_strlen_zero(cid)) {
06384       ast_callerid_parse(cid, &name, &num);
06385       if (!name)
06386          name = num;
06387    } else
06388       name = "Unknown Caller";
06389 
06390    /* If deleted, show "undeleted" */
06391 
06392    if (vms->deleted[vms->curmsg])
06393       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06394 
06395    /* Except "Exit" */
06396    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06397    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06398       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06399    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06400 
06401    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06402    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06403    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06404    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06405    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06406    bytes += ast_adsi_set_keys(buf + bytes, keys);
06407    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06408 
06409    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06410 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06267 {
06268    unsigned char buf[256];
06269    int bytes = 0;
06270    unsigned char keys[8];
06271    int x;
06272    if (!ast_adsi_available(chan))
06273       return;
06274 
06275    for (x = 0; x < 8; x++)
06276       keys[x] = 0;
06277    /* Set one key for next */
06278    keys[3] = ADSI_KEY_APPS + 3;
06279 
06280    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06281    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06282    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06283    bytes += ast_adsi_set_keys(buf + bytes, keys);
06284    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06285    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06286 }

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

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

06458 {
06459    unsigned char buf[256] = "";
06460    char buf1[256] = "", buf2[256] = "";
06461    int bytes = 0;
06462    unsigned char keys[8];
06463    int x;
06464 
06465    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06466    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06467    if (!ast_adsi_available(chan))
06468       return;
06469    if (vms->newmessages) {
06470       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06471       if (vms->oldmessages) {
06472          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06473          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06474       } else {
06475          snprintf(buf2, sizeof(buf2), "%s.", newm);
06476       }
06477    } else if (vms->oldmessages) {
06478       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06479       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06480    } else {
06481       strcpy(buf1, "You have no messages.");
06482       buf2[0] = ' ';
06483       buf2[1] = '\0';
06484    }
06485    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06486    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06487    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06488 
06489    for (x = 0; x < 6; x++)
06490       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06491    keys[6] = 0;
06492    keys[7] = 0;
06493 
06494    /* Don't let them listen if there are none */
06495    if (vms->lastmsg < 0)
06496       keys[0] = 1;
06497    bytes += ast_adsi_set_keys(buf + bytes, keys);
06498 
06499    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06500 
06501    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06502 }

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

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

06505 {
06506    unsigned char buf[256] = "";
06507    char buf1[256] = "", buf2[256] = "";
06508    int bytes = 0;
06509    unsigned char keys[8];
06510    int x;
06511 
06512    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06513 
06514    if (!ast_adsi_available(chan))
06515       return;
06516 
06517    /* Original command keys */
06518    for (x = 0; x < 6; x++)
06519       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06520 
06521    keys[6] = 0;
06522    keys[7] = 0;
06523 
06524    if ((vms->lastmsg + 1) < 1)
06525       keys[0] = 0;
06526 
06527    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06528       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06529 
06530    if (vms->lastmsg + 1)
06531       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06532    else
06533       strcpy(buf2, "no messages.");
06534    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06535    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06536    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06537    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06538    bytes += ast_adsi_set_keys(buf + bytes, keys);
06539 
06540    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06541 
06542    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06543    
06544 }

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

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

12764 {
12765    int res = 0;
12766    char filename[PATH_MAX];
12767    struct ast_config *msg_cfg = NULL;
12768    const char *origtime, *context;
12769    char *name, *num;
12770    int retries = 0;
12771    char *cid;
12772    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
12773 
12774    vms->starting = 0; 
12775 
12776    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12777 
12778    /* Retrieve info from VM attribute file */
12779    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
12780    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
12781    msg_cfg = ast_config_load(filename, config_flags);
12782    DISPOSE(vms->curdir, vms->curmsg);
12783    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
12784       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
12785       return 0;
12786    }
12787 
12788    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
12789       ast_config_destroy(msg_cfg);
12790       return 0;
12791    }
12792 
12793    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
12794 
12795    context = ast_variable_retrieve(msg_cfg, "message", "context");
12796    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
12797       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
12798    switch (option) {
12799    case 3: /* Play message envelope */
12800       if (!res)
12801          res = play_message_datetime(chan, vmu, origtime, filename);
12802       if (!res)
12803          res = play_message_callerid(chan, vms, cid, context, 0);
12804 
12805       res = 't';
12806       break;
12807 
12808    case 2:  /* Call back */
12809 
12810       if (ast_strlen_zero(cid))
12811          break;
12812 
12813       ast_callerid_parse(cid, &name, &num);
12814       while ((res > -1) && (res != 't')) {
12815          switch (res) {
12816          case '1':
12817             if (num) {
12818                /* Dial the CID number */
12819                res = dialout(chan, vmu, num, vmu->callback);
12820                if (res) {
12821                   ast_config_destroy(msg_cfg);
12822                   return 9;
12823                }
12824             } else {
12825                res = '2';
12826             }
12827             break;
12828 
12829          case '2':
12830             /* Want to enter a different number, can only do this if there's a dialout context for this user */
12831             if (!ast_strlen_zero(vmu->dialout)) {
12832                res = dialout(chan, vmu, NULL, vmu->dialout);
12833                if (res) {
12834                   ast_config_destroy(msg_cfg);
12835                   return 9;
12836                }
12837             } else {
12838                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
12839                res = ast_play_and_wait(chan, "vm-sorry");
12840             }
12841             ast_config_destroy(msg_cfg);
12842             return res;
12843          case '*':
12844             res = 't';
12845             break;
12846          case '3':
12847          case '4':
12848          case '5':
12849          case '6':
12850          case '7':
12851          case '8':
12852          case '9':
12853          case '0':
12854 
12855             res = ast_play_and_wait(chan, "vm-sorry");
12856             retries++;
12857             break;
12858          default:
12859             if (num) {
12860                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
12861                res = ast_play_and_wait(chan, "vm-num-i-have");
12862                if (!res)
12863                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
12864                if (!res)
12865                   res = ast_play_and_wait(chan, "vm-tocallnum");
12866                /* Only prompt for a caller-specified number if there is a dialout context specified */
12867                if (!ast_strlen_zero(vmu->dialout)) {
12868                   if (!res)
12869                      res = ast_play_and_wait(chan, "vm-calldiffnum");
12870                }
12871             } else {
12872                res = ast_play_and_wait(chan, "vm-nonumber");
12873                if (!ast_strlen_zero(vmu->dialout)) {
12874                   if (!res)
12875                      res = ast_play_and_wait(chan, "vm-toenternumber");
12876                }
12877             }
12878             if (!res)
12879                res = ast_play_and_wait(chan, "vm-star-cancel");
12880             if (!res)
12881                res = ast_waitfordigit(chan, 6000);
12882             if (!res) {
12883                retries++;
12884                if (retries > 3)
12885                   res = 't';
12886             }
12887             break; 
12888             
12889          }
12890          if (res == 't')
12891             res = 0;
12892          else if (res == '*')
12893             res = -1;
12894       }
12895       break;
12896       
12897    case 1:  /* Reply */
12898       /* Send reply directly to sender */
12899       if (ast_strlen_zero(cid))
12900          break;
12901 
12902       ast_callerid_parse(cid, &name, &num);
12903       if (!num) {
12904          ast_verb(3, "No CID number available, no reply sent\n");
12905          if (!res)
12906             res = ast_play_and_wait(chan, "vm-nonumber");
12907          ast_config_destroy(msg_cfg);
12908          return res;
12909       } else {
12910          struct ast_vm_user vmu2;
12911          if (find_user(&vmu2, vmu->context, num)) {
12912             struct leave_vm_options leave_options;
12913             char mailbox[AST_MAX_EXTENSION * 2 + 2];
12914             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
12915 
12916             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
12917             
12918             memset(&leave_options, 0, sizeof(leave_options));
12919             leave_options.record_gain = record_gain;
12920             res = leave_voicemail(chan, mailbox, &leave_options);
12921             if (!res)
12922                res = 't';
12923             ast_config_destroy(msg_cfg);
12924             return res;
12925          } else {
12926             /* Sender has no mailbox, can't reply */
12927             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
12928             ast_play_and_wait(chan, "vm-nobox");
12929             res = 't';
12930             ast_config_destroy(msg_cfg);
12931             return res;
12932          }
12933       } 
12934       res = 0;
12935 
12936       break;
12937    }
12938 
12939 #ifndef IMAP_STORAGE
12940    ast_config_destroy(msg_cfg);
12941 
12942    if (!res) {
12943       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12944       vms->heard[msg] = 1;
12945       res = wait_file(chan, vms, vms->fn);
12946    }
12947 #endif
12948    return res;
12949 }

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

Definition at line 10444 of file app_voicemail_odbcstorage.c.

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

10445 {
10446    /* Assumes lock is already held */
10447    char *tmp;
10448    char *stringp;
10449    char *s;
10450    struct ast_vm_user *vmu;
10451    char *mailbox_full;
10452    int new = 0, old = 0, urgent = 0;
10453    char secretfn[PATH_MAX] = "";
10454 
10455    tmp = ast_strdupa(data);
10456 
10457    if (!(vmu = find_or_create(context, box)))
10458       return -1;
10459 
10460    populate_defaults(vmu);
10461 
10462    stringp = tmp;
10463    if ((s = strsep(&stringp, ","))) {
10464       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10465    }
10466    if (stringp && (s = strsep(&stringp, ","))) {
10467       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10468    }
10469    if (stringp && (s = strsep(&stringp, ","))) {
10470       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10471    }
10472    if (stringp && (s = strsep(&stringp, ","))) {
10473       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10474    }
10475    if (stringp && (s = strsep(&stringp, ","))) {
10476       apply_options(vmu, s);
10477    }
10478 
10479    switch (vmu->passwordlocation) {
10480    case OPT_PWLOC_SPOOLDIR:
10481       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10482       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10483    }
10484 
10485    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10486    strcpy(mailbox_full, box);
10487    strcat(mailbox_full, "@");
10488    strcat(mailbox_full, context);
10489 
10490    inboxcount2(mailbox_full, &urgent, &new, &old);
10491    queue_mwi_event(mailbox_full, urgent, new, old);
10492 
10493    return 0;
10494 }

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

References apply_options(), ast_copy_string(), ast_log(), AST_LOG_WARNING, ast_set2_flag, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, 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, 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.

01010 {
01011    int x;
01012    if (!strcasecmp(var, "attach")) {
01013       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01014    } else if (!strcasecmp(var, "attachfmt")) {
01015       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01016    } else if (!strcasecmp(var, "serveremail")) {
01017       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01018    } else if (!strcasecmp(var, "language")) {
01019       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01020    } else if (!strcasecmp(var, "tz")) {
01021       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01022    } else if (!strcasecmp(var, "locale")) {
01023       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01024 #ifdef IMAP_STORAGE
01025    } else if (!strcasecmp(var, "imapuser")) {
01026       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01027       vmu->imapversion = imapversion;
01028    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01029       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01030       vmu->imapversion = imapversion;
01031    } else if (!strcasecmp(var, "imapfolder")) {
01032       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01033    } else if (!strcasecmp(var, "imapvmshareid")) {
01034       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01035       vmu->imapversion = imapversion;
01036 #endif
01037    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01038       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01039    } else if (!strcasecmp(var, "saycid")){
01040       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01041    } else if (!strcasecmp(var, "sendvoicemail")){
01042       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01043    } else if (!strcasecmp(var, "review")){
01044       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01045    } else if (!strcasecmp(var, "tempgreetwarn")){
01046       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01047    } else if (!strcasecmp(var, "messagewrap")){
01048       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01049    } else if (!strcasecmp(var, "operator")) {
01050       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01051    } else if (!strcasecmp(var, "envelope")){
01052       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01053    } else if (!strcasecmp(var, "moveheard")){
01054       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01055    } else if (!strcasecmp(var, "sayduration")){
01056       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01057    } else if (!strcasecmp(var, "saydurationm")){
01058       if (sscanf(value, "%30d", &x) == 1) {
01059          vmu->saydurationm = x;
01060       } else {
01061          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01062       }
01063    } else if (!strcasecmp(var, "forcename")){
01064       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01065    } else if (!strcasecmp(var, "forcegreetings")){
01066       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01067    } else if (!strcasecmp(var, "callback")) {
01068       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01069    } else if (!strcasecmp(var, "dialout")) {
01070       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01071    } else if (!strcasecmp(var, "exitcontext")) {
01072       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01073    } else if (!strcasecmp(var, "minsecs")) {
01074       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01075          vmu->minsecs = x;
01076       } else {
01077          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01078          vmu->minsecs = vmminsecs;
01079       }
01080    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01081       vmu->maxsecs = atoi(value);
01082       if (vmu->maxsecs <= 0) {
01083          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01084          vmu->maxsecs = vmmaxsecs;
01085       } else {
01086          vmu->maxsecs = atoi(value);
01087       }
01088       if (!strcasecmp(var, "maxmessage"))
01089          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01090    } else if (!strcasecmp(var, "maxmsg")) {
01091       vmu->maxmsg = atoi(value);
01092       /* Accept maxmsg=0 (Greetings only voicemail) */
01093       if (vmu->maxmsg < 0) {
01094          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01095          vmu->maxmsg = MAXMSG;
01096       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01097          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01098          vmu->maxmsg = MAXMSGLIMIT;
01099       }
01100    } else if (!strcasecmp(var, "nextaftercmd")) {
01101       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01102    } else if (!strcasecmp(var, "backupdeleted")) {
01103       if (sscanf(value, "%30d", &x) == 1)
01104          vmu->maxdeletedmsg = x;
01105       else if (ast_true(value))
01106          vmu->maxdeletedmsg = MAXMSG;
01107       else
01108          vmu->maxdeletedmsg = 0;
01109 
01110       if (vmu->maxdeletedmsg < 0) {
01111          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01112          vmu->maxdeletedmsg = MAXMSG;
01113       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01114          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01115          vmu->maxdeletedmsg = MAXMSGLIMIT;
01116       }
01117    } else if (!strcasecmp(var, "volgain")) {
01118       sscanf(value, "%30lf", &vmu->volgain);
01119    } else if (!strcasecmp(var, "passwordlocation")) {
01120       if (!strcasecmp(value, "spooldir")) {
01121          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01122       } else {
01123          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01124       }
01125    } else if (!strcasecmp(var, "options")) {
01126       apply_options(vmu, value);
01127    }
01128 }

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

Destructively Parse options and apply.

Definition at line 1242 of file app_voicemail_odbcstorage.c.

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

01243 {  
01244    char *stringp;
01245    char *s;
01246    char *var, *value;
01247    stringp = ast_strdupa(options);
01248    while ((s = strsep(&stringp, "|"))) {
01249       value = s;
01250       if ((var = strsep(&value, "=")) && value) {
01251          apply_option(vmu, var, value);
01252       }
01253    }  
01254 }

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

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

01262 {
01263    for (; var; var = var->next) {
01264       if (!strcasecmp(var->name, "vmsecret")) {
01265          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01266       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01267          if (ast_strlen_zero(retval->password))
01268             ast_copy_string(retval->password, var->value, sizeof(retval->password));
01269       } else if (!strcasecmp(var->name, "uniqueid")) {
01270          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01271       } else if (!strcasecmp(var->name, "pager")) {
01272          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01273       } else if (!strcasecmp(var->name, "email")) {
01274          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01275       } else if (!strcasecmp(var->name, "fullname")) {
01276          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01277       } else if (!strcasecmp(var->name, "context")) {
01278          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01279       } else if (!strcasecmp(var->name, "emailsubject")) {
01280          retval->emailsubject = ast_strdup(var->value);
01281       } else if (!strcasecmp(var->name, "emailbody")) {
01282          retval->emailbody = ast_strdup(var->value);
01283 #ifdef IMAP_STORAGE
01284       } else if (!strcasecmp(var->name, "imapuser")) {
01285          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01286          retval->imapversion = imapversion;
01287       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01288          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01289          retval->imapversion = imapversion;
01290       } else if (!strcasecmp(var->name, "imapfolder")) {
01291          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01292       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01293          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01294          retval->imapversion = imapversion;
01295 #endif
01296       } else
01297          apply_option(retval, var->name, var->value);
01298    }
01299 }

AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)

AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)

static const char* ast_str_encode_mime ( struct ast_str **  end,
ssize_t  maxlen,
const char *  start,
size_t  preamble,
size_t  postamble 
) [static]

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

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

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

Definition at line 4330 of file app_voicemail_odbcstorage.c.

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

04331 {
04332    struct ast_str *tmp = ast_str_alloca(80);
04333    int first_section = 1;
04334 
04335    ast_str_reset(*end);
04336    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04337    for (; *start; start++) {
04338       int need_encoding = 0;
04339       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04340          need_encoding = 1;
04341       }
04342       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04343          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04344          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04345          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04346          /* Start new line */
04347          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04348          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04349          first_section = 0;
04350       }
04351       if (need_encoding && *start == ' ') {
04352          ast_str_append(&tmp, -1, "_");
04353       } else if (need_encoding) {
04354          ast_str_append(&tmp, -1, "=%hhX", *start);
04355       } else {
04356          ast_str_append(&tmp, -1, "%c", *start);
04357       }
04358    }
04359    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04360    return ast_str_buffer(*end);
04361 }

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

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

04259 {
04260    const char *ptr;
04261 
04262    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04263    ast_str_set(buf, maxlen, "\"");
04264    for (ptr = from; *ptr; ptr++) {
04265       if (*ptr == '"' || *ptr == '\\') {
04266          ast_str_append(buf, maxlen, "\\%c", *ptr);
04267       } else {
04268          ast_str_append(buf, maxlen, "%c", *ptr);
04269       }
04270    }
04271    ast_str_append(buf, maxlen, "\"");
04272 
04273    return ast_str_buffer(*buf);
04274 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10496 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, free_user(), OPT_PWLOC_SPOOLDIR, TEST_EXECUTE, TEST_INIT, VM_ALLOCED, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, and VM_TEMPGREETWARN.

10497 {
10498    int res = 0;
10499    struct ast_vm_user *vmu;
10500    /* language parameter seems to only be used for display in manager action */
10501    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10502       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10503       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10504       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10505       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10506       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10507       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir";
10508 #ifdef IMAP_STORAGE
10509    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10510       "imapfolder=INBOX|imapvmshareid=6000";
10511 #endif
10512 
10513    switch (cmd) {
10514    case TEST_INIT:
10515       info->name = "vmuser";
10516       info->category = "/apps/app_voicemail/";
10517       info->summary = "Vmuser unit test";
10518       info->description =
10519          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10520       return AST_TEST_NOT_RUN;
10521    case TEST_EXECUTE:
10522       break;
10523    }
10524 
10525    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10526       return AST_TEST_NOT_RUN;
10527    }
10528    ast_set_flag(vmu, VM_ALLOCED);
10529 
10530    apply_options(vmu, options_string);
10531 
10532    if (!ast_test_flag(vmu, VM_ATTACH)) {
10533       ast_test_status_update(test, "Parse failure for attach option\n");
10534       res = 1;
10535    }
10536    if (strcasecmp(vmu->attachfmt, "wav49")) {
10537       ast_test_status_update(test, "Parse failure for attachftm option\n");
10538       res = 1;
10539    }
10540    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10541       ast_test_status_update(test, "Parse failure for serveremail option\n");
10542       res = 1;
10543    }
10544    if (strcasecmp(vmu->zonetag, "central")) {
10545       ast_test_status_update(test, "Parse failure for tz option\n");
10546       res = 1;
10547    }
10548    if (!ast_test_flag(vmu, VM_DELETE)) {
10549       ast_test_status_update(test, "Parse failure for delete option\n");
10550       res = 1;
10551    }
10552    if (!ast_test_flag(vmu, VM_SAYCID)) {
10553       ast_test_status_update(test, "Parse failure for saycid option\n");
10554       res = 1;
10555    }
10556    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10557       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10558       res = 1;
10559    }
10560    if (!ast_test_flag(vmu, VM_REVIEW)) {
10561       ast_test_status_update(test, "Parse failure for review option\n");
10562       res = 1;
10563    }
10564    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10565       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10566       res = 1;
10567    }
10568    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10569       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10570       res = 1;
10571    }
10572    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10573       ast_test_status_update(test, "Parse failure for operator option\n");
10574       res = 1;
10575    }
10576    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10577       ast_test_status_update(test, "Parse failure for envelope option\n");
10578       res = 1;
10579    }
10580    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10581       ast_test_status_update(test, "Parse failure for moveheard option\n");
10582       res = 1;
10583    }
10584    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10585       ast_test_status_update(test, "Parse failure for sayduration option\n");
10586       res = 1;
10587    }
10588    if (vmu->saydurationm != 5) {
10589       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10590       res = 1;
10591    }
10592    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10593       ast_test_status_update(test, "Parse failure for forcename option\n");
10594       res = 1;
10595    }
10596    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10597       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10598       res = 1;
10599    }
10600    if (strcasecmp(vmu->callback, "somecontext")) {
10601       ast_test_status_update(test, "Parse failure for callbacks option\n");
10602       res = 1;
10603    }
10604    if (strcasecmp(vmu->dialout, "somecontext2")) {
10605       ast_test_status_update(test, "Parse failure for dialout option\n");
10606       res = 1;
10607    }
10608    if (strcasecmp(vmu->exit, "somecontext3")) {
10609       ast_test_status_update(test, "Parse failure for exitcontext option\n");
10610       res = 1;
10611    }
10612    if (vmu->minsecs != 10) {
10613       ast_test_status_update(test, "Parse failure for minsecs option\n");
10614       res = 1;
10615    }
10616    if (vmu->maxsecs != 100) {
10617       ast_test_status_update(test, "Parse failure for maxsecs option\n");
10618       res = 1;
10619    }
10620    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10621       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10622       res = 1;
10623    }
10624    if (vmu->maxdeletedmsg != 50) {
10625       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10626       res = 1;
10627    }
10628    if (vmu->volgain != 1.3) {
10629       ast_test_status_update(test, "Parse failure for volgain option\n");
10630       res = 1;
10631    }
10632    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10633       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10634       res = 1;
10635    }
10636 #ifdef IMAP_STORAGE
10637    apply_options(vmu, option_string2);
10638 
10639    if (strcasecmp(vmu->imapuser, "imapuser")) {
10640       ast_test_status_update(test, "Parse failure for imapuser option\n");
10641       res = 1;
10642    }
10643    if (strcasecmp(vmu->imappassword, "imappasswd")) {
10644       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10645       res = 1;
10646    }
10647    if (strcasecmp(vmu->imapfolder, "INBOX")) {
10648       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10649       res = 1;
10650    }
10651    if (strcasecmp(vmu->imapvmshareid, "6000")) {
10652       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
10653       res = 1;
10654    }
10655 #endif
10656 
10657    free_user(vmu);
10658    return res ? AST_TEST_FAIL : AST_TEST_PASS;
10659 }

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

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

04135 {
04136    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04137       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04138       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04139       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04140    int i, hiteof = 0;
04141    FILE *fi;
04142    struct baseio bio;
04143 
04144    memset(&bio, 0, sizeof(bio));
04145    bio.iocp = BASEMAXINLINE;
04146 
04147    if (!(fi = fopen(filename, "rb"))) {
04148       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04149       return -1;
04150    }
04151 
04152    while (!hiteof){
04153       unsigned char igroup[3], ogroup[4];
04154       int c, n;
04155 
04156       memset(igroup, 0, sizeof(igroup));
04157 
04158       for (n = 0; n < 3; n++) {
04159          if ((c = inchar(&bio, fi)) == EOF) {
04160             hiteof = 1;
04161             break;
04162          }
04163 
04164          igroup[n] = (unsigned char) c;
04165       }
04166 
04167       if (n > 0) {
04168          ogroup[0]= dtable[igroup[0] >> 2];
04169          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04170          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04171          ogroup[3]= dtable[igroup[2] & 0x3F];
04172 
04173          if (n < 3) {
04174             ogroup[3] = '=';
04175 
04176             if (n < 2)
04177                ogroup[2] = '=';
04178          }
04179 
04180          for (i = 0; i < 4; i++)
04181             ochar(&bio, ogroup[i], so);
04182       }
04183    }
04184 
04185    fclose(fi);
04186    
04187    if (fputs(ENDL, so) == EOF) {
04188       return 0;
04189    }
04190 
04191    return 1;
04192 }

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

References ast_copy_string(), ast_realtime_require_field(), ast_update2_realtime(), ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, RQ_CHAR, and SENTINEL.

01222 {
01223    int res = -1;
01224    if (!strcmp(vmu->password, password)) {
01225       /* No change (but an update would return 0 rows updated, so we opt out here) */
01226       return 0;
01227    }
01228 
01229    if (strlen(password) > 10) {
01230       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01231    }
01232    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01233       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01234       res = 0;
01235    }
01236    return res;
01237 }

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

04304 {
04305    for (; *str; str++) {
04306       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04307          return 1;
04308       }
04309    }
04310    return 0;
04311 }

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

01184 {
01185    /* check minimum length */
01186    if (strlen(password) < minpassword)
01187       return 1;
01188    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01189       char cmd[255], buf[255];
01190 
01191       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01192 
01193       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01194       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01195          ast_debug(5, "Result: %s\n", buf);
01196          if (!strncasecmp(buf, "VALID", 5)) {
01197             ast_debug(3, "Passed password check: '%s'\n", buf);
01198             return 0;
01199          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01200             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01201             return 0;
01202          } else {
01203             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01204             return 1;
01205          }
01206       }
01207    }
01208    return 0;
01209 }

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

Definition at line 7722 of file app_voicemail_odbcstorage.c.

References ast_check_realtime(), ast_log(), ast_test_flag, ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, DELETE, vm_state::deleted, ERROR_LOCK_PATH, EXISTS, vm_state::fn, vm_state::heard, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

07723 {
07724    int x = 0;
07725 #ifndef IMAP_STORAGE
07726    int res = 0, nummsg;
07727    char fn2[PATH_MAX];
07728 #endif
07729 
07730    if (vms->lastmsg <= -1) {
07731       goto done;
07732    }
07733 
07734    vms->curmsg = -1;
07735 #ifndef IMAP_STORAGE
07736    /* Get the deleted messages fixed */
07737    if (vm_lock_path(vms->curdir)) {
07738       return ERROR_LOCK_PATH;
07739    }
07740 
07741    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07742    for (x = 0; x < vms->lastmsg + 1; x++) {
07743       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07744          /* Save this message.  It's not in INBOX or hasn't been heard */
07745          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07746          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07747             break;
07748          }
07749          vms->curmsg++;
07750          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07751          if (strcmp(vms->fn, fn2)) {
07752             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07753          }
07754       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07755          /* Move to old folder before deleting */
07756          res = save_to_folder(vmu, vms, x, 1);
07757          if (res == ERROR_LOCK_PATH) {
07758             /* If save failed do not delete the message */
07759             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07760             vms->deleted[x] = 0;
07761             vms->heard[x] = 0;
07762             --x;
07763          }
07764       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07765          /* Move to deleted folder */
07766          res = save_to_folder(vmu, vms, x, 10);
07767          if (res == ERROR_LOCK_PATH) {
07768             /* If save failed do not delete the message */
07769             vms->deleted[x] = 0;
07770             vms->heard[x] = 0;
07771             --x;
07772          }
07773       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07774          /* If realtime storage enabled - we should explicitly delete this message,
07775          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07776          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07777          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07778             DELETE(vms->curdir, x, vms->fn, vmu);
07779          }
07780       }
07781    }
07782 
07783    /* Delete ALL remaining messages */
07784    nummsg = x - 1;
07785    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07786       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07787       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07788          DELETE(vms->curdir, x, vms->fn, vmu);
07789       }
07790    }
07791    ast_unlock_path(vms->curdir);
07792 #else /* defined(IMAP_STORAGE) */
07793    if (vms->deleted) {
07794       /* Since we now expunge after each delete, deleting in reverse order
07795        * ensures that no reordering occurs between each step. */
07796       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
07797          if (vms->deleted[x]) {
07798             ast_debug(3, "IMAP delete of %d\n", x);
07799             DELETE(vms->curdir, x, vms->fn, vmu);
07800          }
07801       }
07802    }
07803 #endif
07804 
07805 done:
07806    if (vms->deleted && vmu->maxmsg) {
07807       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
07808    }
07809    if (vms->heard && vmu->maxmsg) {
07810       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
07811    }
07812 
07813    return 0;
07814 }

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

Definition at line 10805 of file app_voicemail_odbcstorage.c.

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

10806 {
10807    int which = 0;
10808    int wordlen;
10809    struct ast_vm_user *vmu;
10810    const char *context = "";
10811 
10812    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
10813    if (pos > 4)
10814       return NULL;
10815    if (pos == 3)
10816       return (state == 0) ? ast_strdup("for") : NULL;
10817    wordlen = strlen(word);
10818    AST_LIST_TRAVERSE(&users, vmu, list) {
10819       if (!strncasecmp(word, vmu->context, wordlen)) {
10820          if (context && strcmp(context, vmu->context) && ++which > state)
10821             return ast_strdup(vmu->context);
10822          /* ignore repeated contexts ? */
10823          context = vmu->context;
10824       }
10825    }
10826    return NULL;
10827 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

03939 {
03940    int ifd;
03941    int ofd;
03942    int res;
03943    int len;
03944    char buf[4096];
03945 
03946 #ifdef HARDLINK_WHEN_POSSIBLE
03947    /* Hard link if possible; saves disk space & is faster */
03948    if (link(infile, outfile)) {
03949 #endif
03950       if ((ifd = open(infile, O_RDONLY)) < 0) {
03951          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03952          return -1;
03953       }
03954       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03955          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03956          close(ifd);
03957          return -1;
03958       }
03959       do {
03960          len = read(ifd, buf, sizeof(buf));
03961          if (len < 0) {
03962             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03963             close(ifd);
03964             close(ofd);
03965             unlink(outfile);
03966          }
03967          if (len) {
03968             res = write(ofd, buf, len);
03969             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03970                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03971                close(ifd);
03972                close(ofd);
03973                unlink(outfile);
03974             }
03975          }
03976       } while (len);
03977       close(ifd);
03978       close(ofd);
03979       return 0;
03980 #ifdef HARDLINK_WHEN_POSSIBLE
03981    } else {
03982       /* Hard link succeeded */
03983       return 0;
03984    }
03985 #endif
03986 }

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

05175 {
05176    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05177    const char *frombox = mbox(vmu, imbox);
05178    int recipmsgnum;
05179    int res = 0;
05180 
05181    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05182 
05183    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05184       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
05185    } else {
05186       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
05187    }
05188    
05189    if (!dir)
05190       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05191    else
05192       ast_copy_string(fromdir, dir, sizeof(fromdir));
05193 
05194    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05195    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
05196 
05197    if (vm_lock_path(todir))
05198       return ERROR_LOCK_PATH;
05199 
05200    recipmsgnum = last_message_index(recip, todir) + 1;
05201    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05202       make_file(topath, sizeof(topath), todir, recipmsgnum);
05203 #ifndef ODBC_STORAGE
05204       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05205          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05206       } else {
05207 #endif
05208          /* If we are prepending a message for ODBC, then the message already
05209           * exists in the database, but we want to force copying from the
05210           * filesystem (since only the FS contains the prepend). */
05211          copy_plain_file(frompath, topath);
05212          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05213          vm_delete(topath);
05214 #ifndef ODBC_STORAGE
05215       }
05216 #endif
05217    } else {
05218       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05219       res = -1;
05220    }
05221    ast_unlock_path(todir);
05222    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05223       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05224       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05225       flag);
05226    
05227    return res;
05228 }

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

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

03998 {
03999    char frompath2[PATH_MAX], topath2[PATH_MAX];
04000    struct ast_variable *tmp,*var = NULL;
04001    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04002    ast_filecopy(frompath, topath, NULL);
04003    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04004    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04005    if (ast_check_realtime("voicemail_data")) {
04006       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04007       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04008       for (tmp = var; tmp; tmp = tmp->next) {
04009          if (!strcasecmp(tmp->name, "origmailbox")) {
04010             origmailbox = tmp->value;
04011          } else if (!strcasecmp(tmp->name, "context")) {
04012             context = tmp->value;
04013          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04014             macrocontext = tmp->value;
04015          } else if (!strcasecmp(tmp->name, "exten")) {
04016             exten = tmp->value;
04017          } else if (!strcasecmp(tmp->name, "priority")) {
04018             priority = tmp->value;
04019          } else if (!strcasecmp(tmp->name, "callerchan")) {
04020             callerchan = tmp->value;
04021          } else if (!strcasecmp(tmp->name, "callerid")) {
04022             callerid = tmp->value;
04023          } else if (!strcasecmp(tmp->name, "origdate")) {
04024             origdate = tmp->value;
04025          } else if (!strcasecmp(tmp->name, "origtime")) {
04026             origtime = tmp->value;
04027          } else if (!strcasecmp(tmp->name, "category")) {
04028             category = tmp->value;
04029          } else if (!strcasecmp(tmp->name, "duration")) {
04030             duration = tmp->value;
04031          }
04032       }
04033       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);
04034    }
04035    copy(frompath2, topath2);
04036    ast_variables_destroy(var);
04037 }

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

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

03842 {
03843 
03844    int vmcount = 0;
03845    DIR *vmdir = NULL;
03846    struct dirent *vment = NULL;
03847 
03848    if (vm_lock_path(dir))
03849       return ERROR_LOCK_PATH;
03850 
03851    if ((vmdir = opendir(dir))) {
03852       while ((vment = readdir(vmdir))) {
03853          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03854             vmcount++;
03855          }
03856       }
03857       closedir(vmdir);
03858    }
03859    ast_unlock_path(dir);
03860    
03861    return vmcount;
03862 }

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

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

01610 {
01611    mode_t   mode = VOICEMAIL_DIR_MODE;
01612    int res;
01613 
01614    make_dir(dest, len, context, ext, folder);
01615    if ((res = ast_mkdir(dest, mode))) {
01616       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01617       return -1;
01618    }
01619    return 0;
01620 }

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

Definition at line 12691 of file app_voicemail_odbcstorage.c.

References ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_verb, ast_verbose, ast_waitfordigit(), ast_channel::context, ast_channel::exten, option_verbose, ast_channel::priority, and VERBOSE_PREFIX_3.

12692 {
12693    int cmd = 0;
12694    char destination[80] = "";
12695    int retries = 0;
12696 
12697    if (!num) {
12698       ast_verb(3, "Destination number will be entered manually\n");
12699       while (retries < 3 && cmd != 't') {
12700          destination[1] = '\0';
12701          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
12702          if (!cmd)
12703             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
12704          if (!cmd)
12705             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
12706          if (!cmd) {
12707             cmd = ast_waitfordigit(chan, 6000);
12708             if (cmd)
12709                destination[0] = cmd;
12710          }
12711          if (!cmd) {
12712             retries++;
12713          } else {
12714 
12715             if (cmd < 0)
12716                return 0;
12717             if (cmd == '*') {
12718                ast_verb(3, "User hit '*' to cancel outgoing call\n");
12719                return 0;
12720             }
12721             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
12722                retries++;
12723             else
12724                cmd = 't';
12725          }
12726       }
12727       if (retries >= 3) {
12728          return 0;
12729       }
12730       
12731    } else {
12732       if (option_verbose > 2)
12733          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
12734       ast_copy_string(destination, num, sizeof(destination));
12735    }
12736 
12737    if (!ast_strlen_zero(destination)) {
12738       if (destination[strlen(destination) -1 ] == '*')
12739          return 0; 
12740       if (option_verbose > 2)
12741          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
12742       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
12743       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
12744       chan->priority = 0;
12745       return 9;
12746    }
12747    return 0;
12748 }

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

Definition at line 10412 of file app_voicemail_odbcstorage.c.

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

10413 {
10414    struct ast_vm_user *vmu;
10415 
10416    AST_LIST_TRAVERSE(&users, vmu, list) {
10417       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10418          if (strcasecmp(vmu->context, context)) {
10419             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10420                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10421                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10422                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10423          }
10424          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10425          return NULL;
10426       }
10427       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10428          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10429          return NULL;
10430       }
10431    }
10432    
10433    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10434       return NULL;
10435    
10436    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10437    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10438 
10439    AST_LIST_INSERT_TAIL(&users, vmu, list);
10440    
10441    return vmu;
10442 }

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

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

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

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

01371 {
01372    /* This function could be made to generate one from a database, too */
01373    struct ast_vm_user *vmu = NULL, *cur;
01374    AST_LIST_LOCK(&users);
01375 
01376    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01377       context = "default";
01378 
01379    AST_LIST_TRAVERSE(&users, cur, list) {
01380 #ifdef IMAP_STORAGE
01381       if (cur->imapversion != imapversion) {
01382          continue;
01383       }
01384 #endif
01385       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01386          break;
01387       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01388          break;
01389    }
01390    if (cur) {
01391       /* Make a copy, so that on a reload, we have no race */
01392       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01393          memcpy(vmu, cur, sizeof(*vmu));
01394          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01395          AST_LIST_NEXT(vmu, list) = NULL;
01396       }
01397    } else
01398       vmu = find_user_realtime(ivm, context, mailbox);
01399    AST_LIST_UNLOCK(&users);
01400    return vmu;
01401 }

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

Finds a voicemail user from the realtime engine.

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

Definition at line 1333 of file app_voicemail_odbcstorage.c.

References apply_options_full(), ast_calloc, ast_copy_string(), ast_free, ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), globalflags, populate_defaults(), SENTINEL, var, VM_ALLOCED, and VM_SEARCH.

01334 {
01335    struct ast_variable *var;
01336    struct ast_vm_user *retval;
01337 
01338    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01339       if (!ivm)
01340          ast_set_flag(retval, VM_ALLOCED);   
01341       else
01342          memset(retval, 0, sizeof(*retval));
01343       if (mailbox) 
01344          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01345       populate_defaults(retval);
01346       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01347          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01348       else
01349          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01350       if (var) {
01351          apply_options_full(retval, var);
01352          ast_variables_destroy(var);
01353       } else { 
01354          if (!ivm) 
01355             ast_free(retval);
01356          retval = NULL;
01357       }  
01358    } 
01359    return retval;
01360 }

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

Sends a voicemail message to a mailbox recipient.

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

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

Returns:
zero on success, -1 on error.

Definition at line 6939 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_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_waitfordigit(), ast_channel::caller, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), free_user(), globalflags, ast_party_caller::id, inboxcount(), inprocess_count(), ast_channel::language, leave_voicemail(), ast_app::list, LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), STORE, ast_party_name::str, ast_party_number::str, strsep(), vm_state::username, ast_party_name::valid, ast_party_number::valid, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

06940 {
06941 #ifdef IMAP_STORAGE
06942    int todircount = 0;
06943    struct vm_state *dstvms;
06944 #endif
06945    char username[70]="";
06946    char fn[PATH_MAX]; /* for playback of name greeting */
06947    char ecodes[16] = "#";
06948    int res = 0, cmd = 0;
06949    struct ast_vm_user *receiver = NULL, *vmtmp;
06950    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06951    char *stringp;
06952    const char *s;
06953    int saved_messages = 0;
06954    int valid_extensions = 0;
06955    char *dir;
06956    int curmsg;
06957    char urgent_str[7] = "";
06958    char tmptxtfile[PATH_MAX];
06959    int prompt_played = 0;
06960 #ifndef IMAP_STORAGE
06961    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06962 #endif
06963    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
06964       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
06965    }
06966 
06967    if (vms == NULL) return -1;
06968    dir = vms->curdir;
06969    curmsg = vms->curmsg;
06970 
06971    tmptxtfile[0] = '\0';
06972    while (!res && !valid_extensions) {
06973       int use_directory = 0;
06974       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
06975          int done = 0;
06976          int retries = 0;
06977          cmd = 0;
06978          while ((cmd >= 0) && !done ){
06979             if (cmd)
06980                retries = 0;
06981             switch (cmd) {
06982             case '1': 
06983                use_directory = 0;
06984                done = 1;
06985                break;
06986             case '2': 
06987                use_directory = 1;
06988                done = 1;
06989                break;
06990             case '*': 
06991                cmd = 't';
06992                done = 1;
06993                break;
06994             default: 
06995                /* Press 1 to enter an extension press 2 to use the directory */
06996                cmd = ast_play_and_wait(chan, "vm-forward");
06997                if (!cmd)
06998                   cmd = ast_waitfordigit(chan, 3000);
06999                if (!cmd)
07000                   retries++;
07001                if (retries > 3) {
07002                   cmd = 't';
07003                   done = 1;
07004                }
07005                
07006             }
07007          }
07008          if (cmd < 0 || cmd == 't')
07009             break;
07010       }
07011       
07012       if (use_directory) {
07013          /* use app_directory */
07014          
07015          char old_context[sizeof(chan->context)];
07016          char old_exten[sizeof(chan->exten)];
07017          int old_priority;
07018          struct ast_app* directory_app;
07019 
07020          directory_app = pbx_findapp("Directory");
07021          if (directory_app) {
07022             char vmcontext[256];
07023             /* make backup copies */
07024             memcpy(old_context, chan->context, sizeof(chan->context));
07025             memcpy(old_exten, chan->exten, sizeof(chan->exten));
07026             old_priority = chan->priority;
07027             
07028             /* call the the Directory, changes the channel */
07029             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
07030             res = pbx_exec(chan, directory_app, vmcontext);
07031             
07032             ast_copy_string(username, chan->exten, sizeof(username));
07033             
07034             /* restore the old context, exten, and priority */
07035             memcpy(chan->context, old_context, sizeof(chan->context));
07036             memcpy(chan->exten, old_exten, sizeof(chan->exten));
07037             chan->priority = old_priority;
07038          } else {
07039             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
07040             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
07041          }
07042       } else {
07043          /* Ask for an extension */
07044          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
07045          prompt_played++;
07046          if (res || prompt_played > 4)
07047             break;
07048          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
07049             break;
07050       }
07051       
07052       /* start all over if no username */
07053       if (ast_strlen_zero(username))
07054          continue;
07055       stringp = username;
07056       s = strsep(&stringp, "*");
07057       /* start optimistic */
07058       valid_extensions = 1;
07059       while (s) {
07060          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
07061             int oldmsgs;
07062             int newmsgs;
07063             int capacity;
07064             if (inboxcount(s, &newmsgs, &oldmsgs)) {
07065                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
07066                /* Shouldn't happen, but allow trying another extension if it does */
07067                res = ast_play_and_wait(chan, "pbx-invalid");
07068                valid_extensions = 0;
07069                break;
07070             }
07071             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
07072             if ((newmsgs + oldmsgs) >= capacity) {
07073                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
07074                res = ast_play_and_wait(chan, "vm-mailboxfull");
07075                valid_extensions = 0;
07076                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07077                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07078                   free_user(vmtmp);
07079                }
07080                inprocess_count(receiver->mailbox, receiver->context, -1);
07081                break;
07082             }
07083             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
07084          } else {
07085             /* XXX Optimization for the future.  When we encounter a single bad extension,
07086              * bailing out on all of the extensions may not be the way to go.  We should
07087              * probably just bail on that single extension, then allow the user to enter
07088              * several more. XXX
07089              */
07090             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07091                free_user(receiver);
07092             }
07093             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
07094             /* "I am sorry, that's not a valid extension.  Please try again." */
07095             res = ast_play_and_wait(chan, "pbx-invalid");
07096             valid_extensions = 0;
07097             break;
07098          }
07099 
07100          /* play name if available, else play extension number */
07101          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
07102          RETRIEVE(fn, -1, s, receiver->context);
07103          if (ast_fileexists(fn, NULL, NULL) > 0) {
07104             res = ast_stream_and_wait(chan, fn, ecodes);
07105             if (res) {
07106                DISPOSE(fn, -1);
07107                return res;
07108             }
07109          } else {
07110             res = ast_say_digit_str(chan, s, ecodes, chan->language);
07111          }
07112          DISPOSE(fn, -1);
07113 
07114          s = strsep(&stringp, "*");
07115       }
07116       /* break from the loop of reading the extensions */
07117       if (valid_extensions)
07118          break;
07119    }
07120    /* check if we're clear to proceed */
07121    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
07122       return res;
07123    if (is_new_message == 1) {
07124       struct leave_vm_options leave_options;
07125       char mailbox[AST_MAX_EXTENSION * 2 + 2];
07126       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
07127 
07128       /* Send VoiceMail */
07129       memset(&leave_options, 0, sizeof(leave_options));
07130       leave_options.record_gain = record_gain;
07131       cmd = leave_voicemail(chan, mailbox, &leave_options);
07132    } else {
07133       /* Forward VoiceMail */
07134       long duration = 0;
07135       struct vm_state vmstmp;
07136       int copy_msg_result = 0;
07137       memcpy(&vmstmp, vms, sizeof(vmstmp));
07138 
07139       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
07140 
07141       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
07142       if (!cmd) {
07143          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
07144 #ifdef IMAP_STORAGE
07145             int attach_user_voicemail;
07146             char *myserveremail = serveremail;
07147             
07148             /* get destination mailbox */
07149             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
07150             if (!dstvms) {
07151                dstvms = create_vm_state_from_user(vmtmp);
07152             }
07153             if (dstvms) {
07154                init_mailstream(dstvms, 0);
07155                if (!dstvms->mailstream) {
07156                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
07157                } else {
07158                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
07159                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
07160                }
07161             } else {
07162                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
07163             }
07164             if (!ast_strlen_zero(vmtmp->serveremail))
07165                myserveremail = vmtmp->serveremail;
07166             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
07167             /* NULL category for IMAP storage */
07168             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
07169                dstvms->curbox,
07170                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
07171                S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
07172                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
07173                NULL, urgent_str);
07174 #else
07175             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
07176 #endif
07177             saved_messages++;
07178             AST_LIST_REMOVE_CURRENT(list);
07179             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07180             free_user(vmtmp);
07181             if (res)
07182                break;
07183          }
07184          AST_LIST_TRAVERSE_SAFE_END;
07185          if (saved_messages > 0 && !copy_msg_result) {
07186             /* give confirmation that the message was saved */
07187             /* commented out since we can't forward batches yet
07188             if (saved_messages == 1)
07189                res = ast_play_and_wait(chan, "vm-message");
07190             else
07191                res = ast_play_and_wait(chan, "vm-messages");
07192             if (!res)
07193                res = ast_play_and_wait(chan, "vm-saved"); */
07194 #ifdef IMAP_STORAGE
07195             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
07196             if (ast_strlen_zero(vmstmp.introfn))
07197 #endif
07198             res = ast_play_and_wait(chan, "vm-msgsaved");
07199          }
07200 #ifndef IMAP_STORAGE
07201          else {
07202             /* with IMAP, mailbox full warning played by imap_check_limits */
07203             res = ast_play_and_wait(chan, "vm-mailboxfull");
07204          }
07205          /* Restore original message without prepended message if backup exists */
07206          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07207          strcpy(textfile, msgfile);
07208          strcpy(backup, msgfile);
07209          strcpy(backup_textfile, msgfile);
07210          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07211          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
07212          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07213          if (ast_fileexists(backup, NULL, NULL) > 0) {
07214             ast_filerename(backup, msgfile, NULL);
07215             rename(backup_textfile, textfile);
07216          }
07217 #endif
07218       }
07219       DISPOSE(dir, curmsg);
07220 #ifndef IMAP_STORAGE
07221       if (cmd) { /* assuming hangup, cleanup backup file */
07222          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07223          strcpy(textfile, msgfile);
07224          strcpy(backup_textfile, msgfile);
07225          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07226          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07227          rename(backup_textfile, textfile);
07228       }
07229 #endif
07230    }
07231 
07232    /* If anything failed above, we still have this list to free */
07233    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07234       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07235       free_user(vmtmp);
07236    }
07237    return res ? res : cmd;
07238 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1664 of file app_voicemail_odbcstorage.c.

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

01665 {
01666    if (ast_test_flag(vmu, VM_ALLOCED)) {
01667       if (vmu->emailbody != NULL) {
01668          ast_free(vmu->emailbody);
01669          vmu->emailbody = NULL;
01670       }
01671       if (vmu->emailsubject != NULL) {
01672          ast_free(vmu->emailsubject);
01673          vmu->emailsubject = NULL;
01674       }
01675       ast_free(vmu);
01676    }
01677 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11404 of file app_voicemail_odbcstorage.c.

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

11405 {
11406    struct ast_vm_user *current;
11407    AST_LIST_LOCK(&users);
11408    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11409       ast_set_flag(current, VM_ALLOCED);
11410       free_user(current);
11411    }
11412    AST_LIST_UNLOCK(&users);
11413 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11416 of file app_voicemail_odbcstorage.c.

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

11417 {
11418    struct vm_zone *zcur;
11419    AST_LIST_LOCK(&zones);
11420    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11421       free_zone(zcur);
11422    AST_LIST_UNLOCK(&zones);
11423 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4941 of file app_voicemail_odbcstorage.c.

References ast_free.

04942 {
04943    ast_free(z);
04944 }

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

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

04898 {
04899    struct ast_tm tm;
04900    struct timeval t = ast_tvnow();
04901    
04902    ast_localtime(&t, &tm, "UTC");
04903 
04904    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04905 }

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

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_waitfordigit(), ast_channel::language, mbox(), and vm_play_folder_name().

06581 {
06582    int x;
06583    int d;
06584    char fn[PATH_MAX];
06585    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06586    if (d)
06587       return d;
06588    for (x = start; x < 5; x++) { /* For all folders */
06589       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06590          return d;
06591       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06592       if (d)
06593          return d;
06594       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06595       d = vm_play_folder_name(chan, fn);
06596       if (d)
06597          return d;
06598       d = ast_waitfordigit(chan, 500);
06599       if (d)
06600          return d;
06601    }
06602    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06603    if (d)
06604       return d;
06605    d = ast_waitfordigit(chan, 4000);
06606    return d;
06607 }

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

References ast_play_and_wait(), and get_folder().

06622 {
06623    int res = 0;
06624    int loops = 0;
06625    res = ast_play_and_wait(chan, fn);  /* Folder name */
06626    while (((res < '0') || (res > '9')) &&
06627          (res != '#') && (res >= 0) &&
06628          loops < 4) {
06629       res = get_folder(chan, 0);
06630       loops++;
06631    }
06632    if (loops == 4) { /* give up */
06633       return '#';
06634    }
06635    return res;
06636 }

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

Definition at line 1651 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

01652 {
01653    size_t i;
01654 
01655    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01656       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01657          return i;
01658       }
01659    }
01660 
01661    return -1;
01662 }

static int handle_subscribe ( void *  datap  )  [static]

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

11188 {
11189    unsigned int len;
11190    struct mwi_sub *mwi_sub;
11191    struct mwi_sub_task *p = datap;
11192 
11193    len = sizeof(*mwi_sub);
11194    if (!ast_strlen_zero(p->mailbox))
11195       len += strlen(p->mailbox);
11196 
11197    if (!ast_strlen_zero(p->context))
11198       len += strlen(p->context) + 1; /* Allow for seperator */
11199 
11200    if (!(mwi_sub = ast_calloc(1, len)))
11201       return -1;
11202 
11203    mwi_sub->uniqueid = p->uniqueid;
11204    if (!ast_strlen_zero(p->mailbox))
11205       strcpy(mwi_sub->mailbox, p->mailbox);
11206 
11207    if (!ast_strlen_zero(p->context)) {
11208       strcat(mwi_sub->mailbox, "@");
11209       strcat(mwi_sub->mailbox, p->context);
11210    }
11211 
11212    AST_RWLIST_WRLOCK(&mwi_subs);
11213    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11214    AST_RWLIST_UNLOCK(&mwi_subs);
11215    ast_free((void *) p->mailbox);
11216    ast_free((void *) p->context);
11217    ast_free(p);
11218    poll_subscribed_mailbox(mwi_sub);
11219    return 0;
11220 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11165 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, mwi_sub::entry, mwi_sub, mwi_sub_destroy(), ast_event_sub::uniqueid, and mwi_sub::uniqueid.

11166 {
11167    struct mwi_sub *mwi_sub;
11168    uint32_t *uniqueid = datap;
11169    
11170    AST_RWLIST_WRLOCK(&mwi_subs);
11171    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11172       if (mwi_sub->uniqueid == *uniqueid) {
11173          AST_LIST_REMOVE_CURRENT(entry);
11174          break;
11175       }
11176    }
11177    AST_RWLIST_TRAVERSE_SAFE_END
11178    AST_RWLIST_UNLOCK(&mwi_subs);
11179 
11180    if (mwi_sub)
11181       mwi_sub_destroy(mwi_sub);
11182 
11183    ast_free(uniqueid);  
11184    return 0;
11185 }

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

10941 {
10942    switch (cmd) {
10943    case CLI_INIT:
10944       e->command = "voicemail reload";
10945       e->usage =
10946          "Usage: voicemail reload\n"
10947          "       Reload voicemail configuration\n";
10948       return NULL;
10949    case CLI_GENERATE:
10950       return NULL;
10951    }
10952 
10953    if (a->argc != 2)
10954       return CLI_SHOWUSAGE;
10955 
10956    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
10957    load_config(1);
10958    
10959    return CLI_SUCCESS;
10960 }

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 10830 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::list, ast_vm_user::mailbox, ast_cli_args::n, ast_cli_args::pos, show_users_realtime(), ast_cli_entry::usage, ast_cli_args::word, and ast_vm_user::zonetag.

10831 {
10832    struct ast_vm_user *vmu;
10833 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
10834    const char *context = NULL;
10835    int users_counter = 0;
10836 
10837    switch (cmd) {
10838    case CLI_INIT:
10839       e->command = "voicemail show users";
10840       e->usage =
10841          "Usage: voicemail show users [for <context>]\n"
10842          "       Lists all mailboxes currently set up\n";
10843       return NULL;
10844    case CLI_GENERATE:
10845       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10846    }  
10847 
10848    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10849       return CLI_SHOWUSAGE;
10850    if (a->argc == 5) {
10851       if (strcmp(a->argv[3],"for"))
10852          return CLI_SHOWUSAGE;
10853       context = a->argv[4];
10854    }
10855 
10856    if (ast_check_realtime("voicemail")) {
10857       if (!context) {
10858          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10859          return CLI_SHOWUSAGE;
10860       }
10861       return show_users_realtime(a->fd, context);
10862    }
10863 
10864    AST_LIST_LOCK(&users);
10865    if (AST_LIST_EMPTY(&users)) {
10866       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10867       AST_LIST_UNLOCK(&users);
10868       return CLI_FAILURE;
10869    }
10870    if (a->argc == 3)
10871       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10872    else {
10873       int count = 0;
10874       AST_LIST_TRAVERSE(&users, vmu, list) {
10875          if (!strcmp(context, vmu->context))
10876             count++;
10877       }
10878       if (count) {
10879          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10880       } else {
10881          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10882          AST_LIST_UNLOCK(&users);
10883          return CLI_FAILURE;
10884       }
10885    }
10886    AST_LIST_TRAVERSE(&users, vmu, list) {
10887       int newmsgs = 0, oldmsgs = 0;
10888       char count[12], tmp[256] = "";
10889 
10890       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10891          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10892          inboxcount(tmp, &newmsgs, &oldmsgs);
10893          snprintf(count, sizeof(count), "%d", newmsgs);
10894          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10895          users_counter++;
10896       }
10897    }
10898    AST_LIST_UNLOCK(&users);
10899    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10900    return CLI_SUCCESS;
10901 }

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 10904 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, vm_zone::list, vm_zone::msg_format, vm_zone::name, vm_zone::timezone, and ast_cli_entry::usage.

10905 {
10906    struct vm_zone *zone;
10907 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10908    char *res = CLI_SUCCESS;
10909 
10910    switch (cmd) {
10911    case CLI_INIT:
10912       e->command = "voicemail show zones";
10913       e->usage =
10914          "Usage: voicemail show zones\n"
10915          "       Lists zone message formats\n";
10916       return NULL;
10917    case CLI_GENERATE:
10918       return NULL;
10919    }
10920 
10921    if (a->argc != 3)
10922       return CLI_SHOWUSAGE;
10923 
10924    AST_LIST_LOCK(&zones);
10925    if (!AST_LIST_EMPTY(&zones)) {
10926       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10927       AST_LIST_TRAVERSE(&zones, zone, list) {
10928          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10929       }
10930    } else {
10931       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10932       res = CLI_FAILURE;
10933    }
10934    AST_LIST_UNLOCK(&zones);
10935 
10936    return res;
10937 }

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

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

05284 {
05285    char tmp[256], *tmp2 = tmp, *box, *context;
05286    ast_copy_string(tmp, mailbox, sizeof(tmp));
05287    if (ast_strlen_zero(folder)) {
05288       folder = "INBOX";
05289    }
05290    while ((box = strsep(&tmp2, ",&"))) {
05291       if ((context = strchr(box, '@')))
05292          *context++ = '\0';
05293       else
05294          context = "default";
05295       if (__has_voicemail(context, box, folder, 1))
05296          return 1;
05297       /* If we are checking INBOX, we should check Urgent as well */
05298       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05299          return 1;
05300       }
05301    }
05302    return 0;
05303 }

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

Definition at line 5365 of file app_voicemail_odbcstorage.c.

References inboxcount2().

05366 {
05367    int urgentmsgs = 0;
05368    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05369    if (newmsgs) {
05370       *newmsgs += urgentmsgs;
05371    }
05372    return res;
05373 }

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

Definition at line 5306 of file app_voicemail_odbcstorage.c.

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

05307 {
05308    char tmp[256];
05309    char *context;
05310 
05311    /* If no mailbox, return immediately */
05312    if (ast_strlen_zero(mailbox))
05313       return 0;
05314 
05315    if (newmsgs)
05316       *newmsgs = 0;
05317    if (oldmsgs)
05318       *oldmsgs = 0;
05319    if (urgentmsgs)
05320       *urgentmsgs = 0;
05321 
05322    if (strchr(mailbox, ',')) {
05323       int tmpnew, tmpold, tmpurgent;
05324       char *mb, *cur;
05325 
05326       ast_copy_string(tmp, mailbox, sizeof(tmp));
05327       mb = tmp;
05328       while ((cur = strsep(&mb, ", "))) {
05329          if (!ast_strlen_zero(cur)) {
05330             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05331                return -1;
05332             else {
05333                if (newmsgs)
05334                   *newmsgs += tmpnew; 
05335                if (oldmsgs)
05336                   *oldmsgs += tmpold;
05337                if (urgentmsgs)
05338                   *urgentmsgs += tmpurgent;
05339             }
05340          }
05341       }
05342       return 0;
05343    }
05344 
05345    ast_copy_string(tmp, mailbox, sizeof(tmp));
05346    
05347    if ((context = strchr(tmp, '@')))
05348       *context++ = '\0';
05349    else
05350       context = "default";
05351 
05352    if (newmsgs)
05353       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05354    if (oldmsgs)
05355       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05356    if (urgentmsgs)
05357       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05358 
05359    return 0;
05360 }

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

utility used by inchar(), for base_encode()

Definition at line 4069 of file app_voicemail_odbcstorage.c.

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

04070 {
04071    int l;
04072 
04073    if (bio->ateof)
04074       return 0;
04075 
04076    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04077       if (ferror(fi))
04078          return -1;
04079 
04080       bio->ateof = 1;
04081       return 0;
04082    }
04083 
04084    bio->iolen = l;
04085    bio->iocp = 0;
04086 
04087    return 1;
04088 }

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

utility used by base_encode()

Definition at line 4093 of file app_voicemail_odbcstorage.c.

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

04094 {
04095    if (bio->iocp>=bio->iolen) {
04096       if (!inbuf(bio, fi))
04097          return EOF;
04098    }
04099 
04100    return bio->iobuf[bio->iocp++];
04101 }

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

Definition at line 891 of file app_voicemail_odbcstorage.c.

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

00892 {
00893    struct inprocess *i = obj, *j = arg;
00894    if (strcmp(i->mailbox, j->mailbox)) {
00895       return 0;
00896    }
00897    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00898 }

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

Definition at line 900 of file app_voicemail_odbcstorage.c.

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

00901 {
00902    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00903    arg->context = arg->mailbox + strlen(mailbox) + 1;
00904    strcpy(arg->mailbox, mailbox); /* SAFE */
00905    strcpy(arg->context, context); /* SAFE */
00906    ao2_lock(inprocess_container);
00907    if ((i = ao2_find(inprocess_container, arg, 0))) {
00908       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00909       ao2_unlock(inprocess_container);
00910       ao2_ref(i, -1);
00911       return ret;
00912    }
00913    if (delta < 0) {
00914       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00915    }
00916    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00917       ao2_unlock(inprocess_container);
00918       return 0;
00919    }
00920    i->context = i->mailbox + strlen(mailbox) + 1;
00921    strcpy(i->mailbox, mailbox); /* SAFE */
00922    strcpy(i->context, context); /* SAFE */
00923    i->count = delta;
00924    ao2_link(inprocess_container, i);
00925    ao2_unlock(inprocess_container);
00926    ao2_ref(i, -1);
00927    return 0;
00928 }

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

Definition at line 885 of file app_voicemail_odbcstorage.c.

References inprocess::mailbox.

00886 {
00887    const struct inprocess *i = obj;
00888    return atoi(i->mailbox);
00889 }

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

Definition at line 4907 of file app_voicemail_odbcstorage.c.

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

04908 {
04909    int res;
04910    char fn[PATH_MAX];
04911    char dest[PATH_MAX];
04912 
04913    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04914 
04915    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04916       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04917       return -1;
04918    }
04919 
04920    RETRIEVE(fn, -1, ext, context);
04921    if (ast_fileexists(fn, NULL, NULL) > 0) {
04922       res = ast_stream_and_wait(chan, fn, ecodes);
04923       if (res) {
04924          DISPOSE(fn, -1);
04925          return res;
04926       }
04927    } else {
04928       /* Dispose just in case */
04929       DISPOSE(fn, -1);
04930       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04931       if (res)
04932          return res;
04933       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04934       if (res)
04935          return res;
04936    }
04937    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04938    return res;
04939 }

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

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

01309 {
01310    int i;
01311    char *local_key = ast_strdupa(key);
01312 
01313    for (i = 0; i < strlen(key); ++i) {
01314       if (!strchr(VALID_DTMF, *local_key)) {
01315          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01316          return 0;
01317       }
01318       local_key++;
01319    }
01320    return 1;
01321 }

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

References map, ast_vm_user::maxmsg, and MAXMSGLIMIT.

03896 {
03897    int x;
03898    unsigned char map[MAXMSGLIMIT] = "";
03899    DIR *msgdir;
03900    struct dirent *msgdirent;
03901    int msgdirint;
03902 
03903    /* Reading the entire directory into a file map scales better than
03904     * doing a stat repeatedly on a predicted sequence.  I suspect this
03905     * is partially due to stat(2) internally doing a readdir(2) itself to
03906     * find each file. */
03907    if (!(msgdir = opendir(dir))) {
03908       return -1;
03909    }
03910 
03911    while ((msgdirent = readdir(msgdir))) {
03912       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03913          map[msgdirint] = 1;
03914    }
03915    closedir(msgdir);
03916 
03917    for (x = 0; x < vmu->maxmsg; x++) {
03918       if (map[x] == 0)
03919          break;
03920    }
03921 
03922    return x - 1;
03923 }

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

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

05439 {
05440 #ifdef IMAP_STORAGE
05441    int newmsgs, oldmsgs;
05442 #else
05443    char urgdir[PATH_MAX];
05444 #endif
05445    char txtfile[PATH_MAX];
05446    char tmptxtfile[PATH_MAX];
05447    struct vm_state *vms = NULL;
05448    char callerid[256];
05449    FILE *txt;
05450    char date[256];
05451    int txtdes;
05452    int res = 0;
05453    int msgnum;
05454    int duration = 0;
05455    int ausemacro = 0;
05456    int ousemacro = 0;
05457    int ouseexten = 0;
05458    char tmpdur[16];
05459    char priority[16];
05460    char origtime[16];
05461    char dir[PATH_MAX];
05462    char tmpdir[PATH_MAX];
05463    char fn[PATH_MAX];
05464    char prefile[PATH_MAX] = "";
05465    char tempfile[PATH_MAX] = "";
05466    char ext_context[256] = "";
05467    char fmt[80];
05468    char *context;
05469    char ecodes[17] = "#";
05470    struct ast_str *tmp = ast_str_create(16);
05471    char *tmpptr;
05472    struct ast_vm_user *vmu;
05473    struct ast_vm_user svm;
05474    const char *category = NULL;
05475    const char *code;
05476    const char *alldtmf = "0123456789ABCD*#";
05477    char flag[80];
05478 
05479    if (!tmp) {
05480       return -1;
05481    }
05482 
05483    ast_str_set(&tmp, 0, "%s", ext);
05484    ext = ast_str_buffer(tmp);
05485    if ((context = strchr(ext, '@'))) {
05486       *context++ = '\0';
05487       tmpptr = strchr(context, '&');
05488    } else {
05489       tmpptr = strchr(ext, '&');
05490    }
05491 
05492    if (tmpptr)
05493       *tmpptr++ = '\0';
05494 
05495    ast_channel_lock(chan);
05496    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
05497       category = ast_strdupa(category);
05498    }
05499    ast_channel_unlock(chan);
05500 
05501    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
05502       ast_copy_string(flag, "Urgent", sizeof(flag));
05503    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
05504       ast_copy_string(flag, "PRIORITY", sizeof(flag));
05505    } else {
05506       flag[0] = '\0';
05507    }
05508 
05509    ast_debug(3, "Before find_user\n");
05510    if (!(vmu = find_user(&svm, context, ext))) {
05511       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
05512       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05513       ast_free(tmp);
05514       return res;
05515    }
05516    /* Setup pre-file if appropriate */
05517    if (strcmp(vmu->context, "default"))
05518       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
05519    else
05520       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
05521 
05522    /* Set the path to the prefile. Will be one of 
05523       VM_SPOOL_DIRcontext/ext/busy
05524       VM_SPOOL_DIRcontext/ext/unavail
05525       Depending on the flag set in options.
05526    */
05527    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
05528       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
05529    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
05530       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
05531    }
05532    /* Set the path to the tmpfile as
05533       VM_SPOOL_DIR/context/ext/temp
05534       and attempt to create the folder structure.
05535    */
05536    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
05537    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
05538       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
05539       ast_free(tmp);
05540       return -1;
05541    }
05542    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
05543    if (ast_fileexists(tempfile, NULL, NULL) > 0)
05544       ast_copy_string(prefile, tempfile, sizeof(prefile));
05545 
05546    DISPOSE(tempfile, -1);
05547    /* It's easier just to try to make it than to check for its existence */
05548 #ifndef IMAP_STORAGE
05549    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
05550 #else
05551    snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
05552    if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
05553       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
05554    }
05555 #endif
05556 
05557    /* Check current or macro-calling context for special extensions */
05558    if (ast_test_flag(vmu, VM_OPERATOR)) {
05559       if (!ast_strlen_zero(vmu->exit)) {
05560          if (ast_exists_extension(chan, vmu->exit, "o", 1,
05561             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05562             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05563             ouseexten = 1;
05564          }
05565       } else if (ast_exists_extension(chan, chan->context, "o", 1,
05566          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05567          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05568          ouseexten = 1;
05569       } else if (!ast_strlen_zero(chan->macrocontext)
05570          && ast_exists_extension(chan, chan->macrocontext, "o", 1,
05571             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05572          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05573          ousemacro = 1;
05574       }
05575    }
05576 
05577    if (!ast_strlen_zero(vmu->exit)) {
05578       if (ast_exists_extension(chan, vmu->exit, "a", 1,
05579          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05580          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05581       }
05582    } else if (ast_exists_extension(chan, chan->context, "a", 1,
05583       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05584       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05585    } else if (!ast_strlen_zero(chan->macrocontext)
05586       && ast_exists_extension(chan, chan->macrocontext, "a", 1,
05587          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05588       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05589       ausemacro = 1;
05590    }
05591 
05592    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05593       for (code = alldtmf; *code; code++) {
05594          char e[2] = "";
05595          e[0] = *code;
05596          if (strchr(ecodes, e[0]) == NULL
05597             && ast_canmatch_extension(chan, chan->context, e, 1,
05598                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05599             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05600          }
05601       }
05602    }
05603 
05604    /* Play the beginning intro if desired */
05605    if (!ast_strlen_zero(prefile)) {
05606 #ifdef ODBC_STORAGE
05607       int success = 
05608 #endif
05609          RETRIEVE(prefile, -1, ext, context);
05610       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05611          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05612             res = ast_waitstream(chan, ecodes);
05613 #ifdef ODBC_STORAGE
05614          if (success == -1) {
05615             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05616             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05617             store_file(prefile, vmu->mailbox, vmu->context, -1);
05618          }
05619 #endif
05620       } else {
05621          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05622          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05623       }
05624       DISPOSE(prefile, -1);
05625       if (res < 0) {
05626          ast_debug(1, "Hang up during prefile playback\n");
05627          free_user(vmu);
05628          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05629          ast_free(tmp);
05630          return -1;
05631       }
05632    }
05633    if (res == '#') {
05634       /* On a '#' we skip the instructions */
05635       ast_set_flag(options, OPT_SILENT);
05636       res = 0;
05637    }
05638    /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
05639    if (vmu->maxmsg == 0) {
05640       if (option_debug > 2)
05641          ast_log(LOG_DEBUG, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
05642       pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05643       goto leave_vm_out;
05644    }
05645    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05646       res = ast_stream_and_wait(chan, INTRO, ecodes);
05647       if (res == '#') {
05648          ast_set_flag(options, OPT_SILENT);
05649          res = 0;
05650       }
05651    }
05652    if (res > 0)
05653       ast_stopstream(chan);
05654    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05655     other than the operator -- an automated attendant or mailbox login for example */
05656    if (res == '*') {
05657       chan->exten[0] = 'a';
05658       chan->exten[1] = '\0';
05659       if (!ast_strlen_zero(vmu->exit)) {
05660          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05661       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05662          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05663       }
05664       chan->priority = 0;
05665       free_user(vmu);
05666       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05667       ast_free(tmp);
05668       return 0;
05669    }
05670 
05671    /* Check for a '0' here */
05672    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05673    transfer:
05674       if (ouseexten || ousemacro) {
05675          chan->exten[0] = 'o';
05676          chan->exten[1] = '\0';
05677          if (!ast_strlen_zero(vmu->exit)) {
05678             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05679          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05680             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05681          }
05682          ast_play_and_wait(chan, "transfer");
05683          chan->priority = 0;
05684          free_user(vmu);
05685          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05686       }
05687       ast_free(tmp);
05688       return OPERATOR_EXIT;
05689    }
05690 
05691    /* Allow all other digits to exit Voicemail and return to the dialplan */
05692    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05693       if (!ast_strlen_zero(options->exitcontext))
05694          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05695       free_user(vmu);
05696       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05697       ast_free(tmp);
05698       return res;
05699    }
05700 
05701    if (res < 0) {
05702       free_user(vmu);
05703       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05704       ast_free(tmp);
05705       return -1;
05706    }
05707    /* The meat of recording the message...  All the announcements and beeps have been played*/
05708    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05709    if (!ast_strlen_zero(fmt)) {
05710       msgnum = 0;
05711 
05712 #ifdef IMAP_STORAGE
05713       /* Is ext a mailbox? */
05714       /* must open stream for this user to get info! */
05715       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05716       if (res < 0) {
05717          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05718          ast_free(tmp);
05719          return -1;
05720       }
05721       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05722       /* It is possible under certain circumstances that inboxcount did not
05723        * create a vm_state when it was needed. This is a catchall which will
05724        * rarely be used.
05725        */
05726          if (!(vms = create_vm_state_from_user(vmu))) {
05727             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05728             ast_free(tmp);
05729             return -1;
05730          }
05731       }
05732       vms->newmessages++;
05733       
05734       /* here is a big difference! We add one to it later */
05735       msgnum = newmsgs + oldmsgs;
05736       ast_debug(3, "Messagecount set to %d\n", msgnum);
05737       snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05738       /* set variable for compatibility */
05739       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05740 
05741       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
05742          goto leave_vm_out;
05743       }
05744 #else
05745       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
05746          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05747          if (!res)
05748             res = ast_waitstream(chan, "");
05749          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05750          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05751          inprocess_count(vmu->mailbox, vmu->context, -1);
05752          goto leave_vm_out;
05753       }
05754 
05755 #endif
05756       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05757       txtdes = mkstemp(tmptxtfile);
05758       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05759       if (txtdes < 0) {
05760          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05761          if (!res)
05762             res = ast_waitstream(chan, "");
05763          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05764          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05765          inprocess_count(vmu->mailbox, vmu->context, -1);
05766          goto leave_vm_out;
05767       }
05768 
05769       /* Now play the beep once we have the message number for our next message. */
05770       if (res >= 0) {
05771          /* Unless we're *really* silent, try to send the beep */
05772          res = ast_stream_and_wait(chan, "beep", "");
05773       }
05774             
05775       /* Store information in real-time storage */
05776       if (ast_check_realtime("voicemail_data")) {
05777          snprintf(priority, sizeof(priority), "%d", chan->priority);
05778          snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
05779          get_date(date, sizeof(date));
05780          ast_callerid_merge(callerid, sizeof(callerid),
05781             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05782             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05783             "Unknown");
05784          ast_store_realtime("voicemail_data",
05785             "origmailbox", ext,
05786             "context", chan->context,
05787             "macrocontext", chan->macrocontext,
05788             "exten", chan->exten,
05789             "priority", priority,
05790             "callerchan", chan->name,
05791             "callerid", callerid,
05792             "origdate", date,
05793             "origtime", origtime,
05794             "category", S_OR(category, ""),
05795             "filename", tmptxtfile,
05796             SENTINEL);
05797       }
05798 
05799       /* Store information */
05800       txt = fdopen(txtdes, "w+");
05801       if (txt) {
05802          get_date(date, sizeof(date));
05803          ast_callerid_merge(callerid, sizeof(callerid),
05804             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05805             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05806             "Unknown");
05807          fprintf(txt, 
05808             ";\n"
05809             "; Message Information file\n"
05810             ";\n"
05811             "[message]\n"
05812             "origmailbox=%s\n"
05813             "context=%s\n"
05814             "macrocontext=%s\n"
05815             "exten=%s\n"
05816             "rdnis=%s\n"
05817             "priority=%d\n"
05818             "callerchan=%s\n"
05819             "callerid=%s\n"
05820             "origdate=%s\n"
05821             "origtime=%ld\n"
05822             "category=%s\n",
05823             ext,
05824             chan->context,
05825             chan->macrocontext, 
05826             chan->exten,
05827             S_COR(chan->redirecting.from.number.valid,
05828                chan->redirecting.from.number.str, "unknown"),
05829             chan->priority,
05830             chan->name,
05831             callerid,
05832             date, (long) time(NULL),
05833             category ? category : "");
05834       } else {
05835          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
05836          inprocess_count(vmu->mailbox, vmu->context, -1);
05837          if (ast_check_realtime("voicemail_data")) {
05838             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05839          }
05840          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05841          goto leave_vm_out;
05842       }
05843       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms, flag);
05844 
05845       if (txt) {
05846          fprintf(txt, "flag=%s\n", flag);
05847          if (duration < vmu->minsecs) {
05848             fclose(txt);
05849             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmu->minsecs);
05850             ast_filedelete(tmptxtfile, NULL);
05851             unlink(tmptxtfile);
05852             if (ast_check_realtime("voicemail_data")) {
05853                ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05854             }
05855             inprocess_count(vmu->mailbox, vmu->context, -1);
05856          } else {
05857             fprintf(txt, "duration=%d\n", duration);
05858             fclose(txt);
05859             if (vm_lock_path(dir)) {
05860                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
05861                /* Delete files */
05862                ast_filedelete(tmptxtfile, NULL);
05863                unlink(tmptxtfile);
05864                inprocess_count(vmu->mailbox, vmu->context, -1);
05865             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
05866                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
05867                unlink(tmptxtfile);
05868                ast_unlock_path(dir);
05869                inprocess_count(vmu->mailbox, vmu->context, -1);
05870                if (ast_check_realtime("voicemail_data")) {
05871                   ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05872                }
05873             } else {
05874 #ifndef IMAP_STORAGE
05875                msgnum = last_message_index(vmu, dir) + 1;
05876 #endif
05877                make_file(fn, sizeof(fn), dir, msgnum);
05878 
05879                /* assign a variable with the name of the voicemail file */ 
05880 #ifndef IMAP_STORAGE
05881                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
05882 #else
05883                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05884 #endif
05885 
05886                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
05887                ast_filerename(tmptxtfile, fn, NULL);
05888                rename(tmptxtfile, txtfile);
05889                inprocess_count(vmu->mailbox, vmu->context, -1);
05890 
05891                /* Properly set permissions on voicemail text descriptor file.
05892                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
05893                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
05894                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
05895 
05896                ast_unlock_path(dir);
05897                if (ast_check_realtime("voicemail_data")) {
05898                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
05899                   ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
05900                }
05901                /* We must store the file first, before copying the message, because
05902                 * ODBC storage does the entire copy with SQL.
05903                 */
05904                if (ast_fileexists(fn, NULL, NULL) > 0) {
05905                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
05906                }
05907 
05908                /* Are there to be more recipients of this message? */
05909                while (tmpptr) {
05910                   struct ast_vm_user recipu, *recip;
05911                   char *exten, *cntx;
05912                
05913                   exten = strsep(&tmpptr, "&");
05914                   cntx = strchr(exten, '@');
05915                   if (cntx) {
05916                      *cntx = '\0';
05917                      cntx++;
05918                   }
05919                   if ((recip = find_user(&recipu, cntx, exten))) {
05920                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
05921                      free_user(recip);
05922                   }
05923                }
05924 #ifndef IMAP_STORAGE
05925                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
05926                   /* Move the message from INBOX to Urgent folder if this is urgent! */
05927                   char sfn[PATH_MAX];
05928                   char dfn[PATH_MAX];
05929                   int x;
05930                   /* It's easier just to try to make it than to check for its existence */
05931                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
05932                   x = last_message_index(vmu, urgdir) + 1;
05933                   make_file(sfn, sizeof(sfn), dir, msgnum);
05934                   make_file(dfn, sizeof(dfn), urgdir, x);
05935                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
05936                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
05937                   /* Notification must happen for this new message in Urgent folder, not INBOX */
05938                   ast_copy_string(fn, dfn, sizeof(fn));
05939                   msgnum = x;
05940                }
05941 #endif
05942                /* Notification needs to happen after the copy, though. */
05943                if (ast_fileexists(fn, NULL, NULL)) {
05944 #ifdef IMAP_STORAGE
05945                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
05946                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05947                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05948                      flag);
05949 #else
05950                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
05951                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05952                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05953                      flag);
05954 #endif
05955                }
05956 
05957                /* Disposal needs to happen after the optional move and copy */
05958                if (ast_fileexists(fn, NULL, NULL)) {
05959                   DISPOSE(dir, msgnum);
05960                }
05961             }
05962          }
05963       } else {
05964          inprocess_count(vmu->mailbox, vmu->context, -1);
05965       }
05966       if (res == '0') {
05967          goto transfer;
05968       } else if (res > 0 && res != 't')
05969          res = 0;
05970 
05971       if (duration < vmu->minsecs)
05972          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
05973          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05974       else
05975          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05976    } else
05977       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
05978 leave_vm_out:
05979    free_user(vmu);
05980 
05981 #ifdef IMAP_STORAGE
05982    /* expunge message - use UID Expunge if supported on IMAP server*/
05983    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
05984    if (expungeonhangup == 1) {
05985       ast_mutex_lock(&vms->lock);
05986 #ifdef HAVE_IMAP_TK2006
05987       if (LEVELUIDPLUS (vms->mailstream)) {
05988          mail_expunge_full(vms->mailstream, NIL, EX_UID);
05989       } else 
05990 #endif
05991          mail_expunge(vms->mailstream);
05992       ast_mutex_unlock(&vms->lock);
05993    }
05994 #endif
05995 
05996    ast_free(tmp);
05997    return res;
05998 }

static int load_config ( int  reload  )  [static]

Definition at line 11469 of file app_voicemail_odbcstorage.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_unload_realtime(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), vm_zone::list, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, LOG_ERROR, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, var, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, and VOICEMAIL_CONFIG.

11470 {
11471    struct ast_vm_user *current;
11472    struct ast_config *cfg, *ucfg;
11473    char *cat;
11474    struct ast_variable *var;
11475    const char *val;
11476    char *q, *stringp, *tmp;
11477    int x;
11478    int tmpadsi[4];
11479    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11480    char secretfn[PATH_MAX] = "";
11481 
11482    ast_unload_realtime("voicemail");
11483    ast_unload_realtime("voicemail_data");
11484 
11485    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11486       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11487          return 0;
11488       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11489          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11490          ucfg = NULL;
11491       }
11492       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11493       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11494          ast_config_destroy(ucfg);
11495          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11496          return 0;
11497       }
11498    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11499       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11500       return 0;
11501    } else {
11502       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11503       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11504          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11505          ucfg = NULL;
11506       }
11507    }
11508 #ifdef IMAP_STORAGE
11509    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
11510 #endif
11511    /* set audio control prompts */
11512    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
11513    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
11514    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
11515    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
11516    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
11517 
11518    /* Free all the users structure */  
11519    free_vm_users();
11520 
11521    /* Free all the zones structure */
11522    free_vm_zones();
11523 
11524    AST_LIST_LOCK(&users);  
11525 
11526    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
11527    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
11528 
11529    if (cfg) {
11530       /* General settings */
11531 
11532       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
11533          val = "default";
11534       ast_copy_string(userscontext, val, sizeof(userscontext));
11535       /* Attach voice message to mail message ? */
11536       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
11537          val = "yes";
11538       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
11539 
11540       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
11541          val = "no";
11542       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
11543 
11544       volgain = 0.0;
11545       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
11546          sscanf(val, "%30lf", &volgain);
11547 
11548 #ifdef ODBC_STORAGE
11549       strcpy(odbc_database, "asterisk");
11550       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
11551          ast_copy_string(odbc_database, val, sizeof(odbc_database));
11552       }
11553       strcpy(odbc_table, "voicemessages");
11554       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
11555          ast_copy_string(odbc_table, val, sizeof(odbc_table));
11556       }
11557 #endif      
11558       /* Mail command */
11559       strcpy(mailcmd, SENDMAIL);
11560       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
11561          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
11562 
11563       maxsilence = 0;
11564       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
11565          maxsilence = atoi(val);
11566          if (maxsilence > 0)
11567             maxsilence *= 1000;
11568       }
11569       
11570       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
11571          maxmsg = MAXMSG;
11572       } else {
11573          maxmsg = atoi(val);
11574          if (maxmsg < 0) {
11575             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
11576             maxmsg = MAXMSG;
11577          } else if (maxmsg > MAXMSGLIMIT) {
11578             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11579             maxmsg = MAXMSGLIMIT;
11580          }
11581       }
11582 
11583       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
11584          maxdeletedmsg = 0;
11585       } else {
11586          if (sscanf(val, "%30d", &x) == 1)
11587             maxdeletedmsg = x;
11588          else if (ast_true(val))
11589             maxdeletedmsg = MAXMSG;
11590          else
11591             maxdeletedmsg = 0;
11592 
11593          if (maxdeletedmsg < 0) {
11594             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
11595             maxdeletedmsg = MAXMSG;
11596          } else if (maxdeletedmsg > MAXMSGLIMIT) {
11597             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11598             maxdeletedmsg = MAXMSGLIMIT;
11599          }
11600       }
11601 
11602       /* Load date format config for voicemail mail */
11603       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
11604          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
11605       }
11606 
11607       /* Load date format config for voicemail pager mail */
11608       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
11609          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
11610       }
11611 
11612       /* External password changing command */
11613       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
11614          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11615          pwdchange = PWDCHANGE_EXTERNAL;
11616       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
11617          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11618          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
11619       }
11620  
11621       /* External password validation command */
11622       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
11623          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
11624          ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
11625       }
11626 
11627 #ifdef IMAP_STORAGE
11628       /* IMAP server address */
11629       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
11630          ast_copy_string(imapserver, val, sizeof(imapserver));
11631       } else {
11632          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
11633       }
11634       /* IMAP server port */
11635       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
11636          ast_copy_string(imapport, val, sizeof(imapport));
11637       } else {
11638          ast_copy_string(imapport, "143", sizeof(imapport));
11639       }
11640       /* IMAP server flags */
11641       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
11642          ast_copy_string(imapflags, val, sizeof(imapflags));
11643       }
11644       /* IMAP server master username */
11645       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
11646          ast_copy_string(authuser, val, sizeof(authuser));
11647       }
11648       /* IMAP server master password */
11649       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
11650          ast_copy_string(authpassword, val, sizeof(authpassword));
11651       }
11652       /* Expunge on exit */
11653       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
11654          if (ast_false(val))
11655             expungeonhangup = 0;
11656          else
11657             expungeonhangup = 1;
11658       } else {
11659          expungeonhangup = 1;
11660       }
11661       /* IMAP voicemail folder */
11662       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
11663          ast_copy_string(imapfolder, val, sizeof(imapfolder));
11664       } else {
11665          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
11666       }
11667       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
11668          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
11669       }
11670       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
11671          imapgreetings = ast_true(val);
11672       } else {
11673          imapgreetings = 0;
11674       }
11675       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
11676          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
11677       } else {
11678          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
11679       }
11680 
11681       /* There is some very unorthodox casting done here. This is due
11682        * to the way c-client handles the argument passed in. It expects a 
11683        * void pointer and casts the pointer directly to a long without
11684        * first dereferencing it. */
11685       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
11686          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
11687       } else {
11688          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
11689       }
11690 
11691       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
11692          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
11693       } else {
11694          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
11695       }
11696 
11697       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
11698          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
11699       } else {
11700          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
11701       }
11702 
11703       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
11704          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
11705       } else {
11706          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
11707       }
11708 
11709       /* Increment configuration version */
11710       imapversion++;
11711 #endif
11712       /* External voicemail notify application */
11713       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
11714          ast_copy_string(externnotify, val, sizeof(externnotify));
11715          ast_debug(1, "found externnotify: %s\n", externnotify);
11716       } else {
11717          externnotify[0] = '\0';
11718       }
11719 
11720       /* SMDI voicemail notification */
11721       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
11722          ast_debug(1, "Enabled SMDI voicemail notification\n");
11723          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
11724             smdi_iface = ast_smdi_interface_find(val);
11725          } else {
11726             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
11727             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
11728          }
11729          if (!smdi_iface) {
11730             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
11731          } 
11732       }
11733 
11734       /* Silence treshold */
11735       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
11736       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
11737          silencethreshold = atoi(val);
11738       
11739       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
11740          val = ASTERISK_USERNAME;
11741       ast_copy_string(serveremail, val, sizeof(serveremail));
11742       
11743       vmmaxsecs = 0;
11744       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
11745          if (sscanf(val, "%30d", &x) == 1) {
11746             vmmaxsecs = x;
11747          } else {
11748             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
11749          }
11750       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
11751          static int maxmessage_deprecate = 0;
11752          if (maxmessage_deprecate == 0) {
11753             maxmessage_deprecate = 1;
11754             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
11755          }
11756          if (sscanf(val, "%30d", &x) == 1) {
11757             vmmaxsecs = x;
11758          } else {
11759             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
11760          }
11761       }
11762 
11763       vmminsecs = 0;
11764       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
11765          if (sscanf(val, "%30d", &x) == 1) {
11766             vmminsecs = x;
11767             if (maxsilence / 1000 >= vmminsecs) {
11768                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
11769             }
11770          } else {
11771             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
11772          }
11773       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
11774          static int maxmessage_deprecate = 0;
11775          if (maxmessage_deprecate == 0) {
11776             maxmessage_deprecate = 1;
11777             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
11778          }
11779          if (sscanf(val, "%30d", &x) == 1) {
11780             vmminsecs = x;
11781             if (maxsilence / 1000 >= vmminsecs) {
11782                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
11783             }
11784          } else {
11785             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
11786          }
11787       }
11788 
11789       val = ast_variable_retrieve(cfg, "general", "format");
11790       if (!val) {
11791          val = "wav";   
11792       } else {
11793          tmp = ast_strdupa(val);
11794          val = ast_format_str_reduce(tmp);
11795          if (!val) {
11796             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
11797             val = "wav";
11798          }
11799       }
11800       ast_copy_string(vmfmts, val, sizeof(vmfmts));
11801 
11802       skipms = 3000;
11803       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
11804          if (sscanf(val, "%30d", &x) == 1) {
11805             maxgreet = x;
11806          } else {
11807             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
11808          }
11809       }
11810 
11811       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
11812          if (sscanf(val, "%30d", &x) == 1) {
11813             skipms = x;
11814          } else {
11815             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
11816          }
11817       }
11818 
11819       maxlogins = 3;
11820       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
11821          if (sscanf(val, "%30d", &x) == 1) {
11822             maxlogins = x;
11823          } else {
11824             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
11825          }
11826       }
11827 
11828       minpassword = MINPASSWORD;
11829       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
11830          if (sscanf(val, "%30d", &x) == 1) {
11831             minpassword = x;
11832          } else {
11833             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
11834          }
11835       }
11836 
11837       /* Force new user to record name ? */
11838       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
11839          val = "no";
11840       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
11841 
11842       /* Force new user to record greetings ? */
11843       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
11844          val = "no";
11845       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
11846 
11847       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
11848          ast_debug(1, "VM_CID Internal context string: %s\n", val);
11849          stringp = ast_strdupa(val);
11850          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
11851             if (!ast_strlen_zero(stringp)) {
11852                q = strsep(&stringp, ",");
11853                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
11854                   q++;
11855                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
11856                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
11857             } else {
11858                cidinternalcontexts[x][0] = '\0';
11859             }
11860          }
11861       }
11862       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
11863          ast_debug(1, "VM Review Option disabled globally\n");
11864          val = "no";
11865       }
11866       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
11867 
11868       /* Temporary greeting reminder */
11869       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
11870          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
11871          val = "no";
11872       } else {
11873          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
11874       }
11875       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
11876       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
11877          ast_debug(1, "VM next message wrap disabled globally\n");
11878          val = "no";
11879       }
11880       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);  
11881 
11882       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
11883          ast_debug(1, "VM Operator break disabled globally\n");
11884          val = "no";
11885       }
11886       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
11887 
11888       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
11889          ast_debug(1, "VM CID Info before msg disabled globally\n");
11890          val = "no";
11891       } 
11892       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
11893 
11894       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
11895          ast_debug(1, "Send Voicemail msg disabled globally\n");
11896          val = "no";
11897       }
11898       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
11899    
11900       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
11901          ast_debug(1, "ENVELOPE before msg enabled globally\n");
11902          val = "yes";
11903       }
11904       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
11905 
11906       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
11907          ast_debug(1, "Move Heard enabled globally\n");
11908          val = "yes";
11909       }
11910       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
11911 
11912       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
11913          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
11914          val = "no";
11915       }
11916       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);   
11917 
11918       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
11919          ast_debug(1, "Duration info before msg enabled globally\n");
11920          val = "yes";
11921       }
11922       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
11923 
11924       saydurationminfo = 2;
11925       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
11926          if (sscanf(val, "%30d", &x) == 1) {
11927             saydurationminfo = x;
11928          } else {
11929             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
11930          }
11931       }
11932 
11933       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
11934          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
11935          val = "no";
11936       }
11937       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
11938 
11939       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
11940          ast_copy_string(dialcontext, val, sizeof(dialcontext));
11941          ast_debug(1, "found dialout context: %s\n", dialcontext);
11942       } else {
11943          dialcontext[0] = '\0';  
11944       }
11945       
11946       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
11947          ast_copy_string(callcontext, val, sizeof(callcontext));
11948          ast_debug(1, "found callback context: %s\n", callcontext);
11949       } else {
11950          callcontext[0] = '\0';
11951       }
11952 
11953       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
11954          ast_copy_string(exitcontext, val, sizeof(exitcontext));
11955          ast_debug(1, "found operator context: %s\n", exitcontext);
11956       } else {
11957          exitcontext[0] = '\0';
11958       }
11959       
11960       /* load password sounds configuration */
11961       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
11962          ast_copy_string(vm_password, val, sizeof(vm_password));
11963       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
11964          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
11965       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
11966          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
11967       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
11968          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
11969       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
11970          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
11971       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
11972          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
11973       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
11974          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
11975       }
11976       /* load configurable audio prompts */
11977       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
11978          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
11979       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
11980          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
11981       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
11982          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
11983       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
11984          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
11985       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
11986          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
11987 
11988       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
11989          val = "no";
11990       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
11991 
11992       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
11993          val = "voicemail.conf";
11994       }
11995       if (!(strcmp(val, "spooldir"))) {
11996          passwordlocation = OPT_PWLOC_SPOOLDIR;
11997       } else {
11998          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
11999       }
12000 
12001       poll_freq = DEFAULT_POLL_FREQ;
12002       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
12003          if (sscanf(val, "%30u", &poll_freq) != 1) {
12004             poll_freq = DEFAULT_POLL_FREQ;
12005             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
12006          }
12007       }
12008 
12009       poll_mailboxes = 0;
12010       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
12011          poll_mailboxes = ast_true(val);
12012 
12013       if (ucfg) { 
12014          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
12015             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
12016                continue;
12017             if ((current = find_or_create(userscontext, cat))) {
12018                populate_defaults(current);
12019                apply_options_full(current, ast_variable_browse(ucfg, cat));
12020                ast_copy_string(current->context, userscontext, sizeof(current->context));
12021                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
12022                   current->passwordlocation = OPT_PWLOC_USERSCONF;
12023                }
12024 
12025                switch (current->passwordlocation) {
12026                case OPT_PWLOC_SPOOLDIR:
12027                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
12028                   read_password_from_file(secretfn, current->password, sizeof(current->password));
12029                }
12030             }
12031          }
12032          ast_config_destroy(ucfg);
12033       }
12034       cat = ast_category_browse(cfg, NULL);
12035       while (cat) {
12036          if (strcasecmp(cat, "general")) {
12037             var = ast_variable_browse(cfg, cat);
12038             if (strcasecmp(cat, "zonemessages")) {
12039                /* Process mailboxes in this context */
12040                while (var) {
12041                   append_mailbox(cat, var->name, var->value);
12042                   var = var->next;
12043                }
12044             } else {
12045                /* Timezones in this context */
12046                while (var) {
12047                   struct vm_zone *z;
12048                   if ((z = ast_malloc(sizeof(*z)))) {
12049                      char *msg_format, *tzone;
12050                      msg_format = ast_strdupa(var->value);
12051                      tzone = strsep(&msg_format, "|,");
12052                      if (msg_format) {
12053                         ast_copy_string(z->name, var->name, sizeof(z->name));
12054                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
12055                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
12056                         AST_LIST_LOCK(&zones);
12057                         AST_LIST_INSERT_HEAD(&zones, z, list);
12058                         AST_LIST_UNLOCK(&zones);
12059                      } else {
12060                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
12061                         ast_free(z);
12062                      }
12063                   } else {
12064                      AST_LIST_UNLOCK(&users);
12065                      ast_config_destroy(cfg);
12066                      return -1;
12067                   }
12068                   var = var->next;
12069                }
12070             }
12071          }
12072          cat = ast_category_browse(cfg, cat);
12073       }
12074       memset(fromstring, 0, sizeof(fromstring));
12075       memset(pagerfromstring, 0, sizeof(pagerfromstring));
12076       strcpy(charset, "ISO-8859-1");
12077       if (emailbody) {
12078          ast_free(emailbody);
12079          emailbody = NULL;
12080       }
12081       if (emailsubject) {
12082          ast_free(emailsubject);
12083          emailsubject = NULL;
12084       }
12085       if (pagerbody) {
12086          ast_free(pagerbody);
12087          pagerbody = NULL;
12088       }
12089       if (pagersubject) {
12090          ast_free(pagersubject);
12091          pagersubject = NULL;
12092       }
12093       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
12094          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
12095       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
12096          ast_copy_string(fromstring, val, sizeof(fromstring));
12097       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
12098          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
12099       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
12100          ast_copy_string(charset, val, sizeof(charset));
12101       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
12102          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12103          for (x = 0; x < 4; x++) {
12104             memcpy(&adsifdn[x], &tmpadsi[x], 1);
12105          }
12106       }
12107       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
12108          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12109          for (x = 0; x < 4; x++) {
12110             memcpy(&adsisec[x], &tmpadsi[x], 1);
12111          }
12112       }
12113       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
12114          if (atoi(val)) {
12115             adsiver = atoi(val);
12116          }
12117       }
12118       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
12119          ast_copy_string(zonetag, val, sizeof(zonetag));
12120       }
12121       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
12122          ast_copy_string(locale, val, sizeof(locale));
12123       }
12124       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
12125          emailsubject = ast_strdup(val);
12126       }
12127       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
12128          emailbody = ast_strdup(substitute_escapes(val));
12129       }
12130       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
12131          pagersubject = ast_strdup(val);
12132       }
12133       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
12134          pagerbody = ast_strdup(substitute_escapes(val));
12135       }
12136       AST_LIST_UNLOCK(&users);
12137       ast_config_destroy(cfg);
12138 
12139       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
12140          start_poll_thread();
12141       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
12142          stop_poll_thread();;
12143 
12144       return 0;
12145    } else {
12146       AST_LIST_UNLOCK(&users);
12147       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
12148       if (ucfg)
12149          ast_config_destroy(ucfg);
12150       return 0;
12151    }
12152 }

static int load_module ( void   )  [static]

Definition at line 12644 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_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application_xml, ast_taskprocessor_get(), AST_TEST_REGISTER, cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), inprocess_cmp_fn(), inprocess_container, inprocess_hash_fn(), load_config(), mailbox_exists_acf, manager_list_voicemail_users(), messagecount(), mwi_subscription_tps, RQ_CHAR, RQ_UINTEGER3, sayname(), SENTINEL, vm_box_exists(), vm_data_providers, vm_exec(), vm_execmain(), vmauthenticate(), and vmsayname_exec().

12645 {
12646    int res;
12647    my_umask = umask(0);
12648    umask(my_umask);
12649 
12650    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
12651       return AST_MODULE_LOAD_DECLINE;
12652    }
12653 
12654    /* compute the location of the voicemail spool directory */
12655    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
12656    
12657    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
12658       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
12659    }
12660 
12661    if ((res = load_config(0)))
12662       return res;
12663 
12664    res = ast_register_application_xml(app, vm_exec);
12665    res |= ast_register_application_xml(app2, vm_execmain);
12666    res |= ast_register_application_xml(app3, vm_box_exists);
12667    res |= ast_register_application_xml(app4, vmauthenticate);
12668    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
12669    res |= ast_custom_function_register(&mailbox_exists_acf);
12670    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
12671 #ifdef TEST_FRAMEWORK
12672    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
12673    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
12674    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
12675    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
12676 #endif
12677 
12678    if (res)
12679       return res;
12680 
12681    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12682    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
12683 
12684    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
12685    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
12686    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
12687 
12688    return res;
12689 }

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

01564 {
01565    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01566 }

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

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

04387 {
04388    char date[256];
04389    char host[MAXHOSTNAMELEN] = "";
04390    char who[256];
04391    char bound[256];
04392    char dur[256];
04393    struct ast_tm tm;
04394    char enc_cidnum[256] = "", enc_cidname[256] = "";
04395    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04396    char *greeting_attachment; 
04397    char filename[256];
04398 
04399    if (!str1 || !str2) {
04400       ast_free(str1);
04401       ast_free(str2);
04402       return;
04403    }
04404 
04405    if (cidnum) {
04406       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04407    }
04408    if (cidname) {
04409       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04410    }
04411    gethostname(host, sizeof(host) - 1);
04412 
04413    if (strchr(srcemail, '@')) {
04414       ast_copy_string(who, srcemail, sizeof(who));
04415    } else {
04416       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04417    }
04418 
04419    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04420    if (greeting_attachment) {
04421       *greeting_attachment++ = '\0';
04422    }
04423 
04424    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04425    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04426    fprintf(p, "Date: %s" ENDL, date);
04427 
04428    /* Set date format for voicemail mail */
04429    ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04430 
04431    if (!ast_strlen_zero(fromstring)) {
04432       struct ast_channel *ast;
04433       if ((ast = ast_dummy_channel_alloc())) {
04434          char *ptr;
04435          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04436          ast_str_substitute_variables(&str1, 0, ast, fromstring);
04437 
04438          if (check_mime(ast_str_buffer(str1))) {
04439             int first_line = 1;
04440             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04441             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04442                *ptr = '\0';
04443                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04444                first_line = 0;
04445                /* Substring is smaller, so this will never grow */
04446                ast_str_set(&str2, 0, "%s", ptr + 1);
04447             }
04448             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04449          } else {
04450             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04451          }
04452          ast = ast_channel_release(ast);
04453       } else {
04454          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04455       }
04456    } else {
04457       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04458    }
04459 
04460    if (check_mime(vmu->fullname)) {
04461       int first_line = 1;
04462       char *ptr;
04463       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
04464       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04465          *ptr = '\0';
04466          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04467          first_line = 0;
04468          /* Substring is smaller, so this will never grow */
04469          ast_str_set(&str2, 0, "%s", ptr + 1);
04470       }
04471       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
04472    } else {
04473       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
04474    }
04475 
04476    if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
04477       char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
04478       struct ast_channel *ast;
04479       if ((ast = ast_dummy_channel_alloc())) {
04480          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04481          ast_str_substitute_variables(&str1, 0, ast, e_subj);
04482          if (check_mime(ast_str_buffer(str1))) {
04483             int first_line = 1;
04484             char *ptr;
04485             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04486             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04487                *ptr = '\0';
04488                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04489                first_line = 0;
04490                /* Substring is smaller, so this will never grow */
04491                ast_str_set(&str2, 0, "%s", ptr + 1);
04492             }
04493             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04494          } else {
04495             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04496          }
04497          ast = ast_channel_release(ast);
04498       } else {
04499          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04500       }
04501    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04502       if (ast_strlen_zero(flag)) {
04503          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04504       } else {
04505          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04506       }
04507    } else {
04508       if (ast_strlen_zero(flag)) {
04509          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04510       } else {
04511          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04512       }
04513    }
04514 
04515    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1,
04516       (unsigned int) ast_random(), mailbox, (int) getpid(), host);
04517    if (imap) {
04518       /* additional information needed for IMAP searching */
04519       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04520       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04521       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04522       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04523 #ifdef IMAP_STORAGE
04524       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04525 #else
04526       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04527 #endif
04528       /* flag added for Urgent */
04529       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04530       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04531       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04532       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04533       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04534       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04535       if (!ast_strlen_zero(category)) {
04536          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04537       } else {
04538          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04539       }
04540       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04541       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04542       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
04543    }
04544    if (!ast_strlen_zero(cidnum)) {
04545       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04546    }
04547    if (!ast_strlen_zero(cidname)) {
04548       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04549    }
04550    fprintf(p, "MIME-Version: 1.0" ENDL);
04551    if (attach_user_voicemail) {
04552       /* Something unique. */
04553       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox,
04554          (int) getpid(), (unsigned int) ast_random());
04555 
04556       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04557       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04558       fprintf(p, "--%s" ENDL, bound);
04559    }
04560    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04561    if (emailbody || vmu->emailbody) {
04562       char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
04563       struct ast_channel *ast;
04564       if ((ast = ast_dummy_channel_alloc())) {
04565          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04566          ast_str_substitute_variables(&str1, 0, ast, e_body);
04567 #ifdef IMAP_STORAGE
04568             {
04569                /* Convert body to native line terminators for IMAP backend */
04570                char *line = ast_str_buffer(str1), *next;
04571                do {
04572                   /* Terminate line before outputting it to the file */
04573                   if ((next = strchr(line, '\n'))) {
04574                      *next++ = '\0';
04575                   }
04576                   fprintf(p, "%s" ENDL, line);
04577                   line = next;
04578                } while (!ast_strlen_zero(line));
04579             }
04580 #else
04581          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04582 #endif
04583          ast = ast_channel_release(ast);
04584       } else {
04585          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04586       }
04587    } else if (msgnum > -1) {
04588       if (strcmp(vmu->mailbox, mailbox)) {
04589          /* Forwarded type */
04590          struct ast_config *msg_cfg;
04591          const char *v;
04592          int inttime;
04593          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04594          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04595          /* Retrieve info from VM attribute file */
04596          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04597          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04598          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04599             strcat(fromfile, ".txt");
04600          }
04601          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04602             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04603                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04604             }
04605 
04606             /* You might be tempted to do origdate, except that a) it's in the wrong
04607              * format, and b) it's missing for IMAP recordings. */
04608             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04609                struct timeval tv = { inttime, };
04610                struct ast_tm tm;
04611                ast_localtime(&tv, &tm, NULL);
04612                ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04613             }
04614             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04615                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04616                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04617                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04618                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04619                date, origcallerid, origdate);
04620             ast_config_destroy(msg_cfg);
04621          } else {
04622             goto plain_message;
04623          }
04624       } else {
04625 plain_message:
04626          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04627             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04628             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04629             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04630             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04631       }
04632    } else {
04633       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04634             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04635    }
04636 
04637    if (imap || attach_user_voicemail) {
04638       if (!ast_strlen_zero(attach2)) {
04639          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04640          ast_debug(5, "creating second attachment filename %s\n", filename);
04641          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04642          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04643          ast_debug(5, "creating attachment filename %s\n", filename);
04644          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04645       } else {
04646          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04647          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04648          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04649       }
04650    }
04651    ast_free(str1);
04652    ast_free(str2);
04653 }

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

01581 {
01582    return snprintf(dest, len, "%s/msg%04d", dir, num);
01583 }

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

Manager list voicemail users command.

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

11304 {
11305    struct ast_vm_user *vmu = NULL;
11306    const char *id = astman_get_header(m, "ActionID");
11307    char actionid[128] = "";
11308 
11309    if (!ast_strlen_zero(id))
11310       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11311 
11312    AST_LIST_LOCK(&users);
11313 
11314    if (AST_LIST_EMPTY(&users)) {
11315       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11316       AST_LIST_UNLOCK(&users);
11317       return RESULT_SUCCESS;
11318    }
11319    
11320    astman_send_ack(s, m, "Voicemail user list will follow");
11321    
11322    AST_LIST_TRAVERSE(&users, vmu, list) {
11323       char dirname[256];
11324 
11325 #ifdef IMAP_STORAGE
11326       int new, old;
11327       inboxcount(vmu->mailbox, &new, &old);
11328 #endif
11329       
11330       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11331       astman_append(s,
11332          "%s"
11333          "Event: VoicemailUserEntry\r\n"
11334          "VMContext: %s\r\n"
11335          "VoiceMailbox: %s\r\n"
11336          "Fullname: %s\r\n"
11337          "Email: %s\r\n"
11338          "Pager: %s\r\n"
11339          "ServerEmail: %s\r\n"
11340          "MailCommand: %s\r\n"
11341          "Language: %s\r\n"
11342          "TimeZone: %s\r\n"
11343          "Callback: %s\r\n"
11344          "Dialout: %s\r\n"
11345          "UniqueID: %s\r\n"
11346          "ExitContext: %s\r\n"
11347          "SayDurationMinimum: %d\r\n"
11348          "SayEnvelope: %s\r\n"
11349          "SayCID: %s\r\n"
11350          "AttachMessage: %s\r\n"
11351          "AttachmentFormat: %s\r\n"
11352          "DeleteMessage: %s\r\n"
11353          "VolumeGain: %.2f\r\n"
11354          "CanReview: %s\r\n"
11355          "CallOperator: %s\r\n"
11356          "MaxMessageCount: %d\r\n"
11357          "MaxMessageLength: %d\r\n"
11358          "NewMessageCount: %d\r\n"
11359 #ifdef IMAP_STORAGE
11360          "OldMessageCount: %d\r\n"
11361          "IMAPUser: %s\r\n"
11362 #endif
11363          "\r\n",
11364          actionid,
11365          vmu->context,
11366          vmu->mailbox,
11367          vmu->fullname,
11368          vmu->email,
11369          vmu->pager,
11370          vmu->serveremail,
11371          vmu->mailcmd,
11372          vmu->language,
11373          vmu->zonetag,
11374          vmu->callback,
11375          vmu->dialout,
11376          vmu->uniqueid,
11377          vmu->exit,
11378          vmu->saydurationm,
11379          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11380          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11381          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11382          vmu->attachfmt,
11383          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11384          vmu->volgain,
11385          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11386          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11387          vmu->maxmsg,
11388          vmu->maxsecs,
11389 #ifdef IMAP_STORAGE
11390          new, old, vmu->imapuser
11391 #else
11392          count_messages(vmu, dirname)
11393 #endif
11394          );
11395    }     
11396    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11397 
11398    AST_LIST_UNLOCK(&users);
11399 
11400    return RESULT_SUCCESS;
11401 }

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

Definition at line 11137 of file app_voicemail_odbcstorage.c.

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

11138 {
11139    while (poll_thread_run) {
11140       struct timespec ts = { 0, };
11141       struct timeval wait;
11142 
11143       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11144       ts.tv_sec = wait.tv_sec;
11145       ts.tv_nsec = wait.tv_usec * 1000;
11146 
11147       ast_mutex_lock(&poll_lock);
11148       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11149       ast_mutex_unlock(&poll_lock);
11150 
11151       if (!poll_thread_run)
11152          break;
11153 
11154       poll_subscribed_mailboxes();
11155    }
11156 
11157    return NULL;
11158 }

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

Definition at line 1641 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

01642 {
01643 #ifdef IMAP_STORAGE
01644    if (vmu && id == 0) {
01645       return vmu->imapfolder;
01646    }
01647 #endif
01648    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01649 }

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

Definition at line 5232 of file app_voicemail_odbcstorage.c.

References __has_voicemail().

05233 {
05234    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05235 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11160 of file app_voicemail_odbcstorage.c.

References ast_free, and mwi_sub.

11161 {
11162    ast_free(mwi_sub);
11163 }

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

Definition at line 11238 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(), handle_subscribe(), LOG_ERROR, and mwi_subscription_tps.

11239 {
11240    struct mwi_sub_task *mwist;
11241    
11242    if (ast_event_get_type(event) != AST_EVENT_SUB)
11243       return;
11244 
11245    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11246       return;
11247 
11248    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11249       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11250       return;
11251    }
11252    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11253    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11254    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11255    
11256    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11257       ast_free(mwist);
11258    }
11259 }

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

Definition at line 11222 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_taskprocessor_push(), handle_unsubscribe(), mwi_subscription_tps, and mwi_sub_task::uniqueid.

11223 {
11224    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11225    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11226       return;
11227 
11228    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11229       return;
11230 
11231    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11232    *uniqueid = u;
11233    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11234       ast_free(uniqueid);
11235    }
11236 }

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

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

06837 {
06838    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06839    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06840    const char *category;
06841    char *myserveremail = serveremail;
06842 
06843    ast_channel_lock(chan);
06844    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06845       category = ast_strdupa(category);
06846    }
06847    ast_channel_unlock(chan);
06848 
06849 #ifndef IMAP_STORAGE
06850    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06851 #else
06852    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
06853 #endif
06854    make_file(fn, sizeof(fn), todir, msgnum);
06855    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06856 
06857    if (!ast_strlen_zero(vmu->attachfmt)) {
06858       if (strstr(fmt, vmu->attachfmt))
06859          fmt = vmu->attachfmt;
06860       else
06861          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);
06862    }
06863 
06864    /* Attach only the first format */
06865    fmt = ast_strdupa(fmt);
06866    stringp = fmt;
06867    strsep(&stringp, "|");
06868 
06869    if (!ast_strlen_zero(vmu->serveremail))
06870       myserveremail = vmu->serveremail;
06871 
06872    if (!ast_strlen_zero(vmu->email)) {
06873       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06874 
06875       if (attach_user_voicemail)
06876          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06877 
06878       /* XXX possible imap issue, should category be NULL XXX */
06879       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06880 
06881       if (attach_user_voicemail)
06882          DISPOSE(todir, msgnum);
06883    }
06884 
06885    if (!ast_strlen_zero(vmu->pager)) {
06886       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
06887    }
06888 
06889    if (ast_test_flag(vmu, VM_DELETE))
06890       DELETE(todir, msgnum, fn, vmu);
06891 
06892    /* Leave voicemail for someone */
06893    if (ast_app_has_voicemail(ext_context, NULL)) 
06894       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06895 
06896    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06897 
06898    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);
06899    run_externnotify(vmu->context, vmu->mailbox, flag);
06900 
06901 #ifdef IMAP_STORAGE
06902    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06903    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06904       vm_imap_delete(NULL, vms->curmsg, vmu);
06905       vms->newmessages--;  /* Fix new message count */
06906    }
06907 #endif
06908 
06909    return 0;
06910 }

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

utility used by base_encode()

Definition at line 4106 of file app_voicemail_odbcstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

04107 {
04108    if (bio->linelength >= BASELINELEN) {
04109       if (fputs(ENDL, so) == EOF) {
04110          return -1;
04111       }
04112 
04113       bio->linelength = 0;
04114    }
04115 
04116    if (putc(((unsigned char) c), so) == EOF) {
04117       return -1;
04118    }
04119 
04120    bio->linelength++;
04121 
04122    return 1;
04123 }

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

Definition at line 7670 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(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

07671 {
07672    int count_msg, last_msg;
07673 
07674    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07675 
07676    /* Rename the member vmbox HERE so that we don't try to return before
07677     * we know what's going on.
07678     */
07679    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07680 
07681    /* Faster to make the directory than to check if it exists. */
07682    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07683 
07684    /* traverses directory using readdir (or select query for ODBC) */
07685    count_msg = count_messages(vmu, vms->curdir);
07686    if (count_msg < 0) {
07687       return count_msg;
07688    } else {
07689       vms->lastmsg = count_msg - 1;
07690    }
07691 
07692    if (vm_allocate_dh(vms, vmu, count_msg)) {
07693       return -1;
07694    }
07695 
07696    /*
07697    The following test is needed in case sequencing gets messed up.
07698    There appears to be more than one way to mess up sequence, so
07699    we will not try to find all of the root causes--just fix it when
07700    detected.
07701    */
07702 
07703    if (vm_lock_path(vms->curdir)) {
07704       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07705       return ERROR_LOCK_PATH;
07706    }
07707 
07708    /* for local storage, checks directory for messages up to maxmsg limit */
07709    last_msg = last_message_index(vmu, vms->curdir);
07710    ast_unlock_path(vms->curdir);
07711 
07712    if (last_msg < -1) {
07713       return last_msg;
07714    } else if (vms->lastmsg != last_msg) {
07715       ast_log(LOG_NOTICE, "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);
07716    }
07717 
07718    return 0;
07719 }

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

Definition at line 7456 of file app_voicemail_odbcstorage.c.

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

07457 {
07458    int res = 0;
07459    char filename[256], *cid;
07460    const char *origtime, *context, *category, *duration, *flag;
07461    struct ast_config *msg_cfg;
07462    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07463 
07464    vms->starting = 0;
07465    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07466    adsi_message(chan, vms);
07467    if (!vms->curmsg)
07468       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07469    else if (vms->curmsg == vms->lastmsg)
07470       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07471 
07472    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07473    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07474    msg_cfg = ast_config_load(filename, config_flags);
07475    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07476       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07477       return 0;
07478    }
07479    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07480 
07481    /* Play the word urgent if we are listening to urgent messages */
07482    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07483       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07484    }
07485 
07486    if (!res) {
07487       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07488       /* POLISH syntax */
07489       if (!strncasecmp(chan->language, "pl", 2)) {
07490          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07491             int ten, one;
07492             char nextmsg[256];
07493             ten = (vms->curmsg + 1) / 10;
07494             one = (vms->curmsg + 1) % 10;
07495 
07496             if (vms->curmsg < 20) {
07497                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07498                res = wait_file2(chan, vms, nextmsg);
07499             } else {
07500                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07501                res = wait_file2(chan, vms, nextmsg);
07502                if (one > 0) {
07503                   if (!res) {
07504                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07505                      res = wait_file2(chan, vms, nextmsg);
07506                   }
07507                }
07508             }
07509          }
07510          if (!res)
07511             res = wait_file2(chan, vms, "vm-message");
07512       /* HEBREW syntax */
07513       } else if (!strncasecmp(chan->language, "he", 2)) {
07514          if (!vms->curmsg) {
07515             res = wait_file2(chan, vms, "vm-message");
07516             res = wait_file2(chan, vms, "vm-first");
07517          } else if (vms->curmsg == vms->lastmsg) {
07518             res = wait_file2(chan, vms, "vm-message");
07519             res = wait_file2(chan, vms, "vm-last");
07520          } else {
07521             res = wait_file2(chan, vms, "vm-message");
07522             res = wait_file2(chan, vms, "vm-number");
07523             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07524          }
07525       /* VIETNAMESE syntax */
07526       } else if (!strncasecmp(chan->language, "vi", 2)) {
07527          if (!vms->curmsg) {
07528             res = wait_file2(chan, vms, "vm-message");
07529             res = wait_file2(chan, vms, "vm-first");
07530          } else if (vms->curmsg == vms->lastmsg) {
07531             res = wait_file2(chan, vms, "vm-message");
07532             res = wait_file2(chan, vms, "vm-last");
07533          } else {
07534             res = wait_file2(chan, vms, "vm-message");
07535             res = wait_file2(chan, vms, "vm-number");
07536             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07537          }
07538       } else {
07539          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07540             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07541          } else { /* DEFAULT syntax */
07542             res = wait_file2(chan, vms, "vm-message");
07543          }
07544          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07545             if (!res) {
07546                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07547             }
07548          }
07549       }
07550    }
07551 
07552    if (!msg_cfg) {
07553       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07554       return 0;
07555    }
07556 
07557    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07558       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07559       DISPOSE(vms->curdir, vms->curmsg);
07560       ast_config_destroy(msg_cfg);
07561       return 0;
07562    }
07563 
07564    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07565    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07566    category = ast_variable_retrieve(msg_cfg, "message", "category");
07567 
07568    context = ast_variable_retrieve(msg_cfg, "message", "context");
07569    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07570       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07571    if (!res) {
07572       res = play_message_category(chan, category);
07573    }
07574    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07575       res = play_message_datetime(chan, vmu, origtime, filename);
07576    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07577       res = play_message_callerid(chan, vms, cid, context, 0);
07578    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07579       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07580    /* Allow pressing '1' to skip envelope / callerid */
07581    if (res == '1')
07582       res = 0;
07583    ast_config_destroy(msg_cfg);
07584 
07585    if (!res) {
07586       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07587       vms->heard[vms->curmsg] = 1;
07588 #ifdef IMAP_STORAGE
07589       /*IMAP storage stores any prepended message from a forward
07590        * as a separate file from the rest of the message
07591        */
07592       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07593          wait_file(chan, vms, vms->introfn);
07594       }
07595 #endif
07596       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07597          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07598          res = 0;
07599       }
07600    }
07601    DISPOSE(vms->curdir, vms->curmsg);
07602    return res;
07603 }

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

Definition at line 7342 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, cidinternalcontexts, ast_channel::language, MAX_NUM_CID_CONTEXTS, and wait_file2().

07343 {
07344    int res = 0;
07345    int i;
07346    char *callerid, *name;
07347    char prefile[PATH_MAX] = "";
07348    
07349 
07350    /* If voicemail cid is not enabled, or we didn't get cid or context from
07351     * the attribute file, leave now.
07352     *
07353     * TODO Still need to change this so that if this function is called by the
07354     * message envelope (and someone is explicitly requesting to hear the CID),
07355     * it does not check to see if CID is enabled in the config file.
07356     */
07357    if ((cid == NULL)||(context == NULL))
07358       return res;
07359 
07360    /* Strip off caller ID number from name */
07361    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07362    ast_callerid_parse(cid, &name, &callerid);
07363    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07364       /* Check for internal contexts and only */
07365       /* say extension when the call didn't come from an internal context in the list */
07366       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07367          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07368          if ((strcmp(cidinternalcontexts[i], context) == 0))
07369             break;
07370       }
07371       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07372          if (!res) {
07373             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07374             if (!ast_strlen_zero(prefile)) {
07375             /* See if we can find a recorded name for this person instead of their extension number */
07376                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07377                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07378                   if (!callback)
07379                      res = wait_file2(chan, vms, "vm-from");
07380                   res = ast_stream_and_wait(chan, prefile, "");
07381                } else {
07382                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07383                   /* Say "from extension" as one saying to sound smoother */
07384                   if (!callback)
07385                      res = wait_file2(chan, vms, "vm-from-extension");
07386                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07387                }
07388             }
07389          }
07390       } else if (!res) {
07391          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07392          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07393          if (!callback)
07394             res = wait_file2(chan, vms, "vm-from-phonenumber");
07395          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07396       }
07397    } else {
07398       /* Number unknown */
07399       ast_debug(1, "VM-CID: From an unknown number\n");
07400       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07401       res = wait_file2(chan, vms, "vm-unknown-caller");
07402    }
07403    return res;
07404 }

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

Definition at line 7253 of file app_voicemail_odbcstorage.c.

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

07254 {
07255    int res = 0;
07256 
07257    if (!ast_strlen_zero(category))
07258       res = ast_play_and_wait(chan, category);
07259 
07260    if (res) {
07261       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07262       res = 0;
07263    }
07264 
07265    return res;
07266 }

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

Definition at line 7268 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_say_date_with_format, ast_strlen_zero(), ast_tvnow(), ast_channel::language, vm_zone::list, vm_zone::msg_format, vm_zone::name, pbx_builtin_setvar_helper(), vm_zone::timezone, and ast_vm_user::zonetag.

07269 {
07270    int res = 0;
07271    struct vm_zone *the_zone = NULL;
07272    time_t t;
07273 
07274    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07275       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07276       return 0;
07277    }
07278 
07279    /* Does this user have a timezone specified? */
07280    if (!ast_strlen_zero(vmu->zonetag)) {
07281       /* Find the zone in the list */
07282       struct vm_zone *z;
07283       AST_LIST_LOCK(&zones);
07284       AST_LIST_TRAVERSE(&zones, z, list) {
07285          if (!strcmp(z->name, vmu->zonetag)) {
07286             the_zone = z;
07287             break;
07288          }
07289       }
07290       AST_LIST_UNLOCK(&zones);
07291    }
07292 
07293 /* No internal variable parsing for now, so we'll comment it out for the time being */
07294 #if 0
07295    /* Set the DIFF_* variables */
07296    ast_localtime(&t, &time_now, NULL);
07297    tv_now = ast_tvnow();
07298    ast_localtime(&tv_now, &time_then, NULL);
07299 
07300    /* Day difference */
07301    if (time_now.tm_year == time_then.tm_year)
07302       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07303    else
07304       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07305    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07306 
07307    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07308 #endif
07309    if (the_zone) {
07310       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07311    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07312       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07313    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07314       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07315    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07316       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);
07317    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07318       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07319    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07320       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07321    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07322       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07323    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07324       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);
07325    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07326       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07327    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07328       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07329    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07330       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);
07331    } else {
07332       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07333    }
07334 #if 0
07335    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07336 #endif
07337    return res;
07338 }

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

Definition at line 7406 of file app_voicemail_odbcstorage.c.

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

07407 {
07408    int res = 0;
07409    int durationm;
07410    int durations;
07411    /* Verify that we have a duration for the message */
07412    if (duration == NULL)
07413       return res;
07414 
07415    /* Convert from seconds to minutes */
07416    durations = atoi(duration);
07417    durationm = (durations / 60);
07418 
07419    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07420 
07421    if ((!res) && (durationm >= minduration)) {
07422       res = wait_file2(chan, vms, "vm-duration");
07423 
07424       /* POLISH syntax */
07425       if (!strncasecmp(chan->language, "pl", 2)) {
07426          div_t num = div(durationm, 10);
07427 
07428          if (durationm == 1) {
07429             res = ast_play_and_wait(chan, "digits/1z");
07430             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07431          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07432             if (num.rem == 2) {
07433                if (!num.quot) {
07434                   res = ast_play_and_wait(chan, "digits/2-ie");
07435                } else {
07436                   res = say_and_wait(chan, durationm - 2 , chan->language);
07437                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07438                }
07439             } else {
07440                res = say_and_wait(chan, durationm, chan->language);
07441             }
07442             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07443          } else {
07444             res = say_and_wait(chan, durationm, chan->language);
07445             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07446          }
07447       /* DEFAULT syntax */
07448       } else {
07449          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07450          res = wait_file2(chan, vms, "vm-minutes");
07451       }
07452    }
07453    return res;
07454 }

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,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 12951 of file app_voicemail_odbcstorage.c.

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

12954 {
12955    /* Record message & let caller review or re-record it, or set options if applicable */
12956    int res = 0;
12957    int cmd = 0;
12958    int max_attempts = 3;
12959    int attempts = 0;
12960    int recorded = 0;
12961    int msg_exists = 0;
12962    signed char zero_gain = 0;
12963    char tempfile[PATH_MAX];
12964    char *acceptdtmf = "#";
12965    char *canceldtmf = "";
12966    int canceleddtmf = 0;
12967 
12968    /* Note that urgent and private are for flagging messages as such in the future */
12969 
12970    /* barf if no pointer passed to store duration in */
12971    if (duration == NULL) {
12972       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
12973       return -1;
12974    }
12975 
12976    if (!outsidecaller)
12977       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
12978    else
12979       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
12980 
12981    cmd = '3';  /* Want to start by recording */
12982 
12983    while ((cmd >= 0) && (cmd != 't')) {
12984       switch (cmd) {
12985       case '1':
12986          if (!msg_exists) {
12987             /* In this case, 1 is to record a message */
12988             cmd = '3';
12989             break;
12990          } else {
12991             /* Otherwise 1 is to save the existing message */
12992             ast_verb(3, "Saving message as is\n");
12993             if (!outsidecaller) 
12994                ast_filerename(tempfile, recordfile, NULL);
12995             ast_stream_and_wait(chan, "vm-msgsaved", "");
12996             if (!outsidecaller) {
12997                /* Saves to IMAP server only if imapgreeting=yes */
12998                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
12999                DISPOSE(recordfile, -1);
13000             }
13001             cmd = 't';
13002             return res;
13003          }
13004       case '2':
13005          /* Review */
13006          ast_verb(3, "Reviewing the message\n");
13007          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13008          break;
13009       case '3':
13010          msg_exists = 0;
13011          /* Record */
13012          if (recorded == 1) 
13013             ast_verb(3, "Re-recording the message\n");
13014          else  
13015             ast_verb(3, "Recording the message\n");
13016          
13017          if (recorded && outsidecaller) {
13018             cmd = ast_play_and_wait(chan, INTRO);
13019             cmd = ast_play_and_wait(chan, "beep");
13020          }
13021          recorded = 1;
13022          /* 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 */
13023          if (record_gain)
13024             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13025          if (ast_test_flag(vmu, VM_OPERATOR))
13026             canceldtmf = "0";
13027          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13028          if (strchr(canceldtmf, cmd)) {
13029          /* need this flag here to distinguish between pressing '0' during message recording or after */
13030             canceleddtmf = 1;
13031          }
13032          if (record_gain)
13033             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13034          if (cmd == -1) {
13035             /* User has hung up, no options to give */
13036             if (!outsidecaller) {
13037                /* user was recording a greeting and they hung up, so let's delete the recording. */
13038                ast_filedelete(tempfile, NULL);
13039             }     
13040             return cmd;
13041          }
13042          if (cmd == '0') {
13043             break;
13044          } else if (cmd == '*') {
13045             break;
13046 #if 0
13047          } else if (vmu->review && (*duration < 5)) {
13048             /* Message is too short */
13049             ast_verb(3, "Message too short\n");
13050             cmd = ast_play_and_wait(chan, "vm-tooshort");
13051             cmd = ast_filedelete(tempfile, NULL);
13052             break;
13053          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
13054             /* Message is all silence */
13055             ast_verb(3, "Nothing recorded\n");
13056             cmd = ast_filedelete(tempfile, NULL);
13057             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13058             if (!cmd)
13059                cmd = ast_play_and_wait(chan, "vm-speakup");
13060             break;
13061 #endif
13062          } else {
13063             /* If all is well, a message exists */
13064             msg_exists = 1;
13065             cmd = 0;
13066          }
13067          break;
13068       case '4':
13069          if (outsidecaller) {  /* only mark vm messages */
13070             /* Mark Urgent */
13071             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13072                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13073                res = ast_play_and_wait(chan, "vm-marked-urgent");
13074                strcpy(flag, "Urgent");
13075             } else if (flag) {
13076                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13077                res = ast_play_and_wait(chan, "vm-urgent-removed");
13078                strcpy(flag, "");
13079             } else {
13080                ast_play_and_wait(chan, "vm-sorry");
13081             }
13082             cmd = 0;
13083          } else {
13084             cmd = ast_play_and_wait(chan, "vm-sorry");
13085          }
13086          break;
13087       case '5':
13088       case '6':
13089       case '7':
13090       case '8':
13091       case '9':
13092       case '*':
13093       case '#':
13094          cmd = ast_play_and_wait(chan, "vm-sorry");
13095          break;
13096 #if 0 
13097 /*  XXX Commented out for the moment because of the dangers of deleting
13098     a message while recording (can put the message numbers out of sync) */
13099       case '*':
13100          /* Cancel recording, delete message, offer to take another message*/
13101          cmd = ast_play_and_wait(chan, "vm-deleted");
13102          cmd = ast_filedelete(tempfile, NULL);
13103          if (outsidecaller) {
13104             res = vm_exec(chan, NULL);
13105             return res;
13106          }
13107          else
13108             return 1;
13109 #endif
13110       case '0':
13111          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13112             cmd = ast_play_and_wait(chan, "vm-sorry");
13113             break;
13114          }
13115          if (msg_exists || recorded) {
13116             cmd = ast_play_and_wait(chan, "vm-saveoper");
13117             if (!cmd)
13118                cmd = ast_waitfordigit(chan, 3000);
13119             if (cmd == '1') {
13120                ast_filerename(tempfile, recordfile, NULL);
13121                ast_play_and_wait(chan, "vm-msgsaved");
13122                cmd = '0';
13123             } else if (cmd == '4') {
13124                if (flag) {
13125                   ast_play_and_wait(chan, "vm-marked-urgent");
13126                   strcpy(flag, "Urgent");
13127                }
13128                ast_play_and_wait(chan, "vm-msgsaved");
13129                cmd = '0';
13130             } else {
13131                ast_play_and_wait(chan, "vm-deleted");
13132                DELETE(tempfile, -1, tempfile, vmu);
13133                cmd = '0';
13134             }
13135          }
13136          return cmd;
13137       default:
13138          /* If the caller is an ouside caller, and the review option is enabled,
13139             allow them to review the message, but let the owner of the box review
13140             their OGM's */
13141          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13142             return cmd;
13143          if (msg_exists) {
13144             cmd = ast_play_and_wait(chan, "vm-review");
13145             if (!cmd && outsidecaller) {
13146                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13147                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13148                } else if (flag) {
13149                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13150                }
13151             }
13152          } else {
13153             cmd = ast_play_and_wait(chan, "vm-torerecord");
13154             if (!cmd)
13155                cmd = ast_waitfordigit(chan, 600);
13156          }
13157          
13158          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13159             cmd = ast_play_and_wait(chan, "vm-reachoper");
13160             if (!cmd)
13161                cmd = ast_waitfordigit(chan, 600);
13162          }
13163 #if 0
13164          if (!cmd)
13165             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13166 #endif
13167          if (!cmd)
13168             cmd = ast_waitfordigit(chan, 6000);
13169          if (!cmd) {
13170             attempts++;
13171          }
13172          if (attempts > max_attempts) {
13173             cmd = 't';
13174          }
13175       }
13176    }
13177    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13178       /* Hang up or timeout, so delete the recording. */
13179       ast_filedelete(tempfile, NULL);
13180    }
13181 
13182    if (cmd != 't' && outsidecaller)
13183       ast_play_and_wait(chan, "vm-goodbye");
13184 
13185    return cmd;
13186 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11109 of file app_voicemail_odbcstorage.c.

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

11110 {
11111    int new = 0, old = 0, urgent = 0;
11112 
11113    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11114 
11115    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11116       mwi_sub->old_urgent = urgent;
11117       mwi_sub->old_new = new;
11118       mwi_sub->old_old = old;
11119       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11120       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11121    }
11122 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11124 of file app_voicemail_odbcstorage.c.

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

11125 {
11126    struct mwi_sub *mwi_sub;
11127 
11128    AST_RWLIST_RDLOCK(&mwi_subs);
11129    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11130       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11131          poll_subscribed_mailbox(mwi_sub);
11132       }
11133    }
11134    AST_RWLIST_UNLOCK(&mwi_subs);
11135 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

Definition at line 969 of file app_voicemail_odbcstorage.c.

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

00970 {
00971    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00972    vmu->passwordlocation = passwordlocation;
00973    if (saydurationminfo) {
00974       vmu->saydurationm = saydurationminfo;
00975    }
00976    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00977    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00978    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00979    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00980    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
00981    if (vmminsecs) {
00982       vmu->minsecs = vmminsecs;
00983    }
00984    if (vmmaxsecs) {
00985       vmu->maxsecs = vmmaxsecs;
00986    }
00987    if (maxmsg) {
00988       vmu->maxmsg = maxmsg;
00989    }
00990    if (maxdeletedmsg) {
00991       vmu->maxdeletedmsg = maxdeletedmsg;
00992    }
00993    vmu->volgain = volgain;
00994    vmu->emailsubject = NULL;
00995    vmu->emailbody = NULL;
00996 #ifdef IMAP_STORAGE
00997    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
00998 #endif
00999 }

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 4194 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, config_flags, ast_vm_user::context, emaildateformat, ast_vm_user::fullname, ast_vm_user::locale, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, pbx_builtin_setvar_helper(), and S_OR.

04195 {
04196    char callerid[256];
04197    char num[12];
04198    char fromdir[256], fromfile[256];
04199    struct ast_config *msg_cfg;
04200    const char *origcallerid, *origtime;
04201    char origcidname[80], origcidnum[80], origdate[80];
04202    int inttime;
04203    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04204 
04205    /* Prepare variables for substitution in email body and subject */
04206    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04207    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04208    snprintf(num, sizeof(num), "%d", msgnum);
04209    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04210    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04211    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04212    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04213       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04214    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04215    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04216    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04217    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04218    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04219 
04220    /* Retrieve info from VM attribute file */
04221    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04222    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04223    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04224       strcat(fromfile, ".txt");
04225    }
04226    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04227       if (option_debug > 0) {
04228          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04229       }
04230       return;
04231    }
04232 
04233    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04234       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04235       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04236       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04237       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04238    }
04239 
04240    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04241       struct timeval tv = { inttime, };
04242       struct ast_tm tm;
04243       ast_localtime(&tv, &tm, NULL);
04244       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04245       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04246    }
04247    ast_config_destroy(msg_cfg);
04248 }

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

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

06800 {
06801    struct ast_event *event;
06802    char *mailbox, *context;
06803 
06804    /* Strip off @default */
06805    context = mailbox = ast_strdupa(box);
06806    strsep(&context, "@");
06807    if (ast_strlen_zero(context))
06808       context = "default";
06809 
06810    if (!(event = ast_event_new(AST_EVENT_MWI,
06811          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06812          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06813          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06814          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06815          AST_EVENT_IE_END))) {
06816       return;
06817    }
06818 
06819    ast_event_queue_and_cache(event);
06820 }

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

Definition at line 12168 of file app_voicemail_odbcstorage.c.

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

12168                                                                                            {
12169    struct ast_config *pwconf;
12170    struct ast_flags config_flags = { 0 };
12171 
12172    pwconf = ast_config_load(secretfn, config_flags);
12173    if (pwconf) {
12174       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12175       if (val) {
12176          ast_copy_string(password, val, passwordlen);
12177          return;
12178       }
12179    }
12180    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12181 }

static int reload ( void   )  [static]

Definition at line 12605 of file app_voicemail_odbcstorage.c.

References load_config().

12606 {
12607    return load_config(1);
12608 }

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

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

03872 {
03873    char stxt[PATH_MAX];
03874    char dtxt[PATH_MAX];
03875    ast_filerename(sfn, dfn, NULL);
03876    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03877    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03878    if (ast_check_realtime("voicemail_data")) {
03879       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03880    }
03881    rename(stxt, dtxt);
03882 }

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 1413 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::list, ast_vm_user::mailbox, and ast_vm_user::password.

01414 {
01415    /* This function could be made to generate one from a database, too */
01416    struct ast_vm_user *cur;
01417    int res = -1;
01418    AST_LIST_LOCK(&users);
01419    AST_LIST_TRAVERSE(&users, cur, list) {
01420       if ((!context || !strcasecmp(context, cur->context)) &&
01421          (!strcasecmp(mailbox, cur->mailbox)))
01422             break;
01423    }
01424    if (cur) {
01425       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01426       res = 0;
01427    }
01428    AST_LIST_UNLOCK(&users);
01429    return res;
01430 }

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

Definition at line 5375 of file app_voicemail_odbcstorage.c.

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

05376 {
05377    char arguments[255];
05378    char ext_context[256] = "";
05379    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05380    struct ast_smdi_mwi_message *mwi_msg;
05381 
05382    if (!ast_strlen_zero(context))
05383       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05384    else
05385       ast_copy_string(ext_context, extension, sizeof(ext_context));
05386 
05387    if (smdi_iface) {
05388       if (ast_app_has_voicemail(ext_context, NULL)) 
05389          ast_smdi_mwi_set(smdi_iface, extension);
05390       else
05391          ast_smdi_mwi_unset(smdi_iface, extension);
05392 
05393       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05394          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05395          if (!strncmp(mwi_msg->cause, "INV", 3))
05396             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05397          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05398             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05399          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05400          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05401       } else {
05402          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05403       }
05404    }
05405 
05406    if (!ast_strlen_zero(externnotify)) {
05407       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05408          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05409       } else {
05410          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05411          ast_debug(1, "Executing %s\n", arguments);
05412          ast_safe_system(arguments);
05413       }
05414    }
05415 }

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

Definition at line 6007 of file app_voicemail_odbcstorage.c.

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

06008 {
06009 #ifdef IMAP_STORAGE
06010    /* we must use mbox(x) folder names, and copy the message there */
06011    /* simple. huh? */
06012    char sequence[10];
06013    char mailbox[256];
06014    int res;
06015 
06016    /* get the real IMAP message number for this message */
06017    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06018    
06019    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06020    ast_mutex_lock(&vms->lock);
06021    /* if save to Old folder, put in INBOX as read */
06022    if (box == OLD_FOLDER) {
06023       mail_setflag(vms->mailstream, sequence, "\\Seen");
06024       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06025    } else if (box == NEW_FOLDER) {
06026       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06027       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06028    }
06029    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06030       ast_mutex_unlock(&vms->lock);
06031       return 0;
06032    }
06033    /* Create the folder if it don't exist */
06034    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06035    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06036    if (mail_create(vms->mailstream, mailbox) == NIL) 
06037       ast_debug(5, "Folder exists.\n");
06038    else
06039       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06040    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06041    ast_mutex_unlock(&vms->lock);
06042    return res;
06043 #else
06044    char *dir = vms->curdir;
06045    char *username = vms->username;
06046    char *context = vmu->context;
06047    char sfn[PATH_MAX];
06048    char dfn[PATH_MAX];
06049    char ddir[PATH_MAX];
06050    const char *dbox = mbox(vmu, box);
06051    int x, i;
06052    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06053 
06054    if (vm_lock_path(ddir))
06055       return ERROR_LOCK_PATH;
06056 
06057    x = last_message_index(vmu, ddir) + 1;
06058 
06059    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06060       x--;
06061       for (i = 1; i <= x; i++) {
06062          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06063          make_file(sfn, sizeof(sfn), ddir, i);
06064          make_file(dfn, sizeof(dfn), ddir, i - 1);
06065          if (EXISTS(ddir, i, sfn, NULL)) {
06066             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06067          } else
06068             break;
06069       }
06070    } else {
06071       if (x >= vmu->maxmsg) {
06072          ast_unlock_path(ddir);
06073          return -1;
06074       }
06075    }
06076    make_file(sfn, sizeof(sfn), dir, msg);
06077    make_file(dfn, sizeof(dfn), ddir, x);
06078    if (strcmp(sfn, dfn)) {
06079       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06080    }
06081    ast_unlock_path(ddir);
06082 #endif
06083    return 0;
06084 }

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

Definition at line 6000 of file app_voicemail_odbcstorage.c.

References AST_DIGIT_ANY, and ast_say_number().

06001 {
06002    int d;
06003    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06004    return d;
06005 }

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

Definition at line 12154 of file app_voicemail_odbcstorage.c.

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

12155 {
12156    int res = -1;
12157    char dir[PATH_MAX];
12158    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12159    ast_debug(2, "About to try retrieving name file %s\n", dir);
12160    RETRIEVE(dir, -1, mailbox, context);
12161    if (ast_fileexists(dir, NULL, NULL)) {
12162       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12163    }
12164    DISPOSE(dir, -1);
12165    return res;
12166 }

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

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

04708 {
04709    FILE *p = NULL;
04710    char tmp[80] = "/tmp/astmail-XXXXXX";
04711    char tmp2[256];
04712    char *stringp;
04713 
04714    if (vmu && ast_strlen_zero(vmu->email)) {
04715       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04716       return(0);
04717    }
04718 
04719    /* Mail only the first format */
04720    format = ast_strdupa(format);
04721    stringp = format;
04722    strsep(&stringp, "|");
04723 
04724    if (!strcmp(format, "wav49"))
04725       format = "WAV";
04726    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));
04727    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04728       command hangs */
04729    if ((p = vm_mkftemp(tmp)) == NULL) {
04730       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04731       return -1;
04732    } else {
04733       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04734       fclose(p);
04735       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04736       ast_safe_system(tmp2);
04737       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04738    }
04739    return 0;
04740 }

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

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

04743 {
04744    char enc_cidnum[256], enc_cidname[256];
04745    char date[256];
04746    char host[MAXHOSTNAMELEN] = "";
04747    char who[256];
04748    char dur[PATH_MAX];
04749    char tmp[80] = "/tmp/astmail-XXXXXX";
04750    char tmp2[PATH_MAX];
04751    struct ast_tm tm;
04752    FILE *p;
04753    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04754 
04755    if (!str1 || !str2) {
04756       ast_free(str1);
04757       ast_free(str2);
04758       return -1;
04759    }
04760 
04761    if (cidnum) {
04762       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04763    }
04764    if (cidname) {
04765       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04766    }
04767 
04768    if ((p = vm_mkftemp(tmp)) == NULL) {
04769       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04770       ast_free(str1);
04771       ast_free(str2);
04772       return -1;
04773    }
04774    gethostname(host, sizeof(host)-1);
04775    if (strchr(srcemail, '@')) {
04776       ast_copy_string(who, srcemail, sizeof(who));
04777    } else {
04778       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04779    }
04780    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04781    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04782    fprintf(p, "Date: %s\n", date);
04783 
04784    /* Reformat for custom pager format */
04785    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04786 
04787    if (!ast_strlen_zero(pagerfromstring)) {
04788       struct ast_channel *ast;
04789       if ((ast = ast_dummy_channel_alloc())) {
04790          char *ptr;
04791          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04792          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04793 
04794          if (check_mime(ast_str_buffer(str1))) {
04795             int first_line = 1;
04796             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04797             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04798                *ptr = '\0';
04799                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04800                first_line = 0;
04801                /* Substring is smaller, so this will never grow */
04802                ast_str_set(&str2, 0, "%s", ptr + 1);
04803             }
04804             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04805          } else {
04806             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04807          }
04808          ast = ast_channel_release(ast);
04809       } else {
04810          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04811       }
04812    } else {
04813       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04814    }
04815 
04816    if (check_mime(vmu->fullname)) {
04817       int first_line = 1;
04818       char *ptr;
04819       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04820       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04821          *ptr = '\0';
04822          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04823          first_line = 0;
04824          /* Substring is smaller, so this will never grow */
04825          ast_str_set(&str2, 0, "%s", ptr + 1);
04826       }
04827       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04828    } else {
04829       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
04830    }
04831 
04832    if (!ast_strlen_zero(pagersubject)) {
04833       struct ast_channel *ast;
04834       if ((ast = ast_dummy_channel_alloc())) {
04835          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04836          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
04837          if (check_mime(ast_str_buffer(str1))) {
04838             int first_line = 1;
04839             char *ptr;
04840             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04841             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04842                *ptr = '\0';
04843                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04844                first_line = 0;
04845                /* Substring is smaller, so this will never grow */
04846                ast_str_set(&str2, 0, "%s", ptr + 1);
04847             }
04848             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04849          } else {
04850             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04851          }
04852          ast = ast_channel_release(ast);
04853       } else {
04854          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04855       }
04856    } else {
04857       if (ast_strlen_zero(flag)) {
04858          fprintf(p, "Subject: New VM\n\n");
04859       } else {
04860          fprintf(p, "Subject: New %s VM\n\n", flag);
04861       }
04862    }
04863 
04864    if (pagerbody) {
04865       struct ast_channel *ast;
04866       if ((ast = ast_dummy_channel_alloc())) {
04867          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04868          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
04869          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04870          ast = ast_channel_release(ast);
04871       } else {
04872          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04873       }
04874    } else {
04875       fprintf(p, "New %s long %s msg in box %s\n"
04876             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04877    }
04878 
04879    fclose(p);
04880    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04881    ast_safe_system(tmp2);
04882    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04883    ast_free(str1);
04884    ast_free(str2);
04885    return 0;
04886 }

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

Definition at line 10766 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, SENTINEL, and var.

10767 {
10768    struct ast_config *cfg;
10769    const char *cat = NULL;
10770 
10771    if (!(cfg = ast_load_realtime_multientry("voicemail", 
10772       "context", context, SENTINEL))) {
10773       return CLI_FAILURE;
10774    }
10775 
10776    ast_cli(fd,
10777       "\n"
10778       "=============================================================\n"
10779       "=== Configured Voicemail Users ==============================\n"
10780       "=============================================================\n"
10781       "===\n");
10782 
10783    while ((cat = ast_category_browse(cfg, cat))) {
10784       struct ast_variable *var = NULL;
10785       ast_cli(fd,
10786          "=== Mailbox ...\n"
10787          "===\n");
10788       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
10789          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
10790       ast_cli(fd,
10791          "===\n"
10792          "=== ---------------------------------------------------------\n"
10793          "===\n");
10794    }
10795 
10796    ast_cli(fd,
10797       "=============================================================\n"
10798       "\n");
10799 
10800    ast_config_destroy(cfg);
10801 
10802    return CLI_SUCCESS;
10803 }

static void start_poll_thread ( void   )  [static]

Definition at line 11261 of file app_voicemail_odbcstorage.c.

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

static void stop_poll_thread ( void   )  [static]

Definition at line 11279 of file app_voicemail_odbcstorage.c.

References ast_cond_signal, ast_event_unsubscribe(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, mwi_sub_sub, mwi_unsub_sub, and poll_lock.

11280 {
11281    poll_thread_run = 0;
11282 
11283    if (mwi_sub_sub) {
11284       ast_event_unsubscribe(mwi_sub_sub);
11285       mwi_sub_sub = NULL;
11286    }
11287 
11288    if (mwi_unsub_sub) {
11289       ast_event_unsubscribe(mwi_unsub_sub);
11290       mwi_unsub_sub = NULL;
11291    }
11292 
11293    ast_mutex_lock(&poll_lock);
11294    ast_cond_signal(&poll_cond);
11295    ast_mutex_unlock(&poll_lock);
11296 
11297    pthread_join(poll_thread, NULL);
11298 
11299    poll_thread = AST_PTHREADT_NULL;
11300 }

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

00941 {
00942    char *bufptr = buf;
00943    for (; *input; input++) {
00944       if (*input < 32) {
00945          continue;
00946       }
00947       *bufptr++ = *input;
00948       if (bufptr == buf + buflen - 1) {
00949          break;
00950       }
00951    }
00952    *bufptr = '\0';
00953    return buf;
00954 }

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

Definition at line 11425 of file app_voicemail_odbcstorage.c.

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

11426 {
11427    char *current;
11428 
11429    /* Add 16 for fudge factor */
11430    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11431 
11432    ast_str_reset(str);
11433    
11434    /* Substitute strings \r, \n, and \t into the appropriate characters */
11435    for (current = (char *) value; *current; current++) {
11436       if (*current == '\\') {
11437          current++;
11438          if (!*current) {
11439             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11440             break;
11441          }
11442          switch (*current) {
11443          case 'r':
11444             ast_str_append(&str, 0, "\r");
11445             break;
11446          case 'n':
11447 #ifdef IMAP_STORAGE
11448             if (!str->used || str->str[str->used - 1] != '\r') {
11449                ast_str_append(&str, 0, "\r");
11450             }
11451 #endif
11452             ast_str_append(&str, 0, "\n");
11453             break;
11454          case 't':
11455             ast_str_append(&str, 0, "\t");
11456             break;
11457          default:
11458             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11459             break;
11460          }
11461       } else {
11462          ast_str_append(&str, 0, "%c", *current);
11463       }
11464    }
11465 
11466    return ast_str_buffer(str);
11467 }

static int unload_module ( void   )  [static]

Definition at line 12610 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(), cli_voicemail, free_vm_users(), free_vm_zones(), inprocess_container, mailbox_exists_acf, mwi_subscription_tps, and stop_poll_thread().

12611 {
12612    int res;
12613 
12614    res = ast_unregister_application(app);
12615    res |= ast_unregister_application(app2);
12616    res |= ast_unregister_application(app3);
12617    res |= ast_unregister_application(app4);
12618    res |= ast_unregister_application(sayname_app);
12619    res |= ast_custom_function_unregister(&mailbox_exists_acf);
12620    res |= ast_manager_unregister("VoicemailUsersList");
12621    res |= ast_data_unregister(NULL);
12622 #ifdef TEST_FRAMEWORK
12623    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
12624    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
12625    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
12626    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
12627 #endif
12628    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12629    ast_uninstall_vm_functions();
12630    ao2_ref(inprocess_container, -1);
12631 
12632    if (poll_thread != AST_PTHREADT_NULL)
12633       stop_poll_thread();
12634 
12635    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
12636    ast_unload_realtime("voicemail");
12637    ast_unload_realtime("voicemail_data");
12638 
12639    free_vm_users();
12640    free_vm_zones();
12641    return res;
12642 }

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

Definition at line 1679 of file app_voicemail_odbcstorage.c.

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

01679                                                                                         {
01680 
01681    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01682    if (!vms->dh_arraysize) {
01683       /* initial allocation */
01684       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01685          return -1;
01686       }
01687       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01688          return -1;
01689       }
01690       vms->dh_arraysize = arraysize;
01691    } else if (vms->dh_arraysize < arraysize) {
01692       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01693          return -1;
01694       }
01695       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01696          return -1;
01697       }
01698       memset(vms->deleted, 0, arraysize * sizeof(int));
01699       memset(vms->heard, 0, arraysize * sizeof(int));
01700       vms->dh_arraysize = arraysize;
01701    }
01702 
01703    return 0;
01704 }

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

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

09501 {
09502    int useadsi = 0, valid = 0, logretries = 0;
09503    char password[AST_MAX_EXTENSION]="", *passptr;
09504    struct ast_vm_user vmus, *vmu = NULL;
09505 
09506    /* If ADSI is supported, setup login screen */
09507    adsi_begin(chan, &useadsi);
09508    if (!skipuser && useadsi)
09509       adsi_login(chan);
09510    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09511       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09512       return -1;
09513    }
09514    
09515    /* Authenticate them and get their mailbox/password */
09516    
09517    while (!valid && (logretries < max_logins)) {
09518       /* Prompt for, and read in the username */
09519       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09520          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09521          return -1;
09522       }
09523       if (ast_strlen_zero(mailbox)) {
09524          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09525             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09526          } else {
09527             ast_verb(3, "Username not entered\n"); 
09528             return -1;
09529          }
09530       } else if (mailbox[0] == '*') {
09531          /* user entered '*' */
09532          if (ast_exists_extension(chan, chan->context, "a", 1,
09533             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09534             return -1;
09535          }
09536          mailbox[0] = '\0';
09537       }
09538 
09539       if (useadsi)
09540          adsi_password(chan);
09541 
09542       if (!ast_strlen_zero(prefix)) {
09543          char fullusername[80] = "";
09544          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09545          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09546          ast_copy_string(mailbox, fullusername, mailbox_size);
09547       }
09548 
09549       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09550       vmu = find_user(&vmus, context, mailbox);
09551       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09552          /* saved password is blank, so don't bother asking */
09553          password[0] = '\0';
09554       } else {
09555          if (ast_streamfile(chan, vm_password, chan->language)) {
09556             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09557             return -1;
09558          }
09559          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09560             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09561             return -1;
09562          } else if (password[0] == '*') {
09563             /* user entered '*' */
09564             if (ast_exists_extension(chan, chan->context, "a", 1,
09565                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09566                mailbox[0] = '*';
09567                return -1;
09568             }
09569             mailbox[0] = '\0';
09570          }
09571       }
09572 
09573       if (vmu) {
09574          passptr = vmu->password;
09575          if (passptr[0] == '-') passptr++;
09576       }
09577       if (vmu && !strcmp(passptr, password))
09578          valid++;
09579       else {
09580          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09581          if (!ast_strlen_zero(prefix))
09582             mailbox[0] = '\0';
09583       }
09584       logretries++;
09585       if (!valid) {
09586          if (skipuser || logretries >= max_logins) {
09587             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09588                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09589                return -1;
09590             }
09591          } else {
09592             if (useadsi)
09593                adsi_login(chan);
09594             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09595                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09596                return -1;
09597             }
09598          }
09599          if (ast_waitstream(chan, "")) /* Channel is hung up */
09600             return -1;
09601       }
09602    }
09603    if (!valid && (logretries >= max_logins)) {
09604       ast_stopstream(chan);
09605       ast_play_and_wait(chan, "vm-goodbye");
09606       return -1;
09607    }
09608    if (vmu && !skipuser) {
09609       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09610    }
09611    return 0;
09612 }

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

Definition at line 10661 of file app_voicemail_odbcstorage.c.

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

10662 {
10663    struct ast_vm_user svm;
10664    char *context, *box;
10665    AST_DECLARE_APP_ARGS(args,
10666       AST_APP_ARG(mbox);
10667       AST_APP_ARG(options);
10668    );
10669    static int dep_warning = 0;
10670 
10671    if (ast_strlen_zero(data)) {
10672       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10673       return -1;
10674    }
10675 
10676    if (!dep_warning) {
10677       dep_warning = 1;
10678       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10679    }
10680 
10681    box = ast_strdupa(data);
10682 
10683    AST_STANDARD_APP_ARGS(args, box);
10684 
10685    if (args.options) {
10686    }
10687 
10688    if ((context = strchr(args.mbox, '@'))) {
10689       *context = '\0';
10690       context++;
10691    }
10692 
10693    if (find_user(&svm, context, args.mbox)) {
10694       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10695    } else
10696       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10697 
10698    return 0;
10699 }

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

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

09478 {
09479    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09480       return vm_browse_messages_es(chan, vms, vmu);
09481    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09482       return vm_browse_messages_gr(chan, vms, vmu);
09483    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09484       return vm_browse_messages_he(chan, vms, vmu);
09485    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09486       return vm_browse_messages_it(chan, vms, vmu);
09487    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09488       return vm_browse_messages_pt(chan, vms, vmu);
09489    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09490       return vm_browse_messages_vi(chan, vms, vmu);
09491    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09492       return vm_browse_messages_zh(chan, vms, vmu);
09493    } else {                                             /* Default to English syntax */
09494       return vm_browse_messages_en(chan, vms, vmu);
09495    }
09496 }

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

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

09317 {
09318    int cmd = 0;
09319 
09320    if (vms->lastmsg > -1) {
09321       cmd = play_message(chan, vmu, vms);
09322    } else {
09323       cmd = ast_play_and_wait(chan, "vm-youhave");
09324       if (!cmd) 
09325          cmd = ast_play_and_wait(chan, "vm-no");
09326       if (!cmd) {
09327          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09328          cmd = ast_play_and_wait(chan, vms->fn);
09329       }
09330       if (!cmd)
09331          cmd = ast_play_and_wait(chan, "vm-messages");
09332    }
09333    return cmd;
09334 }

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

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

09371 {
09372    int cmd;
09373 
09374    if (vms->lastmsg > -1) {
09375       cmd = play_message(chan, vmu, vms);
09376    } else {
09377       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09378       if (!cmd)
09379          cmd = ast_play_and_wait(chan, "vm-messages");
09380       if (!cmd) {
09381          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09382          cmd = ast_play_and_wait(chan, vms->fn);
09383       }
09384    }
09385    return cmd;
09386 }

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

09265 {
09266    int cmd = 0;
09267 
09268    if (vms->lastmsg > -1) {
09269       cmd = play_message(chan, vmu, vms);
09270    } else {
09271       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09272       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09273          if (!cmd) {
09274             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09275             cmd = ast_play_and_wait(chan, vms->fn);
09276          }
09277          if (!cmd)
09278             cmd = ast_play_and_wait(chan, "vm-messages");
09279       } else {
09280          if (!cmd)
09281             cmd = ast_play_and_wait(chan, "vm-messages");
09282          if (!cmd) {
09283             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09284             cmd = ast_play_and_wait(chan, vms->fn);
09285          }
09286       }
09287    } 
09288    return cmd;
09289 }

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

Definition at line 9292 of file app_voicemail_odbcstorage.c.

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

09293 {
09294    int cmd = 0;
09295 
09296    if (vms->lastmsg > -1) {
09297       cmd = play_message(chan, vmu, vms);
09298    } else {
09299       if (!strcasecmp(vms->fn, "INBOX")) {
09300          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09301       } else {
09302          cmd = ast_play_and_wait(chan, "vm-nomessages");
09303       }
09304    }
09305    return cmd;
09306 }

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

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

09345 {
09346    int cmd;
09347 
09348    if (vms->lastmsg > -1) {
09349       cmd = play_message(chan, vmu, vms);
09350    } else {
09351       cmd = ast_play_and_wait(chan, "vm-no");
09352       if (!cmd)
09353          cmd = ast_play_and_wait(chan, "vm-message");
09354       if (!cmd) {
09355          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09356          cmd = ast_play_and_wait(chan, vms->fn);
09357       }
09358    }
09359    return cmd;
09360 }

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

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

09397 {
09398    int cmd;
09399 
09400    if (vms->lastmsg > -1) {
09401       cmd = play_message(chan, vmu, vms);
09402    } else {
09403       cmd = ast_play_and_wait(chan, "vm-no");
09404       if (!cmd) {
09405          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09406          cmd = ast_play_and_wait(chan, vms->fn);
09407       }
09408       if (!cmd)
09409          cmd = ast_play_and_wait(chan, "vm-messages");
09410    }
09411    return cmd;
09412 }

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

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

09451 {
09452    int cmd = 0;
09453 
09454    if (vms->lastmsg > -1) {
09455       cmd = play_message(chan, vmu, vms);
09456    } else {
09457       cmd = ast_play_and_wait(chan, "vm-no");
09458       if (!cmd) {
09459          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09460          cmd = ast_play_and_wait(chan, vms->fn);
09461       }
09462    }
09463    return cmd;
09464 }

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

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

09423 {
09424    int cmd;
09425 
09426    if (vms->lastmsg > -1) {
09427       cmd = play_message(chan, vmu, vms);
09428    } else {
09429       cmd = ast_play_and_wait(chan, "vm-you");
09430       if (!cmd) 
09431          cmd = ast_play_and_wait(chan, "vm-haveno");
09432       if (!cmd)
09433          cmd = ast_play_and_wait(chan, "vm-messages");
09434       if (!cmd) {
09435          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09436          cmd = ast_play_and_wait(chan, vms->fn);
09437       }
09438    }
09439    return cmd;
09440 }

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

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

01440 {
01441    struct ast_config   *cfg = NULL;
01442    struct ast_variable *var = NULL;
01443    struct ast_category *cat = NULL;
01444    char *category = NULL, *value = NULL, *new = NULL;
01445    const char *tmp = NULL;
01446    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01447    char secretfn[PATH_MAX] = "";
01448    int found = 0;
01449 
01450    if (!change_password_realtime(vmu, newpassword))
01451       return;
01452 
01453    /* check if we should store the secret in the spool directory next to the messages */
01454    switch (vmu->passwordlocation) {
01455    case OPT_PWLOC_SPOOLDIR:
01456       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01457       if (write_password_to_file(secretfn, newpassword) == 0) {
01458          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01459          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01460          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01461          break;
01462       } else {
01463          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01464       }
01465       /* Fall-through */
01466    case OPT_PWLOC_VOICEMAILCONF:
01467       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01468          while ((category = ast_category_browse(cfg, category))) {
01469             if (!strcasecmp(category, vmu->context)) {
01470                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01471                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01472                   break;
01473                }
01474                value = strstr(tmp, ",");
01475                if (!value) {
01476                   new = alloca(strlen(newpassword)+1);
01477                   sprintf(new, "%s", newpassword);
01478                } else {
01479                   new = alloca((strlen(value) + strlen(newpassword) + 1));
01480                   sprintf(new, "%s%s", newpassword, value);
01481                }
01482                if (!(cat = ast_category_get(cfg, category))) {
01483                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01484                   break;
01485                }
01486                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01487                found = 1;
01488             }
01489          }
01490          /* save the results */
01491          if (found) {
01492             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01493             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01494             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01495             break;
01496          }
01497       }
01498       /* Fall-through */
01499    case OPT_PWLOC_USERSCONF:
01500       /* check users.conf and update the password stored for the mailbox */
01501       /* if no vmsecret entry exists create one. */
01502       if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01503          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01504          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01505             ast_debug(4, "users.conf: %s\n", category);
01506             if (!strcasecmp(category, vmu->mailbox)) {
01507                if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01508                   ast_debug(3, "looks like we need to make vmsecret!\n");
01509                   var = ast_variable_new("vmsecret", newpassword, "");
01510                } else {
01511                   var = NULL;
01512                }
01513                new = alloca(strlen(newpassword) + 1);
01514                sprintf(new, "%s", newpassword);
01515                if (!(cat = ast_category_get(cfg, category))) {
01516                   ast_debug(4, "failed to get category!\n");
01517                   ast_free(var);
01518                   break;
01519                }
01520                if (!var) {
01521                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01522                } else {
01523                   ast_variable_append(cat, var);
01524                }
01525                found = 1;
01526                break;
01527             }
01528          }
01529          /* save the results and clean things up */
01530          if (found) {
01531             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01532             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01533             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01534          }
01535       }
01536    }
01537 }

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

Definition at line 1539 of file app_voicemail_odbcstorage.c.

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

01540 {
01541    char buf[255];
01542    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01543    if (!ast_safe_system(buf)) {
01544       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01545       /* Reset the password in memory, too */
01546       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01547    }
01548 }

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

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

01131 {
01132    int fds[2], pid = 0;
01133 
01134    memset(buf, 0, len);
01135 
01136    if (pipe(fds)) {
01137       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01138    } else {
01139       /* good to go*/
01140       pid = ast_safe_fork(0);
01141 
01142       if (pid < 0) {
01143          /* ok maybe not */
01144          close(fds[0]);
01145          close(fds[1]);
01146          snprintf(buf, len, "FAILURE: Fork failed");
01147       } else if (pid) {
01148          /* parent */
01149          close(fds[1]);
01150          if (read(fds[0], buf, len) < 0) {
01151             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01152          }
01153          close(fds[0]);
01154       } else {
01155          /*  child */
01156          AST_DECLARE_APP_ARGS(arg,
01157             AST_APP_ARG(v)[20];
01158          );
01159          char *mycmd = ast_strdupa(command);
01160 
01161          close(fds[0]);
01162          dup2(fds[1], STDOUT_FILENO);
01163          close(fds[1]);
01164          ast_close_fds_above_n(STDOUT_FILENO);
01165 
01166          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01167 
01168          execv(arg.v[0], arg.v); 
01169          printf("FAILURE: %s", strerror(errno));
01170          _exit(0);
01171       }
01172    }
01173    return buf;
01174 }

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

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

04049 {
04050    char *txt;
04051    int txtsize = 0;
04052 
04053    txtsize = (strlen(file) + 5)*sizeof(char);
04054    txt = alloca(txtsize);
04055    /* Sprintf here would safe because we alloca'd exactly the right length,
04056     * but trying to eliminate all sprintf's anyhow
04057     */
04058    if (ast_check_realtime("voicemail_data")) {
04059       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04060    }
04061    snprintf(txt, txtsize, "%s.txt", file);
04062    unlink(txt);
04063    return ast_filedelete(file, NULL);
04064 }

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

Definition at line 10344 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_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, ast_flags::flags, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and vm_app_options.

10345 {
10346    int res = 0;
10347    char *tmp;
10348    struct leave_vm_options leave_options;
10349    struct ast_flags flags = { 0 };
10350    char *opts[OPT_ARG_ARRAY_SIZE];
10351    AST_DECLARE_APP_ARGS(args,
10352       AST_APP_ARG(argv0);
10353       AST_APP_ARG(argv1);
10354    );
10355    
10356    memset(&leave_options, 0, sizeof(leave_options));
10357 
10358    if (chan->_state != AST_STATE_UP)
10359       ast_answer(chan);
10360 
10361    if (!ast_strlen_zero(data)) {
10362       tmp = ast_strdupa(data);
10363       AST_STANDARD_APP_ARGS(args, tmp);
10364       if (args.argc == 2) {
10365          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10366             return -1;
10367          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10368          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10369             int gain;
10370 
10371             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10372                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10373                return -1;
10374             } else {
10375                leave_options.record_gain = (signed char) gain;
10376             }
10377          }
10378          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10379             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10380                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10381          }
10382       }
10383    } else {
10384       char temp[256];
10385       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10386       if (res < 0)
10387          return res;
10388       if (ast_strlen_zero(temp))
10389          return 0;
10390       args.argv0 = ast_strdupa(temp);
10391    }
10392 
10393    res = leave_voicemail(chan, args.argv0, &leave_options);
10394    if (res == 't') {
10395       ast_play_and_wait(chan, "vm-goodbye");
10396       res = 0;
10397    }
10398 
10399    if (res == OPERATOR_EXIT) {
10400       res = 0;
10401    }
10402 
10403    if (res == ERROR_LOCK_PATH) {
10404       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10405       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10406       res = 0;
10407    }
10408 
10409    return res;
10410 }

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

Definition at line 9614 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_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_goto_if_exists(), ast_log(), AST_LOG_ERROR, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, ast_channel::context, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), ast_flags::flags, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, has_voicemail(), language, ast_vm_user::language, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), run_externnotify(), save_to_folder(), say_and_wait(), vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, and VM_SVMAIL.

09615 {
09616    /* XXX This is, admittedly, some pretty horrendous code.  For some
09617       reason it just seemed a lot easier to do with GOTO's.  I feel
09618       like I'm back in my GWBASIC days. XXX */
09619    int res = -1;
09620    int cmd = 0;
09621    int valid = 0;
09622    char prefixstr[80] ="";
09623    char ext_context[256]="";
09624    int box;
09625    int useadsi = 0;
09626    int skipuser = 0;
09627    struct vm_state vms;
09628    struct ast_vm_user *vmu = NULL, vmus;
09629    char *context = NULL;
09630    int silentexit = 0;
09631    struct ast_flags flags = { 0 };
09632    signed char record_gain = 0;
09633    int play_auto = 0;
09634    int play_folder = 0;
09635    int in_urgent = 0;
09636 #ifdef IMAP_STORAGE
09637    int deleted = 0;
09638 #endif
09639 
09640    /* Add the vm_state to the active list and keep it active */
09641    memset(&vms, 0, sizeof(vms));
09642 
09643    vms.lastmsg = -1;
09644 
09645    memset(&vmus, 0, sizeof(vmus));
09646 
09647    if (chan->_state != AST_STATE_UP) {
09648       ast_debug(1, "Before ast_answer\n");
09649       ast_answer(chan);
09650    }
09651 
09652    if (!ast_strlen_zero(data)) {
09653       char *opts[OPT_ARG_ARRAY_SIZE];
09654       char *parse;
09655       AST_DECLARE_APP_ARGS(args,
09656          AST_APP_ARG(argv0);
09657          AST_APP_ARG(argv1);
09658       );
09659 
09660       parse = ast_strdupa(data);
09661 
09662       AST_STANDARD_APP_ARGS(args, parse);
09663 
09664       if (args.argc == 2) {
09665          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09666             return -1;
09667          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09668             int gain;
09669             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
09670                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09671                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09672                   return -1;
09673                } else {
09674                   record_gain = (signed char) gain;
09675                }
09676             } else {
09677                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
09678             }
09679          }
09680          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
09681             play_auto = 1;
09682             if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
09683                /* See if it is a folder name first */
09684                if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
09685                   if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
09686                      play_folder = -1;
09687                   }
09688                } else {
09689                   play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
09690                }
09691             } else {
09692                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
09693             }
09694             if (play_folder > 9 || play_folder < 0) {
09695                ast_log(AST_LOG_WARNING,
09696                   "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
09697                   opts[OPT_ARG_PLAYFOLDER]);
09698                play_folder = 0;
09699             }
09700          }
09701       } else {
09702          /* old style options parsing */
09703          while (*(args.argv0)) {
09704             if (*(args.argv0) == 's')
09705                ast_set_flag(&flags, OPT_SILENT);
09706             else if (*(args.argv0) == 'p')
09707                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
09708             else 
09709                break;
09710             (args.argv0)++;
09711          }
09712 
09713       }
09714 
09715       valid = ast_test_flag(&flags, OPT_SILENT);
09716 
09717       if ((context = strchr(args.argv0, '@')))
09718          *context++ = '\0';
09719 
09720       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
09721          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
09722       else
09723          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
09724 
09725       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
09726          skipuser++;
09727       else
09728          valid = 0;
09729    }
09730 
09731    if (!valid)
09732       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
09733 
09734    ast_debug(1, "After vm_authenticate\n");
09735 
09736    if (vms.username[0] == '*') {
09737       ast_debug(1, "user pressed * in context '%s'\n", chan->context);
09738 
09739       /* user entered '*' */
09740       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
09741          res = 0; /* prevent hangup */
09742          goto out;
09743       }
09744    }
09745 
09746    if (!res) {
09747       valid = 1;
09748       if (!skipuser)
09749          vmu = &vmus;
09750    } else {
09751       res = 0;
09752    }
09753 
09754    /* If ADSI is supported, setup login screen */
09755    adsi_begin(chan, &useadsi);
09756 
09757    if (!valid) {
09758       goto out;
09759    }
09760 
09761 #ifdef IMAP_STORAGE
09762    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
09763    pthread_setspecific(ts_vmstate.key, &vms);
09764 
09765    vms.interactive = 1;
09766    vms.updated = 1;
09767    if (vmu)
09768       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
09769    vmstate_insert(&vms);
09770    init_vm_state(&vms);
09771 #endif
09772    /* Avoid allocating a buffer of 0 bytes, because some platforms really don't like that. */
09773    if (!(vms.deleted = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
09774       ast_log(AST_LOG_ERROR, "Could not allocate memory for deleted message storage!\n");
09775       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09776       return -1;
09777    }
09778    if (!(vms.heard = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
09779       ast_log(AST_LOG_ERROR, "Could not allocate memory for heard message storage!\n");
09780       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09781       return -1;
09782    }
09783    
09784    /* Set language from config to override channel language */
09785    if (!ast_strlen_zero(vmu->language))
09786       ast_string_field_set(chan, language, vmu->language);
09787 
09788    /* Retrieve urgent, old and new message counts */
09789    ast_debug(1, "Before open_mailbox\n");
09790    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09791    if (res < 0)
09792       goto out;
09793    vms.oldmessages = vms.lastmsg + 1;
09794    ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
09795    /* check INBOX */
09796    res = open_mailbox(&vms, vmu, NEW_FOLDER);
09797    if (res < 0)
09798       goto out;
09799    vms.newmessages = vms.lastmsg + 1;
09800    ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
09801    /* Start in Urgent */
09802    in_urgent = 1;
09803    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
09804    if (res < 0)
09805       goto out;
09806    vms.urgentmessages = vms.lastmsg + 1;
09807    ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
09808 
09809    /* Select proper mailbox FIRST!! */
09810    if (play_auto) {
09811       if (vms.urgentmessages) {
09812          in_urgent = 1;
09813          res = open_mailbox(&vms, vmu, 11);
09814       } else {
09815          in_urgent = 0;
09816          res = open_mailbox(&vms, vmu, play_folder);
09817       }
09818       if (res < 0)
09819          goto out;
09820 
09821       /* If there are no new messages, inform the user and hangup */
09822       if (vms.lastmsg == -1) {
09823          in_urgent = 0;
09824          cmd = vm_browse_messages(chan, &vms, vmu);
09825          res = 0;
09826          goto out;
09827       }
09828    } else {
09829       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
09830          /* If we only have old messages start here */
09831          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09832          in_urgent = 0;
09833          play_folder = 1;
09834          if (res < 0)
09835             goto out;
09836       } else if (!vms.urgentmessages && vms.newmessages) {
09837          /* If we have new messages but none are urgent */
09838          in_urgent = 0;
09839          res = open_mailbox(&vms, vmu, NEW_FOLDER);
09840          if (res < 0)
09841             goto out;
09842       }
09843    }
09844 
09845    if (useadsi)
09846       adsi_status(chan, &vms);
09847    res = 0;
09848 
09849    /* Check to see if this is a new user */
09850    if (!strcasecmp(vmu->mailbox, vmu->password) && 
09851       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
09852       if (ast_play_and_wait(chan, "vm-newuser") == -1)
09853          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
09854       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
09855       if ((cmd == 't') || (cmd == '#')) {
09856          /* Timeout */
09857          res = 0;
09858          goto out;
09859       } else if (cmd < 0) {
09860          /* Hangup */
09861          res = -1;
09862          goto out;
09863       }
09864    }
09865 #ifdef IMAP_STORAGE
09866       ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
09867       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
09868          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
09869          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09870       }
09871       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09872       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
09873          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09874          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09875       }
09876 #endif
09877    if (play_auto) {
09878       cmd = '1';
09879    } else {
09880       cmd = vm_intro(chan, vmu, &vms);
09881    }
09882 
09883    vms.repeats = 0;
09884    vms.starting = 1;
09885    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09886       /* Run main menu */
09887       switch (cmd) {
09888       case '1': /* First message */
09889          vms.curmsg = 0;
09890          /* Fall through */
09891       case '5': /* Play current message */
09892          cmd = vm_browse_messages(chan, &vms, vmu);
09893          break;
09894       case '2': /* Change folders */
09895          if (useadsi)
09896             adsi_folders(chan, 0, "Change to folder...");
09897          cmd = get_folder2(chan, "vm-changeto", 0);
09898          if (cmd == '#') {
09899             cmd = 0;
09900          } else if (cmd > 0) {
09901             cmd = cmd - '0';
09902             res = close_mailbox(&vms, vmu);
09903             if (res == ERROR_LOCK_PATH)
09904                goto out;
09905             /* If folder is not urgent, set in_urgent to zero! */
09906             if (cmd != 11) in_urgent = 0;
09907             res = open_mailbox(&vms, vmu, cmd);
09908             if (res < 0)
09909                goto out;
09910             play_folder = cmd;
09911             cmd = 0;
09912          }
09913          if (useadsi)
09914             adsi_status2(chan, &vms);
09915             
09916          if (!cmd)
09917             cmd = vm_play_folder_name(chan, vms.vmbox);
09918 
09919          vms.starting = 1;
09920          break;
09921       case '3': /* Advanced options */
09922          cmd = 0;
09923          vms.repeats = 0;
09924          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09925             switch (cmd) {
09926             case '1': /* Reply */
09927                if (vms.lastmsg > -1 && !vms.starting) {
09928                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
09929                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09930                      res = cmd;
09931                      goto out;
09932                   }
09933                } else
09934                   cmd = ast_play_and_wait(chan, "vm-sorry");
09935                cmd = 't';
09936                break;
09937             case '2': /* Callback */
09938                if (!vms.starting)
09939                   ast_verb(3, "Callback Requested\n");
09940                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
09941                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
09942                   if (cmd == 9) {
09943                      silentexit = 1;
09944                      goto out;
09945                   } else if (cmd == ERROR_LOCK_PATH) {
09946                      res = cmd;
09947                      goto out;
09948                   }
09949                } else 
09950                   cmd = ast_play_and_wait(chan, "vm-sorry");
09951                cmd = 't';
09952                break;
09953             case '3': /* Envelope */
09954                if (vms.lastmsg > -1 && !vms.starting) {
09955                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
09956                   if (cmd == ERROR_LOCK_PATH) {
09957                      res = cmd;
09958                      goto out;
09959                   }
09960                } else
09961                   cmd = ast_play_and_wait(chan, "vm-sorry");
09962                cmd = 't';
09963                break;
09964             case '4': /* Dialout */
09965                if (!ast_strlen_zero(vmu->dialout)) {
09966                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
09967                   if (cmd == 9) {
09968                      silentexit = 1;
09969                      goto out;
09970                   }
09971                } else 
09972                   cmd = ast_play_and_wait(chan, "vm-sorry");
09973                cmd = 't';
09974                break;
09975 
09976             case '5': /* Leave VoiceMail */
09977                if (ast_test_flag(vmu, VM_SVMAIL)) {
09978                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
09979                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09980                      res = cmd;
09981                      goto out;
09982                   }
09983                } else
09984                   cmd = ast_play_and_wait(chan, "vm-sorry");
09985                cmd = 't';
09986                break;
09987                
09988             case '*': /* Return to main menu */
09989                cmd = 't';
09990                break;
09991 
09992             default:
09993                cmd = 0;
09994                if (!vms.starting) {
09995                   cmd = ast_play_and_wait(chan, "vm-toreply");
09996                }
09997                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
09998                   cmd = ast_play_and_wait(chan, "vm-tocallback");
09999                }
10000                if (!cmd && !vms.starting) {
10001                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
10002                }
10003                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
10004                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
10005                }
10006                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
10007                   cmd = ast_play_and_wait(chan, "vm-leavemsg");
10008                if (!cmd)
10009                   cmd = ast_play_and_wait(chan, "vm-starmain");
10010                if (!cmd)
10011                   cmd = ast_waitfordigit(chan, 6000);
10012                if (!cmd)
10013                   vms.repeats++;
10014                if (vms.repeats > 3)
10015                   cmd = 't';
10016             }
10017          }
10018          if (cmd == 't') {
10019             cmd = 0;
10020             vms.repeats = 0;
10021          }
10022          break;
10023       case '4': /* Go to the previous message */
10024          if (vms.curmsg > 0) {
10025             vms.curmsg--;
10026             cmd = play_message(chan, vmu, &vms);
10027          } else {
10028             /* Check if we were listening to new
10029                messages.  If so, go to Urgent messages
10030                instead of saying "no more messages"
10031             */
10032             if (in_urgent == 0 && vms.urgentmessages > 0) {
10033                /* Check for Urgent messages */
10034                in_urgent = 1;
10035                res = close_mailbox(&vms, vmu);
10036                if (res == ERROR_LOCK_PATH)
10037                   goto out;
10038                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
10039                if (res < 0)
10040                   goto out;
10041                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
10042                vms.curmsg = vms.lastmsg;
10043                if (vms.lastmsg < 0)
10044                   cmd = ast_play_and_wait(chan, "vm-nomore");
10045             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10046                vms.curmsg = vms.lastmsg;
10047                cmd = play_message(chan, vmu, &vms);
10048             } else {
10049                cmd = ast_play_and_wait(chan, "vm-nomore");
10050             }
10051          }
10052          break;
10053       case '6': /* Go to the next message */
10054          if (vms.curmsg < vms.lastmsg) {
10055             vms.curmsg++;
10056             cmd = play_message(chan, vmu, &vms);
10057          } else {
10058             if (in_urgent && vms.newmessages > 0) {
10059                /* Check if we were listening to urgent
10060                 * messages.  If so, go to regular new messages
10061                 * instead of saying "no more messages"
10062                 */
10063                in_urgent = 0;
10064                res = close_mailbox(&vms, vmu);
10065                if (res == ERROR_LOCK_PATH)
10066                   goto out;
10067                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10068                if (res < 0)
10069                   goto out;
10070                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10071                vms.curmsg = -1;
10072                if (vms.lastmsg < 0) {
10073                   cmd = ast_play_and_wait(chan, "vm-nomore");
10074                }
10075             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10076                vms.curmsg = 0;
10077                cmd = play_message(chan, vmu, &vms);
10078             } else {
10079                cmd = ast_play_and_wait(chan, "vm-nomore");
10080             }
10081          }
10082          break;
10083       case '7': /* Delete the current message */
10084          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
10085             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
10086             if (useadsi)
10087                adsi_delete(chan, &vms);
10088             if (vms.deleted[vms.curmsg]) {
10089                if (play_folder == 0) {
10090                   if (in_urgent) {
10091                      vms.urgentmessages--;
10092                   } else {
10093                      vms.newmessages--;
10094                   }
10095                }
10096                else if (play_folder == 1)
10097                   vms.oldmessages--;
10098                cmd = ast_play_and_wait(chan, "vm-deleted");
10099             } else {
10100                if (play_folder == 0) {
10101                   if (in_urgent) {
10102                      vms.urgentmessages++;
10103                   } else {
10104                      vms.newmessages++;
10105                   }
10106                }
10107                else if (play_folder == 1)
10108                   vms.oldmessages++;
10109                cmd = ast_play_and_wait(chan, "vm-undeleted");
10110             }
10111             if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10112                if (vms.curmsg < vms.lastmsg) {
10113                   vms.curmsg++;
10114                   cmd = play_message(chan, vmu, &vms);
10115                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10116                   vms.curmsg = 0;
10117                   cmd = play_message(chan, vmu, &vms);
10118                } else {
10119                   /* Check if we were listening to urgent
10120                      messages.  If so, go to regular new messages
10121                      instead of saying "no more messages"
10122                   */
10123                   if (in_urgent == 1) {
10124                      /* Check for new messages */
10125                      in_urgent = 0;
10126                      res = close_mailbox(&vms, vmu);
10127                      if (res == ERROR_LOCK_PATH)
10128                         goto out;
10129                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
10130                      if (res < 0)
10131                         goto out;
10132                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10133                      vms.curmsg = -1;
10134                      if (vms.lastmsg < 0)
10135                         cmd = ast_play_and_wait(chan, "vm-nomore");
10136                   } else {
10137                      cmd = ast_play_and_wait(chan, "vm-nomore");
10138                   }
10139                }
10140             }
10141          } else /* Delete not valid if we haven't selected a message */
10142             cmd = 0;
10143 #ifdef IMAP_STORAGE
10144          deleted = 1;
10145 #endif
10146          break;
10147    
10148       case '8': /* Forward the current messgae */
10149          if (vms.lastmsg > -1) {
10150             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10151             if (cmd == ERROR_LOCK_PATH) {
10152                res = cmd;
10153                goto out;
10154             }
10155          } else {
10156             /* Check if we were listening to urgent
10157                messages.  If so, go to regular new messages
10158                instead of saying "no more messages"
10159             */
10160             if (in_urgent == 1 && vms.newmessages > 0) {
10161                /* Check for new messages */
10162                in_urgent = 0;
10163                res = close_mailbox(&vms, vmu);
10164                if (res == ERROR_LOCK_PATH)
10165                   goto out;
10166                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10167                if (res < 0)
10168                   goto out;
10169                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10170                vms.curmsg = -1;
10171                if (vms.lastmsg < 0)
10172                   cmd = ast_play_and_wait(chan, "vm-nomore");
10173             } else {
10174                cmd = ast_play_and_wait(chan, "vm-nomore");
10175             }
10176          }
10177          break;
10178       case '9': /* Save message to folder */
10179          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
10180             /* No message selected */
10181             cmd = 0;
10182             break;
10183          }
10184          if (useadsi)
10185             adsi_folders(chan, 1, "Save to folder...");
10186          cmd = get_folder2(chan, "vm-savefolder", 1);
10187          box = 0; /* Shut up compiler */
10188          if (cmd == '#') {
10189             cmd = 0;
10190             break;
10191          } else if (cmd > 0) {
10192             box = cmd = cmd - '0';
10193             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
10194             if (cmd == ERROR_LOCK_PATH) {
10195                res = cmd;
10196                goto out;
10197 #ifndef IMAP_STORAGE
10198             } else if (!cmd) {
10199                vms.deleted[vms.curmsg] = 1;
10200 #endif
10201             } else {
10202                vms.deleted[vms.curmsg] = 0;
10203                vms.heard[vms.curmsg] = 0;
10204             }
10205          }
10206          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
10207          if (useadsi)
10208             adsi_message(chan, &vms);
10209          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
10210          if (!cmd) {
10211             cmd = ast_play_and_wait(chan, "vm-message");
10212             if (!cmd) 
10213                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
10214             if (!cmd)
10215                cmd = ast_play_and_wait(chan, "vm-savedto");
10216             if (!cmd)
10217                cmd = vm_play_folder_name(chan, vms.fn);
10218          } else {
10219             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10220          }
10221          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
10222             if (vms.curmsg < vms.lastmsg) {
10223                vms.curmsg++;
10224                cmd = play_message(chan, vmu, &vms);
10225             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10226                vms.curmsg = 0;
10227                cmd = play_message(chan, vmu, &vms);
10228             } else {
10229                /* Check if we were listening to urgent
10230                   messages.  If so, go to regular new messages
10231                   instead of saying "no more messages"
10232                */
10233                if (in_urgent == 1 && vms.newmessages > 0) {
10234                   /* Check for new messages */
10235                   in_urgent = 0;
10236                   res = close_mailbox(&vms, vmu);
10237                   if (res == ERROR_LOCK_PATH)
10238                      goto out;
10239                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
10240                   if (res < 0)
10241                      goto out;
10242                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10243                   vms.curmsg = -1;
10244                   if (vms.lastmsg < 0)
10245                      cmd = ast_play_and_wait(chan, "vm-nomore");
10246                } else {
10247                   cmd = ast_play_and_wait(chan, "vm-nomore");
10248                }
10249             }
10250          }
10251          break;
10252       case '*': /* Help */
10253          if (!vms.starting) {
10254             cmd = ast_play_and_wait(chan, "vm-onefor");
10255             if (!strncasecmp(chan->language, "he", 2)) {
10256                cmd = ast_play_and_wait(chan, "vm-for");
10257             }
10258             if (!cmd)
10259                cmd = vm_play_folder_name(chan, vms.vmbox);
10260             if (!cmd)
10261                cmd = ast_play_and_wait(chan, "vm-opts");
10262             if (!cmd)
10263                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
10264          } else
10265             cmd = 0;
10266          break;
10267       case '0': /* Mailbox options */
10268          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
10269          if (useadsi)
10270             adsi_status(chan, &vms);
10271          break;
10272       default: /* Nothing */
10273          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
10274          break;
10275       }
10276    }
10277    if ((cmd == 't') || (cmd == '#')) {
10278       /* Timeout */
10279       res = 0;
10280    } else {
10281       /* Hangup */
10282       res = -1;
10283    }
10284 
10285 out:
10286    if (res > -1) {
10287       ast_stopstream(chan);
10288       adsi_goodbye(chan);
10289       if (valid && res != OPERATOR_EXIT) {
10290          if (silentexit)
10291             res = ast_play_and_wait(chan, "vm-dialout");
10292          else 
10293             res = ast_play_and_wait(chan, "vm-goodbye");
10294       }
10295       if ((valid && res > 0) || res == OPERATOR_EXIT) {
10296          res = 0;
10297       }
10298       if (useadsi)
10299          ast_adsi_unload_session(chan);
10300    }
10301    if (vmu)
10302       close_mailbox(&vms, vmu);
10303    if (valid) {
10304       int new = 0, old = 0, urgent = 0;
10305       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
10306       ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
10307       /* Urgent flag not passwd to externnotify here */
10308       run_externnotify(vmu->context, vmu->mailbox, NULL);
10309       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
10310       queue_mwi_event(ext_context, urgent, new, old);
10311    }
10312 #ifdef IMAP_STORAGE
10313    /* expunge message - use UID Expunge if supported on IMAP server*/
10314    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10315    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10316       ast_mutex_lock(&vms.lock);
10317 #ifdef HAVE_IMAP_TK2006
10318       if (LEVELUIDPLUS (vms.mailstream)) {
10319          mail_expunge_full(vms.mailstream, NIL, EX_UID);
10320       } else 
10321 #endif
10322          mail_expunge(vms.mailstream);
10323       ast_mutex_unlock(&vms.lock);
10324    }
10325    /*  before we delete the state, we should copy pertinent info
10326     *  back to the persistent model */
10327    if (vmu) {
10328       vmstate_delete(&vms);
10329    }
10330 #endif
10331    if (vmu)
10332       free_user(vmu);
10333    if (vms.deleted)
10334       ast_free(vms.deleted);
10335    if (vms.heard)
10336       ast_free(vms.heard);
10337 
10338 #ifdef IMAP_STORAGE
10339    pthread_setspecific(ts_vmstate.key, NULL);
10340 #endif
10341    return res;
10342 }

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 6656 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_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), CONFIG_FLAG_NOCACHE, config_flags, CONFIG_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

06658 {
06659 #ifdef IMAP_STORAGE
06660    int res;
06661 #endif
06662    int cmd = 0;
06663    int retries = 0, prepend_duration = 0, already_recorded = 0;
06664    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06665    char textfile[PATH_MAX];
06666    struct ast_config *msg_cfg;
06667    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06668 #ifndef IMAP_STORAGE
06669    signed char zero_gain = 0;
06670 #endif
06671    const char *duration_str;
06672 
06673    /* Must always populate duration correctly */
06674    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06675    strcpy(textfile, msgfile);
06676    strcpy(backup, msgfile);
06677    strcpy(backup_textfile, msgfile);
06678    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06679    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06680    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06681 
06682    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06683       *duration = atoi(duration_str);
06684    } else {
06685       *duration = 0;
06686    }
06687 
06688    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06689       if (cmd)
06690          retries = 0;
06691       switch (cmd) {
06692       case '1': 
06693 
06694 #ifdef IMAP_STORAGE
06695          /* Record new intro file */
06696          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06697          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06698          res = ast_play_and_wait(chan, INTRO);
06699          res = ast_play_and_wait(chan, "beep");
06700          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, record_gain, vms, flag);
06701          cmd = 't';
06702 #else
06703 
06704          /* prepend a message to the current message, update the metadata and return */
06705 
06706          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06707          strcpy(textfile, msgfile);
06708          strncat(textfile, ".txt", sizeof(textfile) - 1);
06709          *duration = 0;
06710 
06711          /* if we can't read the message metadata, stop now */
06712          if (!msg_cfg) {
06713             cmd = 0;
06714             break;
06715          }
06716          
06717          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06718          if (already_recorded) {
06719             ast_filecopy(backup, msgfile, NULL);
06720             copy(backup_textfile, textfile);
06721          }
06722          else {
06723             ast_filecopy(msgfile, backup, NULL);
06724             copy(textfile,backup_textfile);
06725          }
06726          already_recorded = 1;
06727 
06728          if (record_gain)
06729             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06730 
06731          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06732          if (cmd == 'S') {
06733             ast_filerename(backup, msgfile, NULL);
06734          }
06735 
06736          if (record_gain)
06737             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06738 
06739          
06740          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06741             *duration = atoi(duration_str);
06742 
06743          if (prepend_duration) {
06744             struct ast_category *msg_cat;
06745             /* need enough space for a maximum-length message duration */
06746             char duration_buf[12];
06747 
06748             *duration += prepend_duration;
06749             msg_cat = ast_category_get(msg_cfg, "message");
06750             snprintf(duration_buf, 11, "%ld", *duration);
06751             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06752                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06753             }
06754          }
06755 
06756 #endif
06757          break;
06758       case '2': 
06759          /* NULL out introfile so we know there is no intro! */
06760 #ifdef IMAP_STORAGE
06761          *vms->introfn = '\0';
06762 #endif
06763          cmd = 't';
06764          break;
06765       case '*':
06766          cmd = '*';
06767          break;
06768       default: 
06769          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
06770             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06771          if (!cmd)
06772             cmd = ast_play_and_wait(chan, "vm-starmain");
06773             /* "press star to return to the main menu" */
06774          if (!cmd)
06775             cmd = ast_waitfordigit(chan, 6000);
06776          if (!cmd)
06777             retries++;
06778          if (retries > 3)
06779             cmd = 't';
06780       }
06781    }
06782 
06783    if (msg_cfg)
06784       ast_config_destroy(msg_cfg);
06785    if (prepend_duration)
06786       *duration = prepend_duration;
06787 
06788    if (already_recorded && cmd == -1) {
06789       /* restore original message if prepention cancelled */
06790       ast_filerename(backup, msgfile, NULL);
06791       rename(backup_textfile, textfile);
06792    }
06793 
06794    if (cmd == 't' || cmd == 'S')
06795       cmd = 0;
06796    return cmd;
06797 }

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

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

08956 {
08957    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08958       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08959    } else {             /* Default to ENGLISH */
08960       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08961    }
08962 }

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

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

08855 {
08856    int res = 0;
08857    /* Play instructions and wait for new command */
08858    while (!res) {
08859       if (vms->starting) {
08860          if (vms->lastmsg > -1) {
08861             if (skipadvanced)
08862                res = ast_play_and_wait(chan, "vm-onefor-full");
08863             else
08864                res = ast_play_and_wait(chan, "vm-onefor");
08865             if (!res)
08866                res = vm_play_folder_name(chan, vms->vmbox);
08867          }
08868          if (!res) {
08869             if (skipadvanced)
08870                res = ast_play_and_wait(chan, "vm-opts-full");
08871             else
08872                res = ast_play_and_wait(chan, "vm-opts");
08873          }
08874       } else {
08875          /* Added for additional help */
08876          if (skipadvanced) {
08877             res = ast_play_and_wait(chan, "vm-onefor-full");
08878             if (!res)
08879                res = vm_play_folder_name(chan, vms->vmbox);
08880             res = ast_play_and_wait(chan, "vm-opts-full");
08881          }
08882          /* Logic:
08883           * If the current message is not the first OR
08884           * if we're listening to the first new message and there are
08885           * also urgent messages, then prompt for navigation to the
08886           * previous message
08887           */
08888          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08889             res = ast_play_and_wait(chan, "vm-prev");
08890          }
08891          if (!res && !skipadvanced)
08892             res = ast_play_and_wait(chan, "vm-advopts");
08893          if (!res)
08894             res = ast_play_and_wait(chan, "vm-repeat");
08895          /* Logic:
08896           * If we're not listening to the last message OR
08897           * we're listening to the last urgent message and there are
08898           * also new non-urgent messages, then prompt for navigation
08899           * to the next message
08900           */
08901          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08902             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08903             res = ast_play_and_wait(chan, "vm-next");
08904          }
08905          if (!res) {
08906             if (!vms->deleted[vms->curmsg])
08907                res = ast_play_and_wait(chan, "vm-delete");
08908             else
08909                res = ast_play_and_wait(chan, "vm-undelete");
08910             if (!res)
08911                res = ast_play_and_wait(chan, "vm-toforward");
08912             if (!res)
08913                res = ast_play_and_wait(chan, "vm-savemessage");
08914          }
08915       }
08916       if (!res) {
08917          res = ast_play_and_wait(chan, "vm-helpexit");
08918       }
08919       if (!res)
08920          res = ast_waitfordigit(chan, 6000);
08921       if (!res) {
08922          vms->repeats++;
08923          if (vms->repeats > 2) {
08924             res = 't';
08925          }
08926       }
08927    }
08928    return res;
08929 }

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

08932 {
08933    int res = 0;
08934    /* Play instructions and wait for new command */
08935    while (!res) {
08936       if (vms->lastmsg > -1) {
08937          res = ast_play_and_wait(chan, "vm-listen");
08938          if (!res)
08939             res = vm_play_folder_name(chan, vms->vmbox);
08940          if (!res)
08941             res = ast_play_and_wait(chan, "press");
08942          if (!res)
08943             res = ast_play_and_wait(chan, "digits/1");
08944       }
08945       if (!res)
08946          res = ast_play_and_wait(chan, "vm-opts");
08947       if (!res) {
08948          vms->starting = 0;
08949          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08950       }
08951    }
08952    return res;
08953 }

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

Definition at line 8792 of file app_voicemail_odbcstorage.c.

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

08793 {
08794    char prefile[256];
08795    
08796    /* Notify the user that the temp greeting is set and give them the option to remove it */
08797    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08798    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08799       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08800       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08801          ast_play_and_wait(chan, "vm-tempgreetactive");
08802       }
08803       DISPOSE(prefile, -1);
08804    }
08805 
08806    /* Play voicemail intro - syntax is different for different languages */
08807    if (0) {
08808       return 0;
08809    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08810       return vm_intro_cs(chan, vms);
08811    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08812       static int deprecation_warning = 0;
08813       if (deprecation_warning++ % 10 == 0) {
08814          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08815       }
08816       return vm_intro_cs(chan, vms);
08817    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08818       return vm_intro_de(chan, vms);
08819    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08820       return vm_intro_es(chan, vms);
08821    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08822       return vm_intro_fr(chan, vms);
08823    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08824       return vm_intro_gr(chan, vms);
08825    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08826       return vm_intro_he(chan, vms);
08827    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08828       return vm_intro_it(chan, vms);
08829    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08830       return vm_intro_nl(chan, vms);
08831    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08832       return vm_intro_no(chan, vms);
08833    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08834       return vm_intro_pl(chan, vms);
08835    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08836       return vm_intro_pt_BR(chan, vms);
08837    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08838       return vm_intro_pt(chan, vms);
08839    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08840       return vm_intro_multilang(chan, vms, "n");
08841    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08842       return vm_intro_se(chan, vms);
08843    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08844       return vm_intro_multilang(chan, vms, "n");
08845    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
08846       return vm_intro_vi(chan, vms);
08847    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08848       return vm_intro_zh(chan, vms);
08849    } else {                                             /* Default to ENGLISH */
08850       return vm_intro_en(chan, vms);
08851    }
08852 }

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

Definition at line 8662 of file app_voicemail_odbcstorage.c.

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

08663 {
08664    int res;
08665    res = ast_play_and_wait(chan, "vm-youhave");
08666    if (!res) {
08667       if (vms->newmessages) {
08668          if (vms->newmessages == 1) {
08669             res = ast_play_and_wait(chan, "digits/jednu");
08670          } else {
08671             res = say_and_wait(chan, vms->newmessages, chan->language);
08672          }
08673          if (!res) {
08674             if ((vms->newmessages == 1))
08675                res = ast_play_and_wait(chan, "vm-novou");
08676             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08677                res = ast_play_and_wait(chan, "vm-nove");
08678             if (vms->newmessages > 4)
08679                res = ast_play_and_wait(chan, "vm-novych");
08680          }
08681          if (vms->oldmessages && !res)
08682             res = ast_play_and_wait(chan, "vm-and");
08683          else if (!res) {
08684             if ((vms->newmessages == 1))
08685                res = ast_play_and_wait(chan, "vm-zpravu");
08686             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08687                res = ast_play_and_wait(chan, "vm-zpravy");
08688             if (vms->newmessages > 4)
08689                res = ast_play_and_wait(chan, "vm-zprav");
08690          }
08691       }
08692       if (!res && vms->oldmessages) {
08693          res = say_and_wait(chan, vms->oldmessages, chan->language);
08694          if (!res) {
08695             if ((vms->oldmessages == 1))
08696                res = ast_play_and_wait(chan, "vm-starou");
08697             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08698                res = ast_play_and_wait(chan, "vm-stare");
08699             if (vms->oldmessages > 4)
08700                res = ast_play_and_wait(chan, "vm-starych");
08701          }
08702          if (!res) {
08703             if ((vms->oldmessages == 1))
08704                res = ast_play_and_wait(chan, "vm-zpravu");
08705             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08706                res = ast_play_and_wait(chan, "vm-zpravy");
08707             if (vms->oldmessages > 4)
08708                res = ast_play_and_wait(chan, "vm-zprav");
08709          }
08710       }
08711       if (!res) {
08712          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08713             res = ast_play_and_wait(chan, "vm-no");
08714             if (!res)
08715                res = ast_play_and_wait(chan, "vm-zpravy");
08716          }
08717       }
08718    }
08719    return res;
08720 }

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

Definition at line 8358 of file app_voicemail_odbcstorage.c.

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

08359 {
08360    /* Introduce messages they have */
08361    int res;
08362    res = ast_play_and_wait(chan, "vm-youhave");
08363    if (!res) {
08364       if (vms->newmessages) {
08365          if ((vms->newmessages == 1))
08366             res = ast_play_and_wait(chan, "digits/1F");
08367          else
08368             res = say_and_wait(chan, vms->newmessages, chan->language);
08369          if (!res)
08370             res = ast_play_and_wait(chan, "vm-INBOX");
08371          if (vms->oldmessages && !res)
08372             res = ast_play_and_wait(chan, "vm-and");
08373          else if (!res) {
08374             if ((vms->newmessages == 1))
08375                res = ast_play_and_wait(chan, "vm-message");
08376             else
08377                res = ast_play_and_wait(chan, "vm-messages");
08378          }
08379             
08380       }
08381       if (!res && vms->oldmessages) {
08382          if (vms->oldmessages == 1)
08383             res = ast_play_and_wait(chan, "digits/1F");
08384          else
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->oldmessages && !vms->newmessages && !vms->urgentmessages) {
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_en ( struct ast_channel chan,
struct vm_state vms 
) [static]

Definition at line 8107 of file app_voicemail_odbcstorage.c.

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

08108 {
08109    int res;
08110 
08111    /* Introduce messages they have */
08112    res = ast_play_and_wait(chan, "vm-youhave");
08113    if (!res) {
08114       if (vms->urgentmessages) {
08115          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08116          if (!res)
08117             res = ast_play_and_wait(chan, "vm-Urgent");
08118          if ((vms->oldmessages || vms->newmessages) && !res) {
08119             res = ast_play_and_wait(chan, "vm-and");
08120          } else if (!res) {
08121             if ((vms->urgentmessages == 1))
08122                res = ast_play_and_wait(chan, "vm-message");
08123             else
08124                res = ast_play_and_wait(chan, "vm-messages");
08125          }
08126       }
08127       if (vms->newmessages) {
08128          res = say_and_wait(chan, vms->newmessages, chan->language);
08129          if (!res)
08130             res = ast_play_and_wait(chan, "vm-INBOX");
08131          if (vms->oldmessages && !res)
08132             res = ast_play_and_wait(chan, "vm-and");
08133          else if (!res) {
08134             if ((vms->newmessages == 1))
08135                res = ast_play_and_wait(chan, "vm-message");
08136             else
08137                res = ast_play_and_wait(chan, "vm-messages");
08138          }
08139             
08140       }
08141       if (!res && vms->oldmessages) {
08142          res = say_and_wait(chan, vms->oldmessages, chan->language);
08143          if (!res)
08144             res = ast_play_and_wait(chan, "vm-Old");
08145          if (!res) {
08146             if (vms->oldmessages == 1)
08147                res = ast_play_and_wait(chan, "vm-message");
08148             else
08149                res = ast_play_and_wait(chan, "vm-messages");
08150          }
08151       }
08152       if (!res) {
08153          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08154             res = ast_play_and_wait(chan, "vm-no");
08155             if (!res)
08156                res = ast_play_and_wait(chan, "vm-messages");
08157          }
08158       }
08159    }
08160    return res;
08161 }

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

Definition at line 8407 of file app_voicemail_odbcstorage.c.

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

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-youhaveno");
08413       if (!res)
08414          res = ast_play_and_wait(chan, "vm-messages");
08415    } else {
08416       res = ast_play_and_wait(chan, "vm-youhave");
08417    }
08418    if (!res) {
08419       if (vms->newmessages) {
08420          if (!res) {
08421             if ((vms->newmessages == 1)) {
08422                res = ast_play_and_wait(chan, "digits/1M");
08423                if (!res)
08424                   res = ast_play_and_wait(chan, "vm-message");
08425                if (!res)
08426                   res = ast_play_and_wait(chan, "vm-INBOXs");
08427             } else {
08428                res = say_and_wait(chan, vms->newmessages, chan->language);
08429                if (!res)
08430                   res = ast_play_and_wait(chan, "vm-messages");
08431                if (!res)
08432                   res = ast_play_and_wait(chan, "vm-INBOX");
08433             }
08434          }
08435          if (vms->oldmessages && !res)
08436             res = ast_play_and_wait(chan, "vm-and");
08437       }
08438       if (vms->oldmessages) {
08439          if (!res) {
08440             if (vms->oldmessages == 1) {
08441                res = ast_play_and_wait(chan, "digits/1M");
08442                if (!res)
08443                   res = ast_play_and_wait(chan, "vm-message");
08444                if (!res)
08445                   res = ast_play_and_wait(chan, "vm-Olds");
08446             } else {
08447                res = say_and_wait(chan, vms->oldmessages, chan->language);
08448                if (!res)
08449                   res = ast_play_and_wait(chan, "vm-messages");
08450                if (!res)
08451                   res = ast_play_and_wait(chan, "vm-Old");
08452             }
08453          }
08454       }
08455    }
08456 return res;
08457 }

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

Definition at line 8505 of file app_voicemail_odbcstorage.c.

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

08506 {
08507    /* Introduce messages they have */
08508    int res;
08509    res = ast_play_and_wait(chan, "vm-youhave");
08510    if (!res) {
08511       if (vms->newmessages) {
08512          res = say_and_wait(chan, vms->newmessages, chan->language);
08513          if (!res)
08514             res = ast_play_and_wait(chan, "vm-INBOX");
08515          if (vms->oldmessages && !res)
08516             res = ast_play_and_wait(chan, "vm-and");
08517          else if (!res) {
08518             if ((vms->newmessages == 1))
08519                res = ast_play_and_wait(chan, "vm-message");
08520             else
08521                res = ast_play_and_wait(chan, "vm-messages");
08522          }
08523             
08524       }
08525       if (!res && vms->oldmessages) {
08526          res = say_and_wait(chan, vms->oldmessages, chan->language);
08527          if (!res)
08528             res = ast_play_and_wait(chan, "vm-Old");
08529          if (!res) {
08530             if (vms->oldmessages == 1)
08531                res = ast_play_and_wait(chan, "vm-message");
08532             else
08533                res = ast_play_and_wait(chan, "vm-messages");
08534          }
08535       }
08536       if (!res) {
08537          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08538             res = ast_play_and_wait(chan, "vm-no");
08539             if (!res)
08540                res = ast_play_and_wait(chan, "vm-messages");
08541          }
08542       }
08543    }
08544    return res;
08545 }

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

Definition at line 7906 of file app_voicemail_odbcstorage.c.

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

07907 {
07908    int res = 0;
07909 
07910    if (vms->newmessages) {
07911       res = ast_play_and_wait(chan, "vm-youhave");
07912       if (!res) 
07913          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07914       if (!res) {
07915          if ((vms->newmessages == 1)) {
07916             res = ast_play_and_wait(chan, "vm-INBOX");
07917             if (!res)
07918                res = ast_play_and_wait(chan, "vm-message");
07919          } else {
07920             res = ast_play_and_wait(chan, "vm-INBOXs");
07921             if (!res)
07922                res = ast_play_and_wait(chan, "vm-messages");
07923          }
07924       }
07925    } else if (vms->oldmessages){
07926       res = ast_play_and_wait(chan, "vm-youhave");
07927       if (!res)
07928          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07929       if ((vms->oldmessages == 1)){
07930          res = ast_play_and_wait(chan, "vm-Old");
07931          if (!res)
07932             res = ast_play_and_wait(chan, "vm-message");
07933       } else {
07934          res = ast_play_and_wait(chan, "vm-Olds");
07935          if (!res)
07936             res = ast_play_and_wait(chan, "vm-messages");
07937       }
07938    } else if (!vms->oldmessages && !vms->newmessages) 
07939       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07940    return res;
07941 }

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

Definition at line 8040 of file app_voicemail_odbcstorage.c.

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

08041 {
08042    int res = 0;
08043 
08044    /* Introduce messages they have */
08045    if (!res) {
08046       if ((vms->newmessages) || (vms->oldmessages)) {
08047          res = ast_play_and_wait(chan, "vm-youhave");
08048       }
08049       /*
08050        * The word "shtei" refers to the number 2 in hebrew when performing a count
08051        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08052        * an element, this is one of them.
08053        */
08054       if (vms->newmessages) {
08055          if (!res) {
08056             if (vms->newmessages == 1) {
08057                res = ast_play_and_wait(chan, "vm-INBOX1");
08058             } else {
08059                if (vms->newmessages == 2) {
08060                   res = ast_play_and_wait(chan, "vm-shtei");
08061                } else {
08062                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08063                }
08064                res = ast_play_and_wait(chan, "vm-INBOX");
08065             }
08066          }
08067          if (vms->oldmessages && !res) {
08068             res = ast_play_and_wait(chan, "vm-and");
08069             if (vms->oldmessages == 1) {
08070                res = ast_play_and_wait(chan, "vm-Old1");
08071             } else {
08072                if (vms->oldmessages == 2) {
08073                   res = ast_play_and_wait(chan, "vm-shtei");
08074                } else {
08075                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08076                }
08077                res = ast_play_and_wait(chan, "vm-Old");
08078             }
08079          }
08080       }
08081       if (!res && vms->oldmessages && !vms->newmessages) {
08082          if (!res) {
08083             if (vms->oldmessages == 1) {
08084                res = ast_play_and_wait(chan, "vm-Old1");
08085             } else {
08086                if (vms->oldmessages == 2) {
08087                   res = ast_play_and_wait(chan, "vm-shtei");
08088                } else {
08089                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08090                }
08091                res = ast_play_and_wait(chan, "vm-Old");
08092             }
08093          }
08094       }
08095       if (!res) {
08096          if (!vms->oldmessages && !vms->newmessages) {
08097             if (!res) {
08098                res = ast_play_and_wait(chan, "vm-nomessages");
08099             }
08100          }
08101       }
08102    }
08103    return res;
08104 }

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

Definition at line 8164 of file app_voicemail_odbcstorage.c.

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

08165 {
08166    /* Introduce messages they have */
08167    int res;
08168    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08169       res = ast_play_and_wait(chan, "vm-no") ||
08170          ast_play_and_wait(chan, "vm-message");
08171    else
08172       res = ast_play_and_wait(chan, "vm-youhave");
08173    if (!res && vms->newmessages) {
08174       res = (vms->newmessages == 1) ?
08175          ast_play_and_wait(chan, "digits/un") ||
08176          ast_play_and_wait(chan, "vm-nuovo") ||
08177          ast_play_and_wait(chan, "vm-message") :
08178          /* 2 or more new messages */
08179          say_and_wait(chan, vms->newmessages, chan->language) ||
08180          ast_play_and_wait(chan, "vm-nuovi") ||
08181          ast_play_and_wait(chan, "vm-messages");
08182       if (!res && vms->oldmessages)
08183          res = ast_play_and_wait(chan, "vm-and");
08184    }
08185    if (!res && vms->oldmessages) {
08186       res = (vms->oldmessages == 1) ?
08187          ast_play_and_wait(chan, "digits/un") ||
08188          ast_play_and_wait(chan, "vm-vecchio") ||
08189          ast_play_and_wait(chan, "vm-message") :
08190          /* 2 or more old messages */
08191          say_and_wait(chan, vms->oldmessages, chan->language) ||
08192          ast_play_and_wait(chan, "vm-vecchi") ||
08193          ast_play_and_wait(chan, "vm-messages");
08194    }
08195    return res;
08196 }

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

Definition at line 8000 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(), ast_channel::language, vm_state::newmessages, and vm_state::oldmessages.

08001 {
08002    int res;
08003    int lastnum = 0;
08004 
08005    res = ast_play_and_wait(chan, "vm-youhave");
08006 
08007    if (!res && vms->newmessages) {
08008       lastnum = vms->newmessages;
08009 
08010       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08011          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08012       }
08013 
08014       if (!res && vms->oldmessages) {
08015          res = ast_play_and_wait(chan, "vm-and");
08016       }
08017    }
08018 
08019    if (!res && vms->oldmessages) {
08020       lastnum = vms->oldmessages;
08021 
08022       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08023          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08024       }
08025    }
08026 
08027    if (!res) {
08028       if (lastnum == 0) {
08029          res = ast_play_and_wait(chan, "vm-no");
08030       }
08031       if (!res) {
08032          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08033       }
08034    }
08035 
08036    return res;
08037 }

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

Definition at line 8548 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 8314 of file app_voicemail_odbcstorage.c.

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

08315 {
08316    /* Introduce messages they have */
08317    int res;
08318 
08319    res = ast_play_and_wait(chan, "vm-youhave");
08320    if (res)
08321       return res;
08322 
08323    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08324       res = ast_play_and_wait(chan, "vm-no");
08325       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08326       return res;
08327    }
08328 
08329    if (vms->newmessages) {
08330       if ((vms->newmessages == 1)) {
08331          res = ast_play_and_wait(chan, "digits/1");
08332          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08333          res = res ? res : ast_play_and_wait(chan, "vm-message");
08334       } else {
08335          res = say_and_wait(chan, vms->newmessages, chan->language);
08336          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08337          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08338       }
08339       if (!res && vms->oldmessages)
08340          res = ast_play_and_wait(chan, "vm-and");
08341    }
08342    if (!res && vms->oldmessages) {
08343       if (vms->oldmessages == 1) {
08344          res = ast_play_and_wait(chan, "digits/1");
08345          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08346          res = res ? res : ast_play_and_wait(chan, "vm-message");
08347       } else {
08348          res = say_and_wait(chan, vms->oldmessages, chan->language);
08349          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08350          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08351       }
08352    }
08353 
08354    return res;
08355 }

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

Definition at line 8199 of file app_voicemail_odbcstorage.c.

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

08200 {
08201    /* Introduce messages they have */
08202    int res;
08203    div_t num;
08204 
08205    if (!vms->oldmessages && !vms->newmessages) {
08206       res = ast_play_and_wait(chan, "vm-no");
08207       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08208       return res;
08209    } else {
08210       res = ast_play_and_wait(chan, "vm-youhave");
08211    }
08212 
08213    if (vms->newmessages) {
08214       num = div(vms->newmessages, 10);
08215       if (vms->newmessages == 1) {
08216          res = ast_play_and_wait(chan, "digits/1-a");
08217          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08218          res = res ? res : ast_play_and_wait(chan, "vm-message");
08219       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08220          if (num.rem == 2) {
08221             if (!num.quot) {
08222                res = ast_play_and_wait(chan, "digits/2-ie");
08223             } else {
08224                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08225                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08226             }
08227          } else {
08228             res = say_and_wait(chan, vms->newmessages, chan->language);
08229          }
08230          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08231          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08232       } else {
08233          res = say_and_wait(chan, vms->newmessages, chan->language);
08234          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08235          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08236       }
08237       if (!res && vms->oldmessages)
08238          res = ast_play_and_wait(chan, "vm-and");
08239    }
08240    if (!res && vms->oldmessages) {
08241       num = div(vms->oldmessages, 10);
08242       if (vms->oldmessages == 1) {
08243          res = ast_play_and_wait(chan, "digits/1-a");
08244          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08245          res = res ? res : ast_play_and_wait(chan, "vm-message");
08246       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08247          if (num.rem == 2) {
08248             if (!num.quot) {
08249                res = ast_play_and_wait(chan, "digits/2-ie");
08250             } else {
08251                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08252                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08253             }
08254          } else {
08255             res = say_and_wait(chan, vms->oldmessages, chan->language);
08256          }
08257          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08258          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08259       } else {
08260          res = say_and_wait(chan, vms->oldmessages, chan->language);
08261          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08262          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08263       }
08264    }
08265 
08266    return res;
08267 }

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

Definition at line 8599 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 8460 of file app_voicemail_odbcstorage.c.

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

08460                                                                           {
08461    /* Introduce messages they have */
08462    int res;
08463    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08464       res = ast_play_and_wait(chan, "vm-nomessages");
08465       return res;
08466    } else {
08467       res = ast_play_and_wait(chan, "vm-youhave");
08468    }
08469    if (vms->newmessages) {
08470       if (!res)
08471          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08472       if ((vms->newmessages == 1)) {
08473          if (!res)
08474             res = ast_play_and_wait(chan, "vm-message");
08475          if (!res)
08476             res = ast_play_and_wait(chan, "vm-INBOXs");
08477       } else {
08478          if (!res)
08479             res = ast_play_and_wait(chan, "vm-messages");
08480          if (!res)
08481             res = ast_play_and_wait(chan, "vm-INBOX");
08482       }
08483       if (vms->oldmessages && !res)
08484          res = ast_play_and_wait(chan, "vm-and");
08485    }
08486    if (vms->oldmessages) {
08487       if (!res)
08488          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08489       if (vms->oldmessages == 1) {
08490          if (!res)
08491             res = ast_play_and_wait(chan, "vm-message");
08492          if (!res)
08493             res = ast_play_and_wait(chan, "vm-Olds");
08494       } else {
08495          if (!res)
08496             res = ast_play_and_wait(chan, "vm-messages");
08497          if (!res)
08498             res = ast_play_and_wait(chan, "vm-Old");
08499       }
08500    }
08501    return res;
08502 }

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

Definition at line 8270 of file app_voicemail_odbcstorage.c.

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

08271 {
08272    /* Introduce messages they have */
08273    int res;
08274 
08275    res = ast_play_and_wait(chan, "vm-youhave");
08276    if (res)
08277       return res;
08278 
08279    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08280       res = ast_play_and_wait(chan, "vm-no");
08281       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08282       return res;
08283    }
08284 
08285    if (vms->newmessages) {
08286       if ((vms->newmessages == 1)) {
08287          res = ast_play_and_wait(chan, "digits/ett");
08288          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08289          res = res ? res : ast_play_and_wait(chan, "vm-message");
08290       } else {
08291          res = say_and_wait(chan, vms->newmessages, chan->language);
08292          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08293          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08294       }
08295       if (!res && vms->oldmessages)
08296          res = ast_play_and_wait(chan, "vm-and");
08297    }
08298    if (!res && vms->oldmessages) {
08299       if (vms->oldmessages == 1) {
08300          res = ast_play_and_wait(chan, "digits/ett");
08301          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08302          res = res ? res : ast_play_and_wait(chan, "vm-message");
08303       } else {
08304          res = say_and_wait(chan, vms->oldmessages, chan->language);
08305          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08306          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08307       }
08308    }
08309 
08310    return res;
08311 }

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

Definition at line 8762 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 8723 of file app_voicemail_odbcstorage.c.

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

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

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03181 {
03182    switch (ast_lock_path(path)) {
03183    case AST_LOCK_TIMEOUT:
03184       return -1;
03185    default:
03186       return 0;
03187    }
03188 }

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

Definition at line 1586 of file app_voicemail_odbcstorage.c.

References VOICEMAIL_FILE_MODE.

01587 {
01588    FILE *p = NULL;
01589    int pfd = mkstemp(template);
01590    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01591    if (pfd > -1) {
01592       p = fdopen(pfd, "w+");
01593       if (!p) {
01594          close(pfd);
01595          pfd = -1;
01596       }
01597    }
01598    return p;
01599 }

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 8965 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, check_password(), play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, VM_FORCENAME, vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, and vm_reenterpassword.

08966 {
08967    int cmd = 0;
08968    int duration = 0;
08969    int tries = 0;
08970    char newpassword[80] = "";
08971    char newpassword2[80] = "";
08972    char prefile[PATH_MAX] = "";
08973    unsigned char buf[256];
08974    int bytes = 0;
08975 
08976    if (ast_adsi_available(chan)) {
08977       bytes += adsi_logo(buf + bytes);
08978       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08979       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08980       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08981       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08982       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08983    }
08984 
08985    /* First, have the user change their password 
08986       so they won't get here again */
08987    for (;;) {
08988       newpassword[1] = '\0';
08989       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08990       if (cmd == '#')
08991          newpassword[0] = '\0';
08992       if (cmd < 0 || cmd == 't' || cmd == '#')
08993          return cmd;
08994       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
08995       if (cmd < 0 || cmd == 't' || cmd == '#')
08996          return cmd;
08997       cmd = check_password(vmu, newpassword); /* perform password validation */
08998       if (cmd != 0) {
08999          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09000          cmd = ast_play_and_wait(chan, vm_invalid_password);
09001       } else {
09002          newpassword2[1] = '\0';
09003          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09004          if (cmd == '#')
09005             newpassword2[0] = '\0';
09006          if (cmd < 0 || cmd == 't' || cmd == '#')
09007             return cmd;
09008          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09009          if (cmd < 0 || cmd == 't' || cmd == '#')
09010             return cmd;
09011          if (!strcmp(newpassword, newpassword2))
09012             break;
09013          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09014          cmd = ast_play_and_wait(chan, vm_mismatch);
09015       }
09016       if (++tries == 3)
09017          return -1;
09018       if (cmd != 0) {
09019          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09020       }
09021    }
09022    if (pwdchange & PWDCHANGE_INTERNAL)
09023       vm_change_password(vmu, newpassword);
09024    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09025       vm_change_password_shell(vmu, newpassword);
09026 
09027    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09028    cmd = ast_play_and_wait(chan, vm_passchanged);
09029 
09030    /* If forcename is set, have the user record their name */  
09031    if (ast_test_flag(vmu, VM_FORCENAME)) {
09032       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09033       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09034          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09035          if (cmd < 0 || cmd == 't' || cmd == '#')
09036             return cmd;
09037       }
09038    }
09039 
09040    /* If forcegreetings is set, have the user record their greetings */
09041    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09042       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09043       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09044          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09045          if (cmd < 0 || cmd == 't' || cmd == '#')
09046             return cmd;
09047       }
09048 
09049       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09050       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09051          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09052          if (cmd < 0 || cmd == 't' || cmd == '#')
09053             return cmd;
09054       }
09055    }
09056 
09057    return cmd;
09058 }

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 9060 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_waitfordigit(), check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::password, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, vm_reenterpassword, and vm_tempgreeting().

09061 {
09062    int cmd = 0;
09063    int retries = 0;
09064    int duration = 0;
09065    char newpassword[80] = "";
09066    char newpassword2[80] = "";
09067    char prefile[PATH_MAX] = "";
09068    unsigned char buf[256];
09069    int bytes = 0;
09070 
09071    if (ast_adsi_available(chan)) {
09072       bytes += adsi_logo(buf + bytes);
09073       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09074       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09075       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09076       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09077       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09078    }
09079    while ((cmd >= 0) && (cmd != 't')) {
09080       if (cmd)
09081          retries = 0;
09082       switch (cmd) {
09083       case '1': /* Record your unavailable message */
09084          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09085          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09086          break;
09087       case '2':  /* Record your busy message */
09088          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09089          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09090          break;
09091       case '3': /* Record greeting */
09092          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09093          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09094          break;
09095       case '4':  /* manage the temporary greeting */
09096          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09097          break;
09098       case '5': /* change password */
09099          if (vmu->password[0] == '-') {
09100             cmd = ast_play_and_wait(chan, "vm-no");
09101             break;
09102          }
09103          newpassword[1] = '\0';
09104          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09105          if (cmd == '#')
09106             newpassword[0] = '\0';
09107          else {
09108             if (cmd < 0)
09109                break;
09110             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09111                break;
09112             }
09113          }
09114          cmd = check_password(vmu, newpassword); /* perform password validation */
09115          if (cmd != 0) {
09116             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09117             cmd = ast_play_and_wait(chan, vm_invalid_password);
09118             if (!cmd) {
09119                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09120             }
09121             break;
09122          }
09123          newpassword2[1] = '\0';
09124          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09125          if (cmd == '#')
09126             newpassword2[0] = '\0';
09127          else {
09128             if (cmd < 0)
09129                break;
09130 
09131             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09132                break;
09133             }
09134          }
09135          if (strcmp(newpassword, newpassword2)) {
09136             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09137             cmd = ast_play_and_wait(chan, vm_mismatch);
09138             if (!cmd) {
09139                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09140             }
09141             break;
09142          }
09143          if (pwdchange & PWDCHANGE_INTERNAL)
09144             vm_change_password(vmu, newpassword);
09145          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09146             vm_change_password_shell(vmu, newpassword);
09147 
09148          ast_debug(1, "User %s set password to %s of length %d\n",
09149             vms->username, newpassword, (int) strlen(newpassword));
09150          cmd = ast_play_and_wait(chan, vm_passchanged);
09151          break;
09152       case '*': 
09153          cmd = 't';
09154          break;
09155       default: 
09156          cmd = 0;
09157          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09158          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09159          if (ast_fileexists(prefile, NULL, NULL)) {
09160             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09161          }
09162          DISPOSE(prefile, -1);
09163          if (!cmd) {
09164             cmd = ast_play_and_wait(chan, "vm-options");
09165          }
09166          if (!cmd) {
09167             cmd = ast_waitfordigit(chan, 6000);
09168          }
09169          if (!cmd) {
09170             retries++;
09171          }
09172          if (retries > 3) {
09173             cmd = 't';
09174          }
09175       }
09176    }
09177    if (cmd == 't')
09178       cmd = 0;
09179    return cmd;
09180 }

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

Definition at line 7869 of file app_voicemail_odbcstorage.c.

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

07870 {
07871    int cmd;
07872 
07873    if (  !strncasecmp(chan->language, "it", 2) ||
07874         !strncasecmp(chan->language, "es", 2) ||
07875         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07876       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07877       return cmd ? cmd : ast_play_and_wait(chan, box);
07878    } else if (!strncasecmp(chan->language, "gr", 2)) {
07879       return vm_play_folder_name_gr(chan, box);
07880    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07881       return ast_play_and_wait(chan, box);
07882    } else if (!strncasecmp(chan->language, "pl", 2)) {
07883       return vm_play_folder_name_pl(chan, box);
07884    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07885       return vm_play_folder_name_ua(chan, box);
07886    } else if (!strncasecmp(chan->language, "vi", 2)) {
07887       return ast_play_and_wait(chan, box);
07888    } else {  /* Default English */
07889       cmd = ast_play_and_wait(chan, box);
07890       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07891    }
07892 }

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

Definition at line 7822 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

07823 {
07824    int cmd;
07825    char *buf;
07826 
07827    buf = alloca(strlen(box) + 2);
07828    strcpy(buf, box);
07829    strcat(buf, "s");
07830 
07831    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07832       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07833       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07834    } else {
07835       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07836       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07837    }
07838 }

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

Definition at line 7840 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

07841 {
07842    int cmd;
07843 
07844    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07845       if (!strcasecmp(box, "vm-INBOX"))
07846          cmd = ast_play_and_wait(chan, "vm-new-e");
07847       else
07848          cmd = ast_play_and_wait(chan, "vm-old-e");
07849       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07850    } else {
07851       cmd = ast_play_and_wait(chan, "vm-messages");
07852       return cmd ? cmd : ast_play_and_wait(chan, box);
07853    }
07854 }

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

Definition at line 7856 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

07857 {
07858    int cmd;
07859 
07860    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07861       cmd = ast_play_and_wait(chan, "vm-messages");
07862       return cmd ? cmd : ast_play_and_wait(chan, box);
07863    } else {
07864       cmd = ast_play_and_wait(chan, box);
07865       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07866    }
07867 }

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 9198 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_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

09199 {
09200    int cmd = 0;
09201    int retries = 0;
09202    int duration = 0;
09203    char prefile[PATH_MAX] = "";
09204    unsigned char buf[256];
09205    int bytes = 0;
09206 
09207    if (ast_adsi_available(chan)) {
09208       bytes += adsi_logo(buf + bytes);
09209       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09210       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09211       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09212       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09213       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09214    }
09215 
09216    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09217    while ((cmd >= 0) && (cmd != 't')) {
09218       if (cmd)
09219          retries = 0;
09220       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09221       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09222          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09223          cmd = 't';  
09224       } else {
09225          switch (cmd) {
09226          case '1':
09227             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09228             break;
09229          case '2':
09230             DELETE(prefile, -1, prefile, vmu);
09231             ast_play_and_wait(chan, "vm-tempremoved");
09232             cmd = 't';  
09233             break;
09234          case '*': 
09235             cmd = 't';
09236             break;
09237          default:
09238             cmd = ast_play_and_wait(chan,
09239                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09240                   "vm-tempgreeting2" : "vm-tempgreeting");
09241             if (!cmd)
09242                cmd = ast_waitfordigit(chan, 6000);
09243             if (!cmd)
09244                retries++;
09245             if (retries > 3)
09246                cmd = 't';
09247          }
09248       }
09249       DISPOSE(prefile, -1);
09250    }
09251    if (cmd == 't')
09252       cmd = 0;
09253    return cmd;
09254 }

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

Definition at line 11086 of file app_voicemail_odbcstorage.c.

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

11088 {
11089    struct ast_vm_user *user;
11090 
11091    AST_LIST_LOCK(&users);
11092    AST_LIST_TRAVERSE(&users, user, list) {
11093       vm_users_data_provider_get_helper(search, data_root, user);
11094    }
11095    AST_LIST_UNLOCK(&users);
11096 
11097    return 0;
11098 }

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

11041 {
11042    struct ast_data *data_user, *data_zone;
11043    struct ast_data *data_state;
11044    struct vm_zone *zone = NULL;
11045    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11046    char ext_context[256] = "";
11047 
11048    data_user = ast_data_add_node(data_root, "user");
11049    if (!data_user) {
11050       return -1;
11051    }
11052 
11053    ast_data_add_structure(ast_vm_user, data_user, user);
11054 
11055    AST_LIST_LOCK(&zones);
11056    AST_LIST_TRAVERSE(&zones, zone, list) {
11057       if (!strcmp(zone->name, user->zonetag)) {
11058          break;
11059       }
11060    }
11061    AST_LIST_UNLOCK(&zones);
11062 
11063    /* state */
11064    data_state = ast_data_add_node(data_user, "state");
11065    if (!data_state) {
11066       return -1;
11067    }
11068    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11069    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11070    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11071    ast_data_add_int(data_state, "newmsg", newmsg);
11072    ast_data_add_int(data_state, "oldmsg", oldmsg);
11073 
11074    if (zone) {
11075       data_zone = ast_data_add_node(data_user, "zone");
11076       ast_data_add_structure(vm_zone, data_zone, zone);
11077    }
11078 
11079    if (!ast_data_search_match(search, data_user)) {
11080       ast_data_remove_node(data_root, data_user);
11081    }
11082 
11083    return 0;
11084 }

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

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

10726 {
10727    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
10728    struct ast_vm_user vmus;
10729    char *options = NULL;
10730    int silent = 0, skipuser = 0;
10731    int res = -1;
10732    
10733    if (data) {
10734       s = ast_strdupa(data);
10735       user = strsep(&s, ",");
10736       options = strsep(&s, ",");
10737       if (user) {
10738          s = user;
10739          user = strsep(&s, "@");
10740          context = strsep(&s, "");
10741          if (!ast_strlen_zero(user))
10742             skipuser++;
10743          ast_copy_string(mailbox, user, sizeof(mailbox));
10744       }
10745    }
10746 
10747    if (options) {
10748       silent = (strchr(options, 's')) != NULL;
10749    }
10750 
10751    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
10752       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
10753       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
10754       ast_play_and_wait(chan, "auth-thankyou");
10755       res = 0;
10756    } else if (mailbox[0] == '*') {
10757       /* user entered '*' */
10758       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
10759          res = 0; /* prevent hangup */
10760       }
10761    }
10762 
10763    return res;
10764 }

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

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

12210 {
12211    char *context;
12212    char *args_copy;
12213    int res;
12214 
12215    if (ast_strlen_zero(data)) {
12216       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12217       return -1;
12218    }
12219 
12220    args_copy = ast_strdupa(data);
12221    if ((context = strchr(args_copy, '@'))) {
12222       *context++ = '\0';
12223    } else {
12224       context = "default";
12225    }
12226 
12227    if ((res = sayname(chan, args_copy, context) < 0)) {
12228       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12229       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12230       if (!res) {
12231          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12232       }
12233    }
12234 
12235    return res;
12236 }

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

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

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

Definition at line 4280 of file app_voicemail_odbcstorage.c.

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

04281 {
04282    const struct vm_zone *z = NULL;
04283    struct timeval t = ast_tvnow();
04284 
04285    /* Does this user have a timezone specified? */
04286    if (!ast_strlen_zero(vmu->zonetag)) {
04287       /* Find the zone in the list */
04288       AST_LIST_LOCK(&zones);
04289       AST_LIST_TRAVERSE(&zones, z, list) {
04290          if (!strcmp(z->name, vmu->zonetag))
04291             break;
04292       }
04293       AST_LIST_UNLOCK(&zones);
04294    }
04295    ast_localtime(&t, tm, z ? z->timezone : NULL);
04296    return tm;
04297 }

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

Definition at line 7248 of file app_voicemail_odbcstorage.c.

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

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

Definition at line 7240 of file app_voicemail_odbcstorage.c.

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

07241 {
07242    int res;
07243    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07244       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07245    return res;
07246 }

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

Definition at line 12183 of file app_voicemail_odbcstorage.c.

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

12183                                                                               {
12184    struct ast_config *conf;
12185    struct ast_category *cat;
12186    struct ast_variable *var;
12187 
12188    if (!(conf=ast_config_new())) {
12189       ast_log(LOG_ERROR, "Error creating new config structure\n");
12190       return -1;
12191    }
12192    if (!(cat=ast_category_new("general","",1))) {
12193       ast_log(LOG_ERROR, "Error creating new category structure\n");
12194       return -1;
12195    }
12196    if (!(var=ast_variable_new("password",password,""))) {
12197       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12198       return -1;
12199    }
12200    ast_category_append(conf,cat);
12201    ast_variable_append(cat,var);
12202    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12203       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12204       return -1;
12205    }
12206    return 0;
12207 }


Variable Documentation

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

Definition at line 13197 of file app_voicemail_odbcstorage.c.

char* addesc = "Comedian Mail" [static]

Definition at line 739 of file app_voicemail_odbcstorage.c.

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

Definition at line 854 of file app_voicemail_odbcstorage.c.

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

Definition at line 855 of file app_voicemail_odbcstorage.c.

int adsiver = 1 [static]

Definition at line 856 of file app_voicemail_odbcstorage.c.

char* app = "VoiceMail" [static]

Definition at line 742 of file app_voicemail_odbcstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 745 of file app_voicemail_odbcstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 747 of file app_voicemail_odbcstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 748 of file app_voicemail_odbcstorage.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 13197 of file app_voicemail_odbcstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 840 of file app_voicemail_odbcstorage.c.

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

Definition at line 852 of file app_voicemail_odbcstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 843 of file app_voicemail_odbcstorage.c.

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

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

Definition at line 10962 of file app_voicemail_odbcstorage.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 839 of file app_voicemail_odbcstorage.c.

char* emailbody = NULL [static]

Definition at line 846 of file app_voicemail_odbcstorage.c.

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

Definition at line 857 of file app_voicemail_odbcstorage.c.

char* emailsubject = NULL [static]

Definition at line 847 of file app_voicemail_odbcstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 841 of file app_voicemail_odbcstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 719 of file app_voicemail_odbcstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 718 of file app_voicemail_odbcstorage.c.

char externnotify[160] [static]

Definition at line 762 of file app_voicemail_odbcstorage.c.

char fromstring[100] [static]

Definition at line 850 of file app_voicemail_odbcstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 835 of file app_voicemail_odbcstorage.c.

struct ao2_container* inprocess_container

Definition at line 877 of file app_voicemail_odbcstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 820 of file app_voicemail_odbcstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 822 of file app_voicemail_odbcstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 823 of file app_voicemail_odbcstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 821 of file app_voicemail_odbcstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 824 of file app_voicemail_odbcstorage.c.

char locale[20] [static]

Definition at line 755 of file app_voicemail_odbcstorage.c.

struct ast_custom_function mailbox_exists_acf [static]

Initial value:

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

Definition at line 10720 of file app_voicemail_odbcstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1622 of file app_voicemail_odbcstorage.c.

char mailcmd[160] [static]

Definition at line 761 of file app_voicemail_odbcstorage.c.

int maxdeletedmsg [static]

Definition at line 758 of file app_voicemail_odbcstorage.c.

int maxgreet [static]

Definition at line 768 of file app_voicemail_odbcstorage.c.

int maxlogins [static]

Definition at line 770 of file app_voicemail_odbcstorage.c.

int maxmsg [static]

Definition at line 757 of file app_voicemail_odbcstorage.c.

int maxsilence [static]

Definition at line 756 of file app_voicemail_odbcstorage.c.

int minpassword [static]

Definition at line 771 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 789 of file app_voicemail_odbcstorage.c.

struct ast_taskprocessor* mwi_subscription_tps [static]

Definition at line 815 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 791 of file app_voicemail_odbcstorage.c.

int my_umask [static]

Definition at line 721 of file app_voicemail_odbcstorage.c.

char* pagerbody = NULL [static]

Definition at line 848 of file app_voicemail_odbcstorage.c.

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

Definition at line 858 of file app_voicemail_odbcstorage.c.

char pagerfromstring[100] [static]

Definition at line 851 of file app_voicemail_odbcstorage.c.

char* pagersubject = NULL [static]

Definition at line 849 of file app_voicemail_odbcstorage.c.

int passwordlocation [static]

Definition at line 772 of file app_voicemail_odbcstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 784 of file app_voicemail_odbcstorage.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 779 of file app_voicemail_odbcstorage.c.

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

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 785 of file app_voicemail_odbcstorage.c.

unsigned char poll_thread_run [static]

Definition at line 786 of file app_voicemail_odbcstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 725 of file app_voicemail_odbcstorage.c.

int saydurationminfo [static]

Definition at line 837 of file app_voicemail_odbcstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 750 of file app_voicemail_odbcstorage.c.

char serveremail[80] [static]

Definition at line 760 of file app_voicemail_odbcstorage.c.

int silencethreshold = 128 [static]

Definition at line 759 of file app_voicemail_odbcstorage.c.

int skipms [static]

Definition at line 769 of file app_voicemail_odbcstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 763 of file app_voicemail_odbcstorage.c.

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

Definition at line 737 of file app_voicemail_odbcstorage.c.

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

Definition at line 506 of file app_voicemail_odbcstorage.c.

struct ast_data_entry vm_data_providers[] [static]

Initial value:

 {

}

Definition at line 11105 of file app_voicemail_odbcstorage.c.

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

Definition at line 832 of file app_voicemail_odbcstorage.c.

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

Definition at line 831 of file app_voicemail_odbcstorage.c.

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

Definition at line 828 of file app_voicemail_odbcstorage.c.

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

Definition at line 829 of file app_voicemail_odbcstorage.c.

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

Definition at line 827 of file app_voicemail_odbcstorage.c.

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

Definition at line 833 of file app_voicemail_odbcstorage.c.

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

Definition at line 830 of file app_voicemail_odbcstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 716 of file app_voicemail_odbcstorage.c.

struct ast_data_handler vm_users_data_provider [static]

Initial value:

Definition at line 11100 of file app_voicemail_odbcstorage.c.

char vmfmts[80] [static]

Definition at line 764 of file app_voicemail_odbcstorage.c.

int vmmaxsecs [static]

Definition at line 767 of file app_voicemail_odbcstorage.c.

int vmminsecs [static]

Definition at line 766 of file app_voicemail_odbcstorage.c.

double volgain [static]

Definition at line 765 of file app_voicemail_odbcstorage.c.

char zonetag[80] [static]

Definition at line 754 of file app_voicemail_odbcstorage.c.


Generated on Wed Apr 6 11:29:53 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7