Mon Oct 8 12:39:10 2012

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

Variables

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


Detailed Description

Comedian Mail - Voicemail System.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
unixODBC (http://www.unixodbc.org/)
ExtRef:
A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/)
See also
Note:
For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage

This module requires res_adsi to load. This needs to be optional during compilation.

This file is now almost impossible to work with, due to all #ifdefs. Feels like the database code before realtime. Someone - please come up with a plan to clean this up.

Definition in file app_voicemail_odbcstorage.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 411 of file app_voicemail_odbcstorage.c.

#define BASELINELEN   72

Definition at line 434 of file app_voicemail_odbcstorage.c.

#define BASEMAXINLINE   256

Definition at line 435 of file app_voicemail_odbcstorage.c.

#define CHUNKSIZE   65536

Definition at line 408 of file app_voicemail_odbcstorage.c.

#define COMMAND_TIMEOUT   5000

Definition at line 404 of file app_voicemail_odbcstorage.c.

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

Definition at line 722 of file app_voicemail_odbcstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

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

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 416 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 418 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 419 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 417 of file app_voicemail_odbcstorage.c.

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 420 of file app_voicemail_odbcstorage.c.

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 792 of file app_voicemail_odbcstorage.c.

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

Definition at line 723 of file app_voicemail_odbcstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 718 of file app_voicemail_odbcstorage.c.

#define ENDL   "\n"

Definition at line 439 of file app_voicemail_odbcstorage.c.

#define ERROR_LOCK_PATH   -100

Definition at line 464 of file app_voicemail_odbcstorage.c.

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

Definition at line 720 of file app_voicemail_odbcstorage.c.

#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"

#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"

#define INTRO   "vm-intro"

Definition at line 427 of file app_voicemail_odbcstorage.c.

#define MAX_DATETIME_FORMAT   512

Definition at line 442 of file app_voicemail_odbcstorage.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 443 of file app_voicemail_odbcstorage.c.

#define MAXMSG   100

Definition at line 429 of file app_voicemail_odbcstorage.c.

#define MAXMSGLIMIT   9999

Definition at line 430 of file app_voicemail_odbcstorage.c.

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 432 of file app_voicemail_odbcstorage.c.

#define OPERATOR_EXIT   300

Definition at line 465 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 735 of file app_voicemail_odbcstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 734 of file app_voicemail_odbcstorage.c.

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

Definition at line 721 of file app_voicemail_odbcstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 717 of file app_voicemail_odbcstorage.c.

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

Definition at line 425 of file app_voicemail_odbcstorage.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 402 of file app_voicemail_odbcstorage.c.

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

Definition at line 719 of file app_voicemail_odbcstorage.c.

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 744 of file app_voicemail_odbcstorage.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 421 of file app_voicemail_odbcstorage.c.

#define VM_ALLOCED   (1 << 13)

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

Definition at line 458 of file app_voicemail_odbcstorage.c.

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 456 of file app_voicemail_odbcstorage.c.

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 457 of file app_voicemail_odbcstorage.c.

#define VM_DIRECFORWARD   (1 << 10)

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

Definition at line 455 of file app_voicemail_odbcstorage.c.

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 449 of file app_voicemail_odbcstorage.c.

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 453 of file app_voicemail_odbcstorage.c.

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 452 of file app_voicemail_odbcstorage.c.

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 463 of file app_voicemail_odbcstorage.c.

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 462 of file app_voicemail_odbcstorage.c.

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 461 of file app_voicemail_odbcstorage.c.

#define VM_OPERATOR   (1 << 1)

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

Definition at line 446 of file app_voicemail_odbcstorage.c.

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 454 of file app_voicemail_odbcstorage.c.

#define VM_REVIEW   (1 << 0)

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

Definition at line 445 of file app_voicemail_odbcstorage.c.

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 447 of file app_voicemail_odbcstorage.c.

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 450 of file app_voicemail_odbcstorage.c.

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 459 of file app_voicemail_odbcstorage.c.

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 451 of file app_voicemail_odbcstorage.c.

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 448 of file app_voicemail_odbcstorage.c.

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 460 of file app_voicemail_odbcstorage.c.

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 659 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 410 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 406 of file app_voicemail_odbcstorage.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 407 of file app_voicemail_odbcstorage.c.


Enumeration Type Documentation

enum vm_box

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 468 of file app_voicemail_odbcstorage.c.

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

enum vm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 489 of file app_voicemail_odbcstorage.c.

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

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

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

enum vm_passwordlocation

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 497 of file app_voicemail_odbcstorage.c.

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


Function Documentation

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

Definition at line 5358 of file app_voicemail_odbcstorage.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

05359 {
05360    DIR *dir;
05361    struct dirent *de;
05362    char fn[256];
05363    int ret = 0;
05364 
05365    /* If no mailbox, return immediately */
05366    if (ast_strlen_zero(mailbox))
05367       return 0;
05368 
05369    if (ast_strlen_zero(folder))
05370       folder = "INBOX";
05371    if (ast_strlen_zero(context))
05372       context = "default";
05373 
05374    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05375 
05376    if (!(dir = opendir(fn)))
05377       return 0;
05378 
05379    while ((de = readdir(dir))) {
05380       if (!strncasecmp(de->d_name, "msg", 3)) {
05381          if (shortcircuit) {
05382             ret = 1;
05383             break;
05384          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05385             ret++;
05386          }
05387       }
05388    }
05389 
05390    closedir(dir);
05391 
05392    return ret;
05393 }

static void __reg_module ( void   )  [static]

Definition at line 13661 of file app_voicemail_odbcstorage.c.

static void __unreg_module ( void   )  [static]

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

11017 {
11018    struct ast_vm_user svm;
11019    AST_DECLARE_APP_ARGS(arg,
11020       AST_APP_ARG(mbox);
11021       AST_APP_ARG(context);
11022    );
11023 
11024    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11025 
11026    if (ast_strlen_zero(arg.mbox)) {
11027       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11028       return -1;
11029    }
11030 
11031    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11032    return 0;
11033 }

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

Definition at line 11852 of file app_voicemail_odbcstorage.c.

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

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

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 4772 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, my_umask, VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

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

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

Definition at line 6378 of file app_voicemail_odbcstorage.c.

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

06379 {
06380    int x;
06381    if (!ast_adsi_available(chan))
06382       return;
06383    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06384    if (x < 0)
06385       return;
06386    if (!x) {
06387       if (adsi_load_vmail(chan, useadsi)) {
06388          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06389          return;
06390       }
06391    } else
06392       *useadsi = 1;
06393 }

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

Definition at line 6573 of file app_voicemail_odbcstorage.c.

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

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

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

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

