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/taskprocessor.h"
#include "asterisk/test.h"
#include "asterisk/format_cache.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 MSG_ID_LEN   256
#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 int dump_cache (void *obj, void *arg, int flags)
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_msg_id (char *dst)
 Sets the destination string to a uniquely identifying msg_id string.
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 get_folder_ja (struct ast_channel *chan, int start)
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 *mailbox_id, const char *folder)
static int msg_create_from_file (struct ast_vm_recording_data *recdata)
static void mwi_event_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
static void mwi_sub_destroy (struct mwi_sub *mwi_sub)
static void mwi_sub_event_cb (struct stasis_subscription_change *change)
static void mwi_sub_task_dtor (struct mwi_sub_task *mwist)
static void mwi_unsub_event_cb (struct stasis_subscription_change *change)
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 *channel_id, 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 int separate_mailbox (char *mailbox_id, char **mailbox, char **context)
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 valid_config (const struct ast_config *cfg)
 Check if configuration file is valid.
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_ja (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Japanese 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_ja (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_ja (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_ja (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_sayname (struct ast_channel *chan, const char *mailbox_id)
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, .support_level = AST_MODULE_SUPPORT_CORE, .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 int msg_id_incrementor
static struct stasis_subscriptionmwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
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_vm_greeter_functions 
vm_greeter_table
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_vm_functions vm_table
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
  • Config_vm
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 566 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 589 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 590 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 563 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 559 of file app_voicemail.c.

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

Definition at line 912 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

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

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 571 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 573 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 574 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 572 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 575 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 985 of file app_voicemail.c.

Referenced by actual_load_config().

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

#define DISPOSE ( a,
b   ) 

#define ENDL   "\n"

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

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

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

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

#define MAX_DATETIME_FORMAT   512

Definition at line 597 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 598 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 584 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

#define MAXMSGLIMIT   9999

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

Referenced by actual_load_config().

#define MSG_ID_LEN   256

#define OPERATOR_EXIT   300

Definition at line 620 of file app_voicemail.c.

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

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 926 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 925 of file app_voicemail.c.

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

#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"

Definition at line 580 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

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

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

Definition at line 914 of file app_voicemail.c.

Referenced by add_message_id().

#define VALID_DTMF   "1234567890*#"

Definition at line 576 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 613 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 612 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 610 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 604 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 608 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 607 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 618 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 617 of file app_voicemail.c.

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

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 616 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 601 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 609 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 600 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 602 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 605 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 614 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 606 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 603 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 615 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 843 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 565 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

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

00622             {
00623    NEW_FOLDER,
00624    OLD_FOLDER,
00625    WORK_FOLDER,
00626    FAMILY_FOLDER,
00627    FRIENDS_FOLDER,
00628    GREETINGS_FOLDER
00629 };

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 643 of file app_voicemail.c.

00643                     {
00644    OPT_ARG_RECORDGAIN = 0,
00645    OPT_ARG_PLAYFOLDER = 1,
00646    OPT_ARG_DTMFEXIT   = 2,
00647    /* This *must* be the last value in this enum! */
00648    OPT_ARG_ARRAY_SIZE = 3,
00649 };

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

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

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 651 of file app_voicemail.c.

00651                          {
00652    OPT_PWLOC_VOICEMAILCONF = 0,
00653    OPT_PWLOC_SPOOLDIR      = 1,
00654    OPT_PWLOC_USERSCONF     = 2,
00655 };


Function Documentation

static void __fini_mwi_subs ( void   )  [static]

Definition at line 1027 of file app_voicemail.c.

01046 :
 * 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 5919 of file app_voicemail.c.

References ast_strlen_zero.

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

05920 {
05921    DIR *dir;
05922    struct dirent *de;
05923    char fn[256];
05924    int ret = 0;
05925 
05926    /* If no mailbox, return immediately */
05927    if (ast_strlen_zero(mailbox))
05928       return 0;
05929 
05930    if (ast_strlen_zero(folder))
05931       folder = "INBOX";
05932    if (ast_strlen_zero(context))
05933       context = "default";
05934 
05935    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05936 
05937    if (!(dir = opendir(fn)))
05938       return 0;
05939 
05940    while ((de = readdir(dir))) {
05941       if (!strncasecmp(de->d_name, "msg", 3)) {
05942          if (shortcircuit) {
05943             ret = 1;
05944             break;
05945          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05946             ret++;
05947          }
05948       }
05949    }
05950 
05951    closedir(dir);
05952 
05953    return ret;
05954 }

static void __init_mwi_subs ( void   )  [static]

Definition at line 1027 of file app_voicemail.c.

01046 :
 * 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 16124 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

12335 {
12336    struct ast_vm_user svm;
12337    AST_DECLARE_APP_ARGS(arg,
12338       AST_APP_ARG(mbox);
12339       AST_APP_ARG(context);
12340    );
12341    static int dep_warning = 0;
12342 
12343    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
12344 
12345    if (ast_strlen_zero(arg.mbox)) {
12346       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
12347       return -1;
12348    }
12349 
12350    if (!dep_warning) {
12351       dep_warning = 1;
12352       ast_log(AST_LOG_WARNING, "MAILBOX_EXISTS is deprecated.  Please use ${VM_INFO(%s,exists)} instead.\n", args);
12353    }
12354 
12355    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
12356    return 0;
12357 }

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

Definition at line 12359 of file app_voicemail.c.

References ast_alloca, 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, ast_vm_user::password, S_OR, separate_mailbox(), and ast_vm_user::zonetag.

12360 {
12361    struct ast_vm_user svm;
12362    struct ast_vm_user *vmu = NULL;
12363    char *parse;
12364    char *mailbox;
12365    char *context;
12366    int res = 0;
12367 
12368    AST_DECLARE_APP_ARGS(arg,
12369       AST_APP_ARG(mailbox_context);
12370       AST_APP_ARG(attribute);
12371       AST_APP_ARG(folder);
12372    );
12373 
12374    buf[0] = '\0';
12375 
12376    if (ast_strlen_zero(args)) {
12377       ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12378       return -1;
12379    }
12380 
12381    parse = ast_strdupa(args);
12382    AST_STANDARD_APP_ARGS(arg, parse);
12383 
12384    if (ast_strlen_zero(arg.mailbox_context)
12385       || ast_strlen_zero(arg.attribute)
12386       || separate_mailbox(ast_strdupa(arg.mailbox_context), &mailbox, &context)) {
12387       ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12388       return -1;
12389    }
12390 
12391    vmu = find_user(&svm, context, mailbox);
12392 
12393    if (!strncasecmp(arg.attribute, "exists", 5)) {
12394       ast_copy_string(buf, vmu ? "1" : "0", len);
12395       return 0;
12396    }
12397 
12398    if (vmu) {
12399       if (!strncasecmp(arg.attribute, "password", 8)) {
12400          ast_copy_string(buf, vmu->password, len);
12401       } else if (!strncasecmp(arg.attribute, "fullname", 8)) {
12402          ast_copy_string(buf, vmu->fullname, len);
12403       } else if (!strncasecmp(arg.attribute, "email", 5)) {
12404          ast_copy_string(buf, vmu->email, len);
12405       } else if (!strncasecmp(arg.attribute, "pager", 5)) {
12406          ast_copy_string(buf, vmu->pager, len);
12407       } else if (!strncasecmp(arg.attribute, "language", 8)) {
12408          ast_copy_string(buf, S_OR(vmu->language, ast_channel_language(chan)), len);
12409       } else if (!strncasecmp(arg.attribute, "locale", 6)) {
12410          ast_copy_string(buf, vmu->locale, len);
12411       } else if (!strncasecmp(arg.attribute, "tz", 2)) {
12412          ast_copy_string(buf, vmu->zonetag, len);
12413       } else if (!strncasecmp(arg.attribute, "count", 5)) {
12414          char *mailbox_id;
12415 
12416          mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2);
12417          sprintf(mailbox_id, "%s@%s", mailbox, context);/* Safe */
12418 
12419          /* If mbxfolder is empty messagecount will default to INBOX */
12420          res = messagecount(mailbox_id, arg.folder);
12421          if (res < 0) {
12422             ast_log(LOG_ERROR, "Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
12423             return -1;
12424          }
12425          snprintf(buf, len, "%d", res);
12426       } else {
12427          ast_log(LOG_ERROR, "Unknown attribute '%s' for VM_INFO\n", arg.attribute);
12428          return -1;
12429       }
12430    }
12431 
12432    return 0;
12433 }

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

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

13310 {
13311    struct ast_vm_user *current;
13312    char *cat;
13313    struct ast_variable *var;
13314    const char *val;
13315    char *q, *stringp, *tmp;
13316    int x;
13317    unsigned int tmpadsi[4];
13318    char secretfn[PATH_MAX] = "";
13319 
13320 #ifdef IMAP_STORAGE
13321    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
13322 #endif
13323    /* set audio control prompts */
13324    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
13325    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
13326    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
13327    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
13328    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
13329 
13330    /* Free all the users structure */  
13331    free_vm_users();
13332 
13333    /* Free all the zones structure */
13334    free_vm_zones();
13335 
13336    AST_LIST_LOCK(&users);  
13337 
13338    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
13339    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
13340 
13341    if (cfg) {
13342       /* General settings */
13343 
13344       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
13345          val = "default";
13346       ast_copy_string(userscontext, val, sizeof(userscontext));
13347       /* Attach voice message to mail message ? */
13348       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
13349          val = "yes";
13350       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
13351 
13352       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
13353          val = "no";
13354       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
13355 
13356       volgain = 0.0;
13357       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
13358          sscanf(val, "%30lf", &volgain);
13359 
13360 #ifdef ODBC_STORAGE
13361       strcpy(odbc_database, "asterisk");
13362       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
13363          ast_copy_string(odbc_database, val, sizeof(odbc_database));
13364       }
13365       strcpy(odbc_table, "voicemessages");
13366       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
13367          ast_copy_string(odbc_table, val, sizeof(odbc_table));
13368       }
13369 #endif      
13370       /* Mail command */
13371       strcpy(mailcmd, SENDMAIL);
13372       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
13373          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
13374 
13375       maxsilence = 0;
13376       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
13377          maxsilence = atoi(val);
13378          if (maxsilence > 0)
13379             maxsilence *= 1000;
13380       }
13381       
13382       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
13383          maxmsg = MAXMSG;
13384       } else {
13385          maxmsg = atoi(val);
13386          if (maxmsg < 0) {
13387             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
13388             maxmsg = MAXMSG;
13389          } else if (maxmsg > MAXMSGLIMIT) {
13390             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
13391             maxmsg = MAXMSGLIMIT;
13392          }
13393       }
13394 
13395       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
13396          maxdeletedmsg = 0;
13397       } else {
13398          if (sscanf(val, "%30d", &x) == 1)
13399             maxdeletedmsg = x;
13400          else if (ast_true(val))
13401             maxdeletedmsg = MAXMSG;
13402          else
13403             maxdeletedmsg = 0;
13404 
13405          if (maxdeletedmsg < 0) {
13406             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
13407             maxdeletedmsg = MAXMSG;
13408          } else if (maxdeletedmsg > MAXMSGLIMIT) {
13409             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
13410             maxdeletedmsg = MAXMSGLIMIT;
13411          }
13412       }
13413 
13414       /* Load date format config for voicemail mail */
13415       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
13416          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
13417       }
13418 
13419       /* Load date format config for voicemail pager mail */
13420       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
13421          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
13422       }
13423 
13424       /* External password changing command */
13425       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
13426          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
13427          pwdchange = PWDCHANGE_EXTERNAL;
13428       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
13429          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
13430          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
13431       }
13432 
13433       /* External password validation command */
13434       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
13435          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
13436          ast_debug(1, "found externpasscheck: %s\n", ext_pass_check_cmd);
13437       }
13438 
13439 #ifdef IMAP_STORAGE
13440       /* IMAP server address */
13441       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
13442          ast_copy_string(imapserver, val, sizeof(imapserver));
13443       } else {
13444          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
13445       }
13446       /* IMAP server port */
13447       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
13448          ast_copy_string(imapport, val, sizeof(imapport));
13449       } else {
13450          ast_copy_string(imapport, "143", sizeof(imapport));
13451       }
13452       /* IMAP server flags */
13453       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
13454          ast_copy_string(imapflags, val, sizeof(imapflags));
13455       }
13456       /* IMAP server master username */
13457       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
13458          ast_copy_string(authuser, val, sizeof(authuser));
13459       }
13460       /* IMAP server master password */
13461       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
13462          ast_copy_string(authpassword, val, sizeof(authpassword));
13463       }
13464       /* Expunge on exit */
13465       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
13466          if (ast_false(val))
13467             expungeonhangup = 0;
13468          else
13469             expungeonhangup = 1;
13470       } else {
13471          expungeonhangup = 1;
13472       }
13473       /* IMAP voicemail folder */
13474       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
13475          ast_copy_string(imapfolder, val, sizeof(imapfolder));
13476       } else {
13477          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
13478       }
13479       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
13480          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
13481       }
13482       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
13483          imapgreetings = ast_true(val);
13484       } else {
13485          imapgreetings = 0;
13486       }
13487       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
13488          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
13489       } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
13490          /* Also support greetingsfolder as documented in voicemail.conf.sample */
13491          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
13492       } else {
13493          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
13494       }
13495 
13496       /* There is some very unorthodox casting done here. This is due
13497        * to the way c-client handles the argument passed in. It expects a 
13498        * void pointer and casts the pointer directly to a long without
13499        * first dereferencing it. */
13500       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
13501          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
13502       } else {
13503          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
13504       }
13505 
13506       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
13507          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
13508       } else {
13509          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
13510       }
13511 
13512       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
13513          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
13514       } else {
13515          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
13516       }
13517 
13518       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
13519          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
13520       } else {
13521          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
13522       }
13523 
13524       /* Increment configuration version */
13525       imapversion++;
13526 #endif
13527       /* External voicemail notify application */
13528       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
13529          ast_copy_string(externnotify, val, sizeof(externnotify));
13530          ast_debug(1, "found externnotify: %s\n", externnotify);
13531       } else {
13532          externnotify[0] = '\0';
13533       }
13534 
13535       /* SMDI voicemail notification */
13536       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
13537          ast_debug(1, "Enabled SMDI voicemail notification\n");
13538          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
13539             smdi_iface = ast_smdi_interface_find(val);
13540          } else {
13541             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
13542             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
13543          }
13544          if (!smdi_iface) {
13545             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
13546          }
13547       }
13548 
13549       /* Silence treshold */
13550       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
13551       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
13552          silencethreshold = atoi(val);
13553 
13554       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
13555          val = ASTERISK_USERNAME;
13556       ast_copy_string(serveremail, val, sizeof(serveremail));
13557 
13558       vmmaxsecs = 0;
13559       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
13560          if (sscanf(val, "%30d", &x) == 1) {
13561             vmmaxsecs = x;
13562          } else {
13563             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
13564          }
13565       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
13566          static int maxmessage_deprecate = 0;
13567          if (maxmessage_deprecate == 0) {
13568             maxmessage_deprecate = 1;
13569             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
13570          }
13571          if (sscanf(val, "%30d", &x) == 1) {
13572             vmmaxsecs = x;
13573          } else {
13574             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
13575          }
13576       }
13577 
13578       vmminsecs = 0;
13579       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
13580          if (sscanf(val, "%30d", &x) == 1) {
13581             vmminsecs = x;
13582             if (maxsilence / 1000 >= vmminsecs) {
13583                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
13584             }
13585          } else {
13586             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
13587          }
13588       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
13589          static int maxmessage_deprecate = 0;
13590          if (maxmessage_deprecate == 0) {
13591             maxmessage_deprecate = 1;
13592             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
13593          }
13594          if (sscanf(val, "%30d", &x) == 1) {
13595             vmminsecs = x;
13596             if (maxsilence / 1000 >= vmminsecs) {
13597                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
13598             }
13599          } else {
13600             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
13601          }
13602       }
13603 
13604       val = ast_variable_retrieve(cfg, "general", "format");
13605       if (!val) {
13606          val = "wav";   
13607       } else {
13608          tmp = ast_strdupa(val);
13609          val = ast_format_str_reduce(tmp);
13610          if (!val) {
13611             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
13612             val = "wav";
13613          }
13614       }
13615       ast_copy_string(vmfmts, val, sizeof(vmfmts));
13616 
13617       skipms = 3000;
13618       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
13619          if (sscanf(val, "%30d", &x) == 1) {
13620             maxgreet = x;
13621          } else {
13622             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
13623          }
13624       }
13625 
13626       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
13627          if (sscanf(val, "%30d", &x) == 1) {
13628             skipms = x;
13629          } else {
13630             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
13631          }
13632       }
13633 
13634       maxlogins = 3;
13635       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
13636          if (sscanf(val, "%30d", &x) == 1) {
13637             maxlogins = x;
13638          } else {
13639             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
13640          }
13641       }
13642 
13643       minpassword = MINPASSWORD;
13644       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
13645          if (sscanf(val, "%30d", &x) == 1) {
13646             minpassword = x;
13647          } else {
13648             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
13649          }
13650       }
13651 
13652       /* Force new user to record name ? */
13653       if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
13654          val = "no";
13655       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
13656 
13657       /* Force new user to record greetings ? */
13658       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
13659          val = "no";
13660       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
13661 
13662       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
13663          ast_debug(1, "VM_CID Internal context string: %s\n", val);
13664          stringp = ast_strdupa(val);
13665          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
13666             if (!ast_strlen_zero(stringp)) {
13667                q = strsep(&stringp, ",");
13668                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
13669                   q++;
13670                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
13671                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
13672             } else {
13673                cidinternalcontexts[x][0] = '\0';
13674             }
13675          }
13676       }
13677       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
13678          ast_debug(1, "VM Review Option disabled globally\n");
13679          val = "no";
13680       }
13681       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW);
13682 
13683       /* Temporary greeting reminder */
13684       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
13685          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
13686          val = "no";
13687       } else {
13688          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
13689       }
13690       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
13691       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
13692          ast_debug(1, "VM next message wrap disabled globally\n");
13693          val = "no";
13694       }
13695       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);
13696 
13697       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
13698          ast_debug(1, "VM Operator break disabled globally\n");
13699          val = "no";
13700       }
13701       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);
13702 
13703       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
13704          ast_debug(1, "VM CID Info before msg disabled globally\n");
13705          val = "no";
13706       }
13707       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID);
13708 
13709       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
13710          ast_debug(1, "Send Voicemail msg disabled globally\n");
13711          val = "no";
13712       }
13713       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
13714 
13715       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
13716          ast_debug(1, "ENVELOPE before msg enabled globally\n");
13717          val = "yes";
13718       }
13719       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);
13720 
13721       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
13722          ast_debug(1, "Move Heard enabled globally\n");
13723          val = "yes";
13724       }
13725       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD);
13726 
13727       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
13728          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
13729          val = "no";
13730       }
13731       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);
13732 
13733       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
13734          ast_debug(1, "Duration info before msg enabled globally\n");
13735          val = "yes";
13736       }
13737       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);
13738 
13739       saydurationminfo = 2;
13740       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
13741          if (sscanf(val, "%30d", &x) == 1) {
13742             saydurationminfo = x;
13743          } else {
13744             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
13745          }
13746       }
13747 
13748       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
13749          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
13750          val = "no";
13751       }
13752       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
13753 
13754       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
13755          ast_copy_string(dialcontext, val, sizeof(dialcontext));
13756          ast_debug(1, "found dialout context: %s\n", dialcontext);
13757       } else {
13758          dialcontext[0] = '\0';
13759       }
13760 
13761       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
13762          ast_copy_string(callcontext, val, sizeof(callcontext));
13763          ast_debug(1, "found callback context: %s\n", callcontext);
13764       } else {
13765          callcontext[0] = '\0';
13766       }
13767 
13768       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
13769          ast_copy_string(exitcontext, val, sizeof(exitcontext));
13770          ast_debug(1, "found operator context: %s\n", exitcontext);
13771       } else {
13772          exitcontext[0] = '\0';
13773       }
13774 
13775       /* load password sounds configuration */
13776       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
13777          ast_copy_string(vm_password, val, sizeof(vm_password));
13778       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
13779          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
13780       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
13781          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
13782       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
13783          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
13784       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
13785          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
13786       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
13787          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
13788       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
13789          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
13790       }
13791       if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
13792          ast_copy_string(vm_prepend_timeout, val, sizeof(vm_prepend_timeout));
13793       }
13794       /* load configurable audio prompts */
13795       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
13796          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
13797       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
13798          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
13799       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
13800          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
13801       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
13802          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
13803       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
13804          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
13805 
13806       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
13807          val = "no";
13808       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
13809 
13810       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
13811          val = "voicemail.conf";
13812       }
13813       if (!(strcmp(val, "spooldir"))) {
13814          passwordlocation = OPT_PWLOC_SPOOLDIR;
13815       } else {
13816          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
13817       }
13818 
13819       poll_freq = DEFAULT_POLL_FREQ;
13820       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
13821          if (sscanf(val, "%30u", &poll_freq) != 1) {
13822             poll_freq = DEFAULT_POLL_FREQ;
13823             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
13824          }
13825       }
13826 
13827       poll_mailboxes = 0;
13828       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
13829          poll_mailboxes = ast_true(val);
13830 
13831       memset(fromstring, 0, sizeof(fromstring));
13832       memset(pagerfromstring, 0, sizeof(pagerfromstring));
13833       strcpy(charset, "ISO-8859-1");
13834       if (emailbody) {
13835          ast_free(emailbody);
13836          emailbody = NULL;
13837       }
13838       if (emailsubject) {
13839          ast_free(emailsubject);
13840          emailsubject = NULL;
13841       }
13842       if (pagerbody) {
13843          ast_free(pagerbody);
13844          pagerbody = NULL;
13845       }
13846       if (pagersubject) {
13847          ast_free(pagersubject);
13848          pagersubject = NULL;
13849       }
13850       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
13851          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
13852       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
13853          ast_copy_string(fromstring, val, sizeof(fromstring));
13854       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
13855          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
13856       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
13857          ast_copy_string(charset, val, sizeof(charset));
13858       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
13859          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
13860          for (x = 0; x < 4; x++) {
13861             memcpy(&adsifdn[x], &tmpadsi[x], 1);
13862          }
13863       }
13864       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
13865          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
13866          for (x = 0; x < 4; x++) {
13867             memcpy(&adsisec[x], &tmpadsi[x], 1);
13868          }
13869       }
13870       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
13871          if (atoi(val)) {
13872             adsiver = atoi(val);
13873          }
13874       }
13875       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
13876          ast_copy_string(zonetag, val, sizeof(zonetag));
13877       }
13878       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
13879          ast_copy_string(locale, val, sizeof(locale));
13880       }
13881       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
13882          emailsubject = ast_strdup(substitute_escapes(val));
13883       }
13884       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
13885          emailbody = ast_strdup(substitute_escapes(val));
13886       }
13887       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
13888          pagersubject = ast_strdup(substitute_escapes(val));
13889       }
13890       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
13891          pagerbody = ast_strdup(substitute_escapes(val));
13892       }
13893 
13894       /* load mailboxes from users.conf */
13895       if (ucfg) { 
13896          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
13897             if (!strcasecmp(cat, "general")) {
13898                continue;
13899             }
13900             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
13901                continue;
13902             if ((current = find_or_create(userscontext, cat))) {
13903                populate_defaults(current);
13904                apply_options_full(current, ast_variable_browse(ucfg, cat));
13905                ast_copy_string(current->context, userscontext, sizeof(current->context));
13906                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
13907                   current->passwordlocation = OPT_PWLOC_USERSCONF;
13908                }
13909 
13910                switch (current->passwordlocation) {
13911                case OPT_PWLOC_SPOOLDIR:
13912                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
13913                   read_password_from_file(secretfn, current->password, sizeof(current->password));
13914                }
13915             }
13916          }
13917       }
13918 
13919       /* load mailboxes from voicemail.conf */
13920       cat = ast_category_browse(cfg, NULL);
13921       while (cat) {
13922          if (strcasecmp(cat, "general")) {
13923             var = ast_variable_browse(cfg, cat);
13924             if (strcasecmp(cat, "zonemessages")) {
13925                /* Process mailboxes in this context */
13926                while (var) {
13927                   append_mailbox(cat, var->name, var->value);
13928                   var = var->next;
13929                }
13930             } else {
13931                /* Timezones in this context */
13932                while (var) {
13933                   struct vm_zone *z;
13934                   if ((z = ast_malloc(sizeof(*z)))) {
13935                      char *msg_format, *tzone;
13936                      msg_format = ast_strdupa(var->value);
13937                      tzone = strsep(&msg_format, "|,");
13938                      if (msg_format) {
13939                         ast_copy_string(z->name, var->name, sizeof(z->name));
13940                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
13941                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
13942                         AST_LIST_LOCK(&zones);
13943                         AST_LIST_INSERT_HEAD(&zones, z, list);
13944                         AST_LIST_UNLOCK(&zones);
13945                      } else {
13946                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
13947                         ast_free(z);
13948                      }
13949                   } else {
13950                      AST_LIST_UNLOCK(&users);
13951                      return -1;
13952                   }
13953                   var = var->next;
13954                }
13955             }
13956          }
13957          cat = ast_category_browse(cfg, cat);
13958       }
13959 
13960       AST_LIST_UNLOCK(&users);
13961 
13962       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
13963          start_poll_thread();
13964       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
13965          stop_poll_thread();;
13966 
13967       return 0;
13968    } else {
13969       AST_LIST_UNLOCK(&users);
13970       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
13971       return 0;
13972    }
13973 }

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

