Mon Mar 19 11:30:35 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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 11277 of file app_voicemail_odbcstorage.c.

#define DATA_EXPORT_VM_ZONES ( ZONE   ) 

Value:

ZONE(vm_zone, name, AST_DATA_STRING)      \
   ZONE(vm_zone, timezone, AST_DATA_STRING)  \
   ZONE(vm_zone, msg_format, AST_DATA_STRING)

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

References ast_strlen_zero(), and VM_SPOOL_DIR.

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

static void __reg_module ( void   )  [static]

Definition at line 13602 of file app_voicemail_odbcstorage.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

Definition at line 6371 of file app_voicemail_odbcstorage.c.

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

06372 {
06373    int x;
06374    if (!ast_adsi_available(chan))
06375       return;
06376    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06377    if (x < 0)
06378       return;
06379    if (!x) {
06380       if (adsi_load_vmail(chan, useadsi)) {
06381          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06382          return;
06383       }
06384    } else
06385       *useadsi = 1;
06386 }

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

Definition at line 6560 of file app_voicemail_odbcstorage.c.

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

06561 {
06562    int bytes = 0;
06563    unsigned char buf[256];
06564    unsigned char keys[8];
06565 
06566    int x;
06567 
06568    if (!ast_adsi_available(chan))
06569       return;
06570 
06571    /* New meaning for keys */
06572    for (x = 0; x < 5; x++)
06573       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06574 
06575    keys[6] = 0x0;
06576    keys[7] = 0x0;
06577 
06578    if (!vms->curmsg) {
06579       /* No prev key, provide "Folder" instead */
06580       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06581    }
06582    if (vms->curmsg >= vms->lastmsg) {
06583       /* If last message ... */
06584       if (vms->curmsg) {
06585          /* but not only message, provide "Folder" instead */
06586          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06587       } else {
06588          /* Otherwise if only message, leave blank */
06589          keys[3] = 1;
06590       }
06591    }
06592 
06593    /* If deleted, show "undeleted" */
06594    if (vms->deleted[vms->curmsg]) 
06595       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06596 
06597    /* Except "Exit" */
06598    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06599    bytes += ast_adsi_set_keys(buf + bytes, keys);
06600    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06601 
06602    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06603 }

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

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

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

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06709 {
06710    unsigned char buf[256];
06711    int bytes = 0;
06712 
06713    if (!ast_adsi_available(chan))
06714       return;
06715    bytes += adsi_logo(buf + bytes);
06716    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06717    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06718    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06719    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06720 
06721    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06722 }

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

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

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

static void adsi_login ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 6234 of file app_voicemail_odbcstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

06235 {
06236    int bytes = 0;
06237    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06238    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06239    return bytes;
06240 }

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

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

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

static void adsi_password ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 6605 of file app_voicemail_odbcstorage.c.

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

06606 {
06607    unsigned char buf[256] = "";
06608    char buf1[256] = "", buf2[256] = "";
06609    int bytes = 0;
06610    unsigned char keys[8];
06611    int x;
06612 
06613    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06614    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06615    if (!ast_adsi_available(chan))
06616       return;
06617    if (vms->newmessages) {
06618       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06619       if (vms->oldmessages) {
06620          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06621          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06622       } else {
06623          snprintf(buf2, sizeof(buf2), "%s.", newm);
06624       }
06625    } else if (vms->oldmessages) {
06626       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06627       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06628    } else {
06629       strcpy(buf1, "You have no messages.");
06630       buf2[0] = ' ';
06631       buf2[1] = '\0';
06632    }
06633    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06634    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06635    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06636 
06637    for (x = 0; x < 6; x++)
06638       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06639    keys[6] = 0;
06640    keys[7] = 0;
06641 
06642    /* Don't let them listen if there are none */
06643    if (vms->lastmsg < 0)
06644       keys[0] = 1;
06645    bytes += ast_adsi_set_keys(buf + bytes, keys);
06646 
06647    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06648 
06649    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06650 }

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

Definition at line 6652 of file app_voicemail_odbcstorage.c.

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

06653 {
06654    unsigned char buf[256] = "";
06655    char buf1[256] = "", buf2[256] = "";
06656    int bytes = 0;
06657    unsigned char keys[8];
06658    int x;
06659 
06660    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06661 
06662    if (!ast_adsi_available(chan))
06663       return;
06664 
06665    /* Original command keys */
06666    for (x = 0; x < 6; x++)
06667       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06668 
06669    keys[6] = 0;
06670    keys[7] = 0;
06671 
06672    if ((vms->lastmsg + 1) < 1)
06673       keys[0] = 0;
06674 
06675    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06676       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06677 
06678    if (vms->lastmsg + 1)
06679       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06680    else
06681       strcpy(buf2, "no messages.");
06682    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06683    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06684    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06685    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06686    bytes += ast_adsi_set_keys(buf + bytes, keys);
06687 
06688    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06689 
06690    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06691    
06692 }

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

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

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

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

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

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

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

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

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

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

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

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

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

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

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

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

04416 {
04417    for (; *str; str++) {
04418       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04419          return 1;
04420       }
04421    }
04422    return 0;
04423 }

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

07912 {
07913    int x = 0;
07914 
07915 #ifndef IMAP_STORAGE
07916    int last_msg_idx;
07917    int res = 0, nummsg;
07918    char fn2[PATH_MAX];
07919 #endif
07920 
07921    if (vms->lastmsg <= -1) {
07922       goto done;
07923    }
07924 
07925    vms->curmsg = -1;
07926 #ifndef IMAP_STORAGE
07927    /* Get the deleted messages fixed */
07928    if (vm_lock_path(vms->curdir)) {
07929       return ERROR_LOCK_PATH;
07930    }
07931 
07932    /* update count as message may have arrived while we've got mailbox open */
07933    last_msg_idx = last_message_index(vmu, vms->curdir);
07934    if (last_msg_idx != vms->lastmsg) {
07935       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
07936    }
07937 
07938    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07939    for (x = 0; x < last_msg_idx + 1; x++) {
07940       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07941          /* Save this message.  It's not in INBOX or hasn't been heard */
07942          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07943          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07944             break;
07945          }
07946          vms->curmsg++;
07947          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07948          if (strcmp(vms->fn, fn2)) {
07949             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07950          }
07951       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07952          /* Move to old folder before deleting */
07953          res = save_to_folder(vmu, vms, x, 1);
07954          if (res == ERROR_LOCK_PATH) {
07955             /* If save failed do not delete the message */
07956             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07957             vms->deleted[x] = 0;
07958             vms->heard[x] = 0;
07959             --x;
07960          }
07961       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07962          /* Move to deleted folder */
07963          res = save_to_folder(vmu, vms, x, 10);
07964          if (res == ERROR_LOCK_PATH) {
07965             /* If save failed do not delete the message */
07966             vms->deleted[x] = 0;
07967             vms->heard[x] = 0;
07968             --x;
07969          }
07970       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07971          /* If realtime storage enabled - we should explicitly delete this message,
07972          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07973          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07974          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07975             DELETE(vms->curdir, x, vms->fn, vmu);
07976          }
07977       }
07978    }
07979 
07980    /* Delete ALL remaining messages */
07981    nummsg = x - 1;
07982    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07983       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07984       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07985          DELETE(vms->curdir, x, vms->fn, vmu);
07986       }
07987    }
07988    ast_unlock_path(vms->curdir);
07989 #else /* defined(IMAP_STORAGE) */
07990    if (vms->deleted) {
07991       /* Since we now expunge after each delete, deleting in reverse order
07992        * ensures that no reordering occurs between each step. */
07993       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
07994          if (vms->deleted[x]) {
07995             ast_debug(3, "IMAP delete of %d\n", x);
07996             DELETE(vms->curdir, x, vms->fn, vmu);
07997          }
07998       }
07999    }
08000 #endif
08001 
08002 done:
08003    if (vms->deleted && vmu->maxmsg) {
08004       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
08005    }
08006    if (vms->heard && vmu->maxmsg) {
08007       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
08008    }
08009 
08010    return 0;
08011 }

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