06444 {
06445    unsigned char buf[256];
06446    int bytes = 0;
06447    unsigned char keys[8];
06448    int x, y;
06449 
06450    if (!ast_adsi_available(chan))
06451       return;
06452 
06453    for (x = 0; x < 5; x++) {
06454       y = ADSI_KEY_APPS + 12 + start + x;
06455       if (y > ADSI_KEY_APPS + 12 + 4)
06456          y = 0;
06457       keys[x] = ADSI_KEY_SKT | y;
06458    }
06459    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06460    keys[6] = 0;
06461    keys[7] = 0;
06462 
06463    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06464    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06465    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06466    bytes += ast_adsi_set_keys(buf + bytes, keys);
06467    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06468 
06469    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06470 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06729 {
06730    unsigned char buf[256];
06731    int bytes = 0;
06732 
06733    if (!ast_adsi_available(chan))
06734       return;
06735    bytes += adsi_logo(buf + bytes);
06736    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06737    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06738    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06739    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06740 
06741    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06742 }

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

Definition at line 6249 of file app_voicemail_odbcstorage.c.

References addesc, ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ADSI_MSG_DOWNLOAD, adsifdn, adsisec, adsiver, ast_adsi_begin_download(), ast_adsi_data_mode(), ast_adsi_display(), ast_adsi_download_disconnect(), ast_adsi_end_download(), ast_adsi_load_session(), ast_adsi_load_soft_key(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, and mbox().

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

static void adsi_login ( struct ast_channel chan  )  [static]

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

06396 {
06397    unsigned char buf[256];
06398    int bytes = 0;
06399    unsigned char keys[8];
06400    int x;
06401    if (!ast_adsi_available(chan))
06402       return;
06403 
06404    for (x = 0; x < 8; x++)
06405       keys[x] = 0;
06406    /* Set one key for next */
06407    keys[3] = ADSI_KEY_APPS + 3;
06408 
06409    bytes += adsi_logo(buf + bytes);
06410    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06411    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06412    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06413    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06414    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06415    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06416    bytes += ast_adsi_set_keys(buf + bytes, keys);
06417    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06418    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06419 }

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

Definition at line 6241 of file app_voicemail_odbcstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

06242 {
06243    int bytes = 0;
06244    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06245    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06246    return bytes;
06247 }

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

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

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

static void adsi_password ( struct ast_channel chan  )  [static]

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

06422 {
06423    unsigned char buf[256];
06424    int bytes = 0;
06425    unsigned char keys[8];
06426    int x;
06427    if (!ast_adsi_available(chan))
06428       return;
06429 
06430    for (x = 0; x < 8; x++)
06431       keys[x] = 0;
06432    /* Set one key for next */
06433    keys[3] = ADSI_KEY_APPS + 3;
06434 
06435    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06436    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06437    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06438    bytes += ast_adsi_set_keys(buf + bytes, keys);
06439    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06440    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06441 }

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

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

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

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

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

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

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 13223 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_test_suite_event_notify, ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), name, play_message_callerid(), play_message_datetime(), RETRIEVE, vm_state::starting, and wait_file().

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

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

Definition at line 10743 of file app_voicemail_odbcstorage.c.

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

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

static void apply_option ( struct ast_vm_user vmu,
const char *  var,
const char *  value 
) [static]

Sets a a specific property value.

Parameters:
vmu The voicemail user object to work with.
var The name of the property to be set.
value The value to be set to the property.
The property name must be one of the understood properties. See the source for details.

Definition at line 1037 of file app_voicemail_odbcstorage.c.

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

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

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

Destructively Parse options and apply.

Definition at line 1278 of file app_voicemail_odbcstorage.c.

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

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

static void apply_options_full ( struct ast_vm_user retval,
struct ast_variable var 
) [static]

Loads the options specific to a voicemail user.

This is called when a vm_user structure is being set up, such as from load_options.

Definition at line 1297 of file app_voicemail_odbcstorage.c.

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

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

AST_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 4447 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.

04448 {
04449    struct ast_str *tmp = ast_str_alloca(80);
04450    int first_section = 1;
04451 
04452    ast_str_reset(*end);
04453    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04454    for (; *start; start++) {
04455       int need_encoding = 0;
04456       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04457          need_encoding = 1;
04458       }
04459       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04460          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04461          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04462          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04463          /* Start new line */
04464          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04465          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04466          first_section = 0;
04467       }
04468       if (need_encoding && *start == ' ') {
04469          ast_str_append(&tmp, -1, "_");
04470       } else if (need_encoding) {
04471          ast_str_append(&tmp, -1, "=%hhX", *start);
04472       } else {
04473          ast_str_append(&tmp, -1, "%c", *start);
04474       }
04475    }
04476    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04477    return ast_str_buffer(*end);
04478 }

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

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

04376 {
04377    const char *ptr;
04378 
04379    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04380    ast_str_set(buf, maxlen, "\"");
04381    for (ptr = from; *ptr; ptr++) {
04382       if (*ptr == '"' || *ptr == '\\') {
04383          ast_str_append(buf, maxlen, "\\%c", *ptr);
04384       } else {
04385          ast_str_append(buf, maxlen, "%c", *ptr);
04386       }
04387    }
04388    ast_str_append(buf, maxlen, "\"");
04389 
04390    return ast_str_buffer(*buf);
04391 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

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

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

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

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

static int change_password_realtime ( struct ast_vm_user vmu,
const char *  password 
) [static]

Performs a change of the voicemail passowrd in the realtime engine.

Parameters:
vmu The voicemail user to change the password for.
password The new value to be set to the password for this user.
This only works if there is a realtime engine configured. This is called from the (top level) vm_change_password.

Returns:
zero on success, -1 on error.

Definition at line 1256 of file app_voicemail_odbcstorage.c.

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

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

static int check_mime ( const char *  str  )  [static]

Check if the string would need encoding within the MIME standard, to avoid confusing certain mail software that expects messages to be 7-bit clean.

Definition at line 4420 of file app_voicemail_odbcstorage.c.

04421 {
04422    for (; *str; str++) {
04423       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04424          return 1;
04425       }
04426    }
04427    return 0;
04428 }

static int check_password ( struct ast_vm_user vmu,
char *  password 
) [static]

Check that password meets minimum required length.

Parameters:
vmu The voicemail user to change the password for.
password The password string to check
Returns:
zero on ok, 1 on not ok.

Definition at line 1215 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 7938 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 11120 of file app_voicemail_odbcstorage.c.

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

11121 {
11122    int which = 0;
11123    int wordlen;
11124    struct ast_vm_user *vmu;
11125    const char *context = "";
11126 
11127    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11128    if (pos > 4)
11129       return NULL;
11130    if (pos == 3)
11131       return (state == 0) ? ast_strdup("for") : NULL;
11132    wordlen = strlen(word);
11133    AST_LIST_TRAVERSE(&users, vmu, list) {
11134       if (!strncasecmp(word, vmu->context, wordlen)) {
11135          if (context && strcmp(context, vmu->context) && ++which > state)
11136             return ast_strdup(vmu->context);
11137          /* ignore repeated contexts ? */
11138          context = vmu->context;
11139       }
11140    }
11141    return NULL;
11142 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

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

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 5292 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(), maxmsg, mbox(), ast_party_id::name, notify_new_message(), ast_party_id::number, S_COR, STORE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, ast_party_number::valid, vm_delete(), and vm_lock_path().

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

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

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

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

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

03952 {
03953 
03954    int vmcount = 0;
03955    DIR *vmdir = NULL;
03956    struct dirent *vment = NULL;
03957 
03958    if (vm_lock_path(dir))
03959       return ERROR_LOCK_PATH;
03960 
03961    if ((vmdir = opendir(dir))) {
03962       while ((vment = readdir(vmdir))) {
03963          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03964             vmcount++;
03965          }
03966       }
03967       closedir(vmdir);
03968    }
03969    ast_unlock_path(dir);
03970    
03971    return vmcount;
03972 }

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

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

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

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

Definition at line 13150 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 10703 of file app_voicemail_odbcstorage.c.

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

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

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

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

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

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

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

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

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

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1717 of file app_voicemail_odbcstorage.c.

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

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

static void free_vm_users ( void   )  [static]

Free the users structure.

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

11735 {
11736    struct ast_vm_user *current;
11737    AST_LIST_LOCK(&users);
11738    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11739       ast_set_flag(current, VM_ALLOCED);
11740       free_user(current);
11741    }
11742    AST_LIST_UNLOCK(&users);
11743 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11746 of file app_voicemail_odbcstorage.c.

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

