Thu Oct 11 06:34:36 2012

Asterisk developer's documentation


app_voicemail.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/strings.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj2.h"
#include "asterisk/event.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"

Include dependency graph for app_voicemail.c:

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, k)
#define tdesc   "Comedian Mail (Voicemail System)"
#define UPDATE_MSG_ID(a, b, c, d, e, f)
#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 void __fini_mwi_subs (void)
static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static void __init_mwi_subs (void)
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 acf_vm_info (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 int add_message_id (struct ast_config *msg_cfg, char *dir, int msg, char *filename, char *id, size_t id_size, struct ast_vm_user *vmu, int folder)
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, const char *dest_folder)
 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 void generate_random_string (char *buf, size_t size)
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)
 Load the module.
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, const char *msg_id)
 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 int manager_voicemail_refresh (struct mansession *s, const struct message *m)
static void * mb_poll_thread (void *data)
static const char * mbox (struct ast_vm_user *vmu, int id)
static int message_range_and_existence_check (struct vm_state *vms, const char *msg_ids[], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
 common bounds checking and existence check for Voicemail API functions.
static int messagecount (const char *context, const char *mailbox, const char *folder)
static int msg_create_from_file (struct ast_vm_recording_data *recdata)
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 void notify_new_state (struct ast_vm_user *vmu)
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_by_id (struct ast_channel *chan, const char *mailbox, const char *context, const char *msg_id)
 Finds a message in a specific mailbox by msg_id and plays it to the channel.
static int play_message_by_id_helper (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)
static int play_message_callerid (struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
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, const char *msg_id)
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, int *newmsg, int move)
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, const char *msg_id)
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 const char * vm_index_to_foldername (int id)
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 struct
ast_vm_mailbox_snapshot
vm_mailbox_snapshot_create (const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
static struct
ast_vm_mailbox_snapshot
vm_mailbox_snapshot_destroy (struct ast_vm_mailbox_snapshot *mailbox_snapshot)
static FILE * vm_mkftemp (char *template)
static int vm_msg_forward (const char *from_mailbox, const char *from_context, const char *from_folder, const char *to_mailbox, const char *to_context, const char *to_folder, size_t num_msgs, const char *msg_ids[], int delete_old)
static int vm_msg_move (const char *mailbox, const char *context, size_t num_msgs, const char *oldfolder, const char *old_msg_ids[], const char *newfolder)
static int vm_msg_play (struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb cb)
static int vm_msg_remove (const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
static struct ast_vm_msg_snapshotvm_msg_snapshot_alloc (void)
static int vm_msg_snapshot_create (struct ast_vm_user *vmu, struct vm_state *vms, struct ast_vm_mailbox_snapshot *mailbox_snapshot, int snapshot_index, int mailbox_index, int descending, enum ast_vm_snapshot_sort_val sort_val)
 Create and store off all the msgs in an open mailbox.
static struct ast_vm_msg_snapshotvm_msg_snapshot_destroy (struct ast_vm_msg_snapshot *msg_snapshot)
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_playmsgexec (struct ast_channel *chan, const char *data)
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 = AST_BUILDOPT_SUM, .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}
struct ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static char * playmsg_app = "VoiceMailPlayMsg"
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = { PTHREAD_MUTEX_INITIALIZER , 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 struct ast_custom_function vm_info_acf
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> unixODBC (http://www.unixodbc.org/) 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
Todo:
This module requires res_adsi to load. This needs to be optional during compilation.
Todo:
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.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 562 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 585 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 586 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 559 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 555 of file app_voicemail.c.

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

Definition at line 898 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 12369 of file app_voicemail.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 12396 of file app_voicemail.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 567 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 569 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 570 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 568 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 571 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 971 of file app_voicemail.c.

Referenced by actual_load_config().

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

#define DISPOSE ( a,
 ) 

#define ENDL   "\n"

Definition at line 590 of file app_voicemail.c.

Referenced by add_email_attachment(), base_encode(), make_email_file(), ochar(), and sendpage().

#define ERROR_LOCK_PATH   -100

Definition at line 615 of file app_voicemail.c.

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

Definition at line 896 of file app_voicemail.c.

Referenced by close_mailbox(), copy_message(), resequence_mailbox(), and save_to_folder().

#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 578 of file app_voicemail.c.

Referenced by leave_voicemail(), play_record_review(), and vm_forwardoptions().

#define MAX_DATETIME_FORMAT   512

Definition at line 593 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 594 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 580 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

#define MAXMSGLIMIT   9999

Definition at line 581 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), and last_message_index().

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 583 of file app_voicemail.c.

Referenced by actual_load_config().

#define OPERATOR_EXIT   300

Definition at line 616 of file app_voicemail.c.

Referenced by leave_voicemail(), vm_exec(), and vm_execmain().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 912 of file app_voicemail.c.

Referenced by actual_load_config(), vm_newuser(), and vm_options().

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 911 of file app_voicemail.c.

Referenced by actual_load_config(), vm_newuser(), and vm_options().

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

#define RETRIEVE ( a,
b,
c,
 ) 

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

Definition at line 576 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 553 of file app_voicemail.c.

Referenced by run_externnotify().

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

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 921 of file app_voicemail.c.

#define UPDATE_MSG_ID ( a,
b,
c,
d,
e,
f   ) 

Definition at line 900 of file app_voicemail.c.

Referenced by add_message_id().

#define VALID_DTMF   "1234567890*#"

Definition at line 572 of file app_voicemail.c.

Referenced by is_valid_dtmf().

#define VM_ALLOCED   (1 << 13)

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

Definition at line 609 of file app_voicemail.c.

Referenced by AST_TEST_DEFINE(), find_user(), find_user_realtime(), free_user(), and free_vm_users().

#define VM_ATTACH   (1 << 11)

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 608 of file app_voicemail.c.

Referenced by apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and notify_new_message().

#define VM_DIRECFORWARD   (1 << 10)

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

Definition at line 606 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 600 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_message().

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 604 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_newuser().

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 603 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_newuser().

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 614 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 613 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_instructions_en().

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 612 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and close_mailbox().

#define VM_OPERATOR   (1 << 1)

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

Definition at line 597 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), leave_voicemail(), manager_list_voicemail_users(), and play_record_review().

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 605 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

#define VM_REVIEW   (1 << 0)

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

Definition at line 596 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_record_review().

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 598 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_message().

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 601 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and play_message().

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 610 of file app_voicemail.c.

Referenced by actual_load_config(), find_or_create(), find_user(), and find_user_realtime().

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 602 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_execmain().

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 599 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_execmain().

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 611 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_intro().

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 830 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 561 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 557 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666


Enumeration Type Documentation

enum vm_box

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 618 of file app_voicemail.c.

00618             {
00619    NEW_FOLDER,
00620    OLD_FOLDER,
00621    WORK_FOLDER,
00622    FAMILY_FOLDER,
00623    FRIENDS_FOLDER,
00624    GREETINGS_FOLDER
00625 };

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 639 of file app_voicemail.c.

00639                     {
00640    OPT_ARG_RECORDGAIN = 0,
00641    OPT_ARG_PLAYFOLDER = 1,
00642    OPT_ARG_DTMFEXIT   = 2,
00643    /* This *must* be the last value in this enum! */
00644    OPT_ARG_ARRAY_SIZE = 3,
00645 };

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 627 of file app_voicemail.c.

00627                      {
00628    OPT_SILENT =           (1 << 0),
00629    OPT_BUSY_GREETING =    (1 << 1),
00630    OPT_UNAVAIL_GREETING = (1 << 2),
00631    OPT_RECORDGAIN =       (1 << 3),
00632    OPT_PREPEND_MAILBOX =  (1 << 4),
00633    OPT_AUTOPLAY =         (1 << 6),
00634    OPT_DTMFEXIT =         (1 << 7),
00635    OPT_MESSAGE_Urgent =   (1 << 8),
00636    OPT_MESSAGE_PRIORITY = (1 << 9)
00637 };

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 647 of file app_voicemail.c.

00647                          {
00648    OPT_PWLOC_VOICEMAILCONF = 0,
00649    OPT_PWLOC_SPOOLDIR      = 1,
00650    OPT_PWLOC_USERSCONF     = 2,
00651 };


Function Documentation

static void __fini_mwi_subs ( void   )  [static]

Definition at line 1007 of file app_voicemail.c.

01026 :
 * 1. create a sound along the lines of "Please try again.  When done, press the pound key" which could be spliced

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

Definition at line 5752 of file app_voicemail.c.

References ast_strlen_zero().

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

05753 {
05754    DIR *dir;
05755    struct dirent *de;
05756    char fn[256];
05757    int ret = 0;
05758 
05759    /* If no mailbox, return immediately */
05760    if (ast_strlen_zero(mailbox))
05761       return 0;
05762 
05763    if (ast_strlen_zero(folder))
05764       folder = "INBOX";
05765    if (ast_strlen_zero(context))
05766       context = "default";
05767 
05768    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05769 
05770    if (!(dir = opendir(fn)))
05771       return 0;
05772 
05773    while ((de = readdir(dir))) {
05774       if (!strncasecmp(de->d_name, "msg", 3)) {
05775          if (shortcircuit) {
05776             ret = 1;
05777             break;
05778          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05779             ret++;
05780          }
05781       }
05782    }
05783 
05784    closedir(dir);
05785 
05786    return ret;
05787 }

static void __init_mwi_subs ( void   )  [static]

Definition at line 1007 of file app_voicemail.c.

01026 :
 * 1. create a sound along the lines of "Please try again.  When done, press the pound key" which could be spliced

static void __reg_module ( void   )  [static]

Definition at line 15710 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

Definition at line 15710 of file app_voicemail.c.

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

Definition at line 11987 of file app_voicemail.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_WARNING, AST_NONSTANDARD_APP_ARGS, ast_strlen_zero(), find_user(), LOG_ERROR, and mbox().

11988 {
11989    struct ast_vm_user svm;
11990    AST_DECLARE_APP_ARGS(arg,
11991       AST_APP_ARG(mbox);
11992       AST_APP_ARG(context);
11993    );
11994    static int dep_warning = 0;
11995 
11996    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11997 
11998    if (ast_strlen_zero(arg.mbox)) {
11999       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
12000       return -1;
12001    }
12002 
12003    if (!dep_warning) {
12004       dep_warning = 1;
12005       ast_log(AST_LOG_WARNING, "MAILBOX_EXISTS is deprecated.  Please use ${VM_INFO(%s,exists)} instead.\n", args);
12006    }
12007 
12008    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
12009    return 0;
12010 }

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

Definition at line 12012 of file app_voicemail.c.