Definition at line 11085 of file app_voicemail_odbcstorage.c.

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

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

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

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

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

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

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

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

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

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

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

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

13092 {
13093    int cmd = 0;
13094    char destination[80] = "";
13095    int retries = 0;
13096 
13097    if (!num) {
13098       ast_verb(3, "Destination number will be entered manually\n");
13099       while (retries < 3 && cmd != 't') {
13100          destination[1] = '\0';
13101          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13102          if (!cmd)
13103             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13104          if (!cmd)
13105             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13106          if (!cmd) {
13107             cmd = ast_waitfordigit(chan, 6000);
13108             if (cmd)
13109                destination[0] = cmd;
13110          }
13111          if (!cmd) {
13112             retries++;
13113          } else {
13114 
13115             if (cmd < 0)
13116                return 0;
13117             if (cmd == '*') {
13118                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13119                return 0;
13120             }
13121             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13122                retries++;
13123             else
13124                cmd = 't';
13125          }
13126          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13127       }
13128       if (retries >= 3) {
13129          return 0;
13130       }
13131       
13132    } else {
13133       if (option_verbose > 2)
13134          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13135       ast_copy_string(destination, num, sizeof(destination));
13136    }
13137 
13138    if (!ast_strlen_zero(destination)) {
13139       if (destination[strlen(destination) -1 ] == '*')
13140          return 0; 
13141       if (option_verbose > 2)
13142          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13143       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13144       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13145       chan->priority = 0;
13146       return 9;
13147    }
13148    return 0;
13149 }

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

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

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

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

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

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

11685 {
11686    struct ast_vm_user *current;
11687    AST_LIST_LOCK(&users);
11688    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11689       ast_set_flag(current, VM_ALLOCED);
11690       free_user(current);
11691    }
11692    AST_LIST_UNLOCK(&users);
11693 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11696 of file app_voicemail_odbcstorage.c.

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

11697 {
11698    struct vm_zone *zcur;
11699    AST_LIST_LOCK(&zones);
11700    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11701       free_zone(zcur);
11702    AST_LIST_UNLOCK(&zones);
11703 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5055 of file app_voicemail_odbcstorage.c.

References ast_free.

05056 {
05057    ast_free(z);
05058 }

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

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

05012 {
05013    struct ast_tm tm;
05014    struct timeval t = ast_tvnow();
05015    
05016    ast_localtime(&t, &tm, "UTC");
05017 
05018    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05019 }

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

06729 {
06730    int x;
06731    int d;
06732    char fn[PATH_MAX];
06733    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06734    if (d)
06735       return d;
06736    for (x = start; x < 5; x++) { /* For all folders */
06737       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06738          return d;
06739       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06740       if (d)
06741          return d;
06742       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06743 
06744       /* The inbox folder can have its name changed under certain conditions
06745        * so this checks if the sound file exists for the inbox folder name and
06746        * if it doesn't, plays the default name instead. */
06747       if (x == 0) {
06748          if (ast_fileexists(fn, NULL, NULL)) {
06749             d = vm_play_folder_name(chan, fn);
06750          } else {
06751             ast_verb(1, "failed to find %s\n", fn);
06752             d = vm_play_folder_name(chan, "vm-INBOX");
06753          }
06754       } else {
06755          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06756          d = vm_play_folder_name(chan, fn);
06757       }
06758 
06759       if (d)
06760          return d;
06761       d = ast_waitfordigit(chan, 500);
06762       if (d)
06763          return d;
06764    }
06765 
06766    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06767    if (d)
06768       return d;
06769    d = ast_waitfordigit(chan, 4000);
06770    return d;
06771 }

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

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

06786 {
06787    int res = 0;
06788    int loops = 0;
06789 
06790    res = ast_play_and_wait(chan, fn);  /* Folder name */
06791    while (((res < '0') || (res > '9')) &&
06792          (res != '#') && (res >= 0) &&
06793          loops < 4) {
06794       res = get_folder(chan, 0);
06795       loops++;
06796    }
06797    if (loops == 4) { /* give up */
06798       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06799       return '#';
06800    }
06801    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06802    return res;
06803 }

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

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

static int handle_unsubscribe ( void *  datap  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 5481 of file app_voicemail_odbcstorage.c.

References inboxcount2().

05482 {
05483    int urgentmsgs = 0;
05484    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05485    if (newmsgs) {
05486       *newmsgs += urgentmsgs;
05487    }
05488    return res;
05489 }

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

Definition at line 5422 of file app_voicemail_odbcstorage.c.

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

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

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

utility used by inchar(), for base_encode()

Definition at line 4181 of file app_voicemail_odbcstorage.c.

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

04182 {
04183    int l;
04184 
04185    if (bio->ateof)
04186       return 0;
04187 
04188    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04189       if (ferror(fi))
04190          return -1;
04191 
04192       bio->ateof = 1;
04193       return 0;
04194    }
04195 
04196    bio->iolen = l;
04197    bio->iocp = 0;
04198 
04199    return 1;
04200 }

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

utility used by base_encode()

Definition at line 4205 of file app_voicemail_odbcstorage.c.

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

04206 {
04207    if (bio->iocp>=bio->iolen) {
04208       if (!inbuf(bio, fi))
04209          return EOF;
04210    }
04211 
04212    return bio->iobuf[bio->iocp++];
04213 }

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

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

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

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

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

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

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

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

static int load_config ( int  reload  )  [static]

Definition at line 11752 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_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, and VOICEMAIL_CONFIG.

11753 {
11754    struct ast_config *cfg, *ucfg;
11755    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11756    int res;
11757 
11758    ast_unload_realtime("voicemail");
11759    ast_unload_realtime("voicemail_data");
11760 
11761    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11762       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11763          return 0;
11764       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11765          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11766          ucfg = NULL;
11767       }
11768       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11769       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11770          ast_config_destroy(ucfg);
11771          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11772          return 0;
11773       }
11774    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11775       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11776       return 0;
11777    } else {
11778       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11779       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11780          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11781          ucfg = NULL;
11782       }
11783    }
11784 
11785    res = actual_load_config(reload, cfg, ucfg);
11786 
11787    ast_config_destroy(cfg);
11788    ast_config_destroy(ucfg);
11789 
11790    return res;
11791 }

static int load_module ( void   )  [static]

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

13044 {
13045    int res;
13046    my_umask = umask(0);
13047    umask(my_umask);
13048 
13049    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13050       return AST_MODULE_LOAD_DECLINE;
13051    }
13052 
13053    /* compute the location of the voicemail spool directory */
13054    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13055    
13056    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13057       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13058    }
13059 
13060    if ((res = load_config(0)))
13061       return res;
13062 
13063    res = ast_register_application_xml(app, vm_exec);
13064    res |= ast_register_application_xml(app2, vm_execmain);
13065    res |= ast_register_application_xml(app3, vm_box_exists);
13066    res |= ast_register_application_xml(app4, vmauthenticate);
13067    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13068    res |= ast_custom_function_register(&mailbox_exists_acf);
13069    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13070 #ifdef TEST_FRAMEWORK
13071    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13072    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13073    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13074    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13075    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13076 #endif
13077 
13078    if (res)
13079       return res;
13080 
13081    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13082    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13083 
13084    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13085    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13086    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13087 
13088    return res;
13089 }

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 4498 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_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, ast_channel::name, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

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

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

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

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

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

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

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

References __has_voicemail().

05349 {
05350    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05351 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11440 of file app_voicemail_odbcstorage.c.

References ast_free, and mwi_sub.

11441 {
11442    ast_free(mwi_sub);
11443 }

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

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

11519 {
11520    struct mwi_sub_task *mwist;
11521    
11522    if (ast_event_get_type(event) != AST_EVENT_SUB)
11523       return;
11524 
11525    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11526       return;
11527 
11528    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11529       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11530       return;
11531    }
11532    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11533    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11534    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11535    
11536    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11537       ast_free(mwist);
11538    }
11539 }

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