11747 {
11748    struct vm_zone *zcur;
11749    AST_LIST_LOCK(&zones);
11750    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11751       free_zone(zcur);
11752    AST_LIST_UNLOCK(&zones);
11753 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5060 of file app_voicemail_odbcstorage.c.

References ast_free.

05061 {
05062    ast_free(z);
05063 }

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

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

05017 {
05018    struct ast_tm tm;
05019    struct timeval t = ast_tvnow();
05020    
05021    ast_localtime(&t, &tm, "UTC");
05022 
05023    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05024 }

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

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

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

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

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

06806 {
06807    int res = 0;
06808    int loops = 0;
06809 
06810    res = ast_play_and_wait(chan, fn);  /* Folder name */
06811    while (((res < '0') || (res > '9')) &&
06812          (res != '#') && (res >= 0) &&
06813          loops < 4) {
06814       res = get_folder(chan, 0);
06815       loops++;
06816    }
06817    if (loops == 4) { /* give up */
06818       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06819       return '#';
06820    }
06821    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06822    return res;
06823 }

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

Definition at line 1704 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

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

static int handle_subscribe ( void *  datap  )  [static]

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

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

static int handle_unsubscribe ( void *  datap  )  [static]

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

11483 {
11484    struct mwi_sub *mwi_sub;
11485    uint32_t *uniqueid = datap;
11486    
11487    AST_RWLIST_WRLOCK(&mwi_subs);
11488    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11489       if (mwi_sub->uniqueid == *uniqueid) {
11490          AST_LIST_REMOVE_CURRENT(entry);
11491          break;
11492       }
11493    }
11494    AST_RWLIST_TRAVERSE_SAFE_END
11495    AST_RWLIST_UNLOCK(&mwi_subs);
11496 
11497    if (mwi_sub)
11498       mwi_sub_destroy(mwi_sub);
11499 
11500    ast_free(uniqueid);  
11501    return 0;
11502 }

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

11258 {
11259    switch (cmd) {
11260    case CLI_INIT:
11261       e->command = "voicemail reload";
11262       e->usage =
11263          "Usage: voicemail reload\n"
11264          "       Reload voicemail configuration\n";
11265       return NULL;
11266    case CLI_GENERATE:
11267       return NULL;
11268    }
11269 
11270    if (a->argc != 2)
11271       return CLI_SHOWUSAGE;
11272 
11273    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11274    load_config(1);
11275    
11276    return CLI_SUCCESS;
11277 }

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

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

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

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

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

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

05405 {
05406    char tmp[256], *tmp2 = tmp, *box, *context;
05407    ast_copy_string(tmp, mailbox, sizeof(tmp));
05408    if (ast_strlen_zero(folder)) {
05409       folder = "INBOX";
05410    }
05411    while ((box = strsep(&tmp2, ",&"))) {
05412       if ((context = strchr(box, '@')))
05413          *context++ = '\0';
05414       else
05415          context = "default";
05416       if (__has_voicemail(context, box, folder, 1))
05417          return 1;
05418       /* If we are checking INBOX, we should check Urgent as well */
05419       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05420          return 1;
05421       }
05422    }
05423    return 0;
05424 }

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

Definition at line 5486 of file app_voicemail_odbcstorage.c.

References inboxcount2().

05487 {
05488    int urgentmsgs = 0;
05489    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05490    if (newmsgs) {
05491       *newmsgs += urgentmsgs;
05492    }
05493    return res;
05494 }

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

Definition at line 5427 of file app_voicemail_odbcstorage.c.

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

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

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

utility used by inchar(), for base_encode()

Definition at line 4186 of file app_voicemail_odbcstorage.c.

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

04187 {
04188    int l;
04189 
04190    if (bio->ateof)
04191       return 0;
04192 
04193    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04194       if (ferror(fi))
04195          return -1;
04196 
04197       bio->ateof = 1;
04198       return 0;
04199    }
04200 
04201    bio->iolen = l;
04202    bio->iocp = 0;
04203 
04204    return 1;
04205 }

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

utility used by base_encode()

Definition at line 4210 of file app_voicemail_odbcstorage.c.

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

04211 {
04212    if (bio->iocp>=bio->iolen) {
04213       if (!inbuf(bio, fi))
04214          return EOF;
04215    }
04216 
04217    return bio->iobuf[bio->iocp++];
04218 }

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

Definition at line 916 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 925 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 910 of file app_voicemail_odbcstorage.c.

References inprocess::mailbox.

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

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

Definition at line 5026 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, RETRIEVE, and VM_SPOOL_DIR.

05027 {
05028    int res;
05029    char fn[PATH_MAX];
05030    char dest[PATH_MAX];
05031 
05032    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05033 
05034    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05035       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05036       return -1;
05037    }
05038 
05039    RETRIEVE(fn, -1, ext, context);
05040    if (ast_fileexists(fn, NULL, NULL) > 0) {
05041       res = ast_stream_and_wait(chan, fn, ecodes);
05042       if (res) {
05043          DISPOSE(fn, -1);
05044          return res;
05045       }
05046    } else {
05047       /* Dispose just in case */
05048       DISPOSE(fn, -1);
05049       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05050       if (res)
05051          return res;
05052       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05053       if (res)
05054          return res;
05055    }
05056    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05057    return res;
05058 }

static int is_valid_dtmf ( const char *  key  )  [static]

Determines if a DTMF key entered is valid.

Parameters:
key The character to be compared. expects a single character. Though is capable of handling a string, this is internally copies using ast_strdupa.
Tests the character entered against the set of valid DTMF characters.
Returns:
1 if the character entered is a valid DTMF digit, 0 if the character is invalid.

Definition at line 1352 of file app_voicemail_odbcstorage.c.

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

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

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

Determines the highest message number in use for a given user and mailbox folder.

Parameters:
vmu 
dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.
This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP). Typical use to set the msgnum would be to take the value returned from this method and add one to it.

Note:
Should always be called with a lock already set on dir.
Returns:
the value of zero or greaterto indicate the last message index in use, -1 to indicate none.

Definition at line 4005 of file app_voicemail_odbcstorage.c.

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

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

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 5559 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, leave_vm_options::exitcontext, find_user(), ast_party_caller::id, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, ast_party_id::number, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), RETRIEVE, S_COR, ast_party_number::str, ast_party_number::valid, VM_OPERATOR, VM_SPOOL_DIR, and VOICEMAIL_DIR_MODE.

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

static int load_config ( int  reload  )  [static]

Definition at line 11802 of file app_voicemail_odbcstorage.c.

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

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

static int load_module ( void   )  [static]

Definition at line 13102 of file app_voicemail_odbcstorage.c.

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

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

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

References VM_SPOOL_DIR.

01617 {
01618    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01619 }

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

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

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

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

01634 {
01635    return snprintf(dest, len, "%s/msg%04d", dir, num);
01636 }

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

Manager list voicemail users command.

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

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

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

Definition at line 11454 of file app_voicemail_odbcstorage.c.

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

11455 {
11456    while (poll_thread_run) {
11457       struct timespec ts = { 0, };
11458       struct timeval wait;
11459 
11460       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11461       ts.tv_sec = wait.tv_sec;
11462       ts.tv_nsec = wait.tv_usec * 1000;
11463 
11464       ast_mutex_lock(&poll_lock);
11465       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11466       ast_mutex_unlock(&poll_lock);
11467 
11468       if (!poll_thread_run)
11469          break;
11470 
11471       poll_subscribed_mailboxes();
11472    }
11473 
11474    return NULL;
11475 }

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

Definition at line 1694 of file app_voicemail_odbcstorage.c.

References ARRAY_LEN.

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

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

Definition at line 5353 of file app_voicemail_odbcstorage.c.

References __has_voicemail().