References AST_APP_ARG, ast_channel_language(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_vm_user::email, find_user(), ast_vm_user::fullname, ast_vm_user::language, ast_vm_user::locale, LOG_ERROR, messagecount(), ast_vm_user::pager, parse(), ast_vm_user::password, S_OR, strsep(), and ast_vm_user::zonetag.

12013 {
12014    struct ast_vm_user *vmu = NULL;
12015    char *tmp, *mailbox, *context, *parse;
12016    int res = 0;
12017 
12018    AST_DECLARE_APP_ARGS(arg,
12019       AST_APP_ARG(mailbox_context);
12020       AST_APP_ARG(attribute);
12021       AST_APP_ARG(folder);
12022    );
12023 
12024    buf[0] = '\0';
12025 
12026    if (ast_strlen_zero(args)) {
12027       ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12028       return -1;
12029    }
12030 
12031    parse = ast_strdupa(args);
12032    AST_STANDARD_APP_ARGS(arg, parse);
12033 
12034    if (ast_strlen_zero(arg.mailbox_context) || ast_strlen_zero(arg.attribute)) {
12035       ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12036       return -1;
12037    }
12038 
12039    tmp = ast_strdupa(arg.mailbox_context);
12040    mailbox = strsep(&tmp, "@");
12041    context = strsep(&tmp, "");
12042 
12043    if (ast_strlen_zero(context)) {
12044        context = "default";
12045    }
12046 
12047    vmu = find_user(NULL, context, mailbox);
12048 
12049    if (!strncasecmp(arg.attribute, "exists", 5)) {
12050       ast_copy_string(buf, vmu ? "1" : "0", len);
12051       return 0;
12052    }
12053 
12054    if (vmu) {
12055       if (!strncasecmp(arg.attribute, "password", 8)) {
12056          ast_copy_string(buf, vmu->password, len);
12057       } else if (!strncasecmp(arg.attribute, "fullname", 8)) {
12058          ast_copy_string(buf, vmu->fullname, len);
12059       } else if (!strncasecmp(arg.attribute, "email", 5)) {
12060          ast_copy_string(buf, vmu->email, len);
12061       } else if (!strncasecmp(arg.attribute, "pager", 5)) {
12062          ast_copy_string(buf, vmu->pager, len);
12063       } else if (!strncasecmp(arg.attribute, "language", 8)) {
12064          ast_copy_string(buf, S_OR(vmu->language, ast_channel_language(chan)), len);
12065       } else if (!strncasecmp(arg.attribute, "locale", 6)) {
12066          ast_copy_string(buf, vmu->locale, len);
12067       } else if (!strncasecmp(arg.attribute, "tz", 2)) {
12068          ast_copy_string(buf, vmu->zonetag, len);
12069       } else if (!strncasecmp(arg.attribute, "count", 5)) {
12070          /* If mbxfolder is empty messagecount will default to INBOX */
12071          res = messagecount(context, mailbox, arg.folder);
12072          if (res < 0) {
12073             ast_log(LOG_ERROR, "Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
12074             return -1;
12075          }
12076          snprintf(buf, len, "%d", res);
12077       } else {
12078          ast_log(LOG_ERROR, "Unknown attribute '%s' for VM_INFO\n", arg.attribute);
12079          return -1;
12080       }
12081    }
12082 
12083    return 0;
12084 }

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

Definition at line 12949 of file app_voicemail.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_ERROR, AST_LOG_WARNING, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, cidinternalcontexts, ast_vm_user::context, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), ast_variable::lineno, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, LOG_ERROR, ast_vm_user::mailbox, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, vm_zone::msg_format, vm_zone::name, ast_variable::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, vm_zone::timezone, ast_variable::value, 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_SVMAIL, and VM_TEMPGREETWARN.

Referenced by load_config().

12950 {
12951    struct ast_vm_user *current;
12952    char *cat;
12953    struct ast_variable *var;
12954    const char *val;
12955    char *q, *stringp, *tmp;
12956    int x;
12957    int tmpadsi[4];
12958    char secretfn[PATH_MAX] = "";
12959 
12960 #ifdef IMAP_STORAGE
12961    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
12962 #endif
12963    /* set audio control prompts */
12964    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
12965    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
12966    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
12967    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
12968    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
12969 
12970    /* Free all the users structure */  
12971    free_vm_users();
12972 
12973    /* Free all the zones structure */
12974    free_vm_zones();
12975 
12976    AST_LIST_LOCK(&users);  
12977 
12978    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
12979    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
12980 
12981    if (cfg) {
12982       /* General settings */
12983 
12984       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
12985          val = "default";
12986       ast_copy_string(userscontext, val, sizeof(userscontext));
12987       /* Attach voice message to mail message ? */
12988       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
12989          val = "yes";
12990       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
12991 
12992       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
12993          val = "no";
12994       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
12995 
12996       volgain = 0.0;
12997       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
12998          sscanf(val, "%30lf", &volgain);
12999 
13000 #ifdef ODBC_STORAGE
13001       strcpy(odbc_database, "asterisk");
13002       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
13003          ast_copy_string(odbc_database, val, sizeof(odbc_database));
13004       }
13005       strcpy(odbc_table, "voicemessages");
13006       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
13007          ast_copy_string(odbc_table, val, sizeof(odbc_table));
13008       }
13009 #endif      
13010       /* Mail command */
13011       strcpy(mailcmd, SENDMAIL);
13012       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
13013          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
13014 
13015       maxsilence = 0;
13016       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
13017          maxsilence = atoi(val);
13018          if (maxsilence > 0)
13019             maxsilence *= 1000;
13020       }
13021       
13022       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
13023          maxmsg = MAXMSG;
13024       } else {
13025          maxmsg = atoi(val);
13026          if (maxmsg < 0) {
13027             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
13028             maxmsg = MAXMSG;
13029          } else if (maxmsg > MAXMSGLIMIT) {
13030             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
13031             maxmsg = MAXMSGLIMIT;
13032          }
13033       }
13034 
13035       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
13036          maxdeletedmsg = 0;
13037       } else {
13038          if (sscanf(val, "%30d", &x) == 1)
13039             maxdeletedmsg = x;
13040          else if (ast_true(val))
13041             maxdeletedmsg = MAXMSG;
13042          else
13043             maxdeletedmsg = 0;
13044 
13045          if (maxdeletedmsg < 0) {
13046             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
13047             maxdeletedmsg = MAXMSG;
13048          } else if (maxdeletedmsg > MAXMSGLIMIT) {
13049             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
13050             maxdeletedmsg = MAXMSGLIMIT;
13051          }
13052       }
13053 
13054       /* Load date format config for voicemail mail */
13055       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
13056          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
13057       }
13058 
13059       /* Load date format config for voicemail pager mail */
13060       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
13061          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
13062       }
13063 
13064       /* External password changing command */
13065       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
13066          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
13067          pwdchange = PWDCHANGE_EXTERNAL;
13068       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
13069          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
13070          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
13071       }
13072 
13073       /* External password validation command */
13074       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
13075          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
13076          ast_debug(1, "found externpasscheck: %s\n", ext_pass_check_cmd);
13077       }
13078 
13079 #ifdef IMAP_STORAGE
13080       /* IMAP server address */
13081       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
13082          ast_copy_string(imapserver, val, sizeof(imapserver));
13083       } else {
13084          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
13085       }
13086       /* IMAP server port */
13087       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
13088          ast_copy_string(imapport, val, sizeof(imapport));
13089       } else {
13090          ast_copy_string(imapport, "143", sizeof(imapport));
13091       }
13092       /* IMAP server flags */
13093       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
13094          ast_copy_string(imapflags, val, sizeof(imapflags));
13095       }
13096       /* IMAP server master username */
13097       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
13098          ast_copy_string(authuser, val, sizeof(authuser));
13099       }
13100       /* IMAP server master password */
13101       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
13102          ast_copy_string(authpassword, val, sizeof(authpassword));
13103       }
13104       /* Expunge on exit */
13105       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
13106          if (ast_false(val))
13107             expungeonhangup = 0;
13108          else
13109             expungeonhangup = 1;
13110       } else {
13111          expungeonhangup = 1;
13112       }
13113       /* IMAP voicemail folder */
13114       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
13115          ast_copy_string(imapfolder, val, sizeof(imapfolder));
13116       } else {
13117          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
13118       }
13119       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
13120          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
13121       }
13122       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
13123          imapgreetings = ast_true(val);
13124       } else {
13125          imapgreetings = 0;
13126       }
13127       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
13128          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
13129       } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
13130          /* Also support greetingsfolder as documented in voicemail.conf.sample */
13131          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
13132       } else {
13133          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
13134       }
13135 
13136       /* There is some very unorthodox casting done here. This is due
13137        * to the way c-client handles the argument passed in. It expects a 
13138        * void pointer and casts the pointer directly to a long without
13139        * first dereferencing it. */
13140       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
13141          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
13142       } else {
13143          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
13144       }
13145 
13146       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
13147          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
13148       } else {
13149          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
13150       }
13151 
13152       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
13153          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
13154       } else {
13155          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
13156       }
13157 
13158       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
13159          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
13160       } else {
13161          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
13162       }
13163 
13164       /* Increment configuration version */
13165       imapversion++;
13166 #endif
13167       /* External voicemail notify application */
13168       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
13169          ast_copy_string(externnotify, val, sizeof(externnotify));
13170          ast_debug(1, "found externnotify: %s\n", externnotify);
13171       } else {
13172          externnotify[0] = '\0';
13173       }
13174 
13175       /* SMDI voicemail notification */
13176       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
13177          ast_debug(1, "Enabled SMDI voicemail notification\n");
13178          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
13179             smdi_iface = ast_smdi_interface_find(val);
13180          } else {
13181             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
13182             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
13183          }
13184          if (!smdi_iface) {
13185             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
13186          }
13187       }
13188 
13189       /* Silence treshold */
13190       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
13191       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
13192          silencethreshold = atoi(val);
13193 
13194       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
13195          val = ASTERISK_USERNAME;
13196       ast_copy_string(serveremail, val, sizeof(serveremail));
13197 
13198       vmmaxsecs = 0;
13199       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
13200          if (sscanf(val, "%30d", &x) == 1) {
13201             vmmaxsecs = x;
13202          } else {
13203             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
13204          }
13205       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
13206          static int maxmessage_deprecate = 0;
13207          if (maxmessage_deprecate == 0) {
13208             maxmessage_deprecate = 1;
13209             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
13210          }
13211          if (sscanf(val, "%30d", &x) == 1) {
13212             vmmaxsecs = x;
13213          } else {
13214             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
13215          }
13216       }
13217 
13218       vmminsecs = 0;
13219       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
13220          if (sscanf(val, "%30d", &x) == 1) {
13221             vmminsecs = x;
13222             if (maxsilence / 1000 >= vmminsecs) {
13223                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
13224             }
13225          } else {
13226             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
13227          }
13228       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
13229          static int maxmessage_deprecate = 0;
13230          if (maxmessage_deprecate == 0) {
13231             maxmessage_deprecate = 1;
13232             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
13233          }
13234          if (sscanf(val, "%30d", &x) == 1) {
13235             vmminsecs = x;
13236             if (maxsilence / 1000 >= vmminsecs) {
13237                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
13238             }
13239          } else {
13240             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
13241          }
13242       }
13243 
13244       val = ast_variable_retrieve(cfg, "general", "format");
13245       if (!val) {
13246          val = "wav";   
13247       } else {
13248          tmp = ast_strdupa(val);
13249          val = ast_format_str_reduce(tmp);
13250          if (!val) {
13251             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
13252             val = "wav";
13253          }
13254       }
13255       ast_copy_string(vmfmts, val, sizeof(vmfmts));
13256 
13257       skipms = 3000;
13258       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
13259          if (sscanf(val, "%30d", &x) == 1) {
13260             maxgreet = x;
13261          } else {
13262             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
13263          }
13264       }
13265 
13266       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
13267          if (sscanf(val, "%30d", &x) == 1) {
13268             skipms = x;
13269          } else {
13270             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
13271          }
13272       }
13273 
13274       maxlogins = 3;
13275       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
13276          if (sscanf(val, "%30d", &x) == 1) {
13277             maxlogins = x;
13278          } else {
13279             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
13280          }
13281       }
13282 
13283       minpassword = MINPASSWORD;
13284       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
13285          if (sscanf(val, "%30d", &x) == 1) {
13286             minpassword = x;
13287          } else {
13288             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
13289          }
13290       }
13291 
13292       /* Force new user to record name ? */
13293       if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
13294          val = "no";
13295       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
13296 
13297       /* Force new user to record greetings ? */
13298       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
13299          val = "no";
13300       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
13301 
13302       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
13303          ast_debug(1, "VM_CID Internal context string: %s\n", val);
13304          stringp = ast_strdupa(val);
13305          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
13306             if (!ast_strlen_zero(stringp)) {
13307                q = strsep(&stringp, ",");
13308                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
13309                   q++;
13310                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
13311                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
13312             } else {
13313                cidinternalcontexts[x][0] = '\0';
13314             }
13315          }
13316       }
13317       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
13318          ast_debug(1, "VM Review Option disabled globally\n");
13319          val = "no";
13320       }
13321       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW);
13322 
13323       /* Temporary greeting reminder */
13324       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
13325          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
13326          val = "no";
13327       } else {
13328          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
13329       }
13330       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
13331       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
13332          ast_debug(1, "VM next message wrap disabled globally\n");
13333          val = "no";
13334       }
13335       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);
13336 
13337       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
13338          ast_debug(1, "VM Operator break disabled globally\n");
13339          val = "no";
13340       }
13341       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);
13342 
13343       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
13344          ast_debug(1, "VM CID Info before msg disabled globally\n");
13345          val = "no";
13346       }
13347       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID);
13348 
13349       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
13350          ast_debug(1, "Send Voicemail msg disabled globally\n");
13351          val = "no";
13352       }
13353       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
13354 
13355       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
13356          ast_debug(1, "ENVELOPE before msg enabled globally\n");
13357          val = "yes";
13358       }
13359       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);
13360 
13361       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
13362          ast_debug(1, "Move Heard enabled globally\n");
13363          val = "yes";
13364       }
13365       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD);
13366 
13367       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
13368          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
13369          val = "no";
13370       }
13371       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);
13372 
13373       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
13374          ast_debug(1, "Duration info before msg enabled globally\n");
13375          val = "yes";
13376       }
13377       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);
13378 
13379       saydurationminfo = 2;
13380       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
13381          if (sscanf(val, "%30d", &x) == 1) {
13382             saydurationminfo = x;
13383          } else {
13384             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
13385          }
13386       }
13387 
13388       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
13389          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
13390          val = "no";
13391       }
13392       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
13393 
13394       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
13395          ast_copy_string(dialcontext, val, sizeof(dialcontext));
13396          ast_debug(1, "found dialout context: %s\n", dialcontext);
13397       } else {
13398          dialcontext[0] = '\0';
13399       }
13400 
13401       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
13402          ast_copy_string(callcontext, val, sizeof(callcontext));
13403          ast_debug(1, "found callback context: %s\n", callcontext);
13404       } else {
13405          callcontext[0] = '\0';
13406       }
13407 
13408       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
13409          ast_copy_string(exitcontext, val, sizeof(exitcontext));
13410          ast_debug(1, "found operator context: %s\n", exitcontext);
13411       } else {
13412          exitcontext[0] = '\0';
13413       }
13414 
13415       /* load password sounds configuration */
13416       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
13417          ast_copy_string(vm_password, val, sizeof(vm_password));
13418       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
13419          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
13420       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
13421          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
13422       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
13423          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
13424       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
13425          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
13426       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
13427          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
13428       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
13429          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
13430       }
13431       if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
13432          ast_copy_string(vm_prepend_timeout, val, sizeof(vm_prepend_timeout));
13433       }
13434       /* load configurable audio prompts */
13435       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
13436          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
13437       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
13438          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
13439       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
13440          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
13441       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
13442          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
13443       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
13444          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
13445 
13446       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
13447          val = "no";
13448       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
13449 
13450       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
13451          val = "voicemail.conf";
13452       }
13453       if (!(strcmp(val, "spooldir"))) {
13454          passwordlocation = OPT_PWLOC_SPOOLDIR;
13455       } else {
13456          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
13457       }
13458 
13459       poll_freq = DEFAULT_POLL_FREQ;
13460       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
13461          if (sscanf(val, "%30u", &poll_freq) != 1) {
13462             poll_freq = DEFAULT_POLL_FREQ;
13463             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
13464          }
13465       }
13466 
13467       poll_mailboxes = 0;
13468       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
13469          poll_mailboxes = ast_true(val);
13470 
13471       memset(fromstring, 0, sizeof(fromstring));
13472       memset(pagerfromstring, 0, sizeof(pagerfromstring));
13473       strcpy(charset, "ISO-8859-1");
13474       if (emailbody) {
13475          ast_free(emailbody);
13476          emailbody = NULL;
13477       }
13478       if (emailsubject) {
13479          ast_free(emailsubject);
13480          emailsubject = NULL;
13481       }
13482       if (pagerbody) {
13483          ast_free(pagerbody);
13484          pagerbody = NULL;
13485       }
13486       if (pagersubject) {
13487          ast_free(pagersubject);
13488          pagersubject = NULL;
13489       }
13490       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
13491          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
13492       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
13493          ast_copy_string(fromstring, val, sizeof(fromstring));
13494       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
13495          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
13496       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
13497          ast_copy_string(charset, val, sizeof(charset));
13498       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
13499          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
13500          for (x = 0; x < 4; x++) {
13501             memcpy(&adsifdn[x], &tmpadsi[x], 1);
13502          }
13503       }
13504       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
13505          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
13506          for (x = 0; x < 4; x++) {
13507             memcpy(&adsisec[x], &tmpadsi[x], 1);
13508          }
13509       }
13510       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
13511          if (atoi(val)) {
13512             adsiver = atoi(val);
13513          }
13514       }
13515       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
13516          ast_copy_string(zonetag, val, sizeof(zonetag));
13517       }
13518       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
13519          ast_copy_string(locale, val, sizeof(locale));
13520       }
13521       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
13522          emailsubject = ast_strdup(substitute_escapes(val));
13523       }
13524       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
13525          emailbody = ast_strdup(substitute_escapes(val));
13526       }
13527       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
13528          pagersubject = ast_strdup(substitute_escapes(val));
13529       }
13530       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
13531          pagerbody = ast_strdup(substitute_escapes(val));
13532       }
13533 
13534       /* load mailboxes from users.conf */
13535       if (ucfg) { 
13536          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
13537             if (!strcasecmp(cat, "general")) {
13538                continue;
13539             }
13540             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
13541                continue;
13542             if ((current = find_or_create(userscontext, cat))) {
13543                populate_defaults(current);
13544                apply_options_full(current, ast_variable_browse(ucfg, cat));
13545                ast_copy_string(current->context, userscontext, sizeof(current->context));
13546                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
13547                   current->passwordlocation = OPT_PWLOC_USERSCONF;
13548                }
13549 
13550                switch (current->passwordlocation) {
13551                case OPT_PWLOC_SPOOLDIR:
13552                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
13553                   read_password_from_file(secretfn, current->password, sizeof(current->password));
13554                }
13555             }
13556          }
13557       }
13558 
13559       /* load mailboxes from voicemail.conf */
13560       cat = ast_category_browse(cfg, NULL);
13561       while (cat) {
13562          if (strcasecmp(cat, "general")) {
13563             var = ast_variable_browse(cfg, cat);
13564             if (strcasecmp(cat, "zonemessages")) {
13565                /* Process mailboxes in this context */
13566                while (var) {
13567                   append_mailbox(cat, var->name, var->value);
13568                   var = var->next;
13569                }
13570             } else {
13571                /* Timezones in this context */
13572                while (var) {
13573                   struct vm_zone *z;
13574                   if ((z = ast_malloc(sizeof(*z)))) {
13575                      char *msg_format, *tzone;
13576                      msg_format = ast_strdupa(var->value);
13577                      tzone = strsep(&msg_format, "|,");
13578                      if (msg_format) {
13579                         ast_copy_string(z->name, var->name, sizeof(z->name));
13580                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
13581                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
13582                         AST_LIST_LOCK(&zones);
13583                         AST_LIST_INSERT_HEAD(&zones, z, list);
13584                         AST_LIST_UNLOCK(&zones);
13585                      } else {
13586                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
13587                         ast_free(z);
13588                      }
13589                   } else {
13590                      AST_LIST_UNLOCK(&users);
13591                      return -1;
13592                   }
13593                   var = var->next;
13594                }
13595             }
13596          }
13597          cat = ast_category_browse(cfg, cat);
13598       }
13599 
13600       AST_LIST_UNLOCK(&users);
13601 
13602       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
13603          start_poll_thread();
13604       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
13605          stop_poll_thread();;
13606 
13607       return 0;
13608    } else {
13609       AST_LIST_UNLOCK(&users);
13610       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
13611       return 0;
13612    }
13613 }

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 5141 of file app_voicemail.c.

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

Referenced by make_email_file().

05142 {
05143    char tmpdir[256], newtmp[256];
05144    char fname[256];
05145    char tmpcmd[256];
05146    int tmpfd = -1;
05147    int soxstatus = 0;
05148 
05149    /* Eww. We want formats to tell us their own MIME type */
05150    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
05151 
05152    if (vmu->volgain < -.001 || vmu->volgain > .001) {
05153       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
05154       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
05155       tmpfd = mkstemp(newtmp);
05156       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
05157       ast_debug(3, "newtmp: %s\n", newtmp);
05158       if (tmpfd > -1) {
05159          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
05160          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
05161             attach = newtmp;
05162             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
05163          } else {
05164             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
05165                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
05166             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
05167          }
05168       }
05169    }
05170    fprintf(p, "--%s" ENDL, bound);
05171    if (msgnum > -1)
05172       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
05173    else
05174       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
05175    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
05176    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
05177    if (msgnum > -1)
05178       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
05179    else
05180       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
05181    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
05182    base_encode(fname, p);
05183    if (last)
05184       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
05185    if (tmpfd > -1) {
05186       if (soxstatus == 0) {
05187          unlink(fname);
05188       }
05189       close(tmpfd);
05190       unlink(newtmp);
05191    }
05192    return 0;
05193 }

static int add_message_id ( struct ast_config msg_cfg,
char *  dir,
int  msg,
char *  filename,
char *  id,
size_t  id_size,
struct ast_vm_user vmu,
int  folder 
) [static]

Definition at line 11633 of file app_voicemail.c.

References ast_category_get(), ast_config_text_file_save(), ast_log(), ast_variable_append(), ast_variable_new(), ast_variables_destroy(), generate_random_string(), LOG_ERROR, LOG_WARNING, and UPDATE_MSG_ID.

Referenced by vm_msg_snapshot_create().