Definition at line 11502 of file app_voicemail_odbcstorage.c.

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

11503 {
11504    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11505    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11506       return;
11507 
11508    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11509       return;
11510 
11511    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11512    *uniqueid = u;
11513    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11514       ast_free(uniqueid);
11515    }
11516 }

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

07014 {
07015    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07016    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07017    const char *category;
07018    char *myserveremail = serveremail;
07019 
07020    ast_channel_lock(chan);
07021    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07022       category = ast_strdupa(category);
07023    }
07024    ast_channel_unlock(chan);
07025 
07026 #ifndef IMAP_STORAGE
07027    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07028 #else
07029    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07030 #endif
07031    make_file(fn, sizeof(fn), todir, msgnum);
07032    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07033 
07034    if (!ast_strlen_zero(vmu->attachfmt)) {
07035       if (strstr(fmt, vmu->attachfmt))
07036          fmt = vmu->attachfmt;
07037       else
07038          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);
07039    }
07040 
07041    /* Attach only the first format */
07042    fmt = ast_strdupa(fmt);
07043    stringp = fmt;
07044    strsep(&stringp, "|");
07045 
07046    if (!ast_strlen_zero(vmu->serveremail))
07047       myserveremail = vmu->serveremail;
07048 
07049    if (!ast_strlen_zero(vmu->email)) {
07050       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07051 
07052       if (attach_user_voicemail)
07053          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07054 
07055       /* XXX possible imap issue, should category be NULL XXX */
07056       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07057 
07058       if (attach_user_voicemail)
07059          DISPOSE(todir, msgnum);
07060    }
07061 
07062    if (!ast_strlen_zero(vmu->pager)) {
07063       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07064    }
07065 
07066    if (ast_test_flag(vmu, VM_DELETE))
07067       DELETE(todir, msgnum, fn, vmu);
07068 
07069    /* Leave voicemail for someone */
07070    if (ast_app_has_voicemail(ext_context, NULL)) 
07071       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07072 
07073    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07074 
07075    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);
07076    run_externnotify(vmu->context, vmu->mailbox, flag);
07077 
07078 #ifdef IMAP_STORAGE
07079    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07080    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07081       vm_imap_delete(NULL, vms->curmsg, vmu);
07082       vms->newmessages--;  /* Fix new message count */
07083    }
07084 #endif
07085 
07086    return 0;
07087 }

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

utility used by base_encode()

Definition at line 4218 of file app_voicemail_odbcstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

04219 {
04220    if (bio->linelength >= BASELINELEN) {
04221       if (fputs(ENDL, so) == EOF) {
04222          return -1;
04223       }
04224 
04225       bio->linelength = 0;
04226    }
04227 
04228    if (putc(((unsigned char) c), so) == EOF) {
04229       return -1;
04230    }
04231 
04232    bio->linelength++;
04233 
04234    return 1;
04235 }

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

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

07859 {
07860    int count_msg, last_msg;
07861 
07862    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07863 
07864    /* Rename the member vmbox HERE so that we don't try to return before
07865     * we know what's going on.
07866     */
07867    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07868 
07869    /* Faster to make the directory than to check if it exists. */
07870    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07871 
07872    /* traverses directory using readdir (or select query for ODBC) */
07873    count_msg = count_messages(vmu, vms->curdir);
07874    if (count_msg < 0) {
07875       return count_msg;
07876    } else {
07877       vms->lastmsg = count_msg - 1;
07878    }
07879 
07880    if (vm_allocate_dh(vms, vmu, count_msg)) {
07881       return -1;
07882    }
07883 
07884    /*
07885    The following test is needed in case sequencing gets messed up.
07886    There appears to be more than one way to mess up sequence, so
07887    we will not try to find all of the root causes--just fix it when
07888    detected.
07889    */
07890 
07891    if (vm_lock_path(vms->curdir)) {
07892       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07893       return ERROR_LOCK_PATH;
07894    }
07895 
07896    /* for local storage, checks directory for messages up to maxmsg limit */
07897    last_msg = last_message_index(vmu, vms->curdir);
07898    ast_unlock_path(vms->curdir);
07899 
07900    if (last_msg < -1) {
07901       return last_msg;
07902    } else if (vms->lastmsg != last_msg) {
07903       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);
07904       resequence_mailbox(vmu, vms->curdir, count_msg);
07905    }
07906 
07907    return 0;
07908 }

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

Definition at line 7636 of file app_voicemail_odbcstorage.c.

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

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

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

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

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

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

Definition at line 7433 of file app_voicemail_odbcstorage.c.

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

07434 {
07435    int res = 0;
07436 
07437    if (!ast_strlen_zero(category))
07438       res = ast_play_and_wait(chan, category);
07439 
07440    if (res) {
07441       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07442       res = 0;
07443    }
07444 
07445    return res;
07446 }

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

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

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

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

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

07587 {
07588    int res = 0;
07589    int durationm;
07590    int durations;
07591    /* Verify that we have a duration for the message */
07592    if (duration == NULL)
07593       return res;
07594 
07595    /* Convert from seconds to minutes */
07596    durations = atoi(duration);
07597    durationm = (durations / 60);
07598 
07599    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07600 
07601    if ((!res) && (durationm >= minduration)) {
07602       res = wait_file2(chan, vms, "vm-duration");
07603 
07604       /* POLISH syntax */
07605       if (!strncasecmp(chan->language, "pl", 2)) {
07606          div_t num = div(durationm, 10);
07607 
07608          if (durationm == 1) {
07609             res = ast_play_and_wait(chan, "digits/1z");
07610             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07611          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07612             if (num.rem == 2) {
07613                if (!num.quot) {
07614                   res = ast_play_and_wait(chan, "digits/2-ie");
07615                } else {
07616                   res = say_and_wait(chan, durationm - 2 , chan->language);
07617                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07618                }
07619             } else {
07620                res = say_and_wait(chan, durationm, chan->language);
07621             }
07622             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07623          } else {
07624             res = say_and_wait(chan, durationm, chan->language);
07625             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07626          }
07627       /* DEFAULT syntax */
07628       } else {
07629          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07630          res = wait_file2(chan, vms, "vm-minutes");
07631       }
07632    }
07633    return res;
07634 }

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11389 of file app_voicemail_odbcstorage.c.

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

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

static void poll_subscribed_mailboxes ( void   )  [static]

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

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

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