05354 {
05355    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05356 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11477 of file app_voicemail_odbcstorage.c.

References ast_free, and mwi_sub.

11478 {
11479    ast_free(mwi_sub);
11480 }

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

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

11566 {
11567    struct mwi_sub_task *mwist;
11568    
11569    if (ast_event_get_type(event) != AST_EVENT_SUB)
11570       return;
11571 
11572    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11573       return;
11574 
11575    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11576       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11577       return;
11578    }
11579    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11580    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11581    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11582    
11583    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11584       ast_free(mwist);
11585    }
11586 }

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

Definition at line 11539 of file app_voicemail_odbcstorage.c.

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

11540 {
11541    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11542 
11543    if (!uniqueid) {
11544       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11545       return;
11546    }
11547 
11548    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11549       ast_free(uniqueid);
11550       return;
11551    }
11552 
11553    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11554       ast_free(uniqueid);
11555       return;
11556    }
11557 
11558    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11559    *uniqueid = u;
11560    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11561       ast_free(uniqueid);
11562    }
11563 }

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 7036 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, serveremail, strsep(), VM_ATTACH, vm_delete(), VM_DELETE, and VM_SPOOL_DIR.

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

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

utility used by base_encode()

Definition at line 4223 of file app_voicemail_odbcstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

04224 {
04225    if (bio->linelength >= BASELINELEN) {
04226       if (fputs(ENDL, so) == EOF) {
04227          return -1;
04228       }
04229 
04230       bio->linelength = 0;
04231    }
04232 
04233    if (putc(((unsigned char) c), so) == EOF) {
04234       return -1;
04235    }
04236 
04237    bio->linelength++;
04238 
04239    return 1;
04240 }

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

Definition at line 7885 of file app_voicemail_odbcstorage.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, ast_unlock_path(), ast_vm_user::context, count_messages(), create_dirpath(), vm_state::curbox, vm_state::curdir, ERROR_LOCK_PATH, last_message_index(), vm_state::lastmsg, LOG_NOTICE, ast_vm_user::maxmsg, mbox(), resequence_mailbox(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

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

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

Definition at line 7659 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 7545 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, name, VM_SPOOL_DIR, and wait_file2().

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

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

Definition at line 7456 of file app_voicemail_odbcstorage.c.

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

07457 {
07458    int res = 0;
07459 
07460    if (!ast_strlen_zero(category))
07461       res = ast_play_and_wait(chan, category);
07462 
07463    if (res) {
07464       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07465       res = 0;
07466    }
07467 
07468    return res;
07469 }

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

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

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

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

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

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

static int play_record_review ( struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime,
char *  fmt,
int  outsidecaller,
struct ast_vm_user vmu,
int *  duration,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 13415 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, maxsilence, silencethreshold, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11426 of file app_voicemail_odbcstorage.c.

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

11427 {
11428    int new = 0, old = 0, urgent = 0;
11429 
11430    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11431 
11432    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11433       mwi_sub->old_urgent = urgent;
11434       mwi_sub->old_new = new;
11435       mwi_sub->old_old = old;
11436       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11437       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11438    }
11439 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11442 {
11443    struct mwi_sub *mwi_sub;
11444 
11445    AST_RWLIST_RDLOCK(&mwi_subs);
11446    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11447       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11448          poll_subscribed_mailbox(mwi_sub);
11449       }
11450    }
11451    AST_RWLIST_UNLOCK(&mwi_subs);
11452 }

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

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

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

static void prep_email_sub_vars ( struct ast_channel ast,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  dur,
char *  date,
const char *  category,
const char *  flag 
) [static]

Definition at line 4311 of file app_voicemail_odbcstorage.c.

References ast_callerid_merge(), ast_callerid_split(), ast_config_destroy(), ast_config_load, ast_localtime(), ast_log(), ast_strdupa, ast_strftime_locale(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, 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.

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

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

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

07000 {
07001    struct ast_event *event;
07002    char *mailbox, *context;
07003 
07004    /* Strip off @default */
07005    context = mailbox = ast_strdupa(box);
07006    strsep(&context, "@");
07007    if (ast_strlen_zero(context))
07008       context = "default";
07009 
07010    if (!(event = ast_event_new(AST_EVENT_MWI,
07011          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07012          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07013          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07014          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07015          AST_EVENT_IE_END))) {
07016       return;
07017    }
07018 
07019    ast_event_queue_and_cache(event);
07020 }

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

Definition at line 12532 of file app_voicemail_odbcstorage.c.

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

12532                                                                                            {
12533    struct ast_config *pwconf;
12534    struct ast_flags config_flags = { 0 };
12535 
12536    pwconf = ast_config_load(secretfn, config_flags);
12537    if (pwconf) {
12538       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12539       if (val) {
12540          ast_copy_string(password, val, passwordlen);
12541          ast_config_destroy(pwconf);
12542          return;
12543       }
12544       ast_config_destroy(pwconf);
12545    }
12546    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12547 }

static int reload ( void   )  [static]

Definition at line 13062 of file app_voicemail_odbcstorage.c.

References load_config().

13063 {
13064    return load_config(1);
13065 }

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

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

03982 {
03983    char stxt[PATH_MAX];
03984    char dtxt[PATH_MAX];
03985    ast_filerename(sfn, dfn, NULL);
03986    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03987    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03988    if (ast_check_realtime("voicemail_data")) {
03989       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03990    }
03991    rename(stxt, dtxt);
03992 }

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

Definition at line 6125 of file app_voicemail_odbcstorage.c.

References ast_unlock_path(), ast_vm_user::context, ERROR_LOCK_PATH, EXISTS, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, RENAME, and vm_lock_path().

06126 {
06127    /* we know the actual number of messages, so stop process when number is hit */
06128 
06129    int x, dest;
06130    char sfn[PATH_MAX];
06131    char dfn[PATH_MAX];
06132 
06133    if (vm_lock_path(dir)) {
06134       return ERROR_LOCK_PATH;
06135    }
06136 
06137    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06138       make_file(sfn, sizeof(sfn), dir, x);
06139       if (EXISTS(dir, x, sfn, NULL)) {
06140 
06141          if (x != dest) {
06142             make_file(dfn, sizeof(dfn), dir, dest);
06143             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06144          }
06145 
06146          dest++;
06147       }
06148    }
06149    ast_unlock_path(dir);
06150 
06151    return dest;
06152 }

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

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

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

Definition at line 5496 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, externnotify, ast_smdi_mwi_message::fwd_st, inboxcount2(), smdi_iface, and SMDI_MWI_WAIT_TIMEOUT.

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

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

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

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

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

Definition at line 6155 of file app_voicemail_odbcstorage.c.

References AST_DIGIT_ANY, and ast_say_number().

06156 {
06157    int d;
06158    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06159    return d;
06160 }

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

Definition at line 12518 of file app_voicemail_odbcstorage.c.

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

12519 {
12520    int res = -1;
12521    char dir[PATH_MAX];
12522    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12523    ast_debug(2, "About to try retrieving name file %s\n", dir);
12524    RETRIEVE(dir, -1, mailbox, context);
12525    if (ast_fileexists(dir, NULL, NULL)) {
12526       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12527    }
12528    DISPOSE(dir, -1);
12529    return res;
12530 }

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 4826 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, mailcmd, make_email_file(), strsep(), VM_ATTACH, and vm_mkftemp().