11634 {
11635    struct ast_variable *var;
11636    struct ast_category *cat;
11637    generate_random_string(id, id_size);
11638 
11639    var = ast_variable_new("msg_id", id, "");
11640    if (!var) {
11641       return -1;
11642    }
11643 
11644    cat = ast_category_get(msg_cfg, "message");
11645    if (!cat) {
11646       ast_log(LOG_ERROR, "Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
11647       ast_variables_destroy(var);
11648       return -1;
11649    }
11650 
11651    ast_variable_append(cat, var);
11652 
11653    if (ast_config_text_file_save(filename, msg_cfg, "app_voicemail")) {
11654       ast_log(LOG_WARNING, "Unable to update %s to have a message ID\n", filename);
11655       return -1;
11656    }
11657 
11658    UPDATE_MSG_ID(dir, msg, id, vmu, msg_cfg, folder);
11659    return 0;
11660 }

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

Definition at line 7082 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

07083 {
07084    int x;
07085    if (!ast_adsi_available(chan))
07086       return;
07087    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
07088    if (x < 0)
07089       return;
07090    if (!x) {
07091       if (adsi_load_vmail(chan, useadsi)) {
07092          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
07093          return;
07094       }
07095    } else
07096       *useadsi = 1;
07097 }

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

Definition at line 7278 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_set_keys(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_mutex_lock, ast_mutex_unlock, vm_state::curmsg, vm_state::deleted, and vm_state::lastmsg.

Referenced by vm_execmain().

07279 {
07280    int bytes = 0;
07281    unsigned char buf[256];
07282    unsigned char keys[8];
07283 
07284    int x;
07285 
07286    if (!ast_adsi_available(chan))
07287       return;
07288 
07289    /* New meaning for keys */
07290    for (x = 0; x < 5; x++)
07291       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
07292 
07293    keys[6] = 0x0;
07294    keys[7] = 0x0;
07295 
07296    if (!vms->curmsg) {
07297       /* No prev key, provide "Folder" instead */
07298       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07299    }
07300    if (vms->curmsg >= vms->lastmsg) {
07301       /* If last message ... */
07302       if (vms->curmsg) {
07303          /* but not only message, provide "Folder" instead */
07304          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07305       } else {
07306          /* Otherwise if only message, leave blank */
07307          keys[3] = 1;
07308       }
07309    }
07310 
07311    /* If deleted, show "undeleted" */
07312 #ifdef IMAP_STORAGE
07313    ast_mutex_lock(&vms->lock);
07314 #endif
07315    if (vms->deleted[vms->curmsg]) {
07316       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
07317    }
07318 #ifdef IMAP_STORAGE
07319    ast_mutex_unlock(&vms->lock);
07320 #endif
07321 
07322    /* Except "Exit" */
07323    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
07324    bytes += ast_adsi_set_keys(buf + bytes, keys);
07325    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07326 
07327    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07328 }

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

Definition at line 7147 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

Referenced by vm_execmain().

07148 {
07149    unsigned char buf[256];
07150    int bytes = 0;
07151    unsigned char keys[8];
07152    int x, y;
07153 
07154    if (!ast_adsi_available(chan))
07155       return;
07156 
07157    for (x = 0; x < 5; x++) {
07158       y = ADSI_KEY_APPS + 12 + start + x;
07159       if (y > ADSI_KEY_APPS + 12 + 4)
07160          y = 0;
07161       keys[x] = ADSI_KEY_SKT | y;
07162    }
07163    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
07164    keys[6] = 0;
07165    keys[7] = 0;
07166 
07167    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
07168    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
07169    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07170    bytes += ast_adsi_set_keys(buf + bytes, keys);
07171    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07172 
07173    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07174 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 7433 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

Referenced by vm_execmain().

07434 {
07435    unsigned char buf[256];
07436    int bytes = 0;
07437 
07438    if (!ast_adsi_available(chan))
07439       return;
07440    bytes += adsi_logo(buf + bytes);
07441    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
07442    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
07443    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07444    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07445 
07446    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07447 }

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

Definition at line 6953 of file app_voicemail.c.

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

Referenced by adsi_begin().

06954 {
06955    unsigned char buf[256];
06956    int bytes = 0;
06957    int x;
06958    char num[5];
06959 
06960    *useadsi = 0;
06961    bytes += ast_adsi_data_mode(buf + bytes);
06962    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06963 
06964    bytes = 0;
06965    bytes += adsi_logo(buf);
06966    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06967 #ifdef DISPLAY
06968    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06969 #endif
06970    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06971    bytes += ast_adsi_data_mode(buf + bytes);
06972    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06973 
06974    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06975       bytes = 0;
06976       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06977       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06978       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06979       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06980       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06981       return 0;
06982    }
06983 
06984 #ifdef DISPLAY
06985    /* Add a dot */
06986    bytes = 0;
06987    bytes += ast_adsi_logo(buf);
06988    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06989    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06990    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06991    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06992 #endif
06993    bytes = 0;
06994    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06995    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06996    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06997    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06998    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06999    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
07000    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07001 
07002 #ifdef DISPLAY
07003    /* Add another dot */
07004    bytes = 0;
07005    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
07006    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07007 
07008    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07009    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07010 #endif
07011 
07012    bytes = 0;
07013    /* These buttons we load but don't use yet */
07014    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
07015    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
07016    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
07017    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
07018    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
07019    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
07020    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07021 
07022 #ifdef DISPLAY
07023    /* Add another dot */
07024    bytes = 0;
07025    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
07026    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07027    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07028 #endif
07029 
07030    bytes = 0;
07031    for (x = 0; x < 5; x++) {
07032       snprintf(num, sizeof(num), "%d", x);
07033       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
07034    }
07035    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
07036    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07037 
07038 #ifdef DISPLAY
07039    /* Add another dot */
07040    bytes = 0;
07041    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
07042    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07043    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07044 #endif
07045 
07046    if (ast_adsi_end_download(chan)) {
07047       bytes = 0;
07048       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
07049       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
07050       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07051       bytes += ast_adsi_voice_mode(buf + bytes, 0);
07052       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07053       return 0;
07054    }
07055    bytes = 0;
07056    bytes += ast_adsi_download_disconnect(buf + bytes);
07057    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07058    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07059 
07060    ast_debug(1, "Done downloading scripts...\n");
07061 
07062 #ifdef DISPLAY
07063    /* Add last dot */
07064    bytes = 0;
07065    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
07066    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07067 #endif
07068    ast_debug(1, "Restarting session...\n");
07069 
07070    bytes = 0;
07071    /* Load the session now */
07072    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
07073       *useadsi = 1;
07074       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
07075    } else
07076       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
07077 
07078    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07079    return 0;
07080 }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 7099 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_input_control(), ast_adsi_input_format(), ast_adsi_load_soft_key(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

Referenced by vm_authenticate().

07100 {
07101    unsigned char buf[256];
07102    int bytes = 0;
07103    unsigned char keys[8];
07104    int x;
07105    if (!ast_adsi_available(chan))
07106       return;
07107 
07108    for (x = 0; x < 8; x++)
07109       keys[x] = 0;
07110    /* Set one key for next */
07111    keys[3] = ADSI_KEY_APPS + 3;
07112 
07113    bytes += adsi_logo(buf + bytes);
07114    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
07115    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
07116    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07117    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
07118    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
07119    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
07120    bytes += ast_adsi_set_keys(buf + bytes, keys);
07121    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07122    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07123 }

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

Definition at line 6945 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

Referenced by adsi_goodbye(), adsi_load_vmail(), adsi_login(), vm_newuser(), vm_options(), and vm_tempgreeting().

06946 {
06947    int bytes = 0;
06948    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06949    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06950    return bytes;
06951 }

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

Definition at line 7176 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_callerid_parse(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), buf1, buf2, vm_state::curbox, vm_state::curmsg, vm_state::deleted, vm_state::fn, vm_state::lastmsg, and strsep().

Referenced by play_message(), and vm_execmain().

07177 {
07178    int bytes = 0;
07179    unsigned char buf[256]; 
07180    char buf1[256], buf2[256];
07181    char fn2[PATH_MAX];
07182 
07183    char cid[256] = "";
07184    char *val;
07185    char *name, *num;
07186    char datetime[21] = "";
07187    FILE *f;
07188 
07189    unsigned char keys[8];
07190 
07191    int x;
07192 
07193    if (!ast_adsi_available(chan))
07194       return;
07195 
07196    /* Retrieve important info */
07197    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
07198    f = fopen(fn2, "r");
07199    if (f) {
07200       while (!feof(f)) {   
07201          if (!fgets((char *) buf, sizeof(buf), f)) {
07202             continue;
07203          }
07204          if (!feof(f)) {
07205             char *stringp = NULL;
07206             stringp = (char *) buf;
07207             strsep(&stringp, "=");
07208             val = strsep(&stringp, "=");
07209             if (!ast_strlen_zero(val)) {
07210                if (!strcmp((char *) buf, "callerid"))
07211                   ast_copy_string(cid, val, sizeof(cid));
07212                if (!strcmp((char *) buf, "origdate"))
07213                   ast_copy_string(datetime, val, sizeof(datetime));
07214             }
07215          }
07216       }
07217       fclose(f);
07218    }
07219    /* New meaning for keys */
07220    for (x = 0; x < 5; x++)
07221       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
07222    keys[6] = 0x0;
07223    keys[7] = 0x0;
07224 
07225    if (!vms->curmsg) {
07226       /* No prev key, provide "Folder" instead */
07227       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07228    }
07229    if (vms->curmsg >= vms->lastmsg) {
07230       /* If last message ... */
07231       if (vms->curmsg) {
07232          /* but not only message, provide "Folder" instead */
07233          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07234          bytes += ast_adsi_voice_mode(buf + bytes, 0);
07235 
07236       } else {
07237          /* Otherwise if only message, leave blank */
07238          keys[3] = 1;
07239       }
07240    }
07241 
07242    if (!ast_strlen_zero(cid)) {
07243       ast_callerid_parse(cid, &name, &num);
07244       if (!name)
07245          name = num;
07246    } else {
07247       name = "Unknown Caller";
07248    }
07249 
07250    /* If deleted, show "undeleted" */
07251 #ifdef IMAP_STORAGE
07252    ast_mutex_lock(&vms->lock);
07253 #endif
07254    if (vms->deleted[vms->curmsg]) {
07255       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
07256    }
07257 #ifdef IMAP_STORAGE
07258    ast_mutex_unlock(&vms->lock);
07259 #endif
07260 
07261    /* Except "Exit" */
07262    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
07263    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
07264       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
07265    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
07266 
07267    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
07268    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
07269    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
07270    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
07271    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07272    bytes += ast_adsi_set_keys(buf + bytes, keys);
07273    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07274 
07275    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07276 }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 7125 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_input_control(), ast_adsi_input_format(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

Referenced by vm_authenticate().

07126 {
07127    unsigned char buf[256];
07128    int bytes = 0;
07129    unsigned char keys[8];
07130    int x;
07131    if (!ast_adsi_available(chan))
07132       return;
07133 
07134    for (x = 0; x < 8; x++)
07135       keys[x] = 0;
07136    /* Set one key for next */
07137    keys[3] = ADSI_KEY_APPS + 3;
07138 
07139    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07140    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
07141    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
07142    bytes += ast_adsi_set_keys(buf + bytes, keys);
07143    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07144    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07145 }

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

Definition at line 7330 of file app_voicemail.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(), buf1, buf2, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_execmain().

07331 {
07332    unsigned char buf[256] = "";
07333    char buf1[256] = "", buf2[256] = "";
07334    int bytes = 0;
07335    unsigned char keys[8];
07336    int x;
07337 
07338    char *newm = (vms->newmessages == 1) ? "message" : "messages";
07339    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
07340    if (!ast_adsi_available(chan))
07341       return;
07342    if (vms->newmessages) {
07343       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
07344       if (vms->oldmessages) {
07345          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
07346          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
07347       } else {
07348          snprintf(buf2, sizeof(buf2), "%s.", newm);
07349       }
07350    } else if (vms->oldmessages) {
07351       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
07352       snprintf(buf2, sizeof(buf2), "%s.", oldm);
07353    } else {
07354       strcpy(buf1, "You have no messages.");
07355       buf2[0] = ' ';
07356       buf2[1] = '\0';
07357    }
07358    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
07359    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
07360    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07361 
07362    for (x = 0; x < 6; x++)
07363       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
07364    keys[6] = 0;
07365    keys[7] = 0;
07366 
07367    /* Don't let them listen if there are none */
07368    if (vms->lastmsg < 0)
07369       keys[0] = 1;
07370    bytes += ast_adsi_set_keys(buf + bytes, keys);
07371 
07372    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07373 
07374    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07375 }

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

Definition at line 7377 of file app_voicemail.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(), buf1, buf2, vm_state::curbox, and vm_state::lastmsg.

Referenced by vm_execmain().

07378 {
07379    unsigned char buf[256] = "";
07380    char buf1[256] = "", buf2[256] = "";
07381    int bytes = 0;
07382    unsigned char keys[8];
07383    int x;
07384 
07385    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
07386 
07387    if (!ast_adsi_available(chan))
07388       return;
07389 
07390    /* Original command keys */
07391    for (x = 0; x < 6; x++)
07392       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
07393 
07394    keys[6] = 0;
07395    keys[7] = 0;
07396 
07397    if ((vms->lastmsg + 1) < 1)
07398       keys[0] = 0;
07399 
07400    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
07401       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
07402 
07403    if (vms->lastmsg + 1)
07404       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
07405    else
07406       strcpy(buf2, "no messages.");
07407    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
07408    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
07409    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
07410    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07411    bytes += ast_adsi_set_keys(buf + bytes, keys);
07412 
07413    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07414 
07415    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07416    
07417 }

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 14431 of file app_voicemail.c.

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

Referenced by vm_execmain().

14432 {
14433    int res = 0;
14434    char filename[PATH_MAX];
14435    struct ast_config *msg_cfg = NULL;
14436    const char *origtime, *context;
14437    char *name, *num;
14438    int retries = 0;
14439    char *cid;
14440    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
14441 
14442    vms->starting = 0; 
14443 
14444    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
14445 
14446    /* Retrieve info from VM attribute file */
14447    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
14448    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
14449    msg_cfg = ast_config_load(filename, config_flags);
14450    DISPOSE(vms->curdir, vms->curmsg);
14451    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
14452       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
14453       return 0;
14454    }
14455 
14456    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
14457       ast_config_destroy(msg_cfg);
14458       return 0;
14459    }
14460 
14461    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
14462 
14463    context = ast_variable_retrieve(msg_cfg, "message", "context");
14464    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
14465       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
14466    switch (option) {
14467    case 3: /* Play message envelope */
14468       if (!res) {
14469          res = play_message_datetime(chan, vmu, origtime, filename);
14470       }
14471       if (!res) {
14472          res = play_message_callerid(chan, vms, cid, context, 0, 1);
14473       }
14474 
14475       res = 't';
14476       break;
14477 
14478    case 2:  /* Call back */
14479 
14480       if (ast_strlen_zero(cid))
14481          break;
14482 
14483       ast_callerid_parse(cid, &name, &num);
14484       while ((res > -1) && (res != 't')) {
14485          switch (res) {
14486          case '1':
14487             if (num) {
14488                /* Dial the CID number */
14489                res = dialout(chan, vmu, num, vmu->callback);
14490                if (res) {
14491                   ast_config_destroy(msg_cfg);
14492                   return 9;
14493                }
14494             } else {
14495                res = '2';
14496             }
14497             break;
14498 
14499          case '2':
14500             /* Want to enter a different number, can only do this if there's a dialout context for this user */
14501             if (!ast_strlen_zero(vmu->dialout)) {
14502                res = dialout(chan, vmu, NULL, vmu->dialout);
14503                if (res) {
14504                   ast_config_destroy(msg_cfg);
14505                   return 9;
14506                }
14507             } else {
14508                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
14509                res = ast_play_and_wait(chan, "vm-sorry");
14510             }
14511             ast_config_destroy(msg_cfg);
14512             return res;
14513          case '*':
14514             res = 't';
14515             break;
14516          case '3':
14517          case '4':
14518          case '5':
14519          case '6':
14520          case '7':
14521          case '8':
14522          case '9':
14523          case '0':
14524 
14525             res = ast_play_and_wait(chan, "vm-sorry");
14526             retries++;
14527             break;
14528          default:
14529             if (num) {
14530                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
14531                res = ast_play_and_wait(chan, "vm-num-i-have");
14532                if (!res)
14533                   res = play_message_callerid(chan, vms, num, vmu->context, 1, 1);
14534                if (!res)
14535                   res = ast_play_and_wait(chan, "vm-tocallnum");
14536                /* Only prompt for a caller-specified number if there is a dialout context specified */
14537                if (!ast_strlen_zero(vmu->dialout)) {
14538                   if (!res)
14539                      res = ast_play_and_wait(chan, "vm-calldiffnum");
14540                }
14541             } else {
14542                res = ast_play_and_wait(chan, "vm-nonumber");
14543                if (!ast_strlen_zero(vmu->dialout)) {
14544                   if (!res)
14545                      res = ast_play_and_wait(chan, "vm-toenternumber");
14546                }
14547             }
14548             if (!res) {
14549                res = ast_play_and_wait(chan, "vm-star-cancel");
14550             }
14551             if (!res) {
14552                res = ast_waitfordigit(chan, 6000);
14553             }
14554             if (!res) {
14555                retries++;
14556                if (retries > 3) {
14557                   res = 't';
14558                }
14559             }
14560             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
14561             break; 
14562             
14563          }
14564          if (res == 't')
14565             res = 0;
14566          else if (res == '*')
14567             res = -1;
14568       }
14569       break;
14570       
14571    case 1:  /* Reply */
14572       /* Send reply directly to sender */
14573       if (ast_strlen_zero(cid))
14574          break;
14575 
14576       ast_callerid_parse(cid, &name, &num);
14577       if (!num) {
14578          ast_verb(3, "No CID number available, no reply sent\n");
14579          if (!res)
14580             res = ast_play_and_wait(chan, "vm-nonumber");
14581          ast_config_destroy(msg_cfg);
14582          return res;
14583       } else {
14584          struct ast_vm_user vmu2;
14585          if (find_user(&vmu2, vmu->context, num)) {
14586             struct leave_vm_options leave_options;
14587             char mailbox[AST_MAX_EXTENSION * 2 + 2];
14588             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
14589 
14590             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
14591             
14592             memset(&leave_options, 0, sizeof(leave_options));
14593             leave_options.record_gain = record_gain;
14594             res = leave_voicemail(chan, mailbox, &leave_options);
14595             if (!res)
14596                res = 't';
14597             ast_config_destroy(msg_cfg);
14598             return res;
14599          } else {
14600             /* Sender has no mailbox, can't reply */
14601             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
14602             ast_play_and_wait(chan, "vm-nobox");
14603             res = 't';
14604             ast_config_destroy(msg_cfg);
14605             return res;
14606          }
14607       } 
14608       res = 0;
14609 
14610       break;
14611    }
14612 
14613 #ifndef IMAP_STORAGE
14614    ast_config_destroy(msg_cfg);
14615 
14616    if (!res) {
14617       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
14618       vms->heard[msg] = 1;
14619       res = wait_file(chan, vms, vms->fn);
14620    }
14621 #endif
14622    return res;
14623 }

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

Definition at line 11702 of file app_voicemail.c.

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

Referenced by actual_load_config().

11703 {
11704    /* Assumes lock is already held */
11705    char *tmp;
11706    char *stringp;
11707    char *s;
11708    struct ast_vm_user *vmu;
11709    char *mailbox_full;
11710    int new = 0, old = 0, urgent = 0;
11711    char secretfn[PATH_MAX] = "";
11712 
11713    tmp = ast_strdupa(data);
11714 
11715    if (!(vmu = find_or_create(context, box)))
11716       return -1;
11717 
11718    populate_defaults(vmu);
11719 
11720    stringp = tmp;
11721    if ((s = strsep(&stringp, ","))) {
11722       if (!ast_strlen_zero(s) && s[0] == '*') {
11723          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
11724             "\n\tmust be reset in voicemail.conf.\n", box);
11725       }
11726       /* assign password regardless of validity to prevent NULL password from being assigned */
11727       ast_copy_string(vmu->password, s, sizeof(vmu->password));
11728    }
11729    if (stringp && (s = strsep(&stringp, ","))) {
11730       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
11731    }
11732    if (stringp && (s = strsep(&stringp, ","))) {
11733       ast_copy_string(vmu->email, s, sizeof(vmu->email));
11734    }
11735    if (stringp && (s = strsep(&stringp, ","))) {
11736       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
11737    }
11738    if (stringp && (s = strsep(&stringp, ","))) {
11739       apply_options(vmu, s);
11740    }
11741 
11742    switch (vmu->passwordlocation) {
11743    case OPT_PWLOC_SPOOLDIR:
11744       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
11745       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
11746    }
11747 
11748    mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
11749    strcpy(mailbox_full, box);
11750    strcat(mailbox_full, "@");
11751    strcat(mailbox_full, context);
11752 
11753    inboxcount2(mailbox_full, &urgent, &new, &old);
11754    queue_mwi_event(mailbox_full, urgent, new, old);
11755 
11756    return 0;
11757 }

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 1248 of file app_voicemail.c.

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