References ast_callerid_merge(), ast_callerid_split(), ast_config_destroy(), ast_config_load, ast_localtime(), ast_log(), ast_strdupa, ast_strftime_locale(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, emaildateformat, ast_vm_user::fullname, ast_vm_user::locale, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, pbx_builtin_setvar_helper(), and S_OR.

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

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

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

06977 {
06978    struct ast_event *event;
06979    char *mailbox, *context;
06980 
06981    /* Strip off @default */
06982    context = mailbox = ast_strdupa(box);
06983    strsep(&context, "@");
06984    if (ast_strlen_zero(context))
06985       context = "default";
06986 
06987    if (!(event = ast_event_new(AST_EVENT_MWI,
06988          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06989          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06990          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06991          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06992          AST_EVENT_IE_END))) {
06993       return;
06994    }
06995 
06996    ast_event_queue_and_cache(event);
06997 }

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

Definition at line 12482 of file app_voicemail_odbcstorage.c.

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

12482                                                                                            {
12483    struct ast_config *pwconf;
12484    struct ast_flags config_flags = { 0 };
12485 
12486    pwconf = ast_config_load(secretfn, config_flags);
12487    if (pwconf) {
12488       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12489       if (val) {
12490          ast_copy_string(password, val, passwordlen);
12491          return;
12492       }
12493    }
12494    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12495 }

static int reload ( void   )  [static]

Definition at line 13003 of file app_voicemail_odbcstorage.c.

References load_config().

13004 {
13005    return load_config(1);
13006 }

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

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

03976 {
03977    char stxt[PATH_MAX];
03978    char dtxt[PATH_MAX];
03979    ast_filerename(sfn, dfn, NULL);
03980    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03981    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03982    if (ast_check_realtime("voicemail_data")) {
03983       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03984    }
03985    rename(stxt, dtxt);
03986 }

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

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

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

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

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

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

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

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

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

Definition at line 6148 of file app_voicemail_odbcstorage.c.

References AST_DIGIT_ANY, and ast_say_number().

06149 {
06150    int d;
06151    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06152    return d;
06153 }

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

Definition at line 12468 of file app_voicemail_odbcstorage.c.

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

12469 {
12470    int res = -1;
12471    char dir[PATH_MAX];
12472    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12473    ast_debug(2, "About to try retrieving name file %s\n", dir);
12474    RETRIEVE(dir, -1, mailbox, context);
12475    if (ast_fileexists(dir, NULL, NULL)) {
12476       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12477    }
12478    DISPOSE(dir, -1);
12479    return res;
12480 }

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

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

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 4856 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_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().

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

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

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

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

static void start_poll_thread ( void   )  [static]

Definition at line 11541 of file app_voicemail_odbcstorage.c.

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

static void stop_poll_thread ( void   )  [static]

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

11560 {
11561    poll_thread_run = 0;
11562 
11563    if (mwi_sub_sub) {
11564       ast_event_unsubscribe(mwi_sub_sub);
11565       mwi_sub_sub = NULL;
11566    }
11567 
11568    if (mwi_unsub_sub) {
11569       ast_event_unsubscribe(mwi_unsub_sub);
11570       mwi_unsub_sub = NULL;
11571    }
11572 
11573    ast_mutex_lock(&poll_lock);
11574    ast_cond_signal(&poll_cond);
11575    ast_mutex_unlock(&poll_lock);
11576 
11577    pthread_join(poll_thread, NULL);
11578 
11579    poll_thread = AST_PTHREADT_NULL;
11580 }

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

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

static int unload_module ( void   )  [static]

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

13009 {
13010    int res;
13011 
13012    res = ast_unregister_application(app);
13013    res |= ast_unregister_application(app2);
13014    res |= ast_unregister_application(app3);
13015    res |= ast_unregister_application(app4);
13016    res |= ast_unregister_application(sayname_app);
13017    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13018    res |= ast_manager_unregister("VoicemailUsersList");
13019    res |= ast_data_unregister(NULL);
13020 #ifdef TEST_FRAMEWORK
13021    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13022    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13023    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13024    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13025    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13026 #endif
13027    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13028    ast_uninstall_vm_functions();
13029    ao2_ref(inprocess_container, -1);
13030 
13031    if (poll_thread != AST_PTHREADT_NULL)
13032       stop_poll_thread();
13033 
13034    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13035    ast_unload_realtime("voicemail");
13036    ast_unload_realtime("voicemail_data");
13037 
13038    free_vm_users();
13039    free_vm_zones();
13040    return res;
13041 }

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_realloc, 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    if (!vms->dh_arraysize) {
01735       /* initial allocation */
01736       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01737          return -1;
01738       }
01739       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01740          return -1;
01741       }
01742       vms->dh_arraysize = arraysize;
01743    } else if (vms->dh_arraysize < arraysize) {
01744       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01745          return -1;
01746       }
01747       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01748          return -1;
01749       }
01750       memset(vms->deleted, 0, arraysize * sizeof(int));
01751       memset(vms->heard, 0, arraysize * sizeof(int));
01752       vms->dh_arraysize = arraysize;
01753    }
01754 
01755    return 0;
01756 }

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

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

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

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

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

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

09688 {
09689    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09690       return vm_browse_messages_es(chan, vms, vmu);
09691    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09692       return vm_browse_messages_gr(chan, vms, vmu);
09693    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09694       return vm_browse_messages_he(chan, vms, vmu);
09695    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09696       return vm_browse_messages_it(chan, vms, vmu);
09697    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09698       return vm_browse_messages_pt(chan, vms, vmu);
09699    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09700       return vm_browse_messages_vi(chan, vms, vmu);
09701    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09702       return vm_browse_messages_zh(chan, vms, vmu);
09703    } else {                                             /* Default to English syntax */
09704       return vm_browse_messages_en(chan, vms, vmu);
09705    }
09706 }

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

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

09527 {
09528    int cmd = 0;
09529 
09530    if (vms->lastmsg > -1) {
09531       cmd = play_message(chan, vmu, vms);
09532    } else {
09533       cmd = ast_play_and_wait(chan, "vm-youhave");
09534       if (!cmd) 
09535          cmd = ast_play_and_wait(chan, "vm-no");
09536       if (!cmd) {
09537          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09538          cmd = ast_play_and_wait(chan, vms->fn);
09539       }
09540       if (!cmd)
09541          cmd = ast_play_and_wait(chan, "vm-messages");
09542    }
09543    return cmd;
09544 }

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

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

09581 {
09582    int cmd;
09583 
09584    if (vms->lastmsg > -1) {
09585       cmd = play_message(chan, vmu, vms);
09586    } else {
09587       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09588       if (!cmd)
09589          cmd = ast_play_and_wait(chan, "vm-messages");
09590       if (!cmd) {
09591          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09592          cmd = ast_play_and_wait(chan, vms->fn);
09593       }
09594    }
09595    return cmd;
09596 }

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

09475 {
09476    int cmd = 0;
09477 
09478    if (vms->lastmsg > -1) {
09479       cmd = play_message(chan, vmu, vms);
09480    } else {
09481       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09482       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09483          if (!cmd) {
09484             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09485             cmd = ast_play_and_wait(chan, vms->fn);
09486          }
09487          if (!cmd)
09488             cmd = ast_play_and_wait(chan, "vm-messages");
09489       } else {
09490          if (!cmd)
09491             cmd = ast_play_and_wait(chan, "vm-messages");
09492          if (!cmd) {
09493             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09494             cmd = ast_play_and_wait(chan, vms->fn);
09495          }
09496       }
09497    } 
09498    return cmd;
09499 }

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

Definition at line 9502 of file app_voicemail_odbcstorage.c.

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

09503 {
09504    int cmd = 0;
09505 
09506    if (vms->lastmsg > -1) {
09507       cmd = play_message(chan, vmu, vms);
09508    } else {
09509       if (!strcasecmp(vms->fn, "INBOX")) {
09510          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09511       } else {
09512          cmd = ast_play_and_wait(chan, "vm-nomessages");
09513       }
09514    }
09515    return cmd;
09516 }

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

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