04827 {
04828    FILE *p = NULL;
04829    char tmp[80] = "/tmp/astmail-XXXXXX";
04830    char tmp2[256];
04831    char *stringp;
04832 
04833    if (vmu && ast_strlen_zero(vmu->email)) {
04834       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04835       return(0);
04836    }
04837 
04838    /* Mail only the first format */
04839    format = ast_strdupa(format);
04840    stringp = format;
04841    strsep(&stringp, "|");
04842 
04843    if (!strcmp(format, "wav49"))
04844       format = "WAV";
04845    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));
04846    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04847       command hangs */
04848    if ((p = vm_mkftemp(tmp)) == NULL) {
04849       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04850       return -1;
04851    } else {
04852       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04853       fclose(p);
04854       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04855       ast_safe_system(tmp2);
04856       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04857    }
04858    return 0;
04859 }

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

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

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

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

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

11082 {
11083    struct ast_config *cfg;
11084    const char *cat = NULL;
11085 
11086    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11087       "context", context, SENTINEL))) {
11088       return CLI_FAILURE;
11089    }
11090 
11091    ast_cli(fd,
11092       "\n"
11093       "=============================================================\n"
11094       "=== Configured Voicemail Users ==============================\n"
11095       "=============================================================\n"
11096       "===\n");
11097 
11098    while ((cat = ast_category_browse(cfg, cat))) {
11099       struct ast_variable *var = NULL;
11100       ast_cli(fd,
11101          "=== Mailbox ...\n"
11102          "===\n");
11103       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11104          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11105       ast_cli(fd,
11106          "===\n"
11107          "=== ---------------------------------------------------------\n"
11108          "===\n");
11109    }
11110 
11111    ast_cli(fd,
11112       "=============================================================\n"
11113       "\n");
11114 
11115    ast_config_destroy(cfg);
11116 
11117    return CLI_SUCCESS;
11118 }

static void start_poll_thread ( void   )  [static]

Definition at line 11588 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_log(), ast_pthread_create, LOG_ERROR, mb_poll_thread(), mwi_sub_event_cb(), mwi_sub_sub, mwi_unsub_event_cb(), mwi_unsub_sub, poll_thread, and poll_thread_run.

11589 {
11590    int errcode;
11591    mwi_sub_sub = ast_event_subscribe(AST_EVENT_SUB, mwi_sub_event_cb, "Voicemail MWI subscription", NULL,
11592       AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
11593       AST_EVENT_IE_END);
11594 
11595    mwi_unsub_sub = ast_event_subscribe(AST_EVENT_UNSUB, mwi_unsub_event_cb, "Voicemail MWI subscription", NULL,
11596       AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
11597       AST_EVENT_IE_END);
11598 
11599    if (mwi_sub_sub)
11600       ast_event_report_subs(mwi_sub_sub);
11601 
11602    poll_thread_run = 1;
11603 
11604    if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
11605       ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
11606    }
11607 }

static void stop_poll_thread ( void   )  [static]

Definition at line 11609 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, poll_cond, poll_lock, poll_thread, and poll_thread_run.

11610 {
11611    poll_thread_run = 0;
11612 
11613    if (mwi_sub_sub) {
11614       ast_event_unsubscribe(mwi_sub_sub);
11615       mwi_sub_sub = NULL;
11616    }
11617 
11618    if (mwi_unsub_sub) {
11619       ast_event_unsubscribe(mwi_unsub_sub);
11620       mwi_unsub_sub = NULL;
11621    }
11622 
11623    ast_mutex_lock(&poll_lock);
11624    ast_cond_signal(&poll_cond);
11625    ast_mutex_unlock(&poll_lock);
11626 
11627    pthread_join(poll_thread, NULL);
11628 
11629    poll_thread = AST_PTHREADT_NULL;
11630 }

static char* strip_control_and_high ( const char *  input,
char *  buf,
size_t  buflen 
) [static]

Strips control and non 7-bit clean characters from input string.

Note:
To map control and none 7-bit characters to a 7-bit clean characters please use ast_str_encode_mine().

Definition at line 965 of file app_voicemail_odbcstorage.c.

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

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

Definition at line 11755 of file app_voicemail_odbcstorage.c.

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

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

static int unload_module ( void   )  [static]

Definition at line 13067 of file app_voicemail_odbcstorage.c.

References ao2_ref, app, app2, app3, app4, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_manager_unregister(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), AST_TEST_UNREGISTER, ast_uninstall_vm_functions(), ast_unload_realtime(), ast_unregister_application(), cli_voicemail, free_vm_users(), free_vm_zones(), inprocess_container, mailbox_exists_acf, mwi_subscription_tps, poll_thread, sayname_app, and stop_poll_thread().

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

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

Definition at line 1731 of file app_voicemail_odbcstorage.c.

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

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

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 9757 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_test_suite_event_notify, ast_verb, ast_waitstream(), find_user(), ast_vm_user::password, S_COR, and vm_password.

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

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

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

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

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

09737 {
09738    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09739       return vm_browse_messages_es(chan, vms, vmu);
09740    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09741       return vm_browse_messages_gr(chan, vms, vmu);
09742    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09743       return vm_browse_messages_he(chan, vms, vmu);
09744    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09745       return vm_browse_messages_it(chan, vms, vmu);
09746    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09747       return vm_browse_messages_pt(chan, vms, vmu);
09748    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09749       return vm_browse_messages_vi(chan, vms, vmu);
09750    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09751       return vm_browse_messages_zh(chan, vms, vmu);
09752    } else {                                             /* Default to English syntax */
09753       return vm_browse_messages_en(chan, vms, vmu);
09754    }
09755 }

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

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

09576 {
09577    int cmd = 0;
09578 
09579    if (vms->lastmsg > -1) {
09580       cmd = play_message(chan, vmu, vms);
09581    } else {
09582       cmd = ast_play_and_wait(chan, "vm-youhave");
09583       if (!cmd) 
09584          cmd = ast_play_and_wait(chan, "vm-no");
09585       if (!cmd) {
09586          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09587          cmd = ast_play_and_wait(chan, vms->fn);
09588       }
09589       if (!cmd)
09590          cmd = ast_play_and_wait(chan, "vm-messages");
09591    }
09592    return cmd;
09593 }

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

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

09630 {
09631    int cmd;
09632 
09633    if (vms->lastmsg > -1) {
09634       cmd = play_message(chan, vmu, vms);
09635    } else {
09636       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09637       if (!cmd)
09638          cmd = ast_play_and_wait(chan, "vm-messages");
09639       if (!cmd) {
09640          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09641          cmd = ast_play_and_wait(chan, vms->fn);
09642       }
09643    }
09644    return cmd;
09645 }

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

09524 {
09525    int cmd = 0;
09526 
09527    if (vms->lastmsg > -1) {
09528       cmd = play_message(chan, vmu, vms);
09529    } else {
09530       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09531       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09532          if (!cmd) {
09533             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09534             cmd = ast_play_and_wait(chan, vms->fn);
09535          }
09536          if (!cmd)
09537             cmd = ast_play_and_wait(chan, "vm-messages");
09538       } else {
09539          if (!cmd)
09540             cmd = ast_play_and_wait(chan, "vm-messages");
09541          if (!cmd) {
09542             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09543             cmd = ast_play_and_wait(chan, vms->fn);
09544          }
09545       }
09546    } 
09547    return cmd;
09548 }

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

Definition at line 9551 of file app_voicemail_odbcstorage.c.

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

09552 {
09553    int cmd = 0;
09554 
09555    if (vms->lastmsg > -1) {
09556       cmd = play_message(chan, vmu, vms);
09557    } else {
09558       if (!strcasecmp(vms->fn, "INBOX")) {
09559          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09560       } else {
09561          cmd = ast_play_and_wait(chan, "vm-nomessages");
09562       }
09563    }
09564    return cmd;
09565 }

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

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

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

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

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

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

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

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