05299 {
05300    char tmpdir[256], newtmp[256];
05301    char fname[256];
05302    char tmpcmd[256];
05303    int tmpfd = -1;
05304    int soxstatus = 0;
05305 
05306    /* Eww. We want formats to tell us their own MIME type */
05307    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
05308 
05309    if (vmu->volgain < -.001 || vmu->volgain > .001) {
05310       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
05311       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
05312       tmpfd = mkstemp(newtmp);
05313       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
05314       ast_debug(3, "newtmp: %s\n", newtmp);
05315       if (tmpfd > -1) {
05316          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
05317          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
05318             attach = newtmp;
05319             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
05320          } else {
05321             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
05322                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
05323             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
05324          }
05325       }
05326    }
05327    fprintf(p, "--%s" ENDL, bound);
05328    if (msgnum > -1)
05329       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
05330    else
05331       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
05332    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
05333    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
05334    if (msgnum > -1)
05335       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
05336    else
05337       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
05338    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
05339    base_encode(fname, p);
05340    if (last)
05341       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
05342    if (tmpfd > -1) {
05343       if (soxstatus == 0) {
05344          unlink(fname);
05345       }
05346       close(tmpfd);
05347       unlink(newtmp);
05348    }
05349    return 0;
05350 }

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 11980 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_msg_id(), LOG_ERROR, LOG_WARNING, and UPDATE_MSG_ID.