09555 {
09556    int cmd;
09557 
09558    if (vms->lastmsg > -1) {
09559       cmd = play_message(chan, vmu, vms);
09560    } else {
09561       cmd = ast_play_and_wait(chan, "vm-no");
09562       if (!cmd)
09563          cmd = ast_play_and_wait(chan, "vm-message");
09564       if (!cmd) {
09565          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09566          cmd = ast_play_and_wait(chan, vms->fn);
09567       }
09568    }
09569    return cmd;
09570 }

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

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

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

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

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

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

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

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

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

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_flags, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, reset_user_pw(), value, var, 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 (!(tmp = 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 4160 of file app_voicemail_odbcstorage.c.

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

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

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

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

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

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

Definition at line 9834 of file app_voicemail_odbcstorage.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_goto_if_exists(), ast_log(), AST_LOG_ERROR, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_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.

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

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 6823 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_flags, CONFIG_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, maxsilence, play_record_review(), silencethreshold, vm_pls_try_again, and vm_prepend_timeout.

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

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

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

09153 {
09154    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09155       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09156    } else {             /* Default to ENGLISH */
09157       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09158    }
09159 }

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

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

09052 {
09053    int res = 0;
09054    /* Play instructions and wait for new command */
09055    while (!res) {
09056       if (vms->starting) {
09057          if (vms->lastmsg > -1) {
09058             if (skipadvanced)
09059                res = ast_play_and_wait(chan, "vm-onefor-full");
09060             else
09061                res = ast_play_and_wait(chan, "vm-onefor");
09062             if (!res)
09063                res = vm_play_folder_name(chan, vms->vmbox);
09064          }
09065          if (!res) {
09066             if (skipadvanced)
09067                res = ast_play_and_wait(chan, "vm-opts-full");
09068             else
09069                res = ast_play_and_wait(chan, "vm-opts");
09070          }
09071       } else {
09072          /* Added for additional help */
09073          if (skipadvanced) {
09074             res = ast_play_and_wait(chan, "vm-onefor-full");
09075             if (!res)
09076                res = vm_play_folder_name(chan, vms->vmbox);
09077             res = ast_play_and_wait(chan, "vm-opts-full");
09078          }
09079          /* Logic:
09080           * If the current message is not the first OR
09081           * if we're listening to the first new message and there are
09082           * also urgent messages, then prompt for navigation to the
09083           * previous message
09084           */
09085          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09086             res = ast_play_and_wait(chan, "vm-prev");
09087          }
09088          if (!res && !skipadvanced)
09089             res = ast_play_and_wait(chan, "vm-advopts");
09090          if (!res)
09091             res = ast_play_and_wait(chan, "vm-repeat");
09092          /* Logic:
09093           * If we're not listening to the last message OR
09094           * we're listening to the last urgent message and there are
09095           * also new non-urgent messages, then prompt for navigation
09096           * to the next message
09097           */
09098          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09099             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09100             res = ast_play_and_wait(chan, "vm-next");
09101          }
09102          if (!res) {
09103             if (!vms->deleted[vms->curmsg])
09104                res = ast_play_and_wait(chan, "vm-delete");
09105             else
09106                res = ast_play_and_wait(chan, "vm-undelete");
09107             if (!res)
09108                res = ast_play_and_wait(chan, "vm-toforward");
09109             if (!res)
09110                res = ast_play_and_wait(chan, "vm-savemessage");
09111          }
09112       }
09113       if (!res) {
09114          res = ast_play_and_wait(chan, "vm-helpexit");
09115       }
09116       if (!res)
09117          res = ast_waitfordigit(chan, 6000);
09118       if (!res) {
09119          vms->repeats++;
09120          if (vms->repeats > 2) {
09121             res = 't';
09122          }
09123       }
09124    }
09125    return res;
09126 }

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

09129 {
09130    int res = 0;
09131    /* Play instructions and wait for new command */
09132    while (!res) {
09133       if (vms->lastmsg > -1) {
09134          res = ast_play_and_wait(chan, "vm-listen");
09135          if (!res)
09136             res = vm_play_folder_name(chan, vms->vmbox);
09137          if (!res)
09138             res = ast_play_and_wait(chan, "press");
09139          if (!res)
09140             res = ast_play_and_wait(chan, "digits/1");
09141       }
09142       if (!res)
09143          res = ast_play_and_wait(chan, "vm-opts");
09144       if (!res) {
09145          vms->starting = 0;
09146          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09147       }
09148    }
09149    return res;
09150 }

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

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

08990 {
08991    char prefile[256];
08992    
08993    /* Notify the user that the temp greeting is set and give them the option to remove it */
08994    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08995    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08996       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08997       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08998          ast_play_and_wait(chan, "vm-tempgreetactive");
08999       }
09000       DISPOSE(prefile, -1);
09001    }
09002 
09003    /* Play voicemail intro - syntax is different for different languages */
09004    if (0) {
09005       return 0;
09006    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09007       return vm_intro_cs(chan, vms);
09008    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09009       static int deprecation_warning = 0;
09010       if (deprecation_warning++ % 10 == 0) {
09011          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09012       }
09013       return vm_intro_cs(chan, vms);
09014    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09015       return vm_intro_de(chan, vms);
09016    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09017       return vm_intro_es(chan, vms);
09018    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09019       return vm_intro_fr(chan, vms);
09020    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09021       return vm_intro_gr(chan, vms);
09022    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09023       return vm_intro_he(chan, vms);
09024    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09025       return vm_intro_it(chan, vms);
09026    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09027       return vm_intro_nl(chan, vms);
09028    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09029       return vm_intro_no(chan, vms);
09030    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09031       return vm_intro_pl(chan, vms);
09032    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09033       return vm_intro_pt_BR(chan, vms);
09034    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09035       return vm_intro_pt(chan, vms);
09036    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09037       return vm_intro_multilang(chan, vms, "n");
09038    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09039       return vm_intro_se(chan, vms);
09040    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09041       return vm_intro_multilang(chan, vms, "n");
09042    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09043       return vm_intro_vi(chan, vms);
09044    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09045       return vm_intro_zh(chan, vms);
09046    } else {                                             /* Default to ENGLISH */
09047       return vm_intro_en(chan, vms);
09048    }
09049 }

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

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

08860 {
08861    int res;
08862    res = ast_play_and_wait(chan, "vm-youhave");
08863    if (!res) {
08864       if (vms->newmessages) {
08865          if (vms->newmessages == 1) {
08866             res = ast_play_and_wait(chan, "digits/jednu");
08867          } else {
08868             res = say_and_wait(chan, vms->newmessages, chan->language);
08869          }
08870          if (!res) {
08871             if ((vms->newmessages == 1))
08872                res = ast_play_and_wait(chan, "vm-novou");
08873             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08874                res = ast_play_and_wait(chan, "vm-nove");
08875             if (vms->newmessages > 4)
08876                res = ast_play_and_wait(chan, "vm-novych");
08877          }
08878          if (vms->oldmessages && !res)
08879             res = ast_play_and_wait(chan, "vm-and");
08880          else if (!res) {
08881             if ((vms->newmessages == 1))
08882                res = ast_play_and_wait(chan, "vm-zpravu");
08883             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08884                res = ast_play_and_wait(chan, "vm-zpravy");
08885             if (vms->newmessages > 4)
08886                res = ast_play_and_wait(chan, "vm-zprav");
08887          }
08888       }
08889       if (!res && vms->oldmessages) {
08890          res = say_and_wait(chan, vms->oldmessages, chan->language);
08891          if (!res) {
08892             if ((vms->oldmessages == 1))
08893                res = ast_play_and_wait(chan, "vm-starou");
08894             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08895                res = ast_play_and_wait(chan, "vm-stare");
08896             if (vms->oldmessages > 4)
08897                res = ast_play_and_wait(chan, "vm-starych");
08898          }
08899          if (!res) {
08900             if ((vms->oldmessages == 1))
08901                res = ast_play_and_wait(chan, "vm-zpravu");
08902             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08903                res = ast_play_and_wait(chan, "vm-zpravy");
08904             if (vms->oldmessages > 4)
08905                res = ast_play_and_wait(chan, "vm-zprav");
08906          }
08907       }
08908       if (!res) {
08909          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08910             res = ast_play_and_wait(chan, "vm-no");
08911             if (!res)
08912                res = ast_play_and_wait(chan, "vm-zpravy");
08913          }
08914       }
08915    }
08916    return res;
08917 }

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

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

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

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

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