09710 {
09711    int cmd = 0;
09712 
09713    if (vms->lastmsg > -1) {
09714       cmd = play_message(chan, vmu, vms);
09715    } else {
09716       cmd = ast_play_and_wait(chan, "vm-no");
09717       if (!cmd) {
09718          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09719          cmd = ast_play_and_wait(chan, vms->fn);
09720       }
09721    }
09722    return cmd;
09723 }

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

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

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

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 1487 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_test_suite_event_notify, ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, reset_user_pw(), value, var, VM_SPOOL_DIR, VOICEMAIL_CONFIG, and write_password_to_file().

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

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

Definition at line 1590 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 1162 of file app_voicemail_odbcstorage.c.

References AST_APP_ARG, ast_close_fds_above_n(), AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_safe_fork(), ast_strdupa, errno, and LOG_WARNING.

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

static int vm_delete ( char *  file  )  [static]

Removes the voicemail sound and information file.

Parameters:
file The path to the sound file. This will be the the folder and message index, without the extension.
This is used by the DELETE macro when voicemails are stored on the file system.

Returns:
zero on success, -1 on error.

Definition at line 4165 of file app_voicemail_odbcstorage.c.

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

04166 {
04167    char *txt;
04168    int txtsize = 0;
04169 
04170    txtsize = (strlen(file) + 5)*sizeof(char);
04171    txt = alloca(txtsize);
04172    /* Sprintf here would safe because we alloca'd exactly the right length,
04173     * but trying to eliminate all sprintf's anyhow
04174     */
04175    if (ast_check_realtime("voicemail_data")) {
04176       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04177    }
04178    snprintf(txt, txtsize, "%s.txt", file);
04179    unlink(txt);
04180    return ast_filedelete(file, NULL);
04181 }

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

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

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

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

Definition at line 9883 of file app_voicemail_odbcstorage.c.

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

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

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

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

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

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

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

09199 {
09200    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09201       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09202    } else {             /* Default to ENGLISH */
09203       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09204    }
09205 }

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

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

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

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

09175 {
09176    int res = 0;
09177    /* Play instructions and wait for new command */
09178    while (!res) {
09179       if (vms->lastmsg > -1) {
09180          res = ast_play_and_wait(chan, "vm-listen");
09181          if (!res)
09182             res = vm_play_folder_name(chan, vms->vmbox);
09183          if (!res)
09184             res = ast_play_and_wait(chan, "press");
09185          if (!res)
09186             res = ast_play_and_wait(chan, "digits/1");
09187       }
09188       if (!res)
09189          res = ast_play_and_wait(chan, "vm-opts");
09190       if (!res) {
09191          vms->starting = 0;
09192          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09193       }
09194    }
09195    return res;
09196 }

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

Definition at line 9024 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(), VM_SPOOL_DIR, and VM_TEMPGREETWARN.

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

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

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

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

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

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

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

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

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

08340 {
08341    int res;
08342 
08343    /* Introduce messages they have */
08344    res = ast_play_and_wait(chan, "vm-youhave");
08345    if (!res) {
08346       if (vms->urgentmessages) {
08347          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08348          if (!res)
08349             res = ast_play_and_wait(chan, "vm-Urgent");
08350          if ((vms->oldmessages || vms->newmessages) && !res) {
08351             res = ast_play_and_wait(chan, "vm-and");
08352          } else if (!res) {
08353             if ((vms->urgentmessages == 1))
08354                res = ast_play_and_wait(chan, "vm-message");
08355             else
08356                res = ast_play_and_wait(chan, "vm-messages");
08357          }
08358       }
08359       if (vms->newmessages) {
08360          res = say_and_wait(chan, vms->newmessages, chan->language);
08361          if (!res)
08362             res = ast_play_and_wait(chan, "vm-INBOX");
08363          if (vms->oldmessages && !res)
08364             res = ast_play_and_wait(chan, "vm-and");
08365          else if (!res) {
08366             if ((vms->newmessages == 1))
08367                res = ast_play_and_wait(chan, "vm-message");
08368             else
08369                res = ast_play_and_wait(chan, "vm-messages");
08370          }
08371             
08372       }
08373       if (!res && vms->oldmessages) {
08374          res = say_and_wait(chan, vms->oldmessages, chan->language);
08375          if (!res)
08376             res = ast_play_and_wait(chan, "vm-Old");
08377          if (!res) {
08378             if (vms->oldmessages == 1)
08379                res = ast_play_and_wait(chan, "vm-message");
08380             else
08381                res = ast_play_and_wait(chan, "vm-messages");
08382          }
08383       }
08384       if (!res) {
08385          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08386             res = ast_play_and_wait(chan, "vm-no");
08387             if (!res)
08388                res = ast_play_and_wait(chan, "vm-messages");
08389          }
08390       }
08391    }
08392    return res;
08393 }

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

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

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

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

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

08738 {
08739    /* Introduce messages they have */
08740    int res;
08741    res = ast_play_and_wait(chan, "vm-youhave");
08742    if (!res) {
08743       if (vms->newmessages) {
08744          res = say_and_wait(chan, vms->newmessages, chan->language);
08745          if (!res)
08746             res = ast_play_and_wait(chan, "vm-INBOX");
08747          if (vms->oldmessages && !res)
08748             res = ast_play_and_wait(chan, "vm-and");
08749          else if (!res) {
08750             if ((vms->newmessages == 1))
08751                res = ast_play_and_wait(chan, "vm-message");
08752             else
08753                res = ast_play_and_wait(chan, "vm-messages");
08754          }
08755             
08756       }
08757       if (!res && vms->oldmessages) {
08758          res = say_and_wait(chan, vms->oldmessages, chan->language);
08759          if (!res)
08760             res = ast_play_and_wait(chan, "vm-Old");
08761          if (!res) {
08762             if (vms->oldmessages == 1)
08763                res = ast_play_and_wait(chan, "vm-message");
08764             else
08765                res = ast_play_and_wait(chan, "vm-messages");
08766          }
08767       }
08768       if (!res) {
08769          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08770             res = ast_play_and_wait(chan, "vm-no");
08771             if (!res)
08772                res = ast_play_and_wait(chan, "vm-messages");
08773          }
08774       }
08775    }
08776    return res;
08777 }

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

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

08139 {
08140    int res = 0;
08141 
08142    if (vms->newmessages) {
08143       res = ast_play_and_wait(chan, "vm-youhave");
08144       if (!res) 
08145          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08146       if (!res) {
08147          if ((vms->newmessages == 1)) {
08148             res = ast_play_and_wait(chan, "vm-INBOX");
08149             if (!res)
08150                res = ast_play_and_wait(chan, "vm-message");
08151          } else {
08152             res = ast_play_and_wait(chan, "vm-INBOXs");
08153             if (!res)
08154                res = ast_play_and_wait(chan, "vm-messages");
08155          }
08156       }
08157    } else if (vms->oldmessages){
08158       res = ast_play_and_wait(chan, "vm-youhave");
08159       if (!res)
08160          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08161       if ((vms->oldmessages == 1)){
08162          res = ast_play_and_wait(chan, "vm-Old");
08163          if (!res)
08164             res = ast_play_and_wait(chan, "vm-message");
08165       } else {
08166          res = ast_play_and_wait(chan, "vm-Olds");
08167          if (!res)
08168             res = ast_play_and_wait(chan, "vm-messages");
08169       }
08170    } else if (!vms->oldmessages && !vms->newmessages) 
08171       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08172    return res;
08173 }

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

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

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

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

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