Referenced by vm_msg_snapshot_create().

11981 {
11982    struct ast_variable *var;
11983    struct ast_category *cat;
11984    generate_msg_id(id);
11985 
11986    var = ast_variable_new("msg_id", id, "");
11987    if (!var) {
11988       return -1;
11989    }
11990 
11991    cat = ast_category_get(msg_cfg, "message", NULL);
11992    if (!cat) {
11993       ast_log(LOG_ERROR, "Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
11994       ast_variables_destroy(var);
11995       return -1;
11996    }
11997 
11998    ast_variable_append(cat, var);
11999 
12000    if (ast_config_text_file_save(filename, msg_cfg, "app_voicemail")) {
12001       ast_log(LOG_WARNING, "Unable to update %s to have a message ID\n", filename);
12002       return -1;
12003    }
12004 
12005    UPDATE_MSG_ID(dir, msg, id, vmu, msg_cfg, folder);
12006    return 0;
12007 }

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

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

07251 {
07252    int x;
07253    if (!ast_adsi_available(chan))
07254       return;
07255    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
07256    if (x < 0)
07257       return;
07258    if (!x) {
07259       if (adsi_load_vmail(chan, useadsi)) {
07260          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
07261          return;
07262       }
07263    } else
07264       *useadsi = 1;
07265 }

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

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

07447 {
07448    int bytes = 0;
07449    unsigned char buf[256];
07450    unsigned char keys[8];
07451 
07452    int x;
07453 
07454    if (!ast_adsi_available(chan))
07455       return;
07456 
07457    /* New meaning for keys */
07458    for (x = 0; x < 5; x++)
07459       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
07460 
07461    keys[6] = 0x0;
07462    keys[7] = 0x0;
07463 
07464    if (!vms->curmsg) {
07465       /* No prev key, provide "Folder" instead */
07466       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07467    }
07468    if (vms->curmsg >= vms->lastmsg) {
07469       /* If last message ... */
07470       if (vms->curmsg) {
07471          /* but not only message, provide "Folder" instead */
07472          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07473       } else {
07474          /* Otherwise if only message, leave blank */
07475          keys[3] = 1;
07476       }
07477    }
07478 
07479    /* If deleted, show "undeleted" */
07480 #ifdef IMAP_STORAGE
07481    ast_mutex_lock(&vms->lock);
07482 #endif
07483    if (vms->deleted[vms->curmsg]) {
07484       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
07485    }
07486 #ifdef IMAP_STORAGE
07487    ast_mutex_unlock(&vms->lock);
07488 #endif
07489 
07490    /* Except "Exit" */
07491    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
07492    bytes += ast_adsi_set_keys(buf + bytes, keys);
07493    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07494 
07495    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07496 }

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

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

07316 {
07317    unsigned char buf[256];
07318    int bytes = 0;
07319    unsigned char keys[8];
07320    int x, y;
07321 
07322    if (!ast_adsi_available(chan))
07323       return;
07324 
07325    for (x = 0; x < 5; x++) {
07326       y = ADSI_KEY_APPS + 12 + start + x;
07327       if (y > ADSI_KEY_APPS + 12 + 4)
07328          y = 0;
07329       keys[x] = ADSI_KEY_SKT | y;
07330    }
07331    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
07332    keys[6] = 0;
07333    keys[7] = 0;
07334 
07335    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
07336    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
07337    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07338    bytes += ast_adsi_set_keys(buf + bytes, keys);
07339    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07340 
07341    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07342 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

07602 {
07603    unsigned char buf[256];
07604    int bytes = 0;
07605 
07606    if (!ast_adsi_available(chan))
07607       return;
07608    bytes += adsi_logo(buf + bytes);
07609    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
07610    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
07611    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07612    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07613 
07614    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07615 }

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

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

07122 {
07123    unsigned char buf[256];
07124    int bytes = 0;
07125    int x;
07126    char num[5];
07127 
07128    *useadsi = 0;
07129    bytes += ast_adsi_data_mode(buf + bytes);
07130    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07131 
07132    bytes = 0;
07133    bytes += adsi_logo(buf);
07134    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
07135 #ifdef DISPLAY
07136    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
07137 #endif
07138    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07139    bytes += ast_adsi_data_mode(buf + bytes);
07140    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07141 
07142    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
07143       bytes = 0;
07144       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
07145       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
07146       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07147       bytes += ast_adsi_voice_mode(buf + bytes, 0);
07148       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07149       return 0;
07150    }
07151 
07152 #ifdef DISPLAY
07153    /* Add a dot */
07154    bytes = 0;
07155    bytes += ast_adsi_logo(buf);
07156    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
07157    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
07158    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07159    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07160 #endif
07161    bytes = 0;
07162    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
07163    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
07164    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
07165    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
07166    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
07167    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
07168    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07169 
07170 #ifdef DISPLAY
07171    /* Add another dot */
07172    bytes = 0;
07173    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
07174    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07175 
07176    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07177    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07178 #endif
07179 
07180    bytes = 0;
07181    /* These buttons we load but don't use yet */
07182    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
07183    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
07184    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
07185    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
07186    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
07187    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
07188    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07189 
07190 #ifdef DISPLAY
07191    /* Add another dot */
07192    bytes = 0;
07193    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
07194    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07195    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07196 #endif
07197 
07198    bytes = 0;
07199    for (x = 0; x < 5; x++) {
07200       snprintf(num, sizeof(num), "%d", x);
07201       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
07202    }
07203    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
07204    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07205 
07206 #ifdef DISPLAY
07207    /* Add another dot */
07208    bytes = 0;
07209    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
07210    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07211    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07212 #endif
07213 
07214    if (ast_adsi_end_download(chan)) {
07215       bytes = 0;
07216       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
07217       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
07218       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07219       bytes += ast_adsi_voice_mode(buf + bytes, 0);
07220       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07221       return 0;
07222    }
07223    bytes = 0;
07224    bytes += ast_adsi_download_disconnect(buf + bytes);
07225    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07226    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
07227 
07228    ast_debug(1, "Done downloading scripts...\n");
07229 
07230 #ifdef DISPLAY
07231    /* Add last dot */
07232    bytes = 0;
07233    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
07234    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07235 #endif
07236    ast_debug(1, "Restarting session...\n");
07237 
07238    bytes = 0;
07239    /* Load the session now */
07240    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
07241       *useadsi = 1;
07242       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
07243    } else
07244       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
07245 
07246    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07247    return 0;
07248 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

07268 {
07269    unsigned char buf[256];
07270    int bytes = 0;
07271    unsigned char keys[8];
07272    int x;
07273    if (!ast_adsi_available(chan))
07274       return;
07275 
07276    for (x = 0; x < 8; x++)
07277       keys[x] = 0;
07278    /* Set one key for next */
07279    keys[3] = ADSI_KEY_APPS + 3;
07280 
07281    bytes += adsi_logo(buf + bytes);
07282    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
07283    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
07284    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07285    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
07286    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
07287    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
07288    bytes += ast_adsi_set_keys(buf + bytes, keys);
07289    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07290    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07291 }

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

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

07114 {
07115    int bytes = 0;
07116    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
07117    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
07118    return bytes;
07119 }

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

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

07345 {
07346    int bytes = 0;
07347    unsigned char buf[256]; 
07348    char buf1[256], buf2[256];
07349    char fn2[PATH_MAX];
07350 
07351    char cid[256] = "";
07352    char *val;
07353    char *name, *num;
07354    char datetime[21] = "";
07355    FILE *f;
07356 
07357    unsigned char keys[8];
07358 
07359    int x;
07360 
07361    if (!ast_adsi_available(chan))
07362       return;
07363 
07364    /* Retrieve important info */
07365    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
07366    f = fopen(fn2, "r");
07367    if (f) {
07368       while (!feof(f)) {   
07369          if (!fgets((char *) buf, sizeof(buf), f)) {
07370             continue;
07371          }
07372          if (!feof(f)) {
07373             char *stringp = NULL;
07374             stringp = (char *) buf;
07375             strsep(&stringp, "=");
07376             val = strsep(&stringp, "=");
07377             if (!ast_strlen_zero(val)) {
07378                if (!strcmp((char *) buf, "callerid"))
07379                   ast_copy_string(cid, val, sizeof(cid));
07380                if (!strcmp((char *) buf, "origdate"))
07381                   ast_copy_string(datetime, val, sizeof(datetime));
07382             }
07383          }
07384       }
07385       fclose(f);
07386    }
07387    /* New meaning for keys */
07388    for (x = 0; x < 5; x++)
07389       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
07390    keys[6] = 0x0;
07391    keys[7] = 0x0;
07392 
07393    if (!vms->curmsg) {
07394       /* No prev key, provide "Folder" instead */
07395       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07396    }
07397    if (vms->curmsg >= vms->lastmsg) {
07398       /* If last message ... */
07399       if (vms->curmsg) {
07400          /* but not only message, provide "Folder" instead */
07401          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
07402          bytes += ast_adsi_voice_mode(buf + bytes, 0);
07403 
07404       } else {
07405          /* Otherwise if only message, leave blank */
07406          keys[3] = 1;
07407       }
07408    }
07409 
07410    if (!ast_strlen_zero(cid)) {
07411       ast_callerid_parse(cid, &name, &num);
07412       if (!name)
07413          name = num;
07414    } else {
07415       name = "Unknown Caller";
07416    }
07417 
07418    /* If deleted, show "undeleted" */
07419 #ifdef IMAP_STORAGE
07420    ast_mutex_lock(&vms->lock);
07421 #endif
07422    if (vms->deleted[vms->curmsg]) {
07423       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
07424    }
07425 #ifdef IMAP_STORAGE
07426    ast_mutex_unlock(&vms->lock);
07427 #endif
07428 
07429    /* Except "Exit" */
07430    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
07431    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
07432       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
07433    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
07434 
07435    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
07436    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
07437    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
07438    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
07439    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07440    bytes += ast_adsi_set_keys(buf + bytes, keys);
07441    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07442 
07443    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07444 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

07294 {
07295    unsigned char buf[256];
07296    int bytes = 0;
07297    unsigned char keys[8];
07298    int x;
07299    if (!ast_adsi_available(chan))
07300       return;
07301 
07302    for (x = 0; x < 8; x++)
07303       keys[x] = 0;
07304    /* Set one key for next */
07305    keys[3] = ADSI_KEY_APPS + 3;
07306 
07307    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07308    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
07309    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
07310    bytes += ast_adsi_set_keys(buf + bytes, keys);
07311    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07312    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07313 }

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

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

07499 {
07500    unsigned char buf[256] = "";
07501    char buf1[256] = "", buf2[256] = "";
07502    int bytes = 0;
07503    unsigned char keys[8];
07504    int x;
07505 
07506    char *newm = (vms->newmessages == 1) ? "message" : "messages";
07507    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
07508    if (!ast_adsi_available(chan))
07509       return;
07510    if (vms->newmessages) {
07511       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
07512       if (vms->oldmessages) {
07513          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
07514          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
07515       } else {
07516          snprintf(buf2, sizeof(buf2), "%s.", newm);
07517       }
07518    } else if (vms->oldmessages) {
07519       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
07520       snprintf(buf2, sizeof(buf2), "%s.", oldm);
07521    } else {
07522       strcpy(buf1, "You have no messages.");
07523       buf2[0] = ' ';
07524       buf2[1] = '\0';
07525    }
07526    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
07527    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
07528    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07529 
07530    for (x = 0; x < 6; x++)
07531       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
07532    keys[6] = 0;
07533    keys[7] = 0;
07534 
07535    /* Don't let them listen if there are none */
07536    if (vms->lastmsg < 0)
07537       keys[0] = 1;
07538    bytes += ast_adsi_set_keys(buf + bytes, keys);
07539 
07540    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07541 
07542    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07543 }

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

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

07546 {
07547    unsigned char buf[256] = "";
07548    char buf1[256] = "", buf2[256] = "";
07549    int bytes = 0;
07550    unsigned char keys[8];
07551    int x;
07552 
07553    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
07554 
07555    if (!ast_adsi_available(chan))
07556       return;
07557 
07558    /* Original command keys */
07559    for (x = 0; x < 6; x++)
07560       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
07561 
07562    keys[6] = 0;
07563    keys[7] = 0;
07564 
07565    if ((vms->lastmsg + 1) < 1)
07566       keys[0] = 0;
07567 
07568    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
07569       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
07570 
07571    if (vms->lastmsg + 1)
07572       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
07573    else
07574       strcpy(buf2, "no messages.");
07575    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
07576    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
07577    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
07578    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
07579    bytes += ast_adsi_set_keys(buf + bytes, keys);
07580 
07581    bytes += ast_adsi_voice_mode(buf + bytes, 0);
07582 
07583    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
07584    
07585 }

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 14838 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, 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, valid_config(), and wait_file().

Referenced by vm_execmain().

14839 {
14840    int res = 0;
14841    char filename[PATH_MAX];
14842    struct ast_config *msg_cfg = NULL;
14843    const char *origtime, *context;
14844    char *name, *num;
14845    int retries = 0;
14846    char *cid;
14847    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
14848 
14849    vms->starting = 0; 
14850 
14851    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
14852 
14853    /* Retrieve info from VM attribute file */
14854    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
14855    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
14856    msg_cfg = ast_config_load(filename, config_flags);
14857    DISPOSE(vms->curdir, vms->curmsg);
14858    if (!valid_config(msg_cfg)) {
14859       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
14860       return 0;
14861    }
14862 
14863    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
14864       ast_config_destroy(msg_cfg);
14865       return 0;
14866    }
14867 
14868    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
14869 
14870    context = ast_variable_retrieve(msg_cfg, "message", "context");
14871    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
14872       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
14873    switch (option) {
14874    case 3: /* Play message envelope */
14875       if (!res) {
14876          res = play_message_datetime(chan, vmu, origtime, filename);
14877       }
14878       if (!res) {
14879          res = play_message_callerid(chan, vms, cid, context, 0, 1);
14880       }
14881 
14882       res = 't';
14883       break;
14884 
14885    case 2:  /* Call back */
14886 
14887       if (ast_strlen_zero(cid))
14888          break;
14889 
14890       ast_callerid_parse(cid, &name, &num);
14891       while ((res > -1) && (res != 't')) {
14892          switch (res) {
14893          case '1':
14894             if (num) {
14895                /* Dial the CID number */
14896                res = dialout(chan, vmu, num, vmu->callback);
14897                if (res) {
14898                   ast_config_destroy(msg_cfg);
14899                   return 9;
14900                }
14901             } else {
14902                res = '2';
14903             }
14904             break;
14905 
14906          case '2':
14907             /* Want to enter a different number, can only do this if there's a dialout context for this user */
14908             if (!ast_strlen_zero(vmu->dialout)) {
14909                res = dialout(chan, vmu, NULL, vmu->dialout);
14910                if (res) {
14911                   ast_config_destroy(msg_cfg);
14912                   return 9;
14913                }
14914             } else {
14915                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
14916                res = ast_play_and_wait(chan, "vm-sorry");
14917             }
14918             ast_config_destroy(msg_cfg);
14919             return res;
14920          case '*':
14921             res = 't';
14922             break;
14923          case '3':
14924          case '4':
14925          case '5':
14926          case '6':
14927          case '7':
14928          case '8':
14929          case '9':
14930          case '0':
14931 
14932             res = ast_play_and_wait(chan, "vm-sorry");
14933             retries++;
14934             break;
14935          default:
14936             if (num) {
14937                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
14938                res = ast_play_and_wait(chan, "vm-num-i-have");
14939                if (!res)
14940                   res = play_message_callerid(chan, vms, num, vmu->context, 1, 1);
14941                if (!res)
14942                   res = ast_play_and_wait(chan, "vm-tocallnum");
14943                /* Only prompt for a caller-specified number if there is a dialout context specified */
14944                if (!ast_strlen_zero(vmu->dialout)) {
14945                   if (!res)
14946                      res = ast_play_and_wait(chan, "vm-calldiffnum");
14947                }
14948             } else {
14949                res = ast_play_and_wait(chan, "vm-nonumber");
14950                if (!ast_strlen_zero(vmu->dialout)) {
14951                   if (!res)
14952                      res = ast_play_and_wait(chan, "vm-toenternumber");
14953                }
14954             }
14955             if (!res) {
14956                res = ast_play_and_wait(chan, "vm-star-cancel");
14957             }
14958             if (!res) {
14959                res = ast_waitfordigit(chan, 6000);
14960             }
14961             if (!res) {
14962                retries++;
14963                if (retries > 3) {
14964                   res = 't';
14965                }
14966             }
14967             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
14968             break; 
14969             
14970          }
14971          if (res == 't')
14972             res = 0;
14973          else if (res == '*')
14974             res = -1;
14975       }
14976       break;
14977       
14978    case 1:  /* Reply */
14979       /* Send reply directly to sender */
14980       if (ast_strlen_zero(cid))
14981          break;
14982 
14983       ast_callerid_parse(cid, &name, &num);
14984       if (!num) {
14985          ast_verb(3, "No CID number available, no reply sent\n");
14986          if (!res)
14987             res = ast_play_and_wait(chan, "vm-nonumber");
14988          ast_config_destroy(msg_cfg);
14989          return res;
14990       } else {
14991          struct ast_vm_user vmu2;
14992          if (find_user(&vmu2, vmu->context, num)) {
14993             struct leave_vm_options leave_options;
14994             char mailbox[AST_MAX_EXTENSION * 2 + 2];
14995             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
14996 
14997             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
14998             
14999             memset(&leave_options, 0, sizeof(leave_options));
15000             leave_options.record_gain = record_gain;
15001             res = leave_voicemail(chan, mailbox, &leave_options);
15002             if (!res)
15003                res = 't';
15004             ast_config_destroy(msg_cfg);
15005             return res;
15006          } else {
15007             /* Sender has no mailbox, can't reply */
15008             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
15009             ast_play_and_wait(chan, "vm-nobox");
15010             res = 't';
15011             ast_config_destroy(msg_cfg);
15012             return res;
15013          }
15014       } 
15015       res = 0;
15016 
15017       break;
15018    }
15019 
15020    ast_config_destroy(msg_cfg);
15021 
15022 #ifndef IMAP_STORAGE
15023    if (!res) {
15024       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
15025       vms->heard[msg] = 1;
15026       res = wait_file(chan, vms, vms->fn);
15027    }
15028 #endif
15029    return res;
15030 }

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

Definition at line 12049 of file app_voicemail.c.

References apply_options(), ast_alloca, ast_copy_string(), ast_log, ast_strdup, 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().

12050 {
12051    /* Assumes lock is already held */
12052    char *tmp;
12053    char *stringp;
12054    char *s;
12055    struct ast_vm_user *vmu;
12056    char *mailbox_full;
12057    int new = 0, old = 0, urgent = 0;
12058    char secretfn[PATH_MAX] = "";
12059 
12060    tmp = ast_strdupa(data);
12061 
12062    if (!(vmu = find_or_create(context, box)))
12063       return -1;
12064 
12065    populate_defaults(vmu);
12066 
12067    stringp = tmp;
12068    if ((s = strsep(&stringp, ","))) {
12069       if (!ast_strlen_zero(s) && s[0] == '*') {
12070          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
12071             "\n\tmust be reset in voicemail.conf.\n", box);
12072       }
12073       /* assign password regardless of validity to prevent NULL password from being assigned */
12074       ast_copy_string(vmu->password, s, sizeof(vmu->password));
12075    }
12076    if (stringp && (s = strsep(&stringp, ","))) {
12077       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
12078    }
12079    if (stringp && (s = strsep(&stringp, ","))) {
12080       vmu->email = ast_strdup(s);
12081    }
12082    if (stringp && (s = strsep(&stringp, ","))) {
12083       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
12084    }
12085    if (stringp && (s = strsep(&stringp, ","))) {
12086       apply_options(vmu, s);
12087    }
12088 
12089    switch (vmu->passwordlocation) {
12090    case OPT_PWLOC_SPOOLDIR:
12091       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
12092       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
12093    }
12094 
12095    mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
12096    strcpy(mailbox_full, box);
12097    strcat(mailbox_full, "@");
12098    strcat(mailbox_full, context);
12099 
12100    inboxcount2(mailbox_full, &urgent, &new, &old);
12101    queue_mwi_event(NULL, mailbox_full, urgent, new, old);
12102 
12103    return 0;
12104 }

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