Referenced by apply_options(), and apply_options_full().

01249 {
01250    int x;
01251    if (!strcasecmp(var, "attach")) {
01252       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01253    } else if (!strcasecmp(var, "attachfmt")) {
01254       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01255    } else if (!strcasecmp(var, "serveremail")) {
01256       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01257    } else if (!strcasecmp(var, "emailbody")) {
01258       ast_free(vmu->emailbody);
01259       vmu->emailbody = ast_strdup(substitute_escapes(value));
01260    } else if (!strcasecmp(var, "emailsubject")) {
01261       ast_free(vmu->emailsubject);
01262       vmu->emailsubject = ast_strdup(substitute_escapes(value));
01263    } else if (!strcasecmp(var, "language")) {
01264       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01265    } else if (!strcasecmp(var, "tz")) {
01266       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01267    } else if (!strcasecmp(var, "locale")) {
01268       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01269 #ifdef IMAP_STORAGE
01270    } else if (!strcasecmp(var, "imapuser")) {
01271       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01272       vmu->imapversion = imapversion;
01273    } else if (!strcasecmp(var, "imapserver")) {
01274       ast_copy_string(vmu->imapserver, value, sizeof(vmu->imapserver));
01275       vmu->imapversion = imapversion;
01276    } else if (!strcasecmp(var, "imapport")) {
01277       ast_copy_string(vmu->imapport, value, sizeof(vmu->imapport));
01278       vmu->imapversion = imapversion;
01279    } else if (!strcasecmp(var, "imapflags")) {
01280       ast_copy_string(vmu->imapflags, value, sizeof(vmu->imapflags));
01281       vmu->imapversion = imapversion;
01282    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01283       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01284       vmu->imapversion = imapversion;
01285    } else if (!strcasecmp(var, "imapfolder")) {
01286       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01287       vmu->imapversion = imapversion;
01288    } else if (!strcasecmp(var, "imapvmshareid")) {
01289       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01290       vmu->imapversion = imapversion;
01291 #endif
01292    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01293       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01294    } else if (!strcasecmp(var, "saycid")){
01295       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01296    } else if (!strcasecmp(var, "sendvoicemail")){
01297       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01298    } else if (!strcasecmp(var, "review")){
01299       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01300    } else if (!strcasecmp(var, "tempgreetwarn")){
01301       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01302    } else if (!strcasecmp(var, "messagewrap")){
01303       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01304    } else if (!strcasecmp(var, "operator")) {
01305       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01306    } else if (!strcasecmp(var, "envelope")){
01307       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01308    } else if (!strcasecmp(var, "moveheard")){
01309       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01310    } else if (!strcasecmp(var, "sayduration")){
01311       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01312    } else if (!strcasecmp(var, "saydurationm")){
01313       if (sscanf(value, "%30d", &x) == 1) {
01314          vmu->saydurationm = x;
01315       } else {
01316          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01317       }
01318    } else if (!strcasecmp(var, "forcename")){
01319       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01320    } else if (!strcasecmp(var, "forcegreetings")){
01321       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01322    } else if (!strcasecmp(var, "callback")) {
01323       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01324    } else if (!strcasecmp(var, "dialout")) {
01325       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01326    } else if (!strcasecmp(var, "exitcontext")) {
01327       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01328    } else if (!strcasecmp(var, "minsecs")) {
01329       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01330          vmu->minsecs = x;
01331       } else {
01332          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01333          vmu->minsecs = vmminsecs;
01334       }
01335    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01336       vmu->maxsecs = atoi(value);
01337       if (vmu->maxsecs <= 0) {
01338          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01339          vmu->maxsecs = vmmaxsecs;
01340       } else {
01341          vmu->maxsecs = atoi(value);
01342       }
01343       if (!strcasecmp(var, "maxmessage"))
01344          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01345    } else if (!strcasecmp(var, "maxmsg")) {
01346       vmu->maxmsg = atoi(value);
01347       /* Accept maxmsg=0 (Greetings only voicemail) */
01348       if (vmu->maxmsg < 0) {
01349          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01350          vmu->maxmsg = MAXMSG;
01351       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01352          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01353          vmu->maxmsg = MAXMSGLIMIT;
01354       }
01355    } else if (!strcasecmp(var, "nextaftercmd")) {
01356       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01357    } else if (!strcasecmp(var, "backupdeleted")) {
01358       if (sscanf(value, "%30d", &x) == 1)
01359          vmu->maxdeletedmsg = x;
01360       else if (ast_true(value))
01361          vmu->maxdeletedmsg = MAXMSG;
01362       else
01363          vmu->maxdeletedmsg = 0;
01364 
01365       if (vmu->maxdeletedmsg < 0) {
01366          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01367          vmu->maxdeletedmsg = MAXMSG;
01368       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01369          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01370          vmu->maxdeletedmsg = MAXMSGLIMIT;
01371       }
01372    } else if (!strcasecmp(var, "volgain")) {
01373       sscanf(value, "%30lf", &vmu->volgain);
01374    } else if (!strcasecmp(var, "passwordlocation")) {
01375       if (!strcasecmp(value, "spooldir")) {
01376          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01377       } else {
01378          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01379       }
01380    } else if (!strcasecmp(var, "options")) {
01381       apply_options(vmu, value);
01382    }
01383 }

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

Destructively Parse options and apply.

Definition at line 1501 of file app_voicemail.c.

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

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

01502 {  
01503    char *stringp;
01504    char *s;
01505    char *var, *value;
01506    stringp = ast_strdupa(options);
01507    while ((s = strsep(&stringp, "|"))) {
01508       value = s;
01509       if ((var = strsep(&value, "=")) && value) {
01510          apply_option(vmu, var, value);
01511       }
01512    }  
01513 }

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 1520 of file app_voicemail.c.

References apply_option(), ast_copy_string(), ast_free, ast_log(), ast_strdup, ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::fullname, LOG_WARNING, ast_vm_user::mailbox, ast_variable::name, ast_variable::next, ast_vm_user::pager, ast_vm_user::password, substitute_escapes(), ast_vm_user::uniqueid, and ast_variable::value.

Referenced by actual_load_config(), and find_user_realtime().

01521 {
01522    for (; var; var = var->next) {
01523       if (!strcasecmp(var->name, "vmsecret")) {
01524          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01525       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01526          if (ast_strlen_zero(retval->password)) {
01527             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01528                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01529                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01530             } else {
01531                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01532             }
01533          }
01534       } else if (!strcasecmp(var->name, "uniqueid")) {
01535          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01536       } else if (!strcasecmp(var->name, "pager")) {
01537          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01538       } else if (!strcasecmp(var->name, "email")) {
01539          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01540       } else if (!strcasecmp(var->name, "fullname")) {
01541          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01542       } else if (!strcasecmp(var->name, "context")) {
01543          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01544       } else if (!strcasecmp(var->name, "emailsubject")) {
01545          ast_free(retval->emailsubject);
01546          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01547       } else if (!strcasecmp(var->name, "emailbody")) {
01548          ast_free(retval->emailbody);
01549          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01550 #ifdef IMAP_STORAGE
01551       } else if (!strcasecmp(var->name, "imapuser")) {
01552          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01553          retval->imapversion = imapversion;
01554       } else if (!strcasecmp(var->name, "imapserver")) {
01555          ast_copy_string(retval->imapserver, var->value, sizeof(retval->imapserver));
01556          retval->imapversion = imapversion;
01557       } else if (!strcasecmp(var->name, "imapport")) {
01558          ast_copy_string(retval->imapport, var->value, sizeof(retval->imapport));
01559          retval->imapversion = imapversion;
01560       } else if (!strcasecmp(var->name, "imapflags")) {
01561          ast_copy_string(retval->imapflags, var->value, sizeof(retval->imapflags));
01562          retval->imapversion = imapversion;
01563       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01564          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01565          retval->imapversion = imapversion;
01566       } else if (!strcasecmp(var->name, "imapfolder")) {
01567          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01568          retval->imapversion = imapversion;
01569       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01570          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01571          retval->imapversion = imapversion;
01572 #endif
01573       } else
01574          apply_option(retval, var->name, var->value);
01575    }
01576 }

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 4797 of file app_voicemail.c.

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

04798 {
04799    struct ast_str *tmp = ast_str_alloca(80);
04800    int first_section = 1;
04801 
04802    ast_str_reset(*end);
04803    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04804    for (; *start; start++) {
04805       int need_encoding = 0;
04806       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04807          need_encoding = 1;
04808       }
04809       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04810          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04811          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04812          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04813          /* Start new line */
04814          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04815          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04816          first_section = 0;
04817       }
04818       if (need_encoding && *start == ' ') {
04819          ast_str_append(&tmp, -1, "_");
04820       } else if (need_encoding) {
04821          ast_str_append(&tmp, -1, "=%hhX", *start);
04822       } else {
04823          ast_str_append(&tmp, -1, "%c", *start);
04824       }
04825    }
04826    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04827    return ast_str_buffer(*end);
04828 }

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 4725 of file app_voicemail.c.

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

04726 {
04727    const char *ptr;
04728 
04729    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04730    ast_str_set(buf, maxlen, "\"");
04731    for (ptr = from; *ptr; ptr++) {
04732       if (*ptr == '"' || *ptr == '\\') {
04733          ast_str_append(buf, maxlen, "\\%c", *ptr);
04734       } else {
04735          ast_str_append(buf, maxlen, "%c", *ptr);
04736       }
04737    }
04738    ast_str_append(buf, maxlen, "\"");
04739 
04740    return ast_str_buffer(*buf);
04741 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 11759 of file app_voicemail.c.

References apply_options(), ast_calloc, ast_set_flag, AST_TEST_FAIL, ast_test_flag, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, free_user(), ast_vm_user::maxdeletedmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, OPT_PWLOC_SPOOLDIR, ast_vm_user::passwordlocation, populate_defaults(), ast_vm_user::saydurationm, ast_vm_user::serveremail, TEST_EXECUTE, TEST_INIT, VM_ALLOCED, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, ast_vm_user::volgain, and ast_vm_user::zonetag.

11760 {
11761    int res = 0;
11762    struct ast_vm_user *vmu;
11763    /* language parameter seems to only be used for display in manager action */
11764    static const char options_string[] = "attach=yes|attachfmt=wav49|"
11765       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
11766       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
11767       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
11768       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
11769       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
11770       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
11771       "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
11772       "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
11773 #ifdef IMAP_STORAGE
11774    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
11775       "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
11776 #endif
11777 
11778    switch (cmd) {
11779    case TEST_INIT:
11780       info->name = "vmuser";
11781       info->category = "/apps/app_voicemail/";
11782       info->summary = "Vmuser unit test";
11783       info->description =
11784          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
11785       return AST_TEST_NOT_RUN;
11786    case TEST_EXECUTE:
11787       break;
11788    }
11789 
11790    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
11791       return AST_TEST_NOT_RUN;
11792    }
11793    populate_defaults(vmu);
11794    ast_set_flag(vmu, VM_ALLOCED);
11795 
11796    apply_options(vmu, options_string);
11797 
11798    if (!ast_test_flag(vmu, VM_ATTACH)) {
11799       ast_test_status_update(test, "Parse failure for attach option\n");
11800       res = 1;
11801    }
11802    if (strcasecmp(vmu->attachfmt, "wav49")) {
11803       ast_test_status_update(test, "Parse failure for attachftm option\n");
11804       res = 1;
11805    }
11806    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
11807       ast_test_status_update(test, "Parse failure for serveremail option\n");
11808       res = 1;
11809    }
11810    if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
11811       ast_test_status_update(test, "Parse failure for emailsubject option\n");
11812       res = 1;
11813    }
11814    if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
11815       ast_test_status_update(test, "Parse failure for emailbody option\n");
11816       res = 1;
11817    }
11818    if (strcasecmp(vmu->zonetag, "central")) {
11819       ast_test_status_update(test, "Parse failure for tz option\n");
11820       res = 1;
11821    }
11822    if (!ast_test_flag(vmu, VM_DELETE)) {
11823       ast_test_status_update(test, "Parse failure for delete option\n");
11824       res = 1;
11825    }
11826    if (!ast_test_flag(vmu, VM_SAYCID)) {
11827       ast_test_status_update(test, "Parse failure for saycid option\n");
11828       res = 1;
11829    }
11830    if (!ast_test_flag(vmu, VM_SVMAIL)) {
11831       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
11832       res = 1;
11833    }
11834    if (!ast_test_flag(vmu, VM_REVIEW)) {
11835       ast_test_status_update(test, "Parse failure for review option\n");
11836       res = 1;
11837    }
11838    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
11839       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
11840       res = 1;
11841    }
11842    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
11843       ast_test_status_update(test, "Parse failure for messagewrap option\n");
11844       res = 1;
11845    }
11846    if (!ast_test_flag(vmu, VM_OPERATOR)) {
11847       ast_test_status_update(test, "Parse failure for operator option\n");
11848       res = 1;
11849    }
11850    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
11851       ast_test_status_update(test, "Parse failure for envelope option\n");
11852       res = 1;
11853    }
11854    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
11855       ast_test_status_update(test, "Parse failure for moveheard option\n");
11856       res = 1;
11857    }
11858    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
11859       ast_test_status_update(test, "Parse failure for sayduration option\n");
11860       res = 1;
11861    }
11862    if (vmu->saydurationm != 5) {
11863       ast_test_status_update(test, "Parse failure for saydurationm option\n");
11864       res = 1;
11865    }
11866    if (!ast_test_flag(vmu, VM_FORCENAME)) {
11867       ast_test_status_update(test, "Parse failure for forcename option\n");
11868       res = 1;
11869    }
11870    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
11871       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
11872       res = 1;
11873    }
11874    if (strcasecmp(vmu->callback, "somecontext")) {
11875       ast_test_status_update(test, "Parse failure for callbacks option\n");
11876       res = 1;
11877    }
11878    if (strcasecmp(vmu->dialout, "somecontext2")) {
11879       ast_test_status_update(test, "Parse failure for dialout option\n");
11880       res = 1;
11881    }
11882    if (strcasecmp(vmu->exit, "somecontext3")) {
11883       ast_test_status_update(test, "Parse failure for exitcontext option\n");
11884       res = 1;
11885    }
11886    if (vmu->minsecs != 10) {
11887       ast_test_status_update(test, "Parse failure for minsecs option\n");
11888       res = 1;
11889    }
11890    if (vmu->maxsecs != 100) {
11891       ast_test_status_update(test, "Parse failure for maxsecs option\n");
11892       res = 1;
11893    }
11894    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
11895       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
11896       res = 1;
11897    }
11898    if (vmu->maxdeletedmsg != 50) {
11899       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
11900       res = 1;
11901    }
11902    if (vmu->volgain != 1.3) {
11903       ast_test_status_update(test, "Parse failure for volgain option\n");
11904       res = 1;
11905    }
11906    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
11907       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
11908       res = 1;
11909    }
11910 #ifdef IMAP_STORAGE
11911    apply_options(vmu, option_string2);
11912 
11913    if (strcasecmp(vmu->imapuser, "imapuser")) {
11914       ast_test_status_update(test, "Parse failure for imapuser option\n");
11915       res = 1;
11916    }
11917    if (strcasecmp(vmu->imappassword, "imappasswd")) {
11918       ast_test_status_update(test, "Parse failure for imappasswd option\n");
11919       res = 1;
11920    }
11921    if (strcasecmp(vmu->imapfolder, "INBOX")) {
11922       ast_test_status_update(test, "Parse failure for imapfolder option\n");
11923       res = 1;
11924    }
11925    if (strcasecmp(vmu->imapvmshareid, "6000")) {
11926       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
11927       res = 1;
11928    }
11929    if (strcasecmp(vmu->imapserver, "imapserver")) {
11930       ast_test_status_update(test, "Parse failure for imapserver option\n");
11931       res = 1;
11932    }
11933    if (strcasecmp(vmu->imapport, "1234")) {
11934       ast_test_status_update(test, "Parse failure for imapport option\n");
11935       res = 1;
11936    }
11937    if (strcasecmp(vmu->imapflags, "flagged")) {
11938       ast_test_status_update(test, "Parse failure for imapflags option\n");
11939       res = 1;
11940    }
11941 #endif
11942 
11943    free_user(vmu);
11944    return res ? AST_TEST_FAIL : AST_TEST_PASS;
11945 }

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 4603 of file app_voicemail.c.

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