08397 {
08398    /* Introduce messages they have */
08399    int res;
08400    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08401       res = ast_play_and_wait(chan, "vm-no") ||
08402          ast_play_and_wait(chan, "vm-message");
08403    else
08404       res = ast_play_and_wait(chan, "vm-youhave");
08405    if (!res && vms->newmessages) {
08406       res = (vms->newmessages == 1) ?
08407          ast_play_and_wait(chan, "digits/un") ||
08408          ast_play_and_wait(chan, "vm-nuovo") ||
08409          ast_play_and_wait(chan, "vm-message") :
08410          /* 2 or more new messages */
08411          say_and_wait(chan, vms->newmessages, chan->language) ||
08412          ast_play_and_wait(chan, "vm-nuovi") ||
08413          ast_play_and_wait(chan, "vm-messages");
08414       if (!res && vms->oldmessages)
08415          res = ast_play_and_wait(chan, "vm-and");
08416    }
08417    if (!res && vms->oldmessages) {
08418       res = (vms->oldmessages == 1) ?
08419          ast_play_and_wait(chan, "digits/un") ||
08420          ast_play_and_wait(chan, "vm-vecchio") ||
08421          ast_play_and_wait(chan, "vm-message") :
08422          /* 2 or more old messages */
08423          say_and_wait(chan, vms->oldmessages, chan->language) ||
08424          ast_play_and_wait(chan, "vm-vecchi") ||
08425          ast_play_and_wait(chan, "vm-messages");
08426    }
08427    return res;
08428 }

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

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

08233 {
08234    int res;
08235    int lastnum = 0;
08236 
08237    res = ast_play_and_wait(chan, "vm-youhave");
08238 
08239    if (!res && vms->newmessages) {
08240       lastnum = vms->newmessages;
08241 
08242       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08243          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08244       }
08245 
08246       if (!res && vms->oldmessages) {
08247          res = ast_play_and_wait(chan, "vm-and");
08248       }
08249    }
08250 
08251    if (!res && vms->oldmessages) {
08252       lastnum = vms->oldmessages;
08253 
08254       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08255          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08256       }
08257    }
08258 
08259    if (!res) {
08260       if (lastnum == 0) {
08261          res = ast_play_and_wait(chan, "vm-no");
08262       }
08263       if (!res) {
08264          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08265       }
08266    }
08267 
08268    return res;
08269 }

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

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

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

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

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

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

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

Definition at line 8431 of file app_voicemail_odbcstorage.c.

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 8994 of file app_voicemail_odbcstorage.c.

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

08995 {
08996    int res;
08997 
08998    /* Introduce messages they have */
08999    res = ast_play_and_wait(chan, "vm-youhave");
09000    if (!res) {
09001       if (vms->newmessages) {
09002          res = say_and_wait(chan, vms->newmessages, chan->language);
09003          if (!res)
09004             res = ast_play_and_wait(chan, "vm-INBOX");
09005          if (vms->oldmessages && !res)
09006             res = ast_play_and_wait(chan, "vm-and");
09007       }
09008       if (!res && vms->oldmessages) {
09009          res = say_and_wait(chan, vms->oldmessages, chan->language);
09010          if (!res)
09011             res = ast_play_and_wait(chan, "vm-Old");        
09012       }
09013       if (!res) {
09014          if (!vms->oldmessages && !vms->newmessages) {
09015             res = ast_play_and_wait(chan, "vm-no");
09016             if (!res)
09017                res = ast_play_and_wait(chan, "vm-message");
09018          }
09019       }
09020    }
09021    return res;
09022 }

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

Definition at line 8955 of file app_voicemail_odbcstorage.c.

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

08956 {
08957    int res;
08958    /* Introduce messages they have */
08959    res = ast_play_and_wait(chan, "vm-you");
08960 
08961    if (!res && vms->newmessages) {
08962       res = ast_play_and_wait(chan, "vm-have");
08963       if (!res)
08964          res = say_and_wait(chan, vms->newmessages, chan->language);
08965       if (!res)
08966          res = ast_play_and_wait(chan, "vm-tong");
08967       if (!res)
08968          res = ast_play_and_wait(chan, "vm-INBOX");
08969       if (vms->oldmessages && !res)
08970          res = ast_play_and_wait(chan, "vm-and");
08971       else if (!res) 
08972          res = ast_play_and_wait(chan, "vm-messages");
08973    }
08974    if (!res && vms->oldmessages) {
08975       res = ast_play_and_wait(chan, "vm-have");
08976       if (!res)
08977          res = say_and_wait(chan, vms->oldmessages, chan->language);
08978       if (!res)
08979          res = ast_play_and_wait(chan, "vm-tong");
08980       if (!res)
08981          res = ast_play_and_wait(chan, "vm-Old");
08982       if (!res)
08983          res = ast_play_and_wait(chan, "vm-messages");
08984    }
08985    if (!res && !vms->oldmessages && !vms->newmessages) {
08986       res = ast_play_and_wait(chan, "vm-haveno");
08987       if (!res)
08988          res = ast_play_and_wait(chan, "vm-messages");
08989    }
08990    return res;
08991 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03241 {
03242    switch (ast_lock_path(path)) {
03243    case AST_LOCK_TIMEOUT:
03244       return -1;
03245    default:
03246       return 0;
03247    }
03248 }

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

Definition at line 1639 of file app_voicemail_odbcstorage.c.

References my_umask, and VOICEMAIL_FILE_MODE.

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

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

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, check_password(), ast_vm_user::context, ext_pass_cmd, maxgreet, play_record_review(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, VM_FORCENAME, vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, vm_reenterpassword, and VM_SPOOL_DIR.

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

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

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_suite_event_notify, ast_waitfordigit(), check_password(), ast_vm_user::context, DISPOSE, ext_pass_cmd, ast_vm_user::mailbox, maxgreet, ast_vm_user::password, play_record_review(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, vm_reenterpassword, VM_SPOOL_DIR, and vm_tempgreeting().

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

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

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

08102 {
08103    int cmd;
08104 
08105    if (  !strncasecmp(chan->language, "it", 2) ||
08106         !strncasecmp(chan->language, "es", 2) ||
08107         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08108       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08109       return cmd ? cmd : ast_play_and_wait(chan, box);
08110    } else if (!strncasecmp(chan->language, "gr", 2)) {
08111       return vm_play_folder_name_gr(chan, box);
08112    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08113       return ast_play_and_wait(chan, box);
08114    } else if (!strncasecmp(chan->language, "pl", 2)) {
08115       return vm_play_folder_name_pl(chan, box);
08116    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08117       return vm_play_folder_name_ua(chan, box);
08118    } else if (!strncasecmp(chan->language, "vi", 2)) {
08119       return ast_play_and_wait(chan, box);
08120    } else {  /* Default English */
08121       cmd = ast_play_and_wait(chan, box);
08122       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08123    }
08124 }

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

Definition at line 8054 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

08055 {
08056    int cmd;
08057    char *buf;
08058 
08059    buf = alloca(strlen(box) + 2);
08060    strcpy(buf, box);
08061    strcat(buf, "s");
08062 
08063    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08064       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08065       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08066    } else {
08067       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08068       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08069    }
08070 }

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

Definition at line 8072 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

08073 {
08074    int cmd;
08075 
08076    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08077       if (!strcasecmp(box, "vm-INBOX"))
08078          cmd = ast_play_and_wait(chan, "vm-new-e");
08079       else
08080          cmd = ast_play_and_wait(chan, "vm-old-e");
08081       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08082    } else {
08083       cmd = ast_play_and_wait(chan, "vm-messages");
08084       return cmd ? cmd : ast_play_and_wait(chan, box);
08085    }
08086 }

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

Definition at line 8088 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

08089 {
08090    int cmd;
08091 
08092    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08093       cmd = ast_play_and_wait(chan, "vm-messages");
08094       return cmd ? cmd : ast_play_and_wait(chan, box);
08095    } else {
08096       cmd = ast_play_and_wait(chan, box);
08097       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08098    }
08099 }

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

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_fileexists(), ast_play_and_wait(), ast_test_suite_event_notify, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, maxgreet, play_record_review(), RETRIEVE, vm_state::username, and VM_SPOOL_DIR.

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

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

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