01301 {
01302    int x;
01303    if (!strcasecmp(var, "attach")) {
01304       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01305    } else if (!strcasecmp(var, "attachfmt")) {
01306       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01307    } else if (!strcasecmp(var, "serveremail")) {
01308       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01309    } else if (!strcasecmp(var, "emailbody")) {
01310       ast_free(vmu->emailbody);
01311       vmu->emailbody = ast_strdup(substitute_escapes(value));
01312    } else if (!strcasecmp(var, "emailsubject")) {
01313       ast_free(vmu->emailsubject);
01314       vmu->emailsubject = ast_strdup(substitute_escapes(value));
01315    } else if (!strcasecmp(var, "language")) {
01316       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01317    } else if (!strcasecmp(var, "tz")) {
01318       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01319    } else if (!strcasecmp(var, "locale")) {
01320       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01321 #ifdef IMAP_STORAGE
01322    } else if (!strcasecmp(var, "imapuser")) {
01323       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01324       vmu->imapversion = imapversion;
01325    } else if (!strcasecmp(var, "imapserver")) {
01326       ast_copy_string(vmu->imapserver, value, sizeof(vmu->imapserver));
01327       vmu->imapversion = imapversion;
01328    } else if (!strcasecmp(var, "imapport")) {
01329       ast_copy_string(vmu->imapport, value, sizeof(vmu->imapport));
01330       vmu->imapversion = imapversion;
01331    } else if (!strcasecmp(var, "imapflags")) {
01332       ast_copy_string(vmu->imapflags, value, sizeof(vmu->imapflags));
01333       vmu->imapversion = imapversion;
01334    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01335       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01336       vmu->imapversion = imapversion;
01337    } else if (!strcasecmp(var, "imapfolder")) {
01338       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01339       vmu->imapversion = imapversion;
01340    } else if (!strcasecmp(var, "imapvmshareid")) {
01341       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01342       vmu->imapversion = imapversion;
01343 #endif
01344    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01345       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01346    } else if (!strcasecmp(var, "saycid")){
01347       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01348    } else if (!strcasecmp(var, "sendvoicemail")){
01349       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01350    } else if (!strcasecmp(var, "review")){
01351       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01352    } else if (!strcasecmp(var, "tempgreetwarn")){
01353       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01354    } else if (!strcasecmp(var, "messagewrap")){
01355       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01356    } else if (!strcasecmp(var, "operator")) {
01357       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01358    } else if (!strcasecmp(var, "envelope")){
01359       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01360    } else if (!strcasecmp(var, "moveheard")){
01361       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01362    } else if (!strcasecmp(var, "sayduration")){
01363       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01364    } else if (!strcasecmp(var, "saydurationm")){
01365       if (sscanf(value, "%30d", &x) == 1) {
01366          vmu->saydurationm = x;
01367       } else {
01368          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01369       }
01370    } else if (!strcasecmp(var, "forcename")){
01371       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01372    } else if (!strcasecmp(var, "forcegreetings")){
01373       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01374    } else if (!strcasecmp(var, "callback")) {
01375       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01376    } else if (!strcasecmp(var, "dialout")) {
01377       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01378    } else if (!strcasecmp(var, "exitcontext")) {
01379       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01380    } else if (!strcasecmp(var, "minsecs")) {
01381       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01382          vmu->minsecs = x;
01383       } else {
01384          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01385          vmu->minsecs = vmminsecs;
01386       }
01387    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01388       vmu->maxsecs = atoi(value);
01389       if (vmu->maxsecs <= 0) {
01390          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01391          vmu->maxsecs = vmmaxsecs;
01392       } else {
01393          vmu->maxsecs = atoi(value);
01394       }
01395       if (!strcasecmp(var, "maxmessage"))
01396          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01397    } else if (!strcasecmp(var, "maxmsg")) {
01398       vmu->maxmsg = atoi(value);
01399       /* Accept maxmsg=0 (Greetings only voicemail) */
01400       if (vmu->maxmsg < 0) {
01401          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01402          vmu->maxmsg = MAXMSG;
01403       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01404          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01405          vmu->maxmsg = MAXMSGLIMIT;
01406       }
01407    } else if (!strcasecmp(var, "nextaftercmd")) {
01408       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01409    } else if (!strcasecmp(var, "backupdeleted")) {
01410       if (sscanf(value, "%30d", &x) == 1)
01411          vmu->maxdeletedmsg = x;
01412       else if (ast_true(value))
01413          vmu->maxdeletedmsg = MAXMSG;
01414       else
01415          vmu->maxdeletedmsg = 0;
01416 
01417       if (vmu->maxdeletedmsg < 0) {
01418          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01419          vmu->maxdeletedmsg = MAXMSG;
01420       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01421          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01422          vmu->maxdeletedmsg = MAXMSGLIMIT;
01423       }
01424    } else if (!strcasecmp(var, "volgain")) {
01425       sscanf(value, "%30lf", &vmu->volgain);
01426    } else if (!strcasecmp(var, "passwordlocation")) {
01427       if (!strcasecmp(value, "spooldir")) {
01428          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01429       } else {
01430          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01431       }
01432    } else if (!strcasecmp(var, "options")) {
01433       apply_options(vmu, value);
01434    }
01435 }

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

Destructively Parse options and apply.

Definition at line 1553 of file app_voicemail.c.

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

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

01554 {  
01555    char *stringp;
01556    char *s;
01557    char *var, *value;
01558    stringp = ast_strdupa(options);
01559    while ((s = strsep(&stringp, "|"))) {
01560       value = s;
01561       if ((var = strsep(&value, "=")) && value) {
01562          apply_option(vmu, var, value);
01563       }
01564    }  
01565 }

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