08305 {
08306    int res;
08307 
08308    /* Introduce messages they have */
08309    res = ast_play_and_wait(chan, "vm-youhave");
08310    if (!res) {
08311       if (vms->urgentmessages) {
08312          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08313          if (!res)
08314             res = ast_play_and_wait(chan, "vm-Urgent");
08315          if ((vms->oldmessages || vms->newmessages) && !res) {
08316             res = ast_play_and_wait(chan, "vm-and");
08317          } else if (!res) {
08318             if ((vms->urgentmessages == 1))
08319                res = ast_play_and_wait(chan, "vm-message");
08320             else
08321                res = ast_play_and_wait(chan, "vm-messages");
08322          }
08323       }
08324       if (vms->newmessages) {
08325          res = say_and_wait(chan, vms->newmessages, chan->language);
08326          if (!res)
08327             res = ast_play_and_wait(chan, "vm-INBOX");
08328          if (vms->oldmessages && !res)
08329             res = ast_play_and_wait(chan, "vm-and");
08330          else if (!res) {
08331             if ((vms->newmessages == 1))
08332                res = ast_play_and_wait(chan, "vm-message");
08333             else
08334                res = ast_play_and_wait(chan, "vm-messages");
08335          }
08336             
08337       }
08338       if (!res && vms->oldmessages) {
08339          res = say_and_wait(chan, vms->oldmessages, chan->language);
08340          if (!res)
08341             res = ast_play_and_wait(chan, "vm-Old");
08342          if (!res) {
08343             if (vms->oldmessages == 1)
08344                res = ast_play_and_wait(chan, "vm-message");
08345             else
08346                res = ast_play_and_wait(chan, "vm-messages");
08347          }
08348       }
08349       if (!res) {
08350          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08351             res = ast_play_and_wait(chan, "vm-no");
08352             if (!res)
08353                res = ast_play_and_wait(chan, "vm-messages");
08354          }
08355       }
08356    }
08357    return res;
08358 }

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

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

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

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

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

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

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

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

08104 {
08105    int res = 0;
08106 
08107    if (vms->newmessages) {
08108       res = ast_play_and_wait(chan, "vm-youhave");
08109       if (!res) 
08110          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08111       if (!res) {
08112          if ((vms->newmessages == 1)) {
08113             res = ast_play_and_wait(chan, "vm-INBOX");
08114             if (!res)
08115                res = ast_play_and_wait(chan, "vm-message");
08116          } else {
08117             res = ast_play_and_wait(chan, "vm-INBOXs");
08118             if (!res)
08119                res = ast_play_and_wait(chan, "vm-messages");
08120          }
08121       }
08122    } else if (vms->oldmessages){
08123       res = ast_play_and_wait(chan, "vm-youhave");
08124       if (!res)
08125          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08126       if ((vms->oldmessages == 1)){
08127          res = ast_play_and_wait(chan, "vm-Old");
08128          if (!res)
08129             res = ast_play_and_wait(chan, "vm-message");
08130       } else {
08131          res = ast_play_and_wait(chan, "vm-Olds");
08132          if (!res)
08133             res = ast_play_and_wait(chan, "vm-messages");
08134       }
08135    } else if (!vms->oldmessages && !vms->newmessages) 
08136       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08137    return res;
08138 }

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

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

08238 {
08239    int res = 0;
08240 
08241    /* Introduce messages they have */
08242    if (!res) {
08243       if ((vms->newmessages) || (vms->oldmessages)) {
08244          res = ast_play_and_wait(chan, "vm-youhave");
08245       }
08246       /*
08247        * The word "shtei" refers to the number 2 in hebrew when performing a count
08248        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08249        * an element, this is one of them.
08250        */
08251       if (vms->newmessages) {
08252          if (!res) {
08253             if (vms->newmessages == 1) {
08254                res = ast_play_and_wait(chan, "vm-INBOX1");
08255             } else {
08256                if (vms->newmessages == 2) {
08257                   res = ast_play_and_wait(chan, "vm-shtei");
08258                } else {
08259                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08260                }
08261                res = ast_play_and_wait(chan, "vm-INBOX");
08262             }
08263          }
08264          if (vms->oldmessages && !res) {
08265             res = ast_play_and_wait(chan, "vm-and");
08266             if (vms->oldmessages == 1) {
08267                res = ast_play_and_wait(chan, "vm-Old1");
08268             } else {
08269                if (vms->oldmessages == 2) {
08270                   res = ast_play_and_wait(chan, "vm-shtei");
08271                } else {
08272                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08273                }
08274                res = ast_play_and_wait(chan, "vm-Old");
08275             }
08276          }
08277       }
08278       if (!res && vms->oldmessages && !vms->newmessages) {
08279          if (!res) {
08280             if (vms->oldmessages == 1) {
08281                res = ast_play_and_wait(chan, "vm-Old1");
08282             } else {
08283                if (vms->oldmessages == 2) {
08284                   res = ast_play_and_wait(chan, "vm-shtei");
08285                } else {
08286                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08287                }
08288                res = ast_play_and_wait(chan, "vm-Old");
08289             }
08290          }
08291       }
08292       if (!res) {
08293          if (!vms->oldmessages && !vms->newmessages) {
08294             if (!res) {
08295                res = ast_play_and_wait(chan, "vm-nomessages");
08296             }
08297          }
08298       }
08299    }
08300    return res;
08301 }

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

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

08362 {
08363    /* Introduce messages they have */
08364    int res;
08365    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08366       res = ast_play_and_wait(chan, "vm-no") ||
08367          ast_play_and_wait(chan, "vm-message");
08368    else
08369       res = ast_play_and_wait(chan, "vm-youhave");
08370    if (!res && vms->newmessages) {
08371       res = (vms->newmessages == 1) ?
08372          ast_play_and_wait(chan, "digits/un") ||
08373          ast_play_and_wait(chan, "vm-nuovo") ||
08374          ast_play_and_wait(chan, "vm-message") :
08375          /* 2 or more new messages */
08376          say_and_wait(chan, vms->newmessages, chan->language) ||
08377          ast_play_and_wait(chan, "vm-nuovi") ||
08378          ast_play_and_wait(chan, "vm-messages");
08379       if (!res && vms->oldmessages)
08380          res = ast_play_and_wait(chan, "vm-and");
08381    }
08382    if (!res && vms->oldmessages) {
08383       res = (vms->oldmessages == 1) ?
08384          ast_play_and_wait(chan, "digits/un") ||
08385          ast_play_and_wait(chan, "vm-vecchio") ||
08386          ast_play_and_wait(chan, "vm-message") :
08387          /* 2 or more old messages */
08388          say_and_wait(chan, vms->oldmessages, chan->language) ||
08389          ast_play_and_wait(chan, "vm-vecchi") ||
08390          ast_play_and_wait(chan, "vm-messages");
08391    }
08392    return res;
08393 }

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

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

08198 {
08199    int res;
08200    int lastnum = 0;
08201 
08202    res = ast_play_and_wait(chan, "vm-youhave");
08203 
08204    if (!res && vms->newmessages) {
08205       lastnum = vms->newmessages;
08206 
08207       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08208          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08209       }
08210 
08211       if (!res && vms->oldmessages) {
08212          res = ast_play_and_wait(chan, "vm-and");
08213       }
08214    }
08215 
08216    if (!res && vms->oldmessages) {
08217       lastnum = vms->oldmessages;
08218 
08219       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08220          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08221       }
08222    }
08223 
08224    if (!res) {
08225       if (lastnum == 0) {
08226          res = ast_play_and_wait(chan, "vm-no");
08227       }
08228       if (!res) {
08229          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08230       }
08231    }
08232 
08233    return res;
08234 }

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

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

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

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

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

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