04604 {
04605    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04606       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04607       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04608       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04609    int i, hiteof = 0;
04610    FILE *fi;
04611    struct baseio bio;
04612 
04613    memset(&bio, 0, sizeof(bio));
04614    bio.iocp = BASEMAXINLINE;
04615 
04616    if (!(fi = fopen(filename, "rb"))) {
04617       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04618       return -1;
04619    }
04620 
04621    while (!hiteof){
04622       unsigned char igroup[3], ogroup[4];
04623       int c, n;
04624 
04625       memset(igroup, 0, sizeof(igroup));
04626 
04627       for (n = 0; n < 3; n++) {
04628          if ((c = inchar(&bio, fi)) == EOF) {
04629             hiteof = 1;
04630             break;
04631          }
04632 
04633          igroup[n] = (unsigned char) c;
04634       }
04635 
04636       if (n > 0) {
04637          ogroup[0]= dtable[igroup[0] >> 2];
04638          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04639          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04640          ogroup[3]= dtable[igroup[2] & 0x3F];
04641 
04642          if (n < 3) {
04643             ogroup[3] = '=';
04644 
04645             if (n < 2)
04646                ogroup[2] = '=';
04647          }
04648 
04649          for (i = 0; i < 4; i++)
04650             ochar(&bio, ogroup[i], so);
04651       }
04652    }
04653 
04654    fclose(fi);
04655    
04656    if (fputs(ENDL, so) == EOF) {
04657       return 0;
04658    }
04659 
04660    return 1;
04661 }

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 1479 of file app_voicemail.c.

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

Referenced by vm_change_password().

01480 {
01481    int res = -1;
01482    if (!strcmp(vmu->password, password)) {
01483       /* No change (but an update would return 0 rows updated, so we opt out here) */
01484       return 0;
01485    }
01486 
01487    if (strlen(password) > 10) {
01488       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01489    }
01490    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01491       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01492       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01493       res = 0;
01494    }
01495    return res;
01496 }

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 4770 of file app_voicemail.c.

04771 {
04772    for (; *str; str++) {
04773       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04774          return 1;
04775       }
04776    }
04777    return 0;
04778 }

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 1438 of file app_voicemail.c.

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

Referenced by network_thread(), vm_newuser(), and vm_options().

01439 {
01440    /* check minimum length */
01441    if (strlen(password) < minpassword)
01442       return 1;
01443    /* check that password does not contain '*' character */
01444    if (!ast_strlen_zero(password) && password[0] == '*')
01445       return 1;
01446    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01447       char cmd[255], buf[255];
01448 
01449       ast_debug(1, "Verify password policies for %s\n", password);
01450 
01451       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01452       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01453          ast_debug(5, "Result: %s\n", buf);
01454          if (!strncasecmp(buf, "VALID", 5)) {
01455             ast_debug(3, "Passed password check: '%s'\n", buf);
01456             return 0;
01457          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01458             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01459             return 0;
01460          } else {
01461             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01462             return 1;
01463          }
01464       }
01465    }
01466    return 0;
01467 }

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

Definition at line 8712 of file app_voicemail.c.

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

Referenced by play_message_by_id(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

08713 {
08714    int x = 0;
08715    int last_msg_idx = 0;
08716 
08717 #ifndef IMAP_STORAGE
08718    int res = 0, nummsg;
08719    char fn2[PATH_MAX];
08720 #endif
08721 
08722    if (vms->lastmsg <= -1) {
08723       goto done;
08724    }
08725 
08726    vms->curmsg = -1;
08727 #ifndef IMAP_STORAGE
08728    /* Get the deleted messages fixed */
08729    if (vm_lock_path(vms->curdir)) {
08730       return ERROR_LOCK_PATH;
08731    }
08732 
08733    /* update count as message may have arrived while we've got mailbox open */
08734    last_msg_idx = last_message_index(vmu, vms->curdir);
08735    if (last_msg_idx != vms->lastmsg) {
08736       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
08737    }
08738 
08739    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
08740    for (x = 0; x < last_msg_idx + 1; x++) {
08741       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
08742          /* Save this message.  It's not in INBOX or hasn't been heard */
08743          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08744          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
08745             break;
08746          }
08747          vms->curmsg++;
08748          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
08749          if (strcmp(vms->fn, fn2)) {
08750             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
08751          }
08752       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
08753          /* Move to old folder before deleting */
08754          res = save_to_folder(vmu, vms, x, 1, NULL, 0);
08755          if (res == ERROR_LOCK_PATH) {
08756             /* If save failed do not delete the message */
08757             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08758             vms->deleted[x] = 0;
08759             vms->heard[x] = 0;
08760             --x;
08761          }
08762       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08763          /* Move to deleted folder */
08764          res = save_to_folder(vmu, vms, x, 10, NULL, 0);
08765          if (res == ERROR_LOCK_PATH) {
08766             /* If save failed do not delete the message */
08767             vms->deleted[x] = 0;
08768             vms->heard[x] = 0;
08769             --x;
08770          }
08771       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08772          /* If realtime storage enabled - we should explicitly delete this message,
08773          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08774          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08775          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08776             DELETE(vms->curdir, x, vms->fn, vmu);
08777          }
08778       }
08779    }
08780 
08781    /* Delete ALL remaining messages */
08782    nummsg = x - 1;
08783    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08784       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08785       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08786          DELETE(vms->curdir, x, vms->fn, vmu);
08787       }
08788    }
08789    ast_unlock_path(vms->curdir);
08790 #else /* defined(IMAP_STORAGE) */
08791    ast_mutex_lock(&vms->lock);
08792    if (vms->deleted) {
08793       /* Since we now expunge after each delete, deleting in reverse order
08794        * ensures that no reordering occurs between each step. */
08795       last_msg_idx = vms->dh_arraysize;
08796       for (x = last_msg_idx - 1; x >= 0; x--) {
08797          if (vms->deleted[x]) {
08798             ast_debug(3, "IMAP delete of %d\n", x);
08799             DELETE(vms->curdir, x, vms->fn, vmu);
08800          }
08801       }
08802    }
08803 #endif
08804 
08805 done:
08806    if (vms->deleted) {
08807       ast_free(vms->deleted);
08808       vms->deleted = NULL;
08809    }
08810    if (vms->heard) {
08811       ast_free(vms->heard);
08812       vms->heard = NULL;
08813    }
08814    vms->dh_arraysize = 0;
08815 #ifdef IMAP_STORAGE
08816    ast_mutex_unlock(&vms->lock);
08817 #endif
08818 
08819    return 0;
08820 }

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

Definition at line 12176 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

12177 {
12178    int which = 0;
12179    int wordlen;
12180    struct ast_vm_user *vmu;
12181    const char *context = "";
12182 
12183    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
12184    if (pos > 4)
12185       return NULL;
12186    if (pos == 3)
12187       return (state == 0) ? ast_strdup("for") : NULL;
12188    wordlen = strlen(word);
12189    AST_LIST_TRAVERSE(&users, vmu, list) {
12190       if (!strncasecmp(word, vmu->context, wordlen)) {
12191          if (context && strcmp(context, vmu->context) && ++which > state)
12192             return ast_strdup(vmu->context);
12193          /* ignore repeated contexts ? */
12194          context = vmu->context;
12195       }
12196    }
12197    return NULL;
12198 }

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 4408 of file app_voicemail.c.

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

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), config_hook_exec(), copy_plain_file(), filehelper(), iax2_register(), parse_hint_device(), parse_hint_presence(), and vm_forwardoptions().

04409 {
04410    int ifd;
04411    int ofd;
04412    int res;
04413    int len;
04414    char buf[4096];
04415 
04416 #ifdef HARDLINK_WHEN_POSSIBLE
04417    /* Hard link if possible; saves disk space & is faster */
04418    if (link(infile, outfile)) {
04419 #endif
04420       if ((ifd = open(infile, O_RDONLY)) < 0) {
04421          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04422          return -1;
04423       }
04424       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04425          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04426          close(ifd);
04427          return -1;
04428       }
04429       do {
04430          len = read(ifd, buf, sizeof(buf));
04431          if (len < 0) {
04432             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04433             close(ifd);
04434             close(ofd);
04435             unlink(outfile);
04436          } else if (len) {
04437             res = write(ofd, buf, len);
04438             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04439                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04440                close(ifd);
04441                close(ofd);
04442                unlink(outfile);
04443             }
04444          }
04445       } while (len);
04446       close(ifd);
04447       close(ofd);
04448       return 0;
04449 #ifdef HARDLINK_WHEN_POSSIBLE
04450    } else {
04451       /* Hard link succeeded */
04452       return 0;
04453    }
04454 #endif
04455 }

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,
const char *  dest_folder 
) [static]

Copies a message from one mailbox to another.

Parameters:
chan 
vmu 
imbox 
msgnum 
duration 
recip 
fmt 
dir 
flag,dest_folder This is only used by file storage based mailboxes.
Returns:
zero on success, -1 on error.

Definition at line 5681 of file app_voicemail.c.

References ast_channel_caller(), ast_channel_language(), ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), mbox(), ast_party_id::name, notify_new_message(), ast_party_id::number, S_COR, STORE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, ast_party_number::valid, vm_delete(), and vm_lock_path().

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

05682 {
05683    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05684    const char *frombox = mbox(vmu, imbox);
05685    const char *userfolder;
05686    int recipmsgnum;
05687    int res = 0;
05688 
05689    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05690 
05691    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05692       userfolder = "Urgent";
05693    } else if (!ast_strlen_zero(dest_folder)) {
05694       userfolder = dest_folder;
05695    } else {
05696       userfolder = "INBOX";
05697    }
05698 
05699    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05700 
05701    if (!dir)
05702       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05703    else
05704       ast_copy_string(fromdir, dir, sizeof(fromdir));
05705 
05706    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05707    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05708 
05709    if (vm_lock_path(todir))
05710       return ERROR_LOCK_PATH;
05711 
05712    recipmsgnum = last_message_index(recip, todir) + 1;
05713    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05714       make_file(topath, sizeof(topath), todir, recipmsgnum);
05715 #ifndef ODBC_STORAGE
05716       if (EXISTS(fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : "")) {
05717          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05718       } else {
05719 #endif
05720          /* If we are prepending a message for ODBC, then the message already
05721           * exists in the database, but we want to force copying from the
05722           * filesystem (since only the FS contains the prepend). */
05723          copy_plain_file(frompath, topath);
05724          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL);
05725          vm_delete(topath);
05726 #ifndef ODBC_STORAGE
05727       }
05728 #endif
05729    } else {
05730       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05731       res = -1;
05732    }
05733    ast_unlock_path(todir);
05734    if (chan) {
05735       struct ast_party_caller *caller = ast_channel_caller(chan);
05736       notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05737          S_COR(caller->id.number.valid, caller->id.number.str, NULL),
05738          S_COR(caller->id.name.valid, caller->id.name.str, NULL),
05739          flag);
05740    }
05741 
05742    return res;
05743 }

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 4466 of file app_voicemail.c.

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

Referenced by copy_message().

04467 {
04468    char frompath2[PATH_MAX], topath2[PATH_MAX];
04469    struct ast_variable *tmp,*var = NULL;
04470    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04471    ast_filecopy(frompath, topath, NULL);
04472    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04473    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04474    if (ast_check_realtime("voicemail_data")) {
04475       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04476       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04477       for (tmp = var; tmp; tmp = tmp->next) {
04478          if (!strcasecmp(tmp->name, "origmailbox")) {
04479             origmailbox = tmp->value;
04480          } else if (!strcasecmp(tmp->name, "context")) {
04481             context = tmp->value;
04482          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04483             macrocontext = tmp->value;
04484          } else if (!strcasecmp(tmp->name, "exten")) {
04485             exten = tmp->value;
04486          } else if (!strcasecmp(tmp->name, "priority")) {
04487             priority = tmp->value;
04488          } else if (!strcasecmp(tmp->name, "callerchan")) {
04489             callerchan = tmp->value;
04490          } else if (!strcasecmp(tmp->name, "callerid")) {
04491             callerid = tmp->value;
04492          } else if (!strcasecmp(tmp->name, "origdate")) {
04493             origdate = tmp->value;
04494          } else if (!strcasecmp(tmp->name, "origtime")) {
04495             origtime = tmp->value;
04496          } else if (!strcasecmp(tmp->name, "category")) {
04497             category = tmp->value;
04498          } else if (!strcasecmp(tmp->name, "duration")) {
04499             duration = tmp->value;
04500          }
04501       }
04502       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);
04503    }
04504    copy(frompath2, topath2);
04505    ast_variables_destroy(var);
04506 }

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

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

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

04304 {
04305 
04306    int vmcount = 0;
04307    DIR *vmdir = NULL;
04308    struct dirent *vment = NULL;
04309 
04310    if (vm_lock_path(dir))
04311       return ERROR_LOCK_PATH;
04312 
04313    if ((vmdir = opendir(dir))) {
04314       while ((vment = readdir(vmdir))) {
04315          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
04316             vmcount++;
04317          }
04318       }
04319       closedir(vmdir);
04320    }
04321    ast_unlock_path(dir);
04322    
04323    return vmcount;
04324 }

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 1899 of file app_voicemail.c.

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

01900 {
01901    mode_t   mode = VOICEMAIL_DIR_MODE;
01902    int res;
01903 
01904    make_dir(dest, len, context, ext, folder);
01905    if ((res = ast_mkdir(dest, mode))) {
01906       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01907       return -1;
01908    }
01909    return 0;
01910 }

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