01573 {
01574    for (; var; var = var->next) {
01575       if (!strcasecmp(var->name, "vmsecret")) {
01576          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01577       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01578          if (ast_strlen_zero(retval->password)) {
01579             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01580                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01581                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01582             } else {
01583                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01584             }
01585          }
01586       } else if (!strcasecmp(var->name, "uniqueid")) {
01587          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01588       } else if (!strcasecmp(var->name, "pager")) {
01589          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01590       } else if (!strcasecmp(var->name, "email")) {
01591          ast_free(retval->email);
01592          retval->email = ast_strdup(var->value);
01593       } else if (!strcasecmp(var->name, "fullname")) {
01594          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01595       } else if (!strcasecmp(var->name, "context")) {
01596          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01597       } else if (!strcasecmp(var->name, "emailsubject")) {
01598          ast_free(retval->emailsubject);
01599          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01600       } else if (!strcasecmp(var->name, "emailbody")) {
01601          ast_free(retval->emailbody);
01602          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01603 #ifdef IMAP_STORAGE
01604       } else if (!strcasecmp(var->name, "imapuser")) {
01605          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01606          retval->imapversion = imapversion;
01607       } else if (!strcasecmp(var->name, "imapserver")) {
01608          ast_copy_string(retval->imapserver, var->value, sizeof(retval->imapserver));
01609          retval->imapversion = imapversion;
01610       } else if (!strcasecmp(var->name, "imapport")) {
01611          ast_copy_string(retval->imapport, var->value, sizeof(retval->imapport));
01612          retval->imapversion = imapversion;
01613       } else if (!strcasecmp(var->name, "imapflags")) {
01614          ast_copy_string(retval->imapflags, var->value, sizeof(retval->imapflags));
01615          retval->imapversion = imapversion;
01616       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01617          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01618          retval->imapversion = imapversion;
01619       } else if (!strcasecmp(var->name, "imapfolder")) {
01620          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01621          retval->imapversion = imapversion;
01622       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01623          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01624          retval->imapversion = imapversion;
01625 #endif
01626       } else
01627          apply_option(retval, var->name, var->value);
01628    }
01629 }

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

04947 {
04948    struct ast_str *tmp = ast_str_alloca(80);
04949    int first_section = 1;
04950 
04951    ast_str_reset(*end);
04952    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04953    for (; *start; start++) {
04954       int need_encoding = 0;
04955       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04956          need_encoding = 1;
04957       }
04958       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04959          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04960          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04961          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04962          /* Start new line */
04963          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04964          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04965          first_section = 0;
04966       }
04967       if (need_encoding && *start == ' ') {
04968          ast_str_append(&tmp, -1, "_");
04969       } else if (need_encoding) {
04970          ast_str_append(&tmp, -1, "=%hhX", *start);
04971       } else {
04972          ast_str_append(&tmp, -1, "%c", *start);
04973       }
04974    }
04975    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04976    return ast_str_buffer(*end);
04977 }

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

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

04875 {
04876    const char *ptr;
04877 
04878    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04879    ast_str_set(buf, maxlen, "\"");
04880    for (ptr = from; *ptr; ptr++) {
04881       if (*ptr == '"' || *ptr == '\\') {
04882          ast_str_append(buf, maxlen, "\\%c", *ptr);
04883       } else {
04884          ast_str_append(buf, maxlen, "%c", *ptr);
04885       }
04886    }
04887    ast_str_append(buf, maxlen, "\"");
04888 
04889    return ast_str_buffer(*buf);
04890 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

12107 {
12108    int res = 0;
12109    struct ast_vm_user *vmu;
12110    /* language parameter seems to only be used for display in manager action */
12111    static const char options_string[] = "attach=yes|attachfmt=wav49|"
12112       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
12113       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
12114       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
12115       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
12116       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
12117       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
12118       "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
12119       "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
12120 #ifdef IMAP_STORAGE
12121    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
12122       "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
12123 #endif
12124 
12125    switch (cmd) {
12126    case TEST_INIT:
12127       info->name = "vmuser";
12128       info->category = "/apps/app_voicemail/";
12129       info->summary = "Vmuser unit test";
12130       info->description =
12131          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
12132       return AST_TEST_NOT_RUN;
12133    case TEST_EXECUTE:
12134       break;
12135    }
12136 
12137    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
12138       return AST_TEST_NOT_RUN;
12139    }
12140    populate_defaults(vmu);
12141    ast_set_flag(vmu, VM_ALLOCED);
12142 
12143    apply_options(vmu, options_string);
12144 
12145    if (!ast_test_flag(vmu, VM_ATTACH)) {
12146       ast_test_status_update(test, "Parse failure for attach option\n");
12147       res = 1;
12148    }
12149    if (strcasecmp(vmu->attachfmt, "wav49")) {
12150       ast_test_status_update(test, "Parse failure for attachftm option\n");
12151       res = 1;
12152    }
12153    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
12154       ast_test_status_update(test, "Parse failure for serveremail option\n");
12155       res = 1;
12156    }
12157    if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
12158       ast_test_status_update(test, "Parse failure for emailsubject option\n");
12159       res = 1;
12160    }
12161    if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
12162       ast_test_status_update(test, "Parse failure for emailbody option\n");
12163       res = 1;
12164    }
12165    if (strcasecmp(vmu->zonetag, "central")) {
12166       ast_test_status_update(test, "Parse failure for tz option\n");
12167       res = 1;
12168    }
12169    if (!ast_test_flag(vmu, VM_DELETE)) {
12170       ast_test_status_update(test, "Parse failure for delete option\n");
12171       res = 1;
12172    }
12173    if (!ast_test_flag(vmu, VM_SAYCID)) {
12174       ast_test_status_update(test, "Parse failure for saycid option\n");
12175       res = 1;
12176    }
12177    if (!ast_test_flag(vmu, VM_SVMAIL)) {
12178       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
12179       res = 1;
12180    }
12181    if (!ast_test_flag(vmu, VM_REVIEW)) {
12182       ast_test_status_update(test, "Parse failure for review option\n");
12183       res = 1;
12184    }
12185    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
12186       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
12187       res = 1;
12188    }
12189    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
12190       ast_test_status_update(test, "Parse failure for messagewrap option\n");
12191       res = 1;
12192    }
12193    if (!ast_test_flag(vmu, VM_OPERATOR)) {
12194       ast_test_status_update(test, "Parse failure for operator option\n");
12195       res = 1;
12196    }
12197    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
12198       ast_test_status_update(test, "Parse failure for envelope option\n");
12199       res = 1;
12200    }
12201    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
12202       ast_test_status_update(test, "Parse failure for moveheard option\n");
12203       res = 1;
12204    }
12205    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
12206       ast_test_status_update(test, "Parse failure for sayduration option\n");
12207       res = 1;
12208    }
12209    if (vmu->saydurationm != 5) {
12210       ast_test_status_update(test, "Parse failure for saydurationm option\n");
12211       res = 1;
12212    }
12213    if (!ast_test_flag(vmu, VM_FORCENAME)) {
12214       ast_test_status_update(test, "Parse failure for forcename option\n");
12215       res = 1;
12216    }
12217    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
12218       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
12219       res = 1;
12220    }
12221    if (strcasecmp(vmu->callback, "somecontext")) {
12222       ast_test_status_update(test, "Parse failure for callbacks option\n");
12223       res = 1;
12224    }
12225    if (strcasecmp(vmu->dialout, "somecontext2")) {
12226       ast_test_status_update(test, "Parse failure for dialout option\n");
12227       res = 1;
12228    }
12229    if (strcasecmp(vmu->exit, "somecontext3")) {
12230       ast_test_status_update(test, "Parse failure for exitcontext option\n");
12231       res = 1;
12232    }
12233    if (vmu->minsecs != 10) {
12234       ast_test_status_update(test, "Parse failure for minsecs option\n");
12235       res = 1;
12236    }
12237    if (vmu->maxsecs != 100) {
12238       ast_test_status_update(test, "Parse failure for maxsecs option\n");
12239       res = 1;
12240    }
12241    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
12242       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
12243       res = 1;
12244    }
12245    if (vmu->maxdeletedmsg != 50) {
12246       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
12247       res = 1;
12248    }
12249    if (vmu->volgain != 1.3) {
12250       ast_test_status_update(test, "Parse failure for volgain option\n");
12251       res = 1;
12252    }
12253    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
12254       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
12255       res = 1;
12256    }
12257 #ifdef IMAP_STORAGE
12258    apply_options(vmu, option_string2);
12259 
12260    if (strcasecmp(vmu->imapuser, "imapuser")) {
12261       ast_test_status_update(test, "Parse failure for imapuser option\n");
12262       res = 1;
12263    }
12264    if (strcasecmp(vmu->imappassword, "imappasswd")) {
12265       ast_test_status_update(test, "Parse failure for imappasswd option\n");
12266       res = 1;
12267    }
12268    if (strcasecmp(vmu->imapfolder, "INBOX")) {
12269       ast_test_status_update(test, "Parse failure for imapfolder option\n");
12270       res = 1;
12271    }
12272    if (strcasecmp(vmu->imapvmshareid, "6000")) {
12273       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
12274       res = 1;
12275    }
12276    if (strcasecmp(vmu->imapserver, "imapserver")) {
12277       ast_test_status_update(test, "Parse failure for imapserver option\n");
12278       res = 1;
12279    }
12280    if (strcasecmp(vmu->imapport, "1234")) {
12281       ast_test_status_update(test, "Parse failure for imapport option\n");
12282       res = 1;
12283    }
12284    if (strcasecmp(vmu->imapflags, "flagged")) {
12285       ast_test_status_update(test, "Parse failure for imapflags option\n");
12286       res = 1;
12287    }
12288 #endif
12289 
12290    free_user(vmu);
12291    return res ? AST_TEST_FAIL : AST_TEST_PASS;
12292 }

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

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

04753 {
04754    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04755       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04756       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04757       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04758    int i, hiteof = 0;
04759    FILE *fi;
04760    struct baseio bio;
04761 
04762    memset(&bio, 0, sizeof(bio));
04763    bio.iocp = BASEMAXINLINE;
04764 
04765    if (!(fi = fopen(filename, "rb"))) {
04766       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04767       return -1;
04768    }
04769 
04770    while (!hiteof){
04771       unsigned char igroup[3], ogroup[4];
04772       int c, n;
04773 
04774       memset(igroup, 0, sizeof(igroup));
04775 
04776       for (n = 0; n < 3; n++) {
04777          if ((c = inchar(&bio, fi)) == EOF) {
04778             hiteof = 1;
04779             break;
04780          }
04781 
04782          igroup[n] = (unsigned char) c;
04783       }
04784 
04785       if (n > 0) {
04786          ogroup[0]= dtable[igroup[0] >> 2];
04787          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04788          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04789          ogroup[3]= dtable[igroup[2] & 0x3F];
04790 
04791          if (n < 3) {
04792             ogroup[3] = '=';
04793 
04794             if (n < 2)
04795                ogroup[2] = '=';
04796          }
04797 
04798          for (i = 0; i < 4; i++)
04799             ochar(&bio, ogroup[i], so);
04800       }
04801    }
04802 
04803    fclose(fi);
04804    
04805    if (fputs(ENDL, so) == EOF) {
04806       return 0;
04807    }
04808 
04809    return 1;
04810 }

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

01532 {
01533    int res = -1;
01534    if (!strcmp(vmu->password, password)) {
01535       /* No change (but an update would return 0 rows updated, so we opt out here) */
01536       return 0;
01537    }
01538 
01539    if (strlen(password) > 10) {
01540       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01541    }
01542    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01543       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01544       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01545       res = 0;
01546    }
01547    return res;
01548 }

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

04920 {
04921    for (; *str; str++) {
04922       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04923          return 1;
04924       }
04925    }
04926    return 0;
04927 }

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

References ast_debug, ast_log, AST_LOG_NOTICE, AST_LOG_WARNING, ast_strlen_zero, buf, 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().

01491 {
01492    /* check minimum length */
01493    if (strlen(password) < minpassword)
01494       return 1;
01495    /* check that password does not contain '*' character */
01496    if (!ast_strlen_zero(password) && password[0] == '*')
01497       return 1;
01498    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01499       char cmd[255], buf[255];
01500 
01501       ast_debug(1, "Verify password policies for %s\n", password);
01502 
01503       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01504       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01505          ast_debug(5, "Result: %s\n", buf);
01506          if (!strncasecmp(buf, "VALID", 5)) {
01507             ast_debug(3, "Passed password check: '%s'\n", buf);
01508             return 0;
01509          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01510             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01511             return 0;
01512          } else {
01513             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01514             return 1;
01515          }
01516       }
01517    }
01518    return 0;
01519 }

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

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