static int vm_intro_pl ( 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, and say_and_wait().

08397 {
08398    /* Introduce messages they have */
08399    int res;
08400    div_t num;
08401 
08402    if (!vms->oldmessages && !vms->newmessages) {
08403       res = ast_play_and_wait(chan, "vm-no");
08404       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08405       return res;
08406    } else {
08407       res = ast_play_and_wait(chan, "vm-youhave");
08408    }
08409 
08410    if (vms->newmessages) {
08411       num = div(vms->newmessages, 10);
08412       if (vms->newmessages == 1) {
08413          res = ast_play_and_wait(chan, "digits/1-a");
08414          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08415          res = res ? res : ast_play_and_wait(chan, "vm-message");
08416       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08417          if (num.rem == 2) {
08418             if (!num.quot) {
08419                res = ast_play_and_wait(chan, "digits/2-ie");
08420             } else {
08421                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08422                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08423             }
08424          } else {
08425             res = say_and_wait(chan, vms->newmessages, chan->language);
08426          }
08427          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08428          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08429       } else {
08430          res = say_and_wait(chan, vms->newmessages, chan->language);
08431          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08432          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08433       }
08434       if (!res && vms->oldmessages)
08435          res = ast_play_and_wait(chan, "vm-and");
08436    }
08437    if (!res && vms->oldmessages) {
08438       num = div(vms->oldmessages, 10);
08439       if (vms->oldmessages == 1) {
08440          res = ast_play_and_wait(chan, "digits/1-a");
08441          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08442          res = res ? res : ast_play_and_wait(chan, "vm-message");
08443       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08444          if (num.rem == 2) {
08445             if (!num.quot) {
08446                res = ast_play_and_wait(chan, "digits/2-ie");
08447             } else {
08448                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08449                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08450             }
08451          } else {
08452             res = say_and_wait(chan, vms->oldmessages, chan->language);
08453          }
08454          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08455          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08456       } else {
08457          res = say_and_wait(chan, vms->oldmessages, chan->language);
08458          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08459          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08460       }
08461    }
08462 
08463    return res;
08464 }

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

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

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

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

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

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

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

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

08468 {
08469    /* Introduce messages they have */
08470    int res;
08471 
08472    res = ast_play_and_wait(chan, "vm-youhave");
08473    if (res)
08474       return res;
08475 
08476    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08477       res = ast_play_and_wait(chan, "vm-no");
08478       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08479       return res;
08480    }
08481 
08482    if (vms->newmessages) {
08483       if ((vms->newmessages == 1)) {
08484          res = ast_play_and_wait(chan, "digits/ett");
08485          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08486          res = res ? res : ast_play_and_wait(chan, "vm-message");
08487       } else {
08488          res = say_and_wait(chan, vms->newmessages, chan->language);
08489          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08490          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08491       }
08492       if (!res && vms->oldmessages)
08493          res = ast_play_and_wait(chan, "vm-and");
08494    }
08495    if (!res && vms->oldmessages) {
08496       if (vms->oldmessages == 1) {
08497          res = ast_play_and_wait(chan, "digits/ett");
08498          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08499          res = res ? res : ast_play_and_wait(chan, "vm-message");
08500       } else {
08501          res = say_and_wait(chan, vms->oldmessages, chan->language);
08502          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08503          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08504       }
08505    }
08506 
08507    return res;
08508 }

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

Definition at line 8959 of file app_voicemail_odbcstorage.c.

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

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

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

Definition at line 8920 of file app_voicemail_odbcstorage.c.

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

08921 {
08922    int res;
08923    /* Introduce messages they have */
08924    res = ast_play_and_wait(chan, "vm-you");
08925 
08926    if (!res && vms->newmessages) {
08927       res = ast_play_and_wait(chan, "vm-have");
08928       if (!res)
08929          res = say_and_wait(chan, vms->newmessages, chan->language);
08930       if (!res)
08931          res = ast_play_and_wait(chan, "vm-tong");
08932       if (!res)
08933          res = ast_play_and_wait(chan, "vm-INBOX");
08934       if (vms->oldmessages && !res)
08935          res = ast_play_and_wait(chan, "vm-and");
08936       else if (!res) 
08937          res = ast_play_and_wait(chan, "vm-messages");
08938    }
08939    if (!res && vms->oldmessages) {
08940       res = ast_play_and_wait(chan, "vm-have");
08941       if (!res)
08942          res = say_and_wait(chan, vms->oldmessages, chan->language);
08943       if (!res)
08944          res = ast_play_and_wait(chan, "vm-tong");
08945       if (!res)
08946          res = ast_play_and_wait(chan, "vm-Old");
08947       if (!res)
08948          res = ast_play_and_wait(chan, "vm-messages");
08949    }
08950    if (!res && !vms->oldmessages && !vms->newmessages) {
08951       res = ast_play_and_wait(chan, "vm-haveno");
08952       if (!res)
08953          res = ast_play_and_wait(chan, "vm-messages");
08954    }
08955    return res;
08956 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03238 {
03239    switch (ast_lock_path(path)) {
03240    case AST_LOCK_TIMEOUT:
03241       return -1;
03242    default:
03243       return 0;
03244    }
03245 }

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

09163 {
09164    int cmd = 0;
09165    int duration = 0;
09166    int tries = 0;
09167    char newpassword[80] = "";
09168    char newpassword2[80] = "";
09169    char prefile[PATH_MAX] = "";
09170    unsigned char buf[256];
09171    int bytes = 0;
09172 
09173    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09174    if (ast_adsi_available(chan)) {
09175       bytes += adsi_logo(buf + bytes);
09176       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09177       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09178       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09179       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09180       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09181    }
09182 
09183    /* If forcename is set, have the user record their name */
09184    if (ast_test_flag(vmu, VM_FORCENAME)) {
09185       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09186       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09187          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09188          if (cmd < 0 || cmd == 't' || cmd == '#')
09189             return cmd;
09190       }
09191    }
09192 
09193    /* If forcegreetings is set, have the user record their greetings */
09194    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09195       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09196       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09197          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09198          if (cmd < 0 || cmd == 't' || cmd == '#')
09199             return cmd;
09200       }
09201 
09202       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09203       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09204          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09205          if (cmd < 0 || cmd == 't' || cmd == '#')
09206             return cmd;
09207       }
09208    }
09209 
09210    /*
09211     * Change the password last since new users will be able to skip over any steps this one comes before
09212     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09213     */
09214    for (;;) {
09215       newpassword[1] = '\0';
09216       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09217       if (cmd == '#')
09218          newpassword[0] = '\0';
09219       if (cmd < 0 || cmd == 't' || cmd == '#')
09220          return cmd;
09221       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09222       if (cmd < 0 || cmd == 't' || cmd == '#')
09223          return cmd;
09224       cmd = check_password(vmu, newpassword); /* perform password validation */
09225       if (cmd != 0) {
09226          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09227          cmd = ast_play_and_wait(chan, vm_invalid_password);
09228       } else {
09229          newpassword2[1] = '\0';
09230          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09231          if (cmd == '#')
09232             newpassword2[0] = '\0';
09233          if (cmd < 0 || cmd == 't' || cmd == '#')
09234             return cmd;
09235          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09236          if (cmd < 0 || cmd == 't' || cmd == '#')
09237             return cmd;
09238          if (!strcmp(newpassword, newpassword2))
09239             break;
09240          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09241          cmd = ast_play_and_wait(chan, vm_mismatch);
09242       }
09243       if (++tries == 3)
09244          return -1;
09245       if (cmd != 0) {
09246          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09247       }
09248    }
09249    if (pwdchange & PWDCHANGE_INTERNAL)
09250       vm_change_password(vmu, newpassword);
09251    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09252       vm_change_password_shell(vmu, newpassword);
09253 
09254    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09255    cmd = ast_play_and_wait(chan, vm_passchanged);
09256 
09257    return cmd;
09258 }

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