Definition at line 14360 of file app_voicemail.c.

References ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_priority_set(), ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, and ast_waitfordigit().

Referenced by advanced_options(), and vm_execmain().

14361 {
14362    int cmd = 0;
14363    char destination[80] = "";
14364    int retries = 0;
14365 
14366    if (!num) {
14367       ast_verb(3, "Destination number will be entered manually\n");
14368       while (retries < 3 && cmd != 't') {
14369          destination[1] = '\0';
14370          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
14371          if (!cmd)
14372             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
14373          if (!cmd)
14374             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
14375          if (!cmd) {
14376             cmd = ast_waitfordigit(chan, 6000);
14377             if (cmd)
14378                destination[0] = cmd;
14379          }
14380          if (!cmd) {
14381             retries++;
14382          } else {
14383 
14384             if (cmd < 0)
14385                return 0;
14386             if (cmd == '*') {
14387                ast_verb(3, "User hit '*' to cancel outgoing call\n");
14388                return 0;
14389             }
14390             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
14391                retries++;
14392             else
14393                cmd = 't';
14394          }
14395          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
14396       }
14397       if (retries >= 3) {
14398          return 0;
14399       }
14400       
14401    } else {
14402       ast_verb(3, "Destination number is CID number '%s'\n", num);
14403       ast_copy_string(destination, num, sizeof(destination));
14404    }
14405 
14406    if (!ast_strlen_zero(destination)) {
14407       if (destination[strlen(destination) -1 ] == '*')
14408          return 0; 
14409       ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, ast_channel_context(chan));
14410       ast_channel_exten_set(chan, destination);
14411       ast_channel_context_set(chan, outgoing_context);
14412       ast_channel_priority_set(chan, 0);
14413       return 9;
14414    }
14415    return 0;
14416 }

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

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

Referenced by actual_load_config(), and append_mailbox().

11663 {
11664    struct ast_vm_user *vmu;
11665 
11666    if (!ast_strlen_zero(box) && box[0] == '*') {
11667       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
11668             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
11669             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
11670             "\n\tand will be ignored.\n", box, context);
11671       return NULL;
11672    }
11673 
11674    AST_LIST_TRAVERSE(&users, vmu, list) {
11675       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
11676          if (strcasecmp(vmu->context, context)) {
11677             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
11678                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
11679                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
11680                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
11681          }
11682          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
11683          return NULL;
11684       }
11685       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
11686          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
11687          return NULL;
11688       }
11689    }
11690    
11691    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
11692       return NULL;
11693    
11694    ast_copy_string(vmu->context, context, sizeof(vmu->context));
11695    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
11696 
11697    AST_LIST_INSERT_TAIL(&users, vmu, list);
11698    
11699    return vmu;
11700 }

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

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

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

Definition at line 1651 of file app_voicemail.c.

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

01652 {
01653    /* This function could be made to generate one from a database, too */
01654    struct ast_vm_user *vmu = NULL, *cur;
01655    AST_LIST_LOCK(&users);
01656 
01657    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01658       context = "default";
01659 
01660    AST_LIST_TRAVERSE(&users, cur, list) {
01661 #ifdef IMAP_STORAGE
01662       if (cur->imapversion != imapversion) {
01663          continue;
01664       }
01665 #endif
01666       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01667          break;
01668       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01669          break;
01670    }
01671    if (cur) {
01672       /* Make a copy, so that on a reload, we have no race */
01673       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01674          *vmu = *cur;
01675          if (!ivm) {
01676             vmu->emailbody = ast_strdup(cur->emailbody);
01677             vmu->emailsubject = ast_strdup(cur->emailsubject);
01678          }
01679          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01680          AST_LIST_NEXT(vmu, list) = NULL;
01681       }
01682    } else
01683       vmu = find_user_realtime(ivm, context, mailbox);
01684    AST_LIST_UNLOCK(&users);
01685    return vmu;
01686 }

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

Finds a voicemail user from the realtime engine.

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

Definition at line 1610 of file app_voicemail.c.

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

01611 {
01612    struct ast_variable *var;
01613    struct ast_vm_user *retval;
01614 
01615    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01616       if (ivm) {
01617          memset(retval, 0, sizeof(*retval));
01618       }
01619       populate_defaults(retval);
01620       if (!ivm) {
01621          ast_set_flag(retval, VM_ALLOCED);
01622       }
01623       if (mailbox) {
01624          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01625       }
01626       if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
01627          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01628       } else {
01629          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01630       }
01631       if (var) {
01632          apply_options_full(retval, var);
01633          ast_variables_destroy(var);
01634       } else { 
01635          if (!ivm) 
01636             ast_free(retval);
01637          retval = NULL;
01638       }  
01639    } 
01640    return retval;
01641 }

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

Sends a voicemail message to a mailbox recipient.

Parameters:
chan 
context 
vms 
sender 
fmt 
is_new_message Used to indicate the mode for which this method was invoked. Will be 0 when called to forward an existing message (option 8) Will be 1 when called to leave a message (option 3->5)
record_gain 
urgent Reads the destination mailbox(es) from keypad input for CID, or if use_directory feature is enabled, the Directory.
When in the leave message mode (is_new_message == 1):
  • allow the leaving of a message for ourselves. (Will not allow us to forward a message to ourselves, when is_new_message == 0).
  • attempt to determine the context and and mailbox, and then invoke leave_message() function to record and store the message.

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

  • retreives the current message to be forwarded
  • copies the original message to a temporary file, so updates to the envelope can be done.
  • determines the target mailbox and folders
  • copies the message into the target mailbox, using copy_message() or by generating the message into an email attachment if using imap folders.

Returns:
zero on success, -1 on error.

Definition at line 7885 of file app_voicemail.c.

References ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_language(), ast_channel_priority(), ast_channel_priority_set(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), ast_waitfordigit(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, find_user(), vm_state::fn, free_user(), globalflags, inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, pbx_exec(), pbx_findapp(), leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), STORE, strsep(), vm_state::username, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

07886 {
07887 #ifdef IMAP_STORAGE
07888    int todircount = 0;
07889    struct vm_state *dstvms;
07890 #endif
07891    char username[70]="";
07892    char fn[PATH_MAX]; /* for playback of name greeting */
07893    char ecodes[16] = "#";
07894    int res = 0, cmd = 0;
07895    struct ast_vm_user *receiver = NULL, *vmtmp;
07896    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
07897    char *stringp;
07898    const char *s;
07899    int saved_messages = 0;
07900    int valid_extensions = 0;
07901    char *dir;
07902    int curmsg;
07903    char urgent_str[7] = "";
07904    int prompt_played = 0;
07905 #ifndef IMAP_STORAGE
07906    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
07907 #endif
07908    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
07909       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
07910    }
07911 
07912    if (vms == NULL) return -1;
07913    dir = vms->curdir;
07914    curmsg = vms->curmsg;
07915 
07916    ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
07917    while (!res && !valid_extensions) {
07918       int use_directory = 0;
07919       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
07920          int done = 0;
07921          int retries = 0;
07922          cmd = 0;
07923          while ((cmd >= 0) && !done ){
07924             if (cmd)
07925                retries = 0;
07926             switch (cmd) {
07927             case '1': 
07928                use_directory = 0;
07929                done = 1;
07930                break;
07931             case '2': 
07932                use_directory = 1;
07933                done = 1;
07934                break;
07935             case '*': 
07936                cmd = 't';
07937                done = 1;
07938                break;
07939             default: 
07940                /* Press 1 to enter an extension press 2 to use the directory */
07941                cmd = ast_play_and_wait(chan, "vm-forward");
07942                if (!cmd) {
07943                   cmd = ast_waitfordigit(chan, 3000);
07944                }
07945                if (!cmd) {
07946                   retries++;
07947                }
07948                if (retries > 3) {
07949                   cmd = 't';
07950                   done = 1;
07951                }
07952                ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
07953             }
07954          }
07955          if (cmd < 0 || cmd == 't')
07956             break;
07957       }
07958 
07959       if (use_directory) {
07960          /* use app_directory */
07961 
07962          struct ast_app* directory_app;
07963 
07964          directory_app = pbx_findapp("Directory");
07965          if (directory_app) {
07966             char vmcontext[256];
07967             char *old_context;
07968             char *old_exten;
07969             int old_priority;
07970             /* make backup copies */
07971             old_context = ast_strdupa(ast_channel_context(chan));
07972             old_exten = ast_strdupa(ast_channel_exten(chan));
07973             old_priority = ast_channel_priority(chan);
07974 
07975             /* call the the Directory, changes the channel */
07976             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
07977             res = pbx_exec(chan, directory_app, vmcontext);
07978 
07979             ast_copy_string(username, ast_channel_exten(chan), sizeof(username));
07980 
07981             /* restore the old context, exten, and priority */
07982             ast_channel_context_set(chan, old_context);
07983             ast_channel_exten_set(chan, old_exten);
07984             ast_channel_priority_set(chan, old_priority);
07985          } else {
07986             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
07987             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
07988          }
07989       } else {
07990          /* Ask for an extension */
07991          ast_test_suite_event_notify("PLAYBACK", "Message: vm-extension");
07992          res = ast_streamfile(chan, "vm-extension", ast_channel_language(chan)); /* "extension" */
07993          prompt_played++;
07994          if (res || prompt_played > 4)
07995             break;
07996          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#")) < 0)
07997             break;
07998       }
07999 
08000       /* start all over if no username */
08001       if (ast_strlen_zero(username))
08002          continue;
08003       stringp = username;
08004       s = strsep(&stringp, "*");
08005       /* start optimistic */
08006       valid_extensions = 1;
08007       while (s) {
08008          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
08009             int oldmsgs;
08010             int newmsgs;
08011             int capacity;
08012             if (inboxcount(s, &newmsgs, &oldmsgs)) {
08013                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
08014                /* Shouldn't happen, but allow trying another extension if it does */
08015                res = ast_play_and_wait(chan, "pbx-invalid");
08016                valid_extensions = 0;
08017                break;
08018             }
08019             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
08020             if ((newmsgs + oldmsgs) >= capacity) {
08021                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
08022                res = ast_play_and_wait(chan, "vm-mailboxfull");
08023                valid_extensions = 0;
08024                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
08025                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
08026                   free_user(vmtmp);
08027                }
08028                inprocess_count(receiver->mailbox, receiver->context, -1);
08029                break;
08030             }
08031             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
08032          } else {
08033             /* XXX Optimization for the future.  When we encounter a single bad extension,
08034              * bailing out on all of the extensions may not be the way to go.  We should
08035              * probably just bail on that single extension, then allow the user to enter
08036              * several more. XXX
08037              */
08038             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
08039                free_user(receiver);
08040             }
08041             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
08042             /* "I am sorry, that's not a valid extension.  Please try again." */
08043             res = ast_play_and_wait(chan, "pbx-invalid");
08044             valid_extensions = 0;
08045             break;
08046          }
08047 
08048          /* play name if available, else play extension number */
08049          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
08050          RETRIEVE(fn, -1, s, receiver->context);
08051          if (ast_fileexists(fn, NULL, NULL) > 0) {
08052             res = ast_stream_and_wait(chan, fn, ecodes);
08053             if (res) {
08054                DISPOSE(fn, -1);
08055                return res;
08056             }
08057          } else {
08058             res = ast_say_digit_str(chan, s, ecodes, ast_channel_language(chan));
08059          }
08060          DISPOSE(fn, -1);
08061 
08062          s = strsep(&stringp, "*");
08063       }
08064       /* break from the loop of reading the extensions */
08065       if (valid_extensions)
08066          break;
08067    }
08068    /* check if we're clear to proceed */
08069    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
08070       return res;
08071    if (is_new_message == 1) {
08072       struct leave_vm_options leave_options;
08073       char mailbox[AST_MAX_EXTENSION * 2 + 2];
08074       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
08075 
08076       /* Send VoiceMail */
08077       memset(&leave_options, 0, sizeof(leave_options));
08078       leave_options.record_gain = record_gain;
08079       cmd = leave_voicemail(chan, mailbox, &leave_options);
08080    } else {
08081       /* Forward VoiceMail */
08082       long duration = 0;
08083       struct vm_state vmstmp;
08084       int copy_msg_result = 0;
08085 #ifdef IMAP_STORAGE
08086       char filename[PATH_MAX];
08087       struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
08088       const char *msg_id = NULL;
08089       struct ast_config *msg_cfg;
08090 #endif
08091       memcpy(&vmstmp, vms, sizeof(vmstmp));
08092 
08093       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
08094 #ifdef IMAP_STORAGE
08095       make_file(filename, sizeof(filename), dir, curmsg);
08096       strncat(filename, ".txt", sizeof(filename) - strlen(filename) - 1);
08097       msg_cfg = ast_config_load(filename, config_flags);
08098       if (msg_cfg && msg_cfg == CONFIG_STATUS_FILEINVALID) {
08099          msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
08100          ast_config_destroy(msg_cfg);
08101       }
08102 #endif
08103 
08104       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
08105       if (!cmd) {
08106          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
08107 #ifdef IMAP_STORAGE
08108             int attach_user_voicemail;
08109             char *myserveremail = serveremail;
08110             
08111             /* get destination mailbox */
08112             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
08113             if (!dstvms) {
08114                dstvms = create_vm_state_from_user(vmtmp);
08115             }
08116             if (dstvms) {
08117                init_mailstream(dstvms, 0);
08118                if (!dstvms->mailstream) {
08119                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
08120                } else {
08121                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
08122                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
08123                }
08124             } else {
08125                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
08126             }
08127             if (!ast_strlen_zero(vmtmp->serveremail))
08128                myserveremail = vmtmp->serveremail;
08129             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
08130             /* NULL category for IMAP storage */
08131             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
08132                dstvms->curbox,
08133                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
08134                S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
08135                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
08136                NULL, urgent_str, msg_id);
08137 #else
08138             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL);
08139 #endif
08140             saved_messages++;
08141             AST_LIST_REMOVE_CURRENT(list);
08142             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
08143             free_user(vmtmp);
08144             if (res)
08145                break;
08146          }
08147          AST_LIST_TRAVERSE_SAFE_END;
08148          if (saved_messages > 0 && !copy_msg_result) {
08149             /* give confirmation that the message was saved */
08150             /* commented out since we can't forward batches yet
08151             if (saved_messages == 1)
08152                res = ast_play_and_wait(chan, "vm-message");
08153             else
08154                res = ast_play_and_wait(chan, "vm-messages");
08155             if (!res)
08156                res = ast_play_and_wait(chan, "vm-saved"); */
08157 #ifdef IMAP_STORAGE
08158             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
08159             if (ast_strlen_zero(vmstmp.introfn))
08160 #endif
08161             res = ast_play_and_wait(chan, "vm-msgsaved");
08162          }
08163 #ifndef IMAP_STORAGE
08164          else {
08165             /* with IMAP, mailbox full warning played by imap_check_limits */
08166             res = ast_play_and_wait(chan, "vm-mailboxfull");
08167          }
08168          /* Restore original message without prepended message if backup exists */
08169          make_file(msgfile, sizeof(msgfile), dir, curmsg);
08170          strcpy(textfile, msgfile);
08171          strcpy(backup, msgfile);
08172          strcpy(backup_textfile, msgfile);
08173          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
08174          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
08175          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
08176          if (ast_fileexists(backup, NULL, NULL) > 0) {
08177             ast_filerename(backup, msgfile, NULL);
08178             rename(backup_textfile, textfile);
08179          }
08180 #endif
08181       }
08182       DISPOSE(dir, curmsg);
08183 #ifndef IMAP_STORAGE
08184       if (cmd) { /* assuming hangup, cleanup backup file */
08185          make_file(msgfile, sizeof(msgfile), dir, curmsg);
08186          strcpy(textfile, msgfile);
08187          strcpy(backup_textfile, msgfile);
08188          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
08189          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
08190          rename(backup_textfile, textfile);
08191       }
08192 #endif
08193    }
08194 
08195    /* If anything failed above, we still have this list to free */
08196    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
08197       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
08198       free_user(vmtmp);
08199    }
08200    return res ? res : cmd;
08201 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1941 of file app_voicemail.c.

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