08879 {
08880    int x = 0;
08881    int last_msg_idx = 0;
08882 
08883 #ifndef IMAP_STORAGE
08884    int res = 0, nummsg;
08885    char fn2[PATH_MAX];
08886 #endif
08887 
08888    if (vms->lastmsg <= -1) {
08889       goto done;
08890    }
08891 
08892    vms->curmsg = -1;
08893 #ifndef IMAP_STORAGE
08894    /* Get the deleted messages fixed */
08895    if (vm_lock_path(vms->curdir)) {
08896       return ERROR_LOCK_PATH;
08897    }
08898 
08899    /* update count as message may have arrived while we've got mailbox open */
08900    last_msg_idx = last_message_index(vmu, vms->curdir);
08901    if (last_msg_idx != vms->lastmsg) {
08902       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
08903    }
08904 
08905    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
08906    for (x = 0; x < last_msg_idx + 1; x++) {
08907       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
08908          /* Save this message.  It's not in INBOX or hasn't been heard */
08909          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08910          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
08911             break;
08912          }
08913          vms->curmsg++;
08914          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
08915          if (strcmp(vms->fn, fn2)) {
08916             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
08917          }
08918       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
08919          /* Move to old folder before deleting */
08920          res = save_to_folder(vmu, vms, x, 1, NULL, 0);
08921          if (res == ERROR_LOCK_PATH) {
08922             /* If save failed do not delete the message */
08923             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08924             vms->deleted[x] = 0;
08925             vms->heard[x] = 0;
08926             --x;
08927          }
08928       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08929          /* Move to deleted folder */
08930          res = save_to_folder(vmu, vms, x, 10, NULL, 0);
08931          if (res == ERROR_LOCK_PATH) {
08932             /* If save failed do not delete the message */
08933             vms->deleted[x] = 0;
08934             vms->heard[x] = 0;
08935             --x;
08936          }
08937       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08938          /* If realtime storage enabled - we should explicitly delete this message,
08939          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08940          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08941          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08942             DELETE(vms->curdir, x, vms->fn, vmu);
08943          }
08944       }
08945    }
08946 
08947    /* Delete ALL remaining messages */
08948    nummsg = x - 1;
08949    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08950       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08951       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08952          DELETE(vms->curdir, x, vms->fn, vmu);
08953       }
08954    }
08955    ast_unlock_path(vms->curdir);
08956 #else /* defined(IMAP_STORAGE) */
08957    ast_mutex_lock(&vms->lock);
08958    if (vms->deleted) {
08959       /* Since we now expunge after each delete, deleting in reverse order
08960        * ensures that no reordering occurs between each step. */
08961       last_msg_idx = vms->dh_arraysize;
08962       for (x = last_msg_idx - 1; x >= 0; x--) {
08963          if (vms->deleted[x]) {
08964             ast_debug(3, "IMAP delete of %d\n", x);
08965             DELETE(vms->curdir, x, vms->fn, vmu);
08966          }
08967       }
08968    }
08969 #endif
08970 
08971 done:
08972    if (vms->deleted) {
08973       ast_free(vms->deleted);
08974       vms->deleted = NULL;
08975    }
08976    if (vms->heard) {
08977       ast_free(vms->heard);
08978       vms->heard = NULL;
08979    }
08980    vms->dh_arraysize = 0;
08981 #ifdef IMAP_STORAGE
08982    ast_mutex_unlock(&vms->lock);
08983 #endif
08984 
08985    return 0;
08986 }

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

Definition at line 12525 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

12526 {
12527    int which = 0;
12528    int wordlen;
12529    struct ast_vm_user *vmu;
12530    const char *context = "";
12531 
12532    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
12533    if (pos > 4)
12534       return NULL;
12535    if (pos == 3)
12536       return (state == 0) ? ast_strdup("for") : NULL;
12537    wordlen = strlen(word);
12538    AST_LIST_TRAVERSE(&users, vmu, list) {
12539       if (!strncasecmp(word, vmu->context, wordlen)) {
12540          if (context && strcmp(context, vmu->context) && ++which > state)
12541             return ast_strdup(vmu->context);
12542          /* ignore repeated contexts ? */
12543          context = vmu->context;
12544       }
12545    }
12546    return NULL;
12547 }

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

References ast_log, AST_LOG_WARNING, errno, and VOICEMAIL_FILE_MODE.

Referenced by add_supplements(), ast_bucket_file_copy(), ast_func_read(), ast_func_read2(), ast_func_write(), ast_sip_for_each_aor(), ast_sip_sanitize_xml(), ast_sorcery_copy(), AST_TEST_DEFINE(), authenticate_api_key(), check_nonce(), config_hook_exec(), copy_plain_file(), filehelper(), iax2_register(), parse_hint_device(), parse_hint_presence(), and vm_forwardoptions().

04558 {
04559    int ifd;
04560    int ofd;
04561    int res;
04562    int len;
04563    char buf[4096];
04564 
04565 #ifdef HARDLINK_WHEN_POSSIBLE
04566    /* Hard link if possible; saves disk space & is faster */
04567    if (link(infile, outfile)) {
04568 #endif
04569       if ((ifd = open(infile, O_RDONLY)) < 0) {
04570          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04571          return -1;
04572       }
04573       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04574          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04575          close(ifd);
04576          return -1;
04577       }
04578       do {
04579          len = read(ifd, buf, sizeof(buf));
04580          if (len < 0) {
04581             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04582             close(ifd);
04583             close(ofd);
04584             unlink(outfile);
04585          } else if (len) {
04586             res = write(ofd, buf, len);
04587             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04588                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04589                close(ifd);
04590                close(ofd);
04591                unlink(outfile);
04592             }
04593          }
04594       } while (len);
04595       close(ifd);
04596       close(ofd);
04597       return 0;
04598 #ifdef HARDLINK_WHEN_POSSIBLE
04599    } else {
04600       /* Hard link succeeded */
04601       return 0;
04602    }
04603 #endif
04604 }

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

05841 {
05842    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05843    const char *frombox = mbox(vmu, imbox);
05844    const char *userfolder;
05845    int recipmsgnum;
05846    int res = 0;
05847 
05848    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05849 
05850    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05851       userfolder = "Urgent";
05852    } else if (!ast_strlen_zero(dest_folder)) {
05853       userfolder = dest_folder;
05854    } else {
05855       userfolder = "INBOX";
05856    }
05857 
05858    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05859 
05860    if (!dir)
05861       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05862    else
05863       ast_copy_string(fromdir, dir, sizeof(fromdir));
05864 
05865    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05866    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05867 
05868    if (vm_lock_path(todir))
05869       return ERROR_LOCK_PATH;
05870 
05871    recipmsgnum = last_message_index(recip, todir) + 1;
05872    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05873       make_file(topath, sizeof(topath), todir, recipmsgnum);
05874 #ifndef ODBC_STORAGE
05875       if (EXISTS(fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : "")) {
05876          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05877       } else {
05878 #endif
05879          /* If we are prepending a message for ODBC, then the message already
05880           * exists in the database, but we want to force copying from the
05881           * filesystem (since only the FS contains the prepend). */
05882          copy_plain_file(frompath, topath);
05883          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL);
05884          vm_delete(topath);
05885 #ifndef ODBC_STORAGE
05886       }
05887 #endif
05888    } else {
05889       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05890       res = -1;
05891    }
05892    ast_unlock_path(todir);
05893    if (chan) {
05894       struct ast_party_caller *caller = ast_channel_caller(chan);
05895       notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05896          S_COR(caller->id.number.valid, caller->id.number.str, NULL),
05897          S_COR(caller->id.name.valid, caller->id.name.str, NULL),
05898          flag);
05899    }
05900 
05901    return res;
05902 }

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

04616 {
04617    char frompath2[PATH_MAX], topath2[PATH_MAX];
04618    struct ast_variable *tmp,*var = NULL;
04619    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04620    ast_filecopy(frompath, topath, NULL);
04621    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04622    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04623    if (ast_check_realtime("voicemail_data")) {
04624       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04625       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04626       for (tmp = var; tmp; tmp = tmp->next) {
04627          if (!strcasecmp(tmp->name, "origmailbox")) {
04628             origmailbox = tmp->value;
04629          } else if (!strcasecmp(tmp->name, "context")) {
04630             context = tmp->value;
04631          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04632             macrocontext = tmp->value;
04633          } else if (!strcasecmp(tmp->name, "exten")) {
04634             exten = tmp->value;
04635          } else if (!strcasecmp(tmp->name, "priority")) {
04636             priority = tmp->value;
04637          } else if (!strcasecmp(tmp->name, "callerchan")) {
04638             callerchan = tmp->value;
04639          } else if (!strcasecmp(tmp->name, "callerid")) {
04640             callerid = tmp->value;
04641          } else if (!strcasecmp(tmp->name, "origdate")) {
04642             origdate = tmp->value;
04643          } else if (!strcasecmp(tmp->name, "origtime")) {
04644             origtime = tmp->value;
04645          } else if (!strcasecmp(tmp->name, "category")) {
04646             category = tmp->value;
04647          } else if (!strcasecmp(tmp->name, "duration")) {
04648             duration = tmp->value;
04649          }
04650       }
04651       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);
04652    }
04653    copy(frompath2, topath2);
04654    ast_variables_destroy(var);
04655 }

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

04453 {
04454 
04455    int vmcount = 0;
04456    DIR *vmdir = NULL;
04457    struct dirent *vment = NULL;
04458 
04459    if (vm_lock_path(dir))
04460       return ERROR_LOCK_PATH;
04461 
04462    if ((vmdir = opendir(dir))) {
04463       while ((vment = readdir(vmdir))) {
04464          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
04465             vmcount++;
04466          }
04467       }
04468       closedir(vmdir);
04469    }
04470    ast_unlock_path(dir);
04471    
04472    return vmcount;
04473 }

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

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

01967 {
01968    mode_t   mode = VOICEMAIL_DIR_MODE;
01969    int res;
01970 
01971    make_dir(dest, len, context, ext, folder);
01972    if ((res = ast_mkdir(dest, mode))) {
01973       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01974       return -1;
01975    }
01976    return 0;
01977 }

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

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

14768 {
14769    int cmd = 0;
14770    char destination[80] = "";
14771    int retries = 0;
14772 
14773    if (!num) {
14774       ast_verb(3, "Destination number will be entered manually\n");
14775       while (retries < 3 && cmd != 't') {
14776          destination[1] = '\0';
14777          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
14778          if (!cmd)
14779             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
14780          if (!cmd)
14781             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
14782          if (!cmd) {
14783             cmd = ast_waitfordigit(chan, 6000);
14784             if (cmd)
14785                destination[0] = cmd;
14786          }
14787          if (!cmd) {
14788             retries++;
14789          } else {
14790 
14791             if (cmd < 0)
14792                return 0;
14793             if (cmd == '*') {
14794                ast_verb(3, "User hit '*' to cancel outgoing call\n");
14795                return 0;
14796             }
14797             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
14798                retries++;
14799             else
14800                cmd = 't';
14801          }
14802          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
14803       }
14804       if (retries >= 3) {
14805          return 0;
14806       }
14807       
14808    } else {
14809       ast_verb(3, "Destination number is CID number '%s'\n", num);
14810       ast_copy_string(destination, num, sizeof(destination));
14811    }
14812 
14813    if (!ast_strlen_zero(destination)) {
14814       if (destination[strlen(destination) -1 ] == '*')
14815          return 0; 
14816       ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, ast_channel_context(chan));
14817       ast_channel_exten_set(chan, destination);
14818       ast_channel_context_set(chan, outgoing_context);
14819       ast_channel_priority_set(chan, 0);
14820       return 9;
14821    }
14822    return 0;
14823 }

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

Definition at line 12998 of file app_voicemail.c.

References mwi_event_cb().

Referenced by start_poll_thread().

12999 {
13000    struct stasis_message *msg = obj;
13001    mwi_event_cb(NULL, NULL, msg);
13002    return 0;
13003 }

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

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

12010 {
12011    struct ast_vm_user *vmu;
12012 
12013    if (!ast_strlen_zero(box) && box[0] == '*') {
12014       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
12015             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
12016             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
12017             "\n\tand will be ignored.\n", box, context);
12018       return NULL;
12019    }
12020 
12021    AST_LIST_TRAVERSE(&users, vmu, list) {
12022       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
12023          if (strcasecmp(vmu->context, context)) {
12024             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
12025                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
12026                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
12027                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
12028          }
12029          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
12030          return NULL;
12031       }
12032       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
12033          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
12034          return NULL;
12035       }
12036    }
12037    
12038    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
12039       return NULL;
12040    
12041    ast_copy_string(vmu->context, context, sizeof(vmu->context));
12042    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
12043 
12044    AST_LIST_INSERT_TAIL(&users, vmu, list);
12045    
12046    return vmu;
12047 }

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 1704 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::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, find_user_realtime(), globalflags, NULL, VM_ALLOCED, and VM_SEARCH.

01705 {
01706    /* This function could be made to generate one from a database, too */
01707    struct ast_vm_user *vmu = NULL, *cur;
01708    AST_LIST_LOCK(&users);
01709 
01710    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01711       context = "default";
01712 
01713    AST_LIST_TRAVERSE(&users, cur, list) {
01714 #ifdef IMAP_STORAGE
01715       if (cur->imapversion != imapversion) {
01716          continue;
01717       }
01718 #endif
01719       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01720          break;
01721       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01722          break;
01723    }
01724    if (cur) {
01725       /* Make a copy, so that on a reload, we have no race */
01726       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01727          *vmu = *cur;
01728          if (!ivm) {
01729             vmu->email = ast_strdup(cur->email);
01730             vmu->emailbody = ast_strdup(cur->emailbody);
01731             vmu->emailsubject = ast_strdup(cur->emailsubject);
01732          }
01733          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01734          AST_LIST_NEXT(vmu, list) = NULL;
01735       }
01736    } else
01737       vmu = find_user_realtime(ivm, context, mailbox);
01738    AST_LIST_UNLOCK(&users);
01739    return vmu;
01740 }

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 1663 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, NULL, populate_defaults(), retval, SENTINEL, var, VM_ALLOCED, and VM_SEARCH.