11405 {
11406    struct ast_vm_user *user;
11407 
11408    AST_LIST_LOCK(&users);
11409    AST_LIST_TRAVERSE(&users, user, list) {
11410       vm_users_data_provider_get_helper(search, data_root, user);
11411    }
11412    AST_LIST_UNLOCK(&users);
11413 
11414    return 0;
11415 }

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

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

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

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

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

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

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

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

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

04398 {
04399    const struct vm_zone *z = NULL;
04400    struct timeval t = ast_tvnow();
04401 
04402    /* Does this user have a timezone specified? */
04403    if (!ast_strlen_zero(vmu->zonetag)) {
04404       /* Find the zone in the list */
04405       AST_LIST_LOCK(&zones);
04406       AST_LIST_TRAVERSE(&zones, z, list) {
04407          if (!strcmp(z->name, vmu->zonetag))
04408             break;
04409       }
04410       AST_LIST_UNLOCK(&zones);
04411    }
04412    ast_localtime(&t, tm, z ? z->timezone : NULL);
04413    return tm;
04414 }

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

Definition at line 7450 of file app_voicemail_odbcstorage.c.

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

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

Definition at line 7442 of file app_voicemail_odbcstorage.c.

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

07443 {
07444    int res;
07445    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07446       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07447    return res;
07448 }

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

Definition at line 12549 of file app_voicemail_odbcstorage.c.

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

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


Variable Documentation

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

Definition at line 13661 of file app_voicemail_odbcstorage.c.

char* addesc = "Comedian Mail" [static]

Definition at line 750 of file app_voicemail_odbcstorage.c.

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

Definition at line 877 of file app_voicemail_odbcstorage.c.

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

Definition at line 878 of file app_voicemail_odbcstorage.c.

int adsiver = 1 [static]

Definition at line 879 of file app_voicemail_odbcstorage.c.

char* app = "VoiceMail" [static]

Definition at line 753 of file app_voicemail_odbcstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 756 of file app_voicemail_odbcstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 758 of file app_voicemail_odbcstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 759 of file app_voicemail_odbcstorage.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 13661 of file app_voicemail_odbcstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 863 of file app_voicemail_odbcstorage.c.

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

Definition at line 875 of file app_voicemail_odbcstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 866 of file app_voicemail_odbcstorage.c.

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

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

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 862 of file app_voicemail_odbcstorage.c.

char* emailbody = NULL [static]

Definition at line 869 of file app_voicemail_odbcstorage.c.

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

Definition at line 880 of file app_voicemail_odbcstorage.c.

char* emailsubject = NULL [static]

Definition at line 870 of file app_voicemail_odbcstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 864 of file app_voicemail_odbcstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 730 of file app_voicemail_odbcstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 729 of file app_voicemail_odbcstorage.c.

char externnotify[160] [static]

Definition at line 773 of file app_voicemail_odbcstorage.c.

char fromstring[100] [static]

Definition at line 873 of file app_voicemail_odbcstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 858 of file app_voicemail_odbcstorage.c.

struct ao2_container* inprocess_container

Definition at line 902 of file app_voicemail_odbcstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 831 of file app_voicemail_odbcstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 833 of file app_voicemail_odbcstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 834 of file app_voicemail_odbcstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 832 of file app_voicemail_odbcstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 835 of file app_voicemail_odbcstorage.c.

char locale[20] [static]

Definition at line 766 of file app_voicemail_odbcstorage.c.

struct ast_custom_function mailbox_exists_acf [static]

Initial value:

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

Definition at line 11035 of file app_voicemail_odbcstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1675 of file app_voicemail_odbcstorage.c.

char mailcmd[160] [static]

Definition at line 772 of file app_voicemail_odbcstorage.c.

int maxdeletedmsg [static]

Definition at line 769 of file app_voicemail_odbcstorage.c.

int maxgreet [static]

Definition at line 779 of file app_voicemail_odbcstorage.c.

int maxlogins [static]

Definition at line 781 of file app_voicemail_odbcstorage.c.

int maxmsg [static]

Definition at line 768 of file app_voicemail_odbcstorage.c.

int maxsilence [static]

Definition at line 767 of file app_voicemail_odbcstorage.c.

int minpassword [static]

Definition at line 782 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 800 of file app_voicemail_odbcstorage.c.

struct ast_taskprocessor* mwi_subscription_tps [static]

Definition at line 826 of file app_voicemail_odbcstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 802 of file app_voicemail_odbcstorage.c.

int my_umask [static]

Definition at line 732 of file app_voicemail_odbcstorage.c.

char* pagerbody = NULL [static]

Definition at line 871 of file app_voicemail_odbcstorage.c.

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

Definition at line 881 of file app_voicemail_odbcstorage.c.

char pagerfromstring[100] [static]

Definition at line 874 of file app_voicemail_odbcstorage.c.

char* pagersubject = NULL [static]

Definition at line 872 of file app_voicemail_odbcstorage.c.

int passwordlocation [static]

Definition at line 783 of file app_voicemail_odbcstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 795 of file app_voicemail_odbcstorage.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 790 of file app_voicemail_odbcstorage.c.

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

Definition at line 794 of file app_voicemail_odbcstorage.c.

unsigned int poll_mailboxes [static]

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

Definition at line 787 of file app_voicemail_odbcstorage.c.

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 796 of file app_voicemail_odbcstorage.c.

unsigned char poll_thread_run [static]

Definition at line 797 of file app_voicemail_odbcstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 736 of file app_voicemail_odbcstorage.c.

int saydurationminfo [static]

Definition at line 860 of file app_voicemail_odbcstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 761 of file app_voicemail_odbcstorage.c.

char serveremail[80] [static]

Definition at line 771 of file app_voicemail_odbcstorage.c.

int silencethreshold = 128 [static]

Definition at line 770 of file app_voicemail_odbcstorage.c.

int skipms [static]

Definition at line 780 of file app_voicemail_odbcstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 774 of file app_voicemail_odbcstorage.c.

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

Definition at line 748 of file app_voicemail_odbcstorage.c.

struct ast_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 513 of file app_voicemail_odbcstorage.c.

struct ast_data_entry vm_data_providers[] [static]

Initial value:

 {

}

Definition at line 11422 of file app_voicemail_odbcstorage.c.

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

Definition at line 843 of file app_voicemail_odbcstorage.c.

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

Definition at line 842 of file app_voicemail_odbcstorage.c.

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

Definition at line 839 of file app_voicemail_odbcstorage.c.

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

Definition at line 840 of file app_voicemail_odbcstorage.c.

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

Definition at line 838 of file app_voicemail_odbcstorage.c.

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

Definition at line 844 of file app_voicemail_odbcstorage.c.

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

Definition at line 856 of file app_voicemail_odbcstorage.c.

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

Definition at line 841 of file app_voicemail_odbcstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 727 of file app_voicemail_odbcstorage.c.

struct ast_data_handler vm_users_data_provider [static]

Initial value:

Definition at line 11417 of file app_voicemail_odbcstorage.c.

char vmfmts[80] [static]

Definition at line 775 of file app_voicemail_odbcstorage.c.

int vmmaxsecs [static]

Definition at line 778 of file app_voicemail_odbcstorage.c.

int vmminsecs [static]

Definition at line 777 of file app_voicemail_odbcstorage.c.

double volgain [static]

Definition at line 776 of file app_voicemail_odbcstorage.c.

char zonetag[80] [static]

Definition at line 765 of file app_voicemail_odbcstorage.c.


Generated on Mon Oct 8 12:39:10 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7