01942 {
01943    if (ast_test_flag(vmu, VM_ALLOCED)) {
01944 
01945       ast_free(vmu->emailbody);
01946       vmu->emailbody = NULL;
01947 
01948       ast_free(vmu->emailsubject);
01949       vmu->emailsubject = NULL;
01950 
01951       ast_free(vmu);
01952    }
01953 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 12831 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

12832 {
12833    struct ast_vm_user *current;
12834    AST_LIST_LOCK(&users);
12835    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
12836       ast_set_flag(current, VM_ALLOCED);
12837       free_user(current);
12838    }
12839    AST_LIST_UNLOCK(&users);
12840 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 12843 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

12844 {
12845    struct vm_zone *zcur;
12846    AST_LIST_LOCK(&zones);
12847    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
12848       free_zone(zcur);
12849    AST_LIST_UNLOCK(&zones);
12850 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5445 of file app_voicemail.c.

References ast_free.

05446 {
05447    ast_free(z);
05448 }

static void generate_random_string ( char *  buf,
size_t  size 
) [static]

Definition at line 11623 of file app_voicemail.c.

References ast_random().

Referenced by add_message_id(), ast_rtp_new(), build_callid_pvt(), build_callid_registry(), calendar_query_exec(), construct_pidf_body(), do_notify(), and generate_uri().

11624 {
11625    long val[4];
11626    int x;
11627 
11628    for (x=0; x<4; x++)
11629       val[x] = ast_random();
11630    snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]);
11631 }

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 5401 of file app_voicemail.c.

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

05402 {
05403    struct ast_tm tm;
05404    struct timeval t = ast_tvnow();
05405 
05406    ast_localtime(&t, &tm, "UTC");
05407 
05408    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05409 }

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 7453 of file app_voicemail.c.

References ast_channel_language(), AST_DIGIT_ANY, ast_fileexists(), ast_play_and_wait(), ast_say_number(), ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), mbox(), and vm_play_folder_name().

Referenced by get_folder2().

07454 {
07455    int x;
07456    int d;
07457    char fn[PATH_MAX];
07458    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
07459    if (d)
07460       return d;
07461    for (x = start; x < 5; x++) { /* For all folders */
07462       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
07463          return d;
07464       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
07465       if (d)
07466          return d;
07467       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
07468 
07469       /* The inbox folder can have its name changed under certain conditions
07470        * so this checks if the sound file exists for the inbox folder name and
07471        * if it doesn't, plays the default name instead. */
07472       if (x == 0) {
07473          if (ast_fileexists(fn, NULL, NULL)) {
07474             d = vm_play_folder_name(chan, fn);
07475          } else {
07476             ast_verb(1, "failed to find %s\n", fn);
07477             d = vm_play_folder_name(chan, "vm-INBOX");
07478          }
07479       } else {
07480          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
07481          d = vm_play_folder_name(chan, fn);
07482       }
07483 
07484       if (d)
07485          return d;
07486       d = ast_waitfordigit(chan, 500);
07487       if (d)
07488          return d;
07489    }
07490 
07491    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
07492    if (d)
07493       return d;
07494    d = ast_waitfordigit(chan, 4000);
07495    return d;
07496 }

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 7510 of file app_voicemail.c.

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

Referenced by vm_execmain().

07511 {
07512    int res = 0;
07513    int loops = 0;
07514 
07515    res = ast_play_and_wait(chan, fn);  /* Folder name */
07516    while (((res < '0') || (res > '9')) &&
07517          (res != '#') && (res >= 0) &&
07518          loops < 4) {
07519       res = get_folder(chan, 0);
07520       loops++;
07521    }
07522    if (loops == 4) { /* give up */
07523       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
07524       return '#';
07525    }
07526    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07527    return res;
07528 }

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

Definition at line 1928 of file app_voicemail.c.

References ARRAY_LEN.

Referenced by vm_execmain(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

01929 {
01930    size_t i;
01931 
01932    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01933       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01934          return i;
01935       }
01936    }
01937 
01938    return -1;
01939 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 12558 of file app_voicemail.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::mailbox, mwi_sub_task::mailbox, poll_subscribed_mailbox(), mwi_sub_task::uniqueid, and mwi_sub::uniqueid.

Referenced by mwi_sub_event_cb().

12559 {
12560    unsigned int len;
12561    struct mwi_sub *mwi_sub;
12562    struct mwi_sub_task *p = datap;
12563 
12564    len = sizeof(*mwi_sub);
12565    if (!ast_strlen_zero(p->mailbox))
12566       len += strlen(p->mailbox);
12567 
12568    if (!ast_strlen_zero(p->context))
12569       len += strlen(p->context) + 1; /* Allow for seperator */
12570 
12571    if (!(mwi_sub = ast_calloc(1, len)))
12572       return -1;
12573 
12574    mwi_sub->uniqueid = p->uniqueid;
12575    if (!ast_strlen_zero(p->mailbox))
12576       strcpy(mwi_sub->mailbox, p->mailbox);
12577 
12578    if (!ast_strlen_zero(p->context)) {
12579       strcat(mwi_sub->mailbox, "@");
12580       strcat(mwi_sub->mailbox, p->context);
12581    }
12582 
12583    AST_RWLIST_WRLOCK(&mwi_subs);
12584    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
12585    AST_RWLIST_UNLOCK(&mwi_subs);
12586    ast_free((void *) p->mailbox);
12587    ast_free((void *) p->context);
12588    ast_free(p);
12589    poll_subscribed_mailbox(mwi_sub);
12590    return 0;
12591 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 12536 of file app_voicemail.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_destroy(), and mwi_sub::uniqueid.

Referenced by mwi_unsub_event_cb().

12537 {
12538    struct mwi_sub *mwi_sub;
12539    uint32_t *uniqueid = datap;
12540    
12541    AST_RWLIST_WRLOCK(&mwi_subs);
12542    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
12543       if (mwi_sub->uniqueid == *uniqueid) {
12544          AST_LIST_REMOVE_CURRENT(entry);
12545          break;
12546       }
12547    }
12548    AST_RWLIST_TRAVERSE_SAFE_END
12549    AST_RWLIST_UNLOCK(&mwi_subs);
12550 
12551    if (mwi_sub)
12552       mwi_sub_destroy(mwi_sub);
12553 
12554    ast_free(uniqueid);  
12555    return 0;
12556 }

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 12313 of file app_voicemail.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.

12314 {
12315    switch (cmd) {
12316    case CLI_INIT:
12317       e->command = "voicemail reload";
12318       e->usage =
12319          "Usage: voicemail reload\n"
12320          "       Reload voicemail configuration\n";
12321       return NULL;
12322    case CLI_GENERATE:
12323       return NULL;
12324    }
12325 
12326    if (a->argc != 2)
12327       return CLI_SHOWUSAGE;
12328 
12329    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
12330    load_config(1);
12331    
12332    return CLI_SUCCESS;
12333 }

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 12201 of file app_voicemail.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_check_realtime(), ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_voicemail_show_users(), ast_vm_user::context, ast_cli_args::fd, ast_vm_user::fullname, HVSU_OUTPUT_FORMAT, inboxcount(), ast_cli_args::line, ast_vm_user::mailbox, ast_cli_args::n, ast_cli_args::pos, show_users_realtime(), ast_cli_entry::usage, ast_cli_args::word, and ast_vm_user::zonetag.

12202 {
12203    struct ast_vm_user *vmu;
12204 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
12205    const char *context = NULL;
12206    int users_counter = 0;
12207 
12208    switch (cmd) {
12209    case CLI_INIT:
12210       e->command = "voicemail show users";
12211       e->usage =
12212          "Usage: voicemail show users [for <context>]\n"
12213          "       Lists all mailboxes currently set up\n";
12214       return NULL;
12215    case CLI_GENERATE:
12216       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
12217    }  
12218 
12219    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
12220       return CLI_SHOWUSAGE;
12221    if (a->argc == 5) {
12222       if (strcmp(a->argv[3],"for"))
12223          return CLI_SHOWUSAGE;
12224       context = a->argv[4];
12225    }
12226 
12227    if (ast_check_realtime("voicemail")) {
12228       if (!context) {
12229          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
12230          return CLI_SHOWUSAGE;
12231       }
12232       return show_users_realtime(a->fd, context);
12233    }
12234 
12235    AST_LIST_LOCK(&users);
12236    if (AST_LIST_EMPTY(&users)) {
12237       ast_cli(a->fd, "There are no voicemail users currently defined\n");
12238       AST_LIST_UNLOCK(&users);
12239       return CLI_FAILURE;
12240    }
12241    if (!context) {
12242       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
12243    } else {
12244       int count = 0;
12245       AST_LIST_TRAVERSE(&users, vmu, list) {
12246          if (!strcmp(context, vmu->context)) {
12247             count++;
12248             break;
12249          }
12250       }
12251       if (count) {
12252          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
12253       } else {
12254          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
12255          AST_LIST_UNLOCK(&users);
12256          return CLI_FAILURE;
12257       }
12258    }
12259    AST_LIST_TRAVERSE(&users, vmu, list) {
12260       int newmsgs = 0, oldmsgs = 0;
12261       char count[12], tmp[256] = "";
12262 
12263       if (!context || !strcmp(context, vmu->context)) {
12264          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
12265          inboxcount(tmp, &newmsgs, &oldmsgs);
12266          snprintf(count, sizeof(count), "%d", newmsgs);
12267          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
12268          users_counter++;
12269       }
12270    }
12271    AST_LIST_UNLOCK(&users);
12272    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
12273    return CLI_SUCCESS;
12274 }

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 12277 of file app_voicemail.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::msg_format, vm_zone::name, vm_zone::timezone, and ast_cli_entry::usage.

12278 {
12279    struct vm_zone *zone;
12280 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
12281    char *res = CLI_SUCCESS;
12282 
12283    switch (cmd) {
12284    case CLI_INIT:
12285       e->command = "voicemail show zones";
12286       e->usage =
12287          "Usage: voicemail show zones\n"
12288          "       Lists zone message formats\n";
12289       return NULL;
12290    case CLI_GENERATE:
12291       return NULL;
12292    }
12293 
12294    if (a->argc != 3)
12295       return CLI_SHOWUSAGE;
12296 
12297    AST_LIST_LOCK(&zones);
12298    if (!AST_LIST_EMPTY(&zones)) {
12299       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
12300       AST_LIST_TRAVERSE(&zones, zone, list) {
12301          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
12302       }
12303    } else {
12304       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
12305       res = CLI_FAILURE;
12306    }
12307    AST_LIST_UNLOCK(&zones);
12308 
12309    return res;
12310 }

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@context. 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 5798 of file app_voicemail.c.

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

Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), mwi_send_init(), my_has_voicemail(), and vm_execmain().

05799 {
05800    char tmp[256], *tmp2 = tmp, *box, *context;
05801    ast_copy_string(tmp, mailbox, sizeof(tmp));
05802    if (ast_strlen_zero(folder)) {
05803       folder = "INBOX";
05804    }
05805    while ((box = strsep(&tmp2, ",&"))) {
05806       if ((context = strchr(box, '@')))
05807          *context++ = '\0';
05808       else
05809          context = "default";
05810       if (__has_voicemail(context, box, folder, 1))
05811          return 1;
05812       /* If we are checking INBOX, we should check Urgent as well */
05813       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05814          return 1;
05815       }
05816    }
05817    return 0;
05818 }

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

Definition at line 5880 of file app_voicemail.c.

References inboxcount2().

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

05881 {
05882    int urgentmsgs = 0;
05883    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05884    if (newmsgs) {
05885       *newmsgs += urgentmsgs;
05886    }
05887    return res;
05888 }

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

Definition at line 5821 of file app_voicemail.c.

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

Referenced by append_mailbox(), inboxcount(), load_module(), poll_subscribed_mailbox(), run_externnotify(), and vm_users_data_provider_get_helper().

05822 {
05823    char tmp[256];
05824    char *context;
05825 
05826    /* If no mailbox, return immediately */
05827    if (ast_strlen_zero(mailbox))
05828       return 0;
05829 
05830    if (newmsgs)
05831       *newmsgs = 0;
05832    if (oldmsgs)
05833       *oldmsgs = 0;
05834    if (urgentmsgs)
05835       *urgentmsgs = 0;
05836 
05837    if (strchr(mailbox, ',')) {
05838       int tmpnew, tmpold, tmpurgent;
05839       char *mb, *cur;
05840 
05841       ast_copy_string(tmp, mailbox, sizeof(tmp));
05842       mb = tmp;
05843       while ((cur = strsep(&mb, ", "))) {
05844          if (!ast_strlen_zero(cur)) {
05845             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05846                return -1;
05847             else {
05848                if (newmsgs)
05849                   *newmsgs += tmpnew; 
05850                if (oldmsgs)
05851                   *oldmsgs += tmpold;
05852                if (urgentmsgs)
05853                   *urgentmsgs += tmpurgent;
05854             }
05855          }
05856       }
05857       return 0;
05858    }
05859 
05860    ast_copy_string(tmp, mailbox, sizeof(tmp));
05861    
05862    if ((context = strchr(tmp, '@')))
05863       *context++ = '\0';
05864    else
05865       context = "default";
05866 
05867    if (newmsgs)
05868       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05869    if (oldmsgs)
05870       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05871    if (urgentmsgs)
05872       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05873 
05874    return 0;
05875 }

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

utility used by inchar(), for base_encode()

Definition at line 4538 of file app_voicemail.c.

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

Referenced by ast_eivr_getvariable(), ast_eivr_setvariable(), inchar(), netconsole(), sip_addheader(), and sip_removeheader().

04539 {
04540    int l;
04541 
04542    if (bio->ateof)
04543       return 0;
04544 
04545    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04546       if (ferror(fi))
04547          return -1;
04548 
04549       bio->ateof = 1;
04550       return 0;
04551    }
04552 
04553    bio->iolen = l;
04554    bio->iocp = 0;
04555 
04556    return 1;
04557 }

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

utility used by base_encode()

Definition at line 4562 of file app_voicemail.c.

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

Referenced by base_encode().

04563 {
04564    if (bio->iocp>=bio->iolen) {
04565       if (!inbuf(bio, fi))
04566          return EOF;
04567    }
04568 
04569    return bio->iobuf[bio->iocp++];
04570 }

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

Definition at line 1124 of file app_voicemail.c.

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

Referenced by load_module().

01125 {
01126    struct inprocess *i = obj, *j = arg;
01127    if (strcmp(i->mailbox, j->mailbox)) {
01128       return 0;
01129    }
01130    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
01131 }

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

Definition at line 1133 of file app_voicemail.c.

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

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

01134 {
01135    struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
01136    arg->context = arg->mailbox + strlen(mailbox) + 1;
01137    strcpy(arg->mailbox, mailbox); /* SAFE */
01138    strcpy(arg->context, context); /* SAFE */
01139    ao2_lock(inprocess_container);
01140    if ((i = ao2_find(inprocess_container, arg, 0))) {
01141       int ret = ast_atomic_fetchadd_int(&i->count, delta);
01142       ao2_unlock(inprocess_container);
01143       ao2_ref(i, -1);
01144       return ret;
01145    }
01146    if (delta < 0) {
01147       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
01148    }
01149    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
01150       ao2_unlock(inprocess_container);
01151       return 0;
01152    }
01153    i->context = i->mailbox + strlen(mailbox) + 1;
01154    strcpy(i->mailbox, mailbox); /* SAFE */
01155    strcpy(i->context, context); /* SAFE */
01156    i->count = delta;
01157    ao2_link(inprocess_container, i);
01158    ao2_unlock(inprocess_container);
01159    ao2_ref(i, -1);
01160    return 0;
01161 }

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

Definition at line 1118 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

01119 {
01120    const struct inprocess *i = obj;
01121    return atoi(i->mailbox);
01122 }

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

Definition at line 5411 of file app_voicemail.c.

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

05412 {
05413    int res;
05414    char fn[PATH_MAX];
05415    char dest[PATH_MAX];
05416 
05417    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05418 
05419    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05420       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05421       return -1;
05422    }
05423 
05424    RETRIEVE(fn, -1, ext, context);
05425    if (ast_fileexists(fn, NULL, NULL) > 0) {
05426       res = ast_stream_and_wait(chan, fn, ecodes);
05427       if (res) {
05428          DISPOSE(fn, -1);
05429          return res;
05430       }
05431    } else {
05432       /* Dispose just in case */
05433       DISPOSE(fn, -1);
05434       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05435       if (res)
05436          return res;
05437       res = ast_say_digit_str(chan, ext, ecodes, ast_channel_language(chan));
05438       if (res)
05439          return res;
05440    }
05441    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05442    return res;
05443 }

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 1585 of file app_voicemail.c.

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

Referenced by actual_load_config().

01586 {
01587    int i;
01588    char *local_key = ast_strdupa(key);
01589 
01590    for (i = 0; i < strlen(key); ++i) {
01591       if (!strchr(VALID_DTMF, *local_key)) {
01592          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01593          return 0;
01594       }
01595       local_key++;
01596    }
01597    return 1;
01598 }

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 4357 of file app_voicemail.c.

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

Referenced by close_mailbox(), copy_message(), leave_voicemail(), msg_create_from_file(), open_mailbox(), and save_to_folder().