01664 {
01665    struct ast_variable *var;
01666    struct ast_vm_user *retval;
01667 
01668    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01669       if (ivm) {
01670          memset(retval, 0, sizeof(*retval));
01671       }
01672       populate_defaults(retval);
01673       if (!ivm) {
01674          ast_set_flag(retval, VM_ALLOCED);
01675       }
01676       if (mailbox) {
01677          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01678       }
01679       if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
01680          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01681       } else {
01682          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01683       }
01684       if (var) {
01685          apply_options_full(retval, var);
01686          ast_variables_destroy(var);
01687       } else { 
01688          if (!ivm) 
01689             ast_free(retval);
01690          retval = NULL;
01691       }  
01692    } 
01693    return retval;
01694 }

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):

  • retrieves 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 8050 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().

08051 {
08052 #ifdef IMAP_STORAGE
08053    int todircount = 0;
08054    struct vm_state *dstvms;
08055 #endif
08056    char username[70]="";
08057    char fn[PATH_MAX]; /* for playback of name greeting */
08058    char ecodes[16] = "#";
08059    int res = 0, cmd = 0;
08060    struct ast_vm_user *receiver = NULL, *vmtmp;
08061    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
08062    char *stringp;
08063    const char *s;
08064    int saved_messages = 0;
08065    int valid_extensions = 0;
08066    char *dir;
08067    int curmsg;
08068    char urgent_str[7] = "";
08069    int prompt_played = 0;
08070 #ifndef IMAP_STORAGE
08071    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
08072 #endif
08073    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
08074       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
08075    }
08076 
08077    if (vms == NULL) return -1;
08078    dir = vms->curdir;
08079    curmsg = vms->curmsg;
08080 
08081    ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
08082    while (!res && !valid_extensions) {
08083       int use_directory = 0;
08084       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
08085          int done = 0;
08086          int retries = 0;
08087          cmd = 0;
08088          while ((cmd >= 0) && !done ){
08089             if (cmd)
08090                retries = 0;
08091             switch (cmd) {
08092             case '1': 
08093                use_directory = 0;
08094                done = 1;
08095                break;
08096             case '2': 
08097                use_directory = 1;
08098                done = 1;
08099                break;
08100             case '*': 
08101                cmd = 't';
08102                done = 1;
08103                break;
08104             default: 
08105                /* Press 1 to enter an extension press 2 to use the directory */
08106                cmd = ast_play_and_wait(chan, "vm-forward");
08107                if (!cmd) {
08108                   cmd = ast_waitfordigit(chan, 3000);
08109                }
08110                if (!cmd) {
08111                   retries++;
08112                }
08113                if (retries > 3) {
08114                   cmd = 't';
08115                   done = 1;
08116                }
08117                ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
08118             }
08119          }
08120          if (cmd < 0 || cmd == 't')
08121             break;
08122       }
08123 
08124       if (use_directory) {
08125          /* use app_directory */
08126 
08127          struct ast_app* directory_app;
08128 
08129          directory_app = pbx_findapp("Directory");
08130          if (directory_app) {
08131             char vmcontext[256];
08132             char *old_context;
08133             char *old_exten;
08134             int old_priority;
08135             /* make backup copies */
08136             old_context = ast_strdupa(ast_channel_context(chan));
08137             old_exten = ast_strdupa(ast_channel_exten(chan));
08138             old_priority = ast_channel_priority(chan);
08139 
08140             /* call the the Directory, changes the channel */
08141             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
08142             res = pbx_exec(chan, directory_app, vmcontext);
08143 
08144             ast_copy_string(username, ast_channel_exten(chan), sizeof(username));
08145 
08146             /* restore the old context, exten, and priority */
08147             ast_channel_context_set(chan, old_context);
08148             ast_channel_exten_set(chan, old_exten);
08149             ast_channel_priority_set(chan, old_priority);
08150          } else {
08151             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
08152             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
08153          }
08154       } else {
08155          /* Ask for an extension */
08156          res = ast_streamfile(chan, "vm-extension", ast_channel_language(chan)); /* "extension" */
08157          prompt_played++;
08158          if (res || prompt_played > 4)
08159             break;
08160          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#")) < 0)
08161             break;
08162       }
08163 
08164       /* start all over if no username */
08165       if (ast_strlen_zero(username))
08166          continue;
08167       stringp = username;
08168       s = strsep(&stringp, "*");
08169       /* start optimistic */
08170       valid_extensions = 1;
08171       while (s) {
08172          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
08173             int oldmsgs;
08174             int newmsgs;
08175             int capacity;
08176             if (inboxcount(s, &newmsgs, &oldmsgs)) {
08177                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
08178                /* Shouldn't happen, but allow trying another extension if it does */
08179                res = ast_play_and_wait(chan, "pbx-invalid");
08180                valid_extensions = 0;
08181                break;
08182             }
08183             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
08184             if ((newmsgs + oldmsgs) >= capacity) {
08185                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
08186                res = ast_play_and_wait(chan, "vm-mailboxfull");
08187                valid_extensions = 0;
08188                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
08189                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
08190                   free_user(vmtmp);
08191                }
08192                inprocess_count(receiver->mailbox, receiver->context, -1);
08193                break;
08194             }
08195             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
08196          } else {
08197             /* XXX Optimization for the future.  When we encounter a single bad extension,
08198              * bailing out on all of the extensions may not be the way to go.  We should
08199              * probably just bail on that single extension, then allow the user to enter
08200              * several more. XXX
08201              */
08202             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
08203                free_user(receiver);
08204             }
08205             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
08206             /* "I am sorry, that's not a valid extension.  Please try again." */
08207             res = ast_play_and_wait(chan, "pbx-invalid");
08208             valid_extensions = 0;
08209             break;
08210          }
08211 
08212          /* play name if available, else play extension number */
08213          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
08214          RETRIEVE(fn, -1, s, receiver->context);
08215          if (ast_fileexists(fn, NULL, NULL) > 0) {
08216             res = ast_stream_and_wait(chan, fn, ecodes);
08217             if (res) {
08218                DISPOSE(fn, -1);
08219                return res;
08220             }
08221          } else {
08222             res = ast_say_digit_str(chan, s, ecodes, ast_channel_language(chan));
08223          }
08224          DISPOSE(fn, -1);
08225 
08226          s = strsep(&stringp, "*");
08227       }
08228       /* break from the loop of reading the extensions */
08229       if (valid_extensions)
08230          break;
08231    }
08232    /* check if we're clear to proceed */
08233    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
08234       return res;
08235    if (is_new_message == 1) {
08236       struct leave_vm_options leave_options;
08237       char mailbox[AST_MAX_EXTENSION * 2 + 2];
08238       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
08239 
08240       /* Send VoiceMail */
08241       memset(&leave_options, 0, sizeof(leave_options));
08242       leave_options.record_gain = record_gain;
08243       cmd = leave_voicemail(chan, mailbox, &leave_options);
08244    } else {
08245       /* Forward VoiceMail */
08246       long duration = 0;
08247       struct vm_state vmstmp;
08248       int copy_msg_result = 0;
08249 #ifdef IMAP_STORAGE
08250       char filename[PATH_MAX];
08251       struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
08252       const char *msg_id = NULL;
08253       struct ast_config *msg_cfg;
08254 #endif
08255       memcpy(&vmstmp, vms, sizeof(vmstmp));
08256 
08257       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
08258 #ifdef IMAP_STORAGE
08259       make_file(filename, sizeof(filename), dir, curmsg);
08260       strncat(filename, ".txt", sizeof(filename) - strlen(filename) - 1);
08261       msg_cfg = ast_config_load(filename, config_flags);
08262       if (msg_cfg && msg_cfg == CONFIG_STATUS_FILEINVALID) {
08263          msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
08264          ast_config_destroy(msg_cfg);
08265       }
08266 #endif
08267 
08268       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
08269       if (!cmd) {
08270          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
08271 #ifdef IMAP_STORAGE
08272             int attach_user_voicemail;
08273             char *myserveremail = serveremail;
08274             
08275             /* get destination mailbox */
08276             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
08277             if (!dstvms) {
08278                dstvms = create_vm_state_from_user(vmtmp);
08279             }
08280             if (dstvms) {
08281                init_mailstream(dstvms, 0);
08282                if (!dstvms->mailstream) {
08283                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
08284                } else {
08285                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
08286                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
08287                }
08288             } else {
08289                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
08290             }
08291             if (!ast_strlen_zero(vmtmp->serveremail))
08292                myserveremail = vmtmp->serveremail;
08293             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
08294             /* NULL category for IMAP storage */
08295             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
08296                dstvms->curbox,
08297                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
08298                S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
08299                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
08300                NULL, urgent_str, msg_id);
08301 #else
08302             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL);
08303 #endif
08304             saved_messages++;
08305             AST_LIST_REMOVE_CURRENT(list);
08306             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
08307             free_user(vmtmp);
08308             if (res)
08309                break;
08310          }
08311          AST_LIST_TRAVERSE_SAFE_END;
08312          if (saved_messages > 0 && !copy_msg_result) {
08313             /* give confirmation that the message was saved */
08314             /* commented out since we can't forward batches yet
08315             if (saved_messages == 1)
08316                res = ast_play_and_wait(chan, "vm-message");
08317             else
08318                res = ast_play_and_wait(chan, "vm-messages");
08319             if (!res)
08320                res = ast_play_and_wait(chan, "vm-saved"); */
08321 #ifdef IMAP_STORAGE
08322             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
08323             if (ast_strlen_zero(vmstmp.introfn))
08324 #endif
08325             res = ast_play_and_wait(chan, "vm-msgforwarded");
08326          }
08327 #ifndef IMAP_STORAGE
08328          else {
08329             /* with IMAP, mailbox full warning played by imap_check_limits */
08330             res = ast_play_and_wait(chan, "vm-mailboxfull");
08331          }
08332          /* Restore original message without prepended message if backup exists */
08333          make_file(msgfile, sizeof(msgfile), dir, curmsg);
08334          strcpy(textfile, msgfile);
08335          strcpy(backup, msgfile);
08336          strcpy(backup_textfile, msgfile);
08337          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
08338          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
08339          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
08340          if (ast_fileexists(backup, NULL, NULL) > 0) {
08341             ast_filerename(backup, msgfile, NULL);
08342             rename(backup_textfile, textfile);
08343          }
08344 #endif
08345       }
08346       DISPOSE(dir, curmsg);
08347 #ifndef IMAP_STORAGE
08348       if (cmd) { /* assuming hangup, cleanup backup file */
08349          make_file(msgfile, sizeof(msgfile), dir, curmsg);
08350          strcpy(textfile, msgfile);
08351          strcpy(backup_textfile, msgfile);
08352          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
08353          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
08354          rename(backup_textfile, textfile);
08355       }
08356 #endif
08357    }
08358 
08359    /* If anything failed above, we still have this list to free */
08360    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
08361       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
08362       free_user(vmtmp);
08363    }
08364    return res ? res : cmd;
08365 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 2008 of file app_voicemail.c.

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

02009 {
02010    if (ast_test_flag(vmu, VM_ALLOCED)) {
02011 
02012       ast_free(vmu->email);
02013       vmu->email = NULL;
02014 
02015       ast_free(vmu->emailbody);
02016       vmu->emailbody = NULL;
02017 
02018       ast_free(vmu->emailsubject);
02019       vmu->emailsubject = NULL;
02020 
02021       ast_free(vmu);
02022    }
02023 }

static void free_vm_users ( void   )  [static]

Free the users structure.

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

13192 {
13193    struct ast_vm_user *current;
13194    AST_LIST_LOCK(&users);
13195    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
13196       ast_set_flag(current, VM_ALLOCED);
13197       free_user(current);
13198    }
13199    AST_LIST_UNLOCK(&users);
13200 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

13204 {
13205    struct vm_zone *zcur;
13206    AST_LIST_LOCK(&zones);
13207    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
13208       free_zone(zcur);
13209    AST_LIST_UNLOCK(&zones);
13210 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5602 of file app_voicemail.c.

References ast_free.

05603 {
05604    ast_free(z);
05605 }

static void generate_msg_id ( char *  dst  )  [static]

Sets the destination string to a uniquely identifying msg_id string.

Parameters:
dst pointer to a character buffer that should contain MSG_ID_LEN characters.

Definition at line 6113 of file app_voicemail.c.

References ast_atomic_fetchadd_int(), msg_id_incrementor, and MSG_ID_LEN.

Referenced by add_message_id(), leave_voicemail(), and msg_create_from_file().

06114 {
06115    /* msg id is time of msg_id generation plus an incrementing value
06116     * called each time a new msg_id is generated. This should achieve uniqueness,
06117     * but only in single system solutions.
06118     */
06119    unsigned int unique_counter = ast_atomic_fetchadd_int(&msg_id_incrementor, +1);
06120    snprintf(dst, MSG_ID_LEN, "%ld-%08x", (long) time(NULL), unique_counter);
06121 }

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

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

05559 {
05560    struct ast_tm tm;
05561    struct timeval t = ast_tvnow();
05562 
05563    ast_localtime(&t, &tm, "UTC");
05564 
05565    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05566 }

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 7621 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(), d, mbox(), and vm_play_folder_name().

Referenced by get_folder2().

07622 {
07623    int x;
07624    int d;
07625    char fn[PATH_MAX];
07626    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
07627    if (d)
07628       return d;
07629    for (x = start; x < 5; x++) { /* For all folders */
07630       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
07631          return d;
07632       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
07633       if (d)
07634          return d;
07635       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
07636 
07637       /* The inbox folder can have its name changed under certain conditions
07638        * so this checks if the sound file exists for the inbox folder name and
07639        * if it doesn't, plays the default name instead. */
07640       if (x == 0) {
07641          if (ast_fileexists(fn, NULL, NULL)) {
07642             d = vm_play_folder_name(chan, fn);
07643          } else {
07644             ast_verb(4, "Failed to find file %s; falling back to INBOX\n", fn);
07645             d = vm_play_folder_name(chan, "vm-INBOX");
07646          }
07647       } else {
07648          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
07649          d = vm_play_folder_name(chan, fn);
07650       }
07651 
07652       if (d)
07653          return d;
07654       d = ast_waitfordigit(chan, 500);
07655       if (d)
07656          return d;
07657    }
07658 
07659    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
07660    if (d)
07661       return d;
07662    d = ast_waitfordigit(chan, 4000);
07663    return d;
07664 }

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

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

Referenced by vm_execmain().

07707 {
07708    int res = 0;
07709    int loops = 0;
07710 
07711    res = ast_play_and_wait(chan, fn);  /* Folder name */
07712    while (((res < '0') || (res > '9')) &&
07713          (res != '#') && (res >= 0) &&
07714          loops < 4) {
07715                 /* res = get_folder(chan, 0); */
07716                 if (!strcasecmp(ast_channel_language(chan),"ja")) {   /* Japanese syntax */
07717                       res = get_folder_ja(chan, 0);
07718                 } else { /* Default syntax */
07719             res = get_folder(chan, 0);
07720       }
07721       loops++;
07722    }
07723    if (loops == 4) { /* give up */
07724       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
07725       return '#';
07726    }
07727    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07728    return res;
07729 }

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

Definition at line 1995 of file app_voicemail.c.

References ARRAY_LEN.

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

01996 {
01997    size_t i;
01998 
01999    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
02000       if (strcasecmp(name, mailbox_folders[i]) == 0) {
02001          return i;
02002       }
02003    }
02004 
02005    return -1;
02006 }