09261 {
09262    int cmd = 0;
09263    int retries = 0;
09264    int duration = 0;
09265    char newpassword[80] = "";
09266    char newpassword2[80] = "";
09267    char prefile[PATH_MAX] = "";
09268    unsigned char buf[256];
09269    int bytes = 0;
09270 
09271    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09272    if (ast_adsi_available(chan)) {
09273       bytes += adsi_logo(buf + bytes);
09274       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09275       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09276       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09277       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09278       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09279    }
09280    while ((cmd >= 0) && (cmd != 't')) {
09281       if (cmd)
09282          retries = 0;
09283       switch (cmd) {
09284       case '1': /* Record your unavailable message */
09285          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09286          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09287          break;
09288       case '2':  /* Record your busy message */
09289          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09290          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09291          break;
09292       case '3': /* Record greeting */
09293          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09294          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09295          break;
09296       case '4':  /* manage the temporary greeting */
09297          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09298          break;
09299       case '5': /* change password */
09300          if (vmu->password[0] == '-') {
09301             cmd = ast_play_and_wait(chan, "vm-no");
09302             break;
09303          }
09304          newpassword[1] = '\0';
09305          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09306          if (cmd == '#')
09307             newpassword[0] = '\0';
09308          else {
09309             if (cmd < 0)
09310                break;
09311             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09312                break;
09313             }
09314          }
09315          cmd = check_password(vmu, newpassword); /* perform password validation */
09316          if (cmd != 0) {
09317             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09318             cmd = ast_play_and_wait(chan, vm_invalid_password);
09319             if (!cmd) {
09320                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09321             }
09322             break;
09323          }
09324          newpassword2[1] = '\0';
09325          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09326          if (cmd == '#')
09327             newpassword2[0] = '\0';
09328          else {
09329             if (cmd < 0)
09330                break;
09331 
09332             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09333                break;
09334             }
09335          }
09336          if (strcmp(newpassword, newpassword2)) {
09337             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09338             cmd = ast_play_and_wait(chan, vm_mismatch);
09339             if (!cmd) {
09340                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09341             }
09342             break;
09343          }
09344 
09345          if (pwdchange & PWDCHANGE_INTERNAL) {
09346             vm_change_password(vmu, newpassword);
09347          }
09348          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09349             vm_change_password_shell(vmu, newpassword);
09350          }
09351 
09352          ast_debug(1, "User %s set password to %s of length %d\n",
09353             vms->username, newpassword, (int) strlen(newpassword));
09354          cmd = ast_play_and_wait(chan, vm_passchanged);
09355          break;
09356       case '*': 
09357          cmd = 't';
09358          break;
09359       default: 
09360          cmd = 0;
09361          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09362          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09363          if (ast_fileexists(prefile, NULL, NULL)) {
09364             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09365          }
09366          DISPOSE(prefile, -1);
09367          if (!cmd) {
09368             cmd = ast_play_and_wait(chan, "vm-options");
09369          }
09370          if (!cmd) {
09371             cmd = ast_waitfordigit(chan, 6000);
09372          }
09373          if (!cmd) {
09374             retries++;
09375          }
09376          if (retries > 3) {
09377             cmd = 't';
09378          }
09379          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09380       }
09381    }
09382    if (cmd == 't')
09383       cmd = 0;
09384    return cmd;
09385 }

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

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

08067 {
08068    int cmd;
08069 
08070    if (  !strncasecmp(chan->language, "it", 2) ||
08071         !strncasecmp(chan->language, "es", 2) ||
08072         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08073       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08074       return cmd ? cmd : ast_play_and_wait(chan, box);
08075    } else if (!strncasecmp(chan->language, "gr", 2)) {
08076       return vm_play_folder_name_gr(chan, box);
08077    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08078       return ast_play_and_wait(chan, box);
08079    } else if (!strncasecmp(chan->language, "pl", 2)) {
08080       return vm_play_folder_name_pl(chan, box);
08081    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08082       return vm_play_folder_name_ua(chan, box);
08083    } else if (!strncasecmp(chan->language, "vi", 2)) {
08084       return ast_play_and_wait(chan, box);
08085    } else {  /* Default English */
08086       cmd = ast_play_and_wait(chan, box);
08087       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08088    }
08089 }

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

Definition at line 8019 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

08020 {
08021    int cmd;
08022    char *buf;
08023 
08024    buf = alloca(strlen(box) + 2);
08025    strcpy(buf, box);
08026    strcat(buf, "s");
08027 
08028    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08029       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08030       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08031    } else {
08032       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08033       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08034    }
08035 }

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

Definition at line 8037 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

08038 {
08039    int cmd;
08040 
08041    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08042       if (!strcasecmp(box, "vm-INBOX"))
08043          cmd = ast_play_and_wait(chan, "vm-new-e");
08044       else
08045          cmd = ast_play_and_wait(chan, "vm-old-e");
08046       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08047    } else {
08048       cmd = ast_play_and_wait(chan, "vm-messages");
08049       return cmd ? cmd : ast_play_and_wait(chan, box);
08050    }
08051 }

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

Definition at line 8053 of file app_voicemail_odbcstorage.c.

References ast_play_and_wait().

08054 {
08055    int cmd;
08056 
08057    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08058       cmd = ast_play_and_wait(chan, "vm-messages");
08059       return cmd ? cmd : ast_play_and_wait(chan, box);
08060    } else {
08061       cmd = ast_play_and_wait(chan, box);
08062       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08063    }
08064 }

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

09404 {
09405    int cmd = 0;
09406    int retries = 0;
09407    int duration = 0;
09408    char prefile[PATH_MAX] = "";
09409    unsigned char buf[256];
09410    int bytes = 0;
09411 
09412    if (ast_adsi_available(chan)) {
09413       bytes += adsi_logo(buf + bytes);
09414       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09415       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09416       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09417       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09418       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09419    }
09420 
09421    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09422    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09423    while ((cmd >= 0) && (cmd != 't')) {
09424       if (cmd)
09425          retries = 0;
09426       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09427       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09428          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09429          cmd = 't';  
09430       } else {
09431          switch (cmd) {
09432          case '1':
09433             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09434             break;
09435          case '2':
09436             DELETE(prefile, -1, prefile, vmu);
09437             ast_play_and_wait(chan, "vm-tempremoved");
09438             cmd = 't';  
09439             break;
09440          case '*': 
09441             cmd = 't';
09442             break;
09443          default:
09444             cmd = ast_play_and_wait(chan,
09445                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09446                   "vm-tempgreeting2" : "vm-tempgreeting");
09447             if (!cmd) {
09448                cmd = ast_waitfordigit(chan, 6000);
09449             }
09450             if (!cmd) {
09451                retries++;
09452             }
09453             if (retries > 3) {
09454                cmd = 't';
09455             }
09456             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09457          }
09458       }
09459       DISPOSE(prefile, -1);
09460    }
09461    if (cmd == 't')
09462       cmd = 0;
09463    return cmd;
09464 }

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

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

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

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

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

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

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

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

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

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

12524 {
12525    char *context;
12526    char *args_copy;
12527    int res;
12528 
12529    if (ast_strlen_zero(data)) {
12530       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12531       return -1;
12532    }
12533 
12534    args_copy = ast_strdupa(data);
12535    if ((context = strchr(args_copy, '@'))) {
12536       *context++ = '\0';
12537    } else {
12538       context = "default";
12539    }
12540 
12541    if ((res = sayname(chan, args_copy, context) < 0)) {
12542       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12543       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12544       if (!res) {
12545          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12546       }
12547    }
12548 
12549    return res;
12550 }

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

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

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

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

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

07420 {
07421    int res;
07422    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07423       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07424    return res;
07425 }

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

Definition at line 12497 of file app_voicemail_odbcstorage.c.

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

12497                                                                               {
12498    struct ast_config *conf;
12499    struct ast_category *cat;
12500    struct ast_variable *var;
12501 
12502    if (!(conf=ast_config_new())) {
12503       ast_log(LOG_ERROR, "Error creating new config structure\n");
12504       return -1;
12505    }
12506    if (!(cat=ast_category_new("general","",1))) {
12507       ast_log(LOG_ERROR, "Error creating new category structure\n");
12508       return -1;
12509    }
12510    if (!(var=ast_variable_new("password",password,""))) {
12511       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12512       return -1;
12513    }
12514    ast_category_append(conf,cat);
12515    ast_variable_append(cat,var);
12516    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12517       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12518       return -1;
12519    }
12520    return 0;
12521 }


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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", } [static]

Definition at line 13602 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 13602 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 11242 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 11000 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 11385 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 11380 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 Mar 19 11:30:36 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7