04358 {
04359    int x;
04360    unsigned char map[MAXMSGLIMIT] = "";
04361    DIR *msgdir;
04362    struct dirent *msgdirent;
04363    int msgdirint;
04364    char extension[4];
04365    int stopcount = 0;
04366 
04367    /* Reading the entire directory into a file map scales better than
04368     * doing a stat repeatedly on a predicted sequence.  I suspect this
04369     * is partially due to stat(2) internally doing a readdir(2) itself to
04370     * find each file. */
04371    if (!(msgdir = opendir(dir))) {
04372       return -1;
04373    }
04374 
04375    while ((msgdirent = readdir(msgdir))) {
04376       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04377          map[msgdirint] = 1;
04378          stopcount++;
04379          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04380       }
04381    }
04382    closedir(msgdir);
04383 
04384    for (x = 0; x < vmu->maxmsg; x++) {
04385       if (map[x] == 1) {
04386          stopcount--;
04387       } else if (map[x] == 0 && !stopcount) {
04388          break;
04389       }
04390    }
04391 
04392    return x - 1;
04393 }

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 6248 of file app_voicemail.c.

References ast_callerid_merge(), ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_language(), ast_channel_lock, ast_channel_macrocontext(), ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_redirecting(), ast_channel_unlock, ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer(), ast_str_create(), ast_str_hash(), ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verb, ast_waitstream(), ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, find_user(), free_user(), get_date(), inboxcount(), inprocess_count(), INTRO, invent_message(), last_message_index(), LOG_WARNING, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, vm_state::newmessages, notify_new_message(), OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), leave_vm_options::record_gain, RENAME, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, strsep(), transfer, vm_lock_path(), VM_OPERATOR, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

06249 {
06250 #ifdef IMAP_STORAGE
06251    int newmsgs, oldmsgs;
06252 #else
06253    char urgdir[PATH_MAX];
06254 #endif
06255    char txtfile[PATH_MAX];
06256    char tmptxtfile[PATH_MAX];
06257    struct vm_state *vms = NULL;
06258    char callerid[256];
06259    FILE *txt;
06260    char date[256];
06261    int txtdes;
06262    int res = 0;
06263    int msgnum;
06264    int duration = 0;
06265    int sound_duration = 0;
06266    int ausemacro = 0;
06267    int ousemacro = 0;
06268    int ouseexten = 0;
06269    char tmpdur[16];
06270    char priority[16];
06271    char origtime[16];
06272    char dir[PATH_MAX];
06273    char tmpdir[PATH_MAX];
06274    char fn[PATH_MAX];
06275    char prefile[PATH_MAX] = "";
06276    char tempfile[PATH_MAX] = "";
06277    char ext_context[256] = "";
06278    char fmt[80];
06279    char *context;
06280    char ecodes[17] = "#";
06281    struct ast_str *tmp = ast_str_create(16);
06282    char *tmpptr;
06283    struct ast_vm_user *vmu;
06284    struct ast_vm_user svm;
06285    const char *category = NULL;
06286    const char *code;
06287    const char *alldtmf = "0123456789ABCD*#";
06288    char flag[80];
06289 
06290    if (!tmp) {
06291       return -1;
06292    }
06293 
06294    ast_str_set(&tmp, 0, "%s", ext);
06295    ext = ast_str_buffer(tmp);
06296    if ((context = strchr(ext, '@'))) {
06297       *context++ = '\0';
06298       tmpptr = strchr(context, '&');
06299    } else {
06300       tmpptr = strchr(ext, '&');
06301    }
06302 
06303    if (tmpptr)
06304       *tmpptr++ = '\0';
06305 
06306    ast_channel_lock(chan);
06307    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06308       category = ast_strdupa(category);
06309    }
06310    ast_channel_unlock(chan);
06311 
06312    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
06313       ast_copy_string(flag, "Urgent", sizeof(flag));
06314    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
06315       ast_copy_string(flag, "PRIORITY", sizeof(flag));
06316    } else {
06317       flag[0] = '\0';
06318    }
06319 
06320    ast_debug(3, "Before find_user\n");
06321    if (!(vmu = find_user(&svm, context, ext))) {
06322       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
06323       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06324       ast_free(tmp);
06325       return res;
06326    }
06327    /* Setup pre-file if appropriate */
06328    if (strcmp(vmu->context, "default"))
06329       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
06330    else
06331       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
06332 
06333    /* Set the path to the prefile. Will be one of 
06334       VM_SPOOL_DIRcontext/ext/busy
06335       VM_SPOOL_DIRcontext/ext/unavail
06336       Depending on the flag set in options.
06337    */
06338    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
06339       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
06340    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
06341       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
06342    }
06343    /* Set the path to the tmpfile as
06344       VM_SPOOL_DIR/context/ext/temp
06345       and attempt to create the folder structure.
06346    */
06347    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
06348    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
06349       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
06350       ast_free(tmp);
06351       return -1;
06352    }
06353    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
06354    if (ast_fileexists(tempfile, NULL, NULL) > 0)
06355       ast_copy_string(prefile, tempfile, sizeof(prefile));
06356 
06357    DISPOSE(tempfile, -1);
06358    /* It's easier just to try to make it than to check for its existence */
06359 #ifndef IMAP_STORAGE
06360    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
06361 #else
06362    snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
06363    if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
06364       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
06365    }
06366 #endif
06367 
06368    /* Check current or macro-calling context for special extensions */
06369    if (ast_test_flag(vmu, VM_OPERATOR)) {
06370       if (!ast_strlen_zero(vmu->exit)) {
06371          if (ast_exists_extension(chan, vmu->exit, "o", 1,
06372             S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06373             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
06374             ouseexten = 1;
06375          }
06376       } else if (ast_exists_extension(chan, ast_channel_context(chan), "o", 1,
06377          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06378          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
06379          ouseexten = 1;
06380       } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))
06381          && ast_exists_extension(chan, ast_channel_macrocontext(chan), "o", 1,
06382             S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06383          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
06384          ousemacro = 1;
06385       }
06386    }
06387 
06388    if (!ast_strlen_zero(vmu->exit)) {
06389       if (ast_exists_extension(chan, vmu->exit, "a", 1,
06390          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06391          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
06392       }
06393    } else if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
06394       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06395       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
06396    } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))
06397       && ast_exists_extension(chan, ast_channel_macrocontext(chan), "a", 1,
06398          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06399       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
06400       ausemacro = 1;
06401    }
06402 
06403    if (ast_test_flag(options, OPT_DTMFEXIT)) {
06404       for (code = alldtmf; *code; code++) {
06405          char e[2] = "";
06406          e[0] = *code;
06407          if (strchr(ecodes, e[0]) == NULL
06408             && ast_canmatch_extension(chan,
06409                (!ast_strlen_zero(options->exitcontext) ? options->exitcontext : ast_channel_context(chan)),
06410                e, 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
06411             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
06412          }
06413       }
06414    }
06415 
06416    /* Play the beginning intro if desired */
06417    if (!ast_strlen_zero(prefile)) {
06418 #ifdef ODBC_STORAGE
06419       int success = 
06420 #endif
06421          RETRIEVE(prefile, -1, ext, context);
06422       if (ast_fileexists(prefile, NULL, NULL) > 0) {
06423          if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1) 
06424             res = ast_waitstream(chan, ecodes);
06425 #ifdef ODBC_STORAGE
06426          if (success == -1) {
06427             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
06428             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
06429             store_file(prefile, vmu->mailbox, vmu->context, -1);
06430          }
06431 #endif
06432       } else {
06433          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
06434          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
06435       }
06436       DISPOSE(prefile, -1);
06437       if (res < 0) {
06438          ast_debug(1, "Hang up during prefile playback\n");
06439          free_user(vmu);
06440          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06441          ast_free(tmp);
06442          return -1;
06443       }
06444    }
06445    if (res == '#') {
06446       /* On a '#' we skip the instructions */
06447       ast_set_flag(options, OPT_SILENT);
06448       res = 0;
06449    }
06450    /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
06451    if (vmu->maxmsg == 0) {
06452       ast_debug(3, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
06453       pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
06454       goto leave_vm_out;
06455    }
06456    if (!res && !ast_test_flag(options, OPT_SILENT)) {
06457       res = ast_stream_and_wait(chan, INTRO, ecodes);
06458       if (res == '#') {
06459          ast_set_flag(options, OPT_SILENT);
06460          res = 0;
06461       }
06462    }
06463    if (res > 0)
06464       ast_stopstream(chan);
06465    /* Check for a '*' here in case the caller wants to escape from voicemail to something
06466     other than the operator -- an automated attendant or mailbox login for example */
06467    if (res == '*') {
06468       ast_channel_exten_set(chan, "a");
06469       if (!ast_strlen_zero(vmu->exit)) {
06470          ast_channel_context_set(chan, vmu->exit);
06471       } else if (ausemacro && !ast_strlen_zero(ast_channel_macrocontext(chan))) {
06472          ast_channel_context_set(chan, ast_channel_macrocontext(chan));
06473       }
06474       ast_channel_priority_set(chan, 0);
06475       free_user(vmu);
06476       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
06477       ast_free(tmp);
06478       return 0;
06479    }
06480 
06481    /* Check for a '0' here */
06482    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
06483    transfer:
06484       if (ouseexten || ousemacro) {
06485          ast_channel_exten_set(chan, "o");
06486          if (!ast_strlen_zero(vmu->exit)) {
06487             ast_channel_context_set(chan, vmu->exit);
06488          } else if (ousemacro && !ast_strlen_zero(ast_channel_macrocontext(chan))) {
06489             ast_channel_context_set(chan, ast_channel_macrocontext(chan));
06490          }
06491          ast_play_and_wait(chan, "transfer");
06492          ast_channel_priority_set(chan, 0);
06493          free_user(vmu);
06494          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
06495       }
06496       ast_free(tmp);
06497       return OPERATOR_EXIT;
06498    }
06499 
06500    /* Allow all other digits to exit Voicemail and return to the dialplan */
06501    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
06502       if (!ast_strlen_zero(options->exitcontext)) {
06503          ast_channel_context_set(chan, options->exitcontext);
06504       }
06505       free_user(vmu);
06506       ast_free(tmp);
06507       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
06508       return res;
06509    }
06510 
06511    if (res < 0) {
06512       free_user(vmu);
06513       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06514       ast_free(tmp);
06515       return -1;
06516    }
06517    /* The meat of recording the message...  All the announcements and beeps have been played*/
06518    ast_copy_string(fmt, vmfmts, sizeof(fmt));
06519    if (!ast_strlen_zero(fmt)) {
06520       char msg_id[256] = "";
06521       msgnum = 0;
06522 
06523 #ifdef IMAP_STORAGE
06524       /* Is ext a mailbox? */
06525       /* must open stream for this user to get info! */
06526       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
06527       if (res < 0) {
06528          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
06529          ast_free(tmp);
06530          return -1;
06531       }
06532       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
06533       /* It is possible under certain circumstances that inboxcount did not
06534        * create a vm_state when it was needed. This is a catchall which will
06535        * rarely be used.
06536        */
06537          if (!(vms = create_vm_state_from_user(vmu))) {
06538             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
06539             ast_free(tmp);
06540             return -1;
06541          }
06542       }
06543       vms->newmessages++;
06544 
06545       /* here is a big difference! We add one to it later */
06546       msgnum = newmsgs + oldmsgs;
06547       ast_debug(3, "Messagecount set to %d\n", msgnum);
06548       snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
06549       /* set variable for compatibility */
06550       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
06551 
06552       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
06553          goto leave_vm_out;
06554       }
06555 #else
06556       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
06557          res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
06558          if (!res)
06559             res = ast_waitstream(chan, "");
06560          ast_log(AST_LOG_WARNING, "No more messages possible\n");
06561          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06562          inprocess_count(vmu->mailbox, vmu->context, -1);
06563          goto leave_vm_out;
06564       }
06565 
06566 #endif
06567       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
06568       txtdes = mkstemp(tmptxtfile);
06569       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
06570       if (txtdes < 0) {
06571          res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
06572          if (!res)
06573             res = ast_waitstream(chan, "");
06574          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
06575          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06576          inprocess_count(vmu->mailbox, vmu->context, -1);
06577          goto leave_vm_out;
06578       }
06579 
06580       /* Now play the beep once we have the message number for our next message. */
06581       if (res >= 0) {
06582          /* Unless we're *really* silent, try to send the beep */
06583          res = ast_stream_and_wait(chan, "beep", "");
06584       }
06585             
06586       /* Store information in real-time storage */
06587       if (ast_check_realtime("voicemail_data")) {
06588          snprintf(priority, sizeof(priority), "%d", ast_channel_priority(chan));
06589          snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
06590          get_date(date, sizeof(date));
06591          ast_callerid_merge(callerid, sizeof(callerid),
06592             S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
06593             S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
06594             "Unknown");
06595          ast_store_realtime("voicemail_data",
06596             "origmailbox", ext,
06597             "context", ast_channel_context(chan),
06598             "macrocontext", ast_channel_macrocontext(chan),
06599             "exten", ast_channel_exten(chan),
06600             "priority", priority,
06601             "callerchan", ast_channel_name(chan),
06602             "callerid", callerid,
06603             "origdate", date,
06604             "origtime", origtime,
06605             "category", S_OR(category, ""),
06606             "filename", tmptxtfile,
06607             SENTINEL);
06608       }
06609 
06610       /* Store information */
06611       txt = fdopen(txtdes, "w+");
06612       if (txt) {
06613          char msg_id_hash[256] = "";
06614 
06615          /* Every voicemail msg gets its own unique msg id.  The msg id is the originate time
06616           * plus a hash of the extension, context, and callerid of the channel leaving the msg */
06617          snprintf(msg_id_hash, sizeof(msg_id_hash), "%s%s%s", ast_channel_exten(chan), ast_channel_context(chan), callerid);
06618          snprintf(msg_id, sizeof(msg_id), "%ld-%d", (long) time(NULL), ast_str_hash(msg_id_hash));
06619 
06620          get_date(date, sizeof(date));
06621          ast_callerid_merge(callerid, sizeof(callerid),
06622             S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
06623             S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
06624             "Unknown");
06625          fprintf(txt, 
06626             ";\n"
06627             "; Message Information file\n"
06628             ";\n"
06629             "[message]\n"
06630             "origmailbox=%s\n"
06631             "context=%s\n"
06632             "macrocontext=%s\n"
06633             "exten=%s\n"
06634             "rdnis=%s\n"
06635             "priority=%d\n"
06636             "callerchan=%s\n"
06637             "callerid=%s\n"
06638             "origdate=%s\n"
06639             "origtime=%ld\n"
06640             "category=%s\n"
06641             "msg_id=%s\n",
06642             ext,
06643             ast_channel_context(chan),
06644             ast_channel_macrocontext(chan), 
06645             ast_channel_exten(chan),
06646             S_COR(ast_channel_redirecting(chan)->from.number.valid,
06647                ast_channel_redirecting(chan)->from.number.str, "unknown"),
06648             ast_channel_priority(chan),
06649             ast_channel_name(chan),
06650             callerid,
06651             date, (long) time(NULL),
06652             category ? category : "",
06653             msg_id);
06654       } else {
06655          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
06656          inprocess_count(vmu->mailbox, vmu->context, -1);
06657          if (ast_check_realtime("voicemail_data")) {
06658             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06659          }
06660          res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
06661          goto leave_vm_out;
06662       }
06663       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id);
06664 
06665       if (txt) {
06666          fprintf(txt, "flag=%s\n", flag);
06667          if (sound_duration < vmu->minsecs) {
06668             fclose(txt);
06669             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->minsecs);
06670             ast_filedelete(tmptxtfile, NULL);
06671             unlink(tmptxtfile);
06672             if (ast_check_realtime("voicemail_data")) {
06673                ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06674             }
06675             inprocess_count(vmu->mailbox, vmu->context, -1);
06676          } else {
06677             fprintf(txt, "duration=%d\n", duration);
06678             fclose(txt);
06679             if (vm_lock_path(dir)) {
06680                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
06681                /* Delete files */
06682                ast_filedelete(tmptxtfile, NULL);
06683                unlink(tmptxtfile);
06684                inprocess_count(vmu->mailbox, vmu->context, -1);
06685             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
06686                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
06687                unlink(tmptxtfile);
06688                ast_unlock_path(dir);
06689                inprocess_count(vmu->mailbox, vmu->context, -1);
06690                if (ast_check_realtime("voicemail_data")) {
06691                   ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06692                }
06693             } else {
06694 #ifndef IMAP_STORAGE
06695                msgnum = last_message_index(vmu, dir) + 1;
06696 #endif
06697                make_file(fn, sizeof(fn), dir, msgnum);
06698 
06699                /* assign a variable with the name of the voicemail file */ 
06700 #ifndef IMAP_STORAGE
06701                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
06702 #else
06703                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
06704 #endif
06705 
06706                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
06707                ast_filerename(tmptxtfile, fn, NULL);
06708                rename(tmptxtfile, txtfile);
06709                inprocess_count(vmu->mailbox, vmu->context, -1);
06710 
06711                /* Properly set permissions on voicemail text descriptor file.
06712                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
06713                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
06714                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
06715 
06716