static int get_folder_ja ( struct ast_channel chan,
int  start 
) [static]

Definition at line 7667 of file app_voicemail.c.

References ast_channel_language(), AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_waitfordigit(), d, mbox(), and vm_play_folder_name().

Referenced by get_folder2().

07668 {
07669         int x;
07670         int d;
07671         char fn[256];
07672         for (x = start; x< 5; x++) {    /* For all folders */
07673                 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL))) {
07674                         return d;
07675       }
07676       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));     /* Folder name */
07677       d = vm_play_folder_name(chan, fn);
07678       if (d) {
07679                         return d;
07680       }
07681                 d = ast_waitfordigit(chan, 500);
07682                 if (d) {
07683                         return d;
07684       }
07685         }
07686         d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
07687         if (d) {
07688                 return d;
07689    }
07690         d = ast_waitfordigit(chan, 4000);
07691         return d;
07692 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 12907 of file app_voicemail.c.

References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_strlen_zero, mwi_sub_task::context, mwi_sub::mailbox, mwi_sub_task::mailbox, mwi_sub_task_dtor(), poll_subscribed_mailbox(), mwi_sub_task::uniqueid, and mwi_sub::uniqueid.

Referenced by mwi_sub_event_cb().

12908 {
12909    unsigned int len;
12910    struct mwi_sub *mwi_sub;
12911    struct mwi_sub_task *p = datap;
12912 
12913    len = sizeof(*mwi_sub);
12914    if (!ast_strlen_zero(p->mailbox))
12915       len += strlen(p->mailbox);
12916 
12917    if (!ast_strlen_zero(p->context))
12918       len += strlen(p->context) + 1; /* Allow for seperator */
12919 
12920    if (!(mwi_sub = ast_calloc(1, len)))
12921       return -1;
12922 
12923    mwi_sub->uniqueid = ast_strdup(p->uniqueid);
12924    if (!ast_strlen_zero(p->mailbox))
12925       strcpy(mwi_sub->mailbox, p->mailbox);
12926 
12927    if (!ast_strlen_zero(p->context)) {
12928       strcat(mwi_sub->mailbox, "@");
12929       strcat(mwi_sub->mailbox, p->context);
12930    }
12931 
12932    AST_RWLIST_WRLOCK(&mwi_subs);
12933    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
12934    AST_RWLIST_UNLOCK(&mwi_subs);
12935    mwi_sub_task_dtor(p);
12936    poll_subscribed_mailbox(mwi_sub);
12937    return 0;
12938 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

Referenced by mwi_unsub_event_cb().

12887 {
12888    struct mwi_sub *mwi_sub;
12889    char *uniqueid = datap;
12890 
12891    AST_RWLIST_WRLOCK(&mwi_subs);
12892    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
12893       if (!strcmp(mwi_sub->uniqueid, uniqueid)) {
12894          AST_LIST_REMOVE_CURRENT(entry);
12895          /* Don't break here since a duplicate uniqueid
12896           * may have been added as a result of a cache dump. */
12897          mwi_sub_destroy(mwi_sub);
12898       }
12899    }
12900    AST_RWLIST_TRAVERSE_SAFE_END
12901    AST_RWLIST_UNLOCK(&mwi_subs);
12902 
12903    ast_free(uniqueid);
12904    return 0;
12905 }

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

12663 {
12664    switch (cmd) {
12665    case CLI_INIT:
12666       e->command = "voicemail reload";
12667       e->usage =
12668          "Usage: voicemail reload\n"
12669          "       Reload voicemail configuration\n";
12670       return NULL;
12671    case CLI_GENERATE:
12672       return NULL;
12673    }
12674 
12675    if (a->argc != 2)
12676       return CLI_SHOWUSAGE;
12677 
12678    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
12679    load_config(1);
12680    
12681    return CLI_SUCCESS;
12682 }

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

12551 {
12552    struct ast_vm_user *vmu;
12553 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
12554    const char *context = NULL;
12555    int users_counter = 0;
12556 
12557    switch (cmd) {
12558    case CLI_INIT:
12559       e->command = "voicemail show users";
12560       e->usage =
12561          "Usage: voicemail show users [for <context>]\n"
12562          "       Lists all mailboxes currently set up\n";
12563       return NULL;
12564    case CLI_GENERATE:
12565       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
12566    }  
12567 
12568    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
12569       return CLI_SHOWUSAGE;
12570    if (a->argc == 5) {
12571       if (strcmp(a->argv[3],"for"))
12572          return CLI_SHOWUSAGE;
12573       context = a->argv[4];
12574    }
12575 
12576    if (ast_check_realtime("voicemail")) {
12577       if (!context) {
12578          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
12579          return CLI_SHOWUSAGE;
12580       }
12581       return show_users_realtime(a->fd, context);
12582    }
12583 
12584    AST_LIST_LOCK(&users);
12585    if (AST_LIST_EMPTY(&users)) {
12586       ast_cli(a->fd, "There are no voicemail users currently defined\n");
12587       AST_LIST_UNLOCK(&users);
12588       return CLI_FAILURE;
12589    }
12590    if (!context) {
12591       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
12592    } else {
12593       int count = 0;
12594       AST_LIST_TRAVERSE(&users, vmu, list) {
12595          if (!strcmp(context, vmu->context)) {
12596             count++;
12597             break;
12598          }
12599       }
12600       if (count) {
12601          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
12602       } else {
12603          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
12604          AST_LIST_UNLOCK(&users);
12605          return CLI_FAILURE;
12606       }
12607    }
12608    AST_LIST_TRAVERSE(&users, vmu, list) {
12609       int newmsgs = 0, oldmsgs = 0;
12610       char count[12], tmp[256] = "";
12611 
12612       if (!context || !strcmp(context, vmu->context)) {
12613          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
12614          inboxcount(tmp, &newmsgs, &oldmsgs);
12615          snprintf(count, sizeof(count), "%d", newmsgs);
12616          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
12617          users_counter++;
12618       }
12619    }
12620    AST_LIST_UNLOCK(&users);
12621    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
12622    return CLI_SUCCESS;
12623 }

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

12627 {
12628    struct vm_zone *zone;
12629 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
12630    char *res = CLI_SUCCESS;
12631 
12632    switch (cmd) {
12633    case CLI_INIT:
12634       e->command = "voicemail show zones";
12635       e->usage =
12636          "Usage: voicemail show zones\n"
12637          "       Lists zone message formats\n";
12638       return NULL;
12639    case CLI_GENERATE:
12640       return NULL;
12641    }
12642 
12643    if (a->argc != 3)
12644       return CLI_SHOWUSAGE;
12645 
12646    AST_LIST_LOCK(&zones);
12647    if (!AST_LIST_EMPTY(&zones)) {
12648       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
12649       AST_LIST_TRAVERSE(&zones, zone, list) {
12650          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
12651       }
12652    } else {
12653       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
12654       res = CLI_FAILURE;
12655    }
12656    AST_LIST_UNLOCK(&zones);
12657 
12658    return res;
12659 }

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.
Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 5965 of file app_voicemail.c.

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

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

05966 {
05967    char tmp[256], *tmp2 = tmp, *box, *context;
05968    ast_copy_string(tmp, mailbox, sizeof(tmp));
05969    if (ast_strlen_zero(folder)) {
05970       folder = "INBOX";
05971    }
05972    while ((box = strsep(&tmp2, ",&"))) {
05973       if ((context = strchr(box, '@')))
05974          *context++ = '\0';
05975       else
05976          context = "default";
05977       if (__has_voicemail(context, box, folder, 1))
05978          return 1;
05979       /* If we are checking INBOX, we should check Urgent as well */
05980       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05981          return 1;
05982       }
05983    }
05984    return 0;
05985 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 6047 of file app_voicemail.c.

References inboxcount2().

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

06048 {
06049    int urgentmsgs = 0;
06050    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
06051    if (newmsgs) {
06052       *newmsgs += urgentmsgs;
06053    }
06054    return res;
06055 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 5988 of file app_voicemail.c.

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

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

05989 {
05990    char tmp[256];
05991    char *context;
05992 
05993    /* If no mailbox, return immediately */
05994    if (ast_strlen_zero(mailbox))
05995       return 0;
05996 
05997    if (newmsgs)
05998       *newmsgs = 0;
05999    if (oldmsgs)
06000       *oldmsgs = 0;
06001    if (urgentmsgs)
06002       *urgentmsgs = 0;
06003 
06004    if (strchr(mailbox, ',')) {
06005       int tmpnew, tmpold, tmpurgent;
06006       char *mb, *cur;
06007 
06008       ast_copy_string(tmp, mailbox, sizeof(tmp));
06009       mb = tmp;
06010       while ((cur = strsep(&mb, ", "))) {
06011          if (!ast_strlen_zero(cur)) {
06012             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
06013                return -1;
06014             else {
06015                if (newmsgs)
06016                   *newmsgs += tmpnew; 
06017                if (oldmsgs)
06018                   *oldmsgs += tmpold;
06019                if (urgentmsgs)
06020                   *urgentmsgs += tmpurgent;
06021             }
06022          }
06023       }
06024       return 0;
06025    }
06026 
06027    ast_copy_string(tmp, mailbox, sizeof(tmp));
06028    
06029    if ((context = strchr(tmp, '@')))
06030       *context++ = '\0';
06031    else
06032       context = "default";
06033 
06034    if (newmsgs)
06035       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
06036    if (oldmsgs)
06037       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
06038    if (urgentmsgs)
06039       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
06040 
06041    return 0;
06042 }

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

utility used by inchar(), for base_encode()

Definition at line 4687 of file app_voicemail.c.

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

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

04688 {
04689    int l;
04690 
04691    if (bio->ateof)
04692       return 0;
04693 
04694    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04695       if (ferror(fi))
04696          return -1;
04697 
04698       bio->ateof = 1;
04699       return 0;
04700    }
04701 
04702    bio->iolen = l;
04703    bio->iocp = 0;
04704 
04705    return 1;
04706 }

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

utility used by base_encode()

Definition at line 4711 of file app_voicemail.c.

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

Referenced by base_encode().

04712 {
04713    if (bio->iocp>=bio->iolen) {
04714       if (!inbuf(bio, fi))
04715          return EOF;
04716    }
04717 
04718    return bio->iobuf[bio->iocp++];
04719 }

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

Definition at line 1174 of file app_voicemail.c.

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

Referenced by load_module().

01175 {
01176    struct inprocess *i = obj, *j = arg;
01177    if (strcmp(i->mailbox, j->mailbox)) {
01178       return 0;
01179    }
01180    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
01181 }

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

Definition at line 1183 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, inprocess::mailbox, and NULL.

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

01184 {
01185    struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
01186    arg->context = arg->mailbox + strlen(mailbox) + 1;
01187    strcpy(arg->mailbox, mailbox); /* SAFE */
01188    strcpy(arg->context, context); /* SAFE */
01189    ao2_lock(inprocess_container);
01190    if ((i = ao2_find(inprocess_container, arg, 0))) {
01191       int ret = ast_atomic_fetchadd_int(&i->count, delta);
01192       ao2_unlock(inprocess_container);
01193       ao2_ref(i, -1);
01194       return ret;
01195    }
01196    if (delta < 0) {
01197       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
01198    }
01199    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
01200       ao2_unlock(inprocess_container);
01201       return 0;
01202    }
01203    i->context = i->mailbox + strlen(mailbox) + 1;
01204    strcpy(i->mailbox, mailbox); /* SAFE */
01205    strcpy(i->context, context); /* SAFE */
01206    i->count = delta;
01207    ao2_link(inprocess_container, i);
01208    ao2_unlock(inprocess_container);
01209    ao2_ref(i, -1);
01210    return 0;
01211 }

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