Tue Aug 20 16:34:45 2013

Asterisk developer's documentation


app_voicemail_imapstorage.c File Reference

Comedian Mail - Voicemail System. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <time.h>
#include <dirent.h>
#include "asterisk/logger.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/adsi.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/dsp.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/stringfields.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj2.h"
#include "asterisk/event.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"

Go to the source code of this file.

Data Structures

struct  ast_vm_user
struct  baseio
struct  inprocess
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  mwi_sub
 An MWI subscription. More...
struct  mwi_sub_task
struct  vm_state
struct  vm_zone

Defines

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

Enumerations

enum  vm_box {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER, NEW_FOLDER, OLD_FOLDER,
  WORK_FOLDER, FAMILY_FOLDER, FRIENDS_FOLDER, GREETINGS_FOLDER,
  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,
  OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3,
  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), 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), 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, OPT_PWLOC_VOICEMAILCONF = 0,
  OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2, OPT_PWLOC_VOICEMAILCONF = 0, OPT_PWLOC_SPOOLDIR = 1,
  OPT_PWLOC_USERSCONF = 2
}

Functions

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

Variables

static 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 char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_check_cmd [128]
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
struct ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
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_data_entry vm_data_providers []
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_prepend_timeout [80] = "vm-then-pound"
static char vm_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
static struct ast_data_handler vm_users_data_provider
static char vmfmts [80]
static int vmmaxsecs
static int vmminsecs
static double volgain
static char zonetag [80]

Detailed Description

Comedian Mail - Voicemail System.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
unixODBC (http://www.unixodbc.org/)
ExtRef:
A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/)
See also
Note:
For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage
This module requires res_adsi to load. This needs to be optional during compilation.
This file is now almost impossible to work with, due to all #ifdefs. Feels like the database code before realtime. Someone - please come up with a plan to clean this up.

Definition in file app_voicemail_imapstorage.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 438 of file app_voicemail_imapstorage.c.

#define BASELINELEN   72

Definition at line 461 of file app_voicemail_imapstorage.c.

#define BASEMAXINLINE   256

Definition at line 462 of file app_voicemail_imapstorage.c.

#define CHUNKSIZE   65536

Definition at line 435 of file app_voicemail_imapstorage.c.

#define COMMAND_TIMEOUT   5000

Definition at line 431 of file app_voicemail_imapstorage.c.

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

Definition at line 748 of file app_voicemail_imapstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11351 of file app_voicemail_imapstorage.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 11378 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 443 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 445 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 446 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 444 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 447 of file app_voicemail_imapstorage.c.

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 818 of file app_voicemail_imapstorage.c.

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

Definition at line 749 of file app_voicemail_imapstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 744 of file app_voicemail_imapstorage.c.

#define ENDL   "\n"

Definition at line 466 of file app_voicemail_imapstorage.c.

#define ERROR_LOCK_PATH   -100

Definition at line 491 of file app_voicemail_imapstorage.c.

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

Definition at line 746 of file app_voicemail_imapstorage.c.

#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"

Definition at line 454 of file app_voicemail_imapstorage.c.

#define MAX_DATETIME_FORMAT   512

Definition at line 469 of file app_voicemail_imapstorage.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 470 of file app_voicemail_imapstorage.c.

#define MAXMSG   100

Definition at line 456 of file app_voicemail_imapstorage.c.

#define MAXMSGLIMIT   9999

Definition at line 457 of file app_voicemail_imapstorage.c.

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 459 of file app_voicemail_imapstorage.c.

#define OPERATOR_EXIT   300

Definition at line 492 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 761 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 760 of file app_voicemail_imapstorage.c.

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

Definition at line 747 of file app_voicemail_imapstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 743 of file app_voicemail_imapstorage.c.

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

Definition at line 452 of file app_voicemail_imapstorage.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 429 of file app_voicemail_imapstorage.c.

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

Definition at line 745 of file app_voicemail_imapstorage.c.

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 770 of file app_voicemail_imapstorage.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 448 of file app_voicemail_imapstorage.c.

#define VM_ALLOCED   (1 << 13)

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

Definition at line 485 of file app_voicemail_imapstorage.c.

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 483 of file app_voicemail_imapstorage.c.

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 484 of file app_voicemail_imapstorage.c.

#define VM_DIRECFORWARD   (1 << 10)

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

Definition at line 482 of file app_voicemail_imapstorage.c.

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 476 of file app_voicemail_imapstorage.c.

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 480 of file app_voicemail_imapstorage.c.

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 479 of file app_voicemail_imapstorage.c.

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 490 of file app_voicemail_imapstorage.c.

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 489 of file app_voicemail_imapstorage.c.

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 488 of file app_voicemail_imapstorage.c.

#define VM_OPERATOR   (1 << 1)

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

Definition at line 473 of file app_voicemail_imapstorage.c.

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 481 of file app_voicemail_imapstorage.c.

#define VM_REVIEW   (1 << 0)

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

Definition at line 472 of file app_voicemail_imapstorage.c.

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 474 of file app_voicemail_imapstorage.c.

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 477 of file app_voicemail_imapstorage.c.

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 486 of file app_voicemail_imapstorage.c.

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 478 of file app_voicemail_imapstorage.c.

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 475 of file app_voicemail_imapstorage.c.

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 487 of file app_voicemail_imapstorage.c.

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 685 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 437 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 433 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 434 of file app_voicemail_imapstorage.c.


Enumeration Type Documentation

enum vm_box
Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 495 of file app_voicemail_imapstorage.c.

00495             {
00496    NEW_FOLDER,
00497    OLD_FOLDER,
00498    WORK_FOLDER,
00499    FAMILY_FOLDER,
00500    FRIENDS_FOLDER,
00501    GREETINGS_FOLDER
00502 };

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 516 of file app_voicemail_imapstorage.c.

00516                     {
00517    OPT_ARG_RECORDGAIN = 0,
00518    OPT_ARG_PLAYFOLDER = 1,
00519    OPT_ARG_DTMFEXIT   = 2,
00520    /* This *must* be the last value in this enum! */
00521    OPT_ARG_ARRAY_SIZE = 3,
00522 };

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
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 504 of file app_voicemail_imapstorage.c.

00504                      {
00505    OPT_SILENT =           (1 << 0),
00506    OPT_BUSY_GREETING =    (1 << 1),
00507    OPT_UNAVAIL_GREETING = (1 << 2),
00508    OPT_RECORDGAIN =       (1 << 3),
00509    OPT_PREPEND_MAILBOX =  (1 << 4),
00510    OPT_AUTOPLAY =         (1 << 6),
00511    OPT_DTMFEXIT =         (1 << 7),
00512    OPT_MESSAGE_Urgent =   (1 << 8),
00513    OPT_MESSAGE_PRIORITY = (1 << 9)
00514 };

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 524 of file app_voicemail_imapstorage.c.

00524                          {
00525    OPT_PWLOC_VOICEMAILCONF = 0,
00526    OPT_PWLOC_SPOOLDIR      = 1,
00527    OPT_PWLOC_USERSCONF     = 2,
00528 };


Function Documentation

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

Definition at line 5396 of file app_voicemail_imapstorage.c.

References ast_strlen_zero().

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

05397 {
05398    DIR *dir;
05399    struct dirent *de;
05400    char fn[256];
05401    int ret = 0;
05402 
05403    /* If no mailbox, return immediately */
05404    if (ast_strlen_zero(mailbox))
05405       return 0;
05406 
05407    if (ast_strlen_zero(folder))
05408       folder = "INBOX";
05409    if (ast_strlen_zero(context))
05410       context = "default";
05411 
05412    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05413 
05414    if (!(dir = opendir(fn)))
05415       return 0;
05416 
05417    while ((de = readdir(dir))) {
05418       if (!strncasecmp(de->d_name, "msg", 3)) {
05419          if (shortcircuit) {
05420             ret = 1;
05421             break;
05422          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05423             ret++;
05424          }
05425       }
05426    }
05427 
05428    closedir(dir);
05429 
05430    return ret;
05431 }

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

Definition at line 11054 of file app_voicemail_imapstorage.c.

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

11055 {
11056    struct ast_vm_user svm;
11057    AST_DECLARE_APP_ARGS(arg,
11058       AST_APP_ARG(mbox);
11059       AST_APP_ARG(context);
11060    );
11061 
11062    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11063 
11064    if (ast_strlen_zero(arg.mbox)) {
11065       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11066       return -1;
11067    }
11068 
11069    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11070    return 0;
11071 }

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

Definition at line 11888 of file app_voicemail_imapstorage.c.

References append_mailbox(), apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, AST_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, 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, find_or_create(), free_vm_users(), free_vm_zones(), is_valid_dtmf(), ast_variable::lineno, LOG_ERROR, ast_vm_user::mailbox, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, ast_variable::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), SENDMAIL, start_poll_thread(), stop_poll_thread(), substitute_escapes(), THRESHOLD_SILENCE, ast_variable::value, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_PBXSKIP, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, and VM_TEMPGREETWARN.

Referenced by load_config().

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

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 4810 of file app_voicemail_imapstorage.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().

04811 {
04812    char tmpdir[256], newtmp[256];
04813    char fname[256];
04814    char tmpcmd[256];
04815    int tmpfd = -1;
04816    int soxstatus = 0;
04817 
04818    /* Eww. We want formats to tell us their own MIME type */
04819    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04820 
04821    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04822       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04823       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04824       tmpfd = mkstemp(newtmp);
04825       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04826       ast_debug(3, "newtmp: %s\n", newtmp);
04827       if (tmpfd > -1) {
04828          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04829          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04830             attach = newtmp;
04831             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04832          } else {
04833             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04834                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04835             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04836          }
04837       }
04838    }
04839    fprintf(p, "--%s" ENDL, bound);
04840    if (msgnum > -1)
04841       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04842    else
04843       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04844    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04845    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04846    if (msgnum > -1)
04847       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04848    else
04849       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04850    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04851    base_encode(fname, p);
04852    if (last)
04853       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04854    if (tmpfd > -1) {
04855       if (soxstatus == 0) {
04856          unlink(fname);
04857       }
04858       close(tmpfd);
04859       unlink(newtmp);
04860    }
04861    return 0;
04862 }

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

Definition at line 6416 of file app_voicemail_imapstorage.c.

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

Referenced by vm_authenticate(), and vm_execmain().

06417 {
06418    int x;
06419    if (!ast_adsi_available(chan))
06420       return;
06421    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06422    if (x < 0)
06423       return;
06424    if (!x) {
06425       if (adsi_load_vmail(chan, useadsi)) {
06426          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06427          return;
06428       }
06429    } else
06430       *useadsi = 1;
06431 }

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

Definition at line 6611 of file app_voicemail_imapstorage.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().

06612 {
06613    int bytes = 0;
06614    unsigned char buf[256];
06615    unsigned char keys[8];
06616 
06617    int x;
06618 
06619    if (!ast_adsi_available(chan))
06620       return;
06621 
06622    /* New meaning for keys */
06623    for (x = 0; x < 5; x++)
06624       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06625 
06626    keys[6] = 0x0;
06627    keys[7] = 0x0;
06628 
06629    if (!vms->curmsg) {
06630       /* No prev key, provide "Folder" instead */
06631       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06632    }
06633    if (vms->curmsg >= vms->lastmsg) {
06634       /* If last message ... */
06635       if (vms->curmsg) {
06636          /* but not only message, provide "Folder" instead */
06637          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06638       } else {
06639          /* Otherwise if only message, leave blank */
06640          keys[3] = 1;
06641       }
06642    }
06643 
06644    /* If deleted, show "undeleted" */
06645 #ifdef IMAP_STORAGE
06646    ast_mutex_lock(&vms->lock);
06647 #endif
06648    if (vms->deleted[vms->curmsg]) {
06649       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06650    }
06651 #ifdef IMAP_STORAGE
06652    ast_mutex_unlock(&vms->lock);
06653 #endif
06654 
06655    /* Except "Exit" */
06656    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06657    bytes += ast_adsi_set_keys(buf + bytes, keys);
06658    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06659 
06660    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06661 }

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

Definition at line 6481 of file app_voicemail_imapstorage.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().

06482 {
06483    unsigned char buf[256];
06484    int bytes = 0;
06485    unsigned char keys[8];
06486    int x, y;
06487 
06488    if (!ast_adsi_available(chan))
06489       return;
06490 
06491    for (x = 0; x < 5; x++) {
06492       y = ADSI_KEY_APPS + 12 + start + x;
06493       if (y > ADSI_KEY_APPS + 12 + 4)
06494          y = 0;
06495       keys[x] = ADSI_KEY_SKT | y;
06496    }
06497    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06498    keys[6] = 0;
06499    keys[7] = 0;
06500 
06501    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06502    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06503    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06504    bytes += ast_adsi_set_keys(buf + bytes, keys);
06505    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06506 
06507    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06508 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 6766 of file app_voicemail_imapstorage.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().

06767 {
06768    unsigned char buf[256];
06769    int bytes = 0;
06770 
06771    if (!ast_adsi_available(chan))
06772       return;
06773    bytes += adsi_logo(buf + bytes);
06774    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06775    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06776    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06777    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06778 
06779    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06780 }

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

Definition at line 6287 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ADSI_MSG_DOWNLOAD, 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().

06288 {
06289    unsigned char buf[256];
06290    int bytes = 0;
06291    int x;
06292    char num[5];
06293 
06294    *useadsi = 0;
06295    bytes += ast_adsi_data_mode(buf + bytes);
06296    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06297 
06298    bytes = 0;
06299    bytes += adsi_logo(buf);
06300    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06301 #ifdef DISPLAY
06302    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06303 #endif
06304    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06305    bytes += ast_adsi_data_mode(buf + bytes);
06306    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06307 
06308    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06309       bytes = 0;
06310       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06311       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06312       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06313       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06314       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06315       return 0;
06316    }
06317 
06318 #ifdef DISPLAY
06319    /* Add a dot */
06320    bytes = 0;
06321    bytes += ast_adsi_logo(buf);
06322    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06323    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06324    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06325    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06326 #endif
06327    bytes = 0;
06328    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06329    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06330    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06331    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06332    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06333    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06334    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06335 
06336 #ifdef DISPLAY
06337    /* Add another dot */
06338    bytes = 0;
06339    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06340    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06341 
06342    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06343    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06344 #endif
06345 
06346    bytes = 0;
06347    /* These buttons we load but don't use yet */
06348    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06349    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06350    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06351    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06352    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06353    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06354    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06355 
06356 #ifdef DISPLAY
06357    /* Add another dot */
06358    bytes = 0;
06359    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06360    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06361    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06362 #endif
06363 
06364    bytes = 0;
06365    for (x = 0; x < 5; x++) {
06366       snprintf(num, sizeof(num), "%d", x);
06367       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06368    }
06369    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06370    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06371 
06372 #ifdef DISPLAY
06373    /* Add another dot */
06374    bytes = 0;
06375    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06376    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06377    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06378 #endif
06379 
06380    if (ast_adsi_end_download(chan)) {
06381       bytes = 0;
06382       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06383       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06384       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06385       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06386       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06387       return 0;
06388    }
06389    bytes = 0;
06390    bytes += ast_adsi_download_disconnect(buf + bytes);
06391    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06392    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06393 
06394    ast_debug(1, "Done downloading scripts...\n");
06395 
06396 #ifdef DISPLAY
06397    /* Add last dot */
06398    bytes = 0;
06399    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06400    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06401 #endif
06402    ast_debug(1, "Restarting session...\n");
06403 
06404    bytes = 0;
06405    /* Load the session now */
06406    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06407       *useadsi = 1;
06408       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06409    } else
06410       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06411 
06412    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06413    return 0;
06414 }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 6433 of file app_voicemail_imapstorage.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().

06434 {
06435    unsigned char buf[256];
06436    int bytes = 0;
06437    unsigned char keys[8];
06438    int x;
06439    if (!ast_adsi_available(chan))
06440       return;
06441 
06442    for (x = 0; x < 8; x++)
06443       keys[x] = 0;
06444    /* Set one key for next */
06445    keys[3] = ADSI_KEY_APPS + 3;
06446 
06447    bytes += adsi_logo(buf + bytes);
06448    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06449    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06450    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06451    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06452    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06453    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06454    bytes += ast_adsi_set_keys(buf + bytes, keys);
06455    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06456    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06457 }

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

Definition at line 6279 of file app_voicemail_imapstorage.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().

06280 {
06281    int bytes = 0;
06282    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06283    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06284    return bytes;
06285 }

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

Definition at line 6510 of file app_voicemail_imapstorage.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(), vm_state::curbox, vm_state::curmsg, vm_state::deleted, vm_state::fn, and vm_state::lastmsg.

Referenced by play_message(), and vm_execmain().

06511 {
06512    int bytes = 0;
06513    unsigned char buf[256]; 
06514    char buf1[256], buf2[256];
06515    char fn2[PATH_MAX];
06516 
06517    char cid[256] = "";
06518    char *val;
06519    char *name, *num;
06520    char datetime[21] = "";
06521    FILE *f;
06522 
06523    unsigned char keys[8];
06524 
06525    int x;
06526 
06527    if (!ast_adsi_available(chan))
06528       return;
06529 
06530    /* Retrieve important info */
06531    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06532    f = fopen(fn2, "r");
06533    if (f) {
06534       while (!feof(f)) {   
06535          if (!fgets((char *) buf, sizeof(buf), f)) {
06536             continue;
06537          }
06538          if (!feof(f)) {
06539             char *stringp = NULL;
06540             stringp = (char *) buf;
06541             strsep(&stringp, "=");
06542             val = strsep(&stringp, "=");
06543             if (!ast_strlen_zero(val)) {
06544                if (!strcmp((char *) buf, "callerid"))
06545                   ast_copy_string(cid, val, sizeof(cid));
06546                if (!strcmp((char *) buf, "origdate"))
06547                   ast_copy_string(datetime, val, sizeof(datetime));
06548             }
06549          }
06550       }
06551       fclose(f);
06552    }
06553    /* New meaning for keys */
06554    for (x = 0; x < 5; x++)
06555       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06556    keys[6] = 0x0;
06557    keys[7] = 0x0;
06558 
06559    if (!vms->curmsg) {
06560       /* No prev key, provide "Folder" instead */
06561       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06562    }
06563    if (vms->curmsg >= vms->lastmsg) {
06564       /* If last message ... */
06565       if (vms->curmsg) {
06566          /* but not only message, provide "Folder" instead */
06567          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06568          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06569 
06570       } else {
06571          /* Otherwise if only message, leave blank */
06572          keys[3] = 1;
06573       }
06574    }
06575 
06576    if (!ast_strlen_zero(cid)) {
06577       ast_callerid_parse(cid, &name, &num);
06578       if (!name)
06579          name = num;
06580    } else
06581       name = "Unknown Caller";
06582 
06583    /* If deleted, show "undeleted" */
06584 #ifdef IMAP_STORAGE
06585    ast_mutex_lock(&vms->lock);
06586 #endif
06587    if (vms->deleted[vms->curmsg]) {
06588       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06589    }
06590 #ifdef IMAP_STORAGE
06591    ast_mutex_unlock(&vms->lock);
06592 #endif
06593 
06594    /* Except "Exit" */
06595    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06596    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06597       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06598    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06599 
06600    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06601    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06602    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06603    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06604    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06605    bytes += ast_adsi_set_keys(buf + bytes, keys);
06606    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06607 
06608    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06609 }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 6459 of file app_voicemail_imapstorage.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().

06460 {
06461    unsigned char buf[256];
06462    int bytes = 0;
06463    unsigned char keys[8];
06464    int x;
06465    if (!ast_adsi_available(chan))
06466       return;
06467 
06468    for (x = 0; x < 8; x++)
06469       keys[x] = 0;
06470    /* Set one key for next */
06471    keys[3] = ADSI_KEY_APPS + 3;
06472 
06473    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06474    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06475    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06476    bytes += ast_adsi_set_keys(buf + bytes, keys);
06477    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06478    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06479 }

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

Definition at line 6663 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

06664 {
06665    unsigned char buf[256] = "";
06666    char buf1[256] = "", buf2[256] = "";
06667    int bytes = 0;
06668    unsigned char keys[8];
06669    int x;
06670 
06671    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06672    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06673    if (!ast_adsi_available(chan))
06674       return;
06675    if (vms->newmessages) {
06676       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06677       if (vms->oldmessages) {
06678          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06679          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06680       } else {
06681          snprintf(buf2, sizeof(buf2), "%s.", newm);
06682       }
06683    } else if (vms->oldmessages) {
06684       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06685       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06686    } else {
06687       strcpy(buf1, "You have no messages.");
06688       buf2[0] = ' ';
06689       buf2[1] = '\0';
06690    }
06691    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06692    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06693    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06694 
06695    for (x = 0; x < 6; x++)
06696       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06697    keys[6] = 0;
06698    keys[7] = 0;
06699 
06700    /* Don't let them listen if there are none */
06701    if (vms->lastmsg < 0)
06702       keys[0] = 1;
06703    bytes += ast_adsi_set_keys(buf + bytes, keys);
06704 
06705    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06706 
06707    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06708 }

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

Definition at line 6710 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

06711 {
06712    unsigned char buf[256] = "";
06713    char buf1[256] = "", buf2[256] = "";
06714    int bytes = 0;
06715    unsigned char keys[8];
06716    int x;
06717 
06718    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06719 
06720    if (!ast_adsi_available(chan))
06721       return;
06722 
06723    /* Original command keys */
06724    for (x = 0; x < 6; x++)
06725       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06726 
06727    keys[6] = 0;
06728    keys[7] = 0;
06729 
06730    if ((vms->lastmsg + 1) < 1)
06731       keys[0] = 0;
06732 
06733    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06734       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06735 
06736    if (vms->lastmsg + 1)
06737       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06738    else
06739       strcpy(buf2, "no messages.");
06740    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06741    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06742    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06743    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06744    bytes += ast_adsi_set_keys(buf + bytes, keys);
06745 
06746    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06747 
06748    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06749    
06750 }

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 13259 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

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

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

Definition at line 10781 of file app_voicemail_imapstorage.c.

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

Referenced by actual_load_config().

10782 {
10783    /* Assumes lock is already held */
10784    char *tmp;
10785    char *stringp;
10786    char *s;
10787    struct ast_vm_user *vmu;
10788    char *mailbox_full;
10789    int new = 0, old = 0, urgent = 0;
10790    char secretfn[PATH_MAX] = "";
10791 
10792    tmp = ast_strdupa(data);
10793 
10794    if (!(vmu = find_or_create(context, box)))
10795       return -1;
10796 
10797    populate_defaults(vmu);
10798 
10799    stringp = tmp;
10800    if ((s = strsep(&stringp, ","))) {
10801       if (!ast_strlen_zero(s) && s[0] == '*') {
10802          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10803             "\n\tmust be reset in voicemail.conf.\n", box);
10804       }
10805       /* assign password regardless of validity to prevent NULL password from being assigned */
10806       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10807    }
10808    if (stringp && (s = strsep(&stringp, ","))) {
10809       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10810    }
10811    if (stringp && (s = strsep(&stringp, ","))) {
10812       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10813    }
10814    if (stringp && (s = strsep(&stringp, ","))) {
10815       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10816    }
10817    if (stringp && (s = strsep(&stringp, ","))) {
10818       apply_options(vmu, s);
10819    }
10820 
10821    switch (vmu->passwordlocation) {
10822    case OPT_PWLOC_SPOOLDIR:
10823       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10824       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10825    }
10826 
10827    mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
10828    strcpy(mailbox_full, box);
10829    strcat(mailbox_full, "@");
10830    strcat(mailbox_full, context);
10831 
10832    inboxcount2(mailbox_full, &urgent, &new, &old);
10833    queue_mwi_event(mailbox_full, urgent, new, old);
10834 
10835    return 0;
10836 }

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 1063 of file app_voicemail_imapstorage.c.

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

Referenced by apply_options(), and apply_options_full().

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

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

Destructively Parse options and apply.

Definition at line 1304 of file app_voicemail_imapstorage.c.

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

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

01305 {  
01306    char *stringp;
01307    char *s;
01308    char *var, *value;
01309    stringp = ast_strdupa(options);
01310    while ((s = strsep(&stringp, "|"))) {
01311       value = s;
01312       if ((var = strsep(&value, "=")) && value) {
01313          apply_option(vmu, var, value);
01314       }
01315    }  
01316 }

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 1323 of file app_voicemail_imapstorage.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().

01324 {
01325    for (; var; var = var->next) {
01326       if (!strcasecmp(var->name, "vmsecret")) {
01327          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01328       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01329          if (ast_strlen_zero(retval->password)) {
01330             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01331                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01332                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01333             } else {
01334                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01335             }
01336          }
01337       } else if (!strcasecmp(var->name, "uniqueid")) {
01338          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01339       } else if (!strcasecmp(var->name, "pager")) {
01340          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01341       } else if (!strcasecmp(var->name, "email")) {
01342          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01343       } else if (!strcasecmp(var->name, "fullname")) {
01344          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01345       } else if (!strcasecmp(var->name, "context")) {
01346          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01347       } else if (!strcasecmp(var->name, "emailsubject")) {
01348          ast_free(retval->emailsubject);
01349          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01350       } else if (!strcasecmp(var->name, "emailbody")) {
01351          ast_free(retval->emailbody);
01352          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01353 #ifdef IMAP_STORAGE
01354       } else if (!strcasecmp(var->name, "imapuser")) {
01355          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01356          retval->imapversion = imapversion;
01357       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01358          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01359          retval->imapversion = imapversion;
01360       } else if (!strcasecmp(var->name, "imapfolder")) {
01361          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01362       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01363          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01364          retval->imapversion = imapversion;
01365 #endif
01366       } else
01367          apply_option(retval, var->name, var->value);
01368    }
01369 }

AST_APP_OPTIONS ( vm_app_options   ) 
AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)
AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)
static AST_LIST_HEAD_STATIC ( zones  ,
vm_zone   
) [static]
static AST_LIST_HEAD_STATIC ( users  ,
ast_vm_user   
) [static]
AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
tdesc  ,
load = load_module,
unload = unload_module,
reload = reload,
nonoptreq = "res_adsi,res_smdi" 
)
AST_MUTEX_DEFINE_STATIC ( poll_lock   ) 
static AST_RWLIST_HEAD_STATIC ( mwi_subs  ,
mwi_sub   
) [static]
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 4485 of file app_voicemail_imapstorage.c.

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

Referenced by make_email_file(), and sendpage().

04486 {
04487    struct ast_str *tmp = ast_str_alloca(80);
04488    int first_section = 1;
04489 
04490    ast_str_reset(*end);
04491    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04492    for (; *start; start++) {
04493       int need_encoding = 0;
04494       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04495          need_encoding = 1;
04496       }
04497       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04498          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04499          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04500          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04501          /* Start new line */
04502          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04503          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04504          first_section = 0;
04505       }
04506       if (need_encoding && *start == ' ') {
04507          ast_str_append(&tmp, -1, "_");
04508       } else if (need_encoding) {
04509          ast_str_append(&tmp, -1, "=%hhX", *start);
04510       } else {
04511          ast_str_append(&tmp, -1, "%c", *start);
04512       }
04513    }
04514    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04515    return ast_str_buffer(*end);
04516 }

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 4413 of file app_voicemail_imapstorage.c.

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

Referenced by make_email_file(), and sendpage().

04414 {
04415    const char *ptr;
04416 
04417    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04418    ast_str_set(buf, maxlen, "\"");
04419    for (ptr = from; *ptr; ptr++) {
04420       if (*ptr == '"' || *ptr == '\\') {
04421          ast_str_append(buf, maxlen, "\\%c", *ptr);
04422       } else {
04423          ast_str_append(buf, maxlen, "%c", *ptr);
04424       }
04425    }
04426    ast_str_append(buf, maxlen, "\"");
04427 
04428    return ast_str_buffer(*buf);
04429 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10838 of file app_voicemail_imapstorage.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.

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

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 4289 of file app_voicemail_imapstorage.c.

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

Referenced by add_email_attachment().

04290 {
04291    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04292       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04293       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04294       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04295    int i, hiteof = 0;
04296    FILE *fi;
04297    struct baseio bio;
04298 
04299    memset(&bio, 0, sizeof(bio));
04300    bio.iocp = BASEMAXINLINE;
04301 
04302    if (!(fi = fopen(filename, "rb"))) {
04303       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04304       return -1;
04305    }
04306 
04307    while (!hiteof){
04308       unsigned char igroup[3], ogroup[4];
04309       int c, n;
04310 
04311       memset(igroup, 0, sizeof(igroup));
04312 
04313       for (n = 0; n < 3; n++) {
04314          if ((c = inchar(&bio, fi)) == EOF) {
04315             hiteof = 1;
04316             break;
04317          }
04318 
04319          igroup[n] = (unsigned char) c;
04320       }
04321 
04322       if (n > 0) {
04323          ogroup[0]= dtable[igroup[0] >> 2];
04324          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04325          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04326          ogroup[3]= dtable[igroup[2] & 0x3F];
04327 
04328          if (n < 3) {
04329             ogroup[3] = '=';
04330 
04331             if (n < 2)
04332                ogroup[2] = '=';
04333          }
04334 
04335          for (i = 0; i < 4; i++)
04336             ochar(&bio, ogroup[i], so);
04337       }
04338    }
04339 
04340    fclose(fi);
04341    
04342    if (fputs(ENDL, so) == EOF) {
04343       return 0;
04344    }
04345 
04346    return 1;
04347 }

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 1282 of file app_voicemail_imapstorage.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().

01283 {
01284    int res = -1;
01285    if (!strcmp(vmu->password, password)) {
01286       /* No change (but an update would return 0 rows updated, so we opt out here) */
01287       return 0;
01288    }
01289 
01290    if (strlen(password) > 10) {
01291       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01292    }
01293    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01294       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01295       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01296       res = 0;
01297    }
01298    return res;
01299 }

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 4458 of file app_voicemail_imapstorage.c.

Referenced by make_email_file(), and sendpage().

04459 {
04460    for (; *str; str++) {
04461       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04462          return 1;
04463       }
04464    }
04465    return 0;
04466 }

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 1241 of file app_voicemail_imapstorage.c.

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

Referenced by vm_newuser(), and vm_options().

01242 {
01243    /* check minimum length */
01244    if (strlen(password) < minpassword)
01245       return 1;
01246    /* check that password does not contain '*' character */
01247    if (!ast_strlen_zero(password) && password[0] == '*')
01248       return 1;
01249    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01250       char cmd[255], buf[255];
01251 
01252       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01253 
01254       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01255       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01256          ast_debug(5, "Result: %s\n", buf);
01257          if (!strncasecmp(buf, "VALID", 5)) {
01258             ast_debug(3, "Passed password check: '%s'\n", buf);
01259             return 0;
01260          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01261             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01262             return 0;
01263          } else {
01264             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01265             return 1;
01266          }
01267       }
01268    }
01269    return 0;
01270 }

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

Definition at line 7976 of file app_voicemail_imapstorage.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 vm_execmain().

07977 {
07978    int x = 0;
07979    int last_msg_idx = 0;
07980 
07981 #ifndef IMAP_STORAGE
07982    int res = 0, nummsg;
07983    char fn2[PATH_MAX];
07984 #endif
07985 
07986    if (vms->lastmsg <= -1) {
07987       goto done;
07988    }
07989 
07990    vms->curmsg = -1;
07991 #ifndef IMAP_STORAGE
07992    /* Get the deleted messages fixed */
07993    if (vm_lock_path(vms->curdir)) {
07994       return ERROR_LOCK_PATH;
07995    }
07996 
07997    /* update count as message may have arrived while we've got mailbox open */
07998    last_msg_idx = last_message_index(vmu, vms->curdir);
07999    if (last_msg_idx != vms->lastmsg) {
08000       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
08001    }
08002 
08003    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
08004    for (x = 0; x < last_msg_idx + 1; x++) {
08005       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
08006          /* Save this message.  It's not in INBOX or hasn't been heard */
08007          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08008          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
08009             break;
08010          }
08011          vms->curmsg++;
08012          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
08013          if (strcmp(vms->fn, fn2)) {
08014             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
08015          }
08016       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
08017          /* Move to old folder before deleting */
08018          res = save_to_folder(vmu, vms, x, 1);
08019          if (res == ERROR_LOCK_PATH) {
08020             /* If save failed do not delete the message */
08021             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08022             vms->deleted[x] = 0;
08023             vms->heard[x] = 0;
08024             --x;
08025          }
08026       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08027          /* Move to deleted folder */
08028          res = save_to_folder(vmu, vms, x, 10);
08029          if (res == ERROR_LOCK_PATH) {
08030             /* If save failed do not delete the message */
08031             vms->deleted[x] = 0;
08032             vms->heard[x] = 0;
08033             --x;
08034          }
08035       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08036          /* If realtime storage enabled - we should explicitly delete this message,
08037          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08038          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08039          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08040             DELETE(vms->curdir, x, vms->fn, vmu);
08041          }
08042       }
08043    }
08044 
08045    /* Delete ALL remaining messages */
08046    nummsg = x - 1;
08047    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08048       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08049       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08050          DELETE(vms->curdir, x, vms->fn, vmu);
08051       }
08052    }
08053    ast_unlock_path(vms->curdir);
08054 #else /* defined(IMAP_STORAGE) */
08055    ast_mutex_lock(&vms->lock);
08056    if (vms->deleted) {
08057       /* Since we now expunge after each delete, deleting in reverse order
08058        * ensures that no reordering occurs between each step. */
08059       last_msg_idx = vms->dh_arraysize;
08060       for (x = last_msg_idx - 1; x >= 0; x--) {
08061          if (vms->deleted[x]) {
08062             ast_debug(3, "IMAP delete of %d\n", x);
08063             DELETE(vms->curdir, x, vms->fn, vmu);
08064          }
08065       }
08066    }
08067 #endif
08068 
08069 done:
08070    if (vms->deleted) {
08071       ast_free(vms->deleted);
08072       vms->deleted = NULL;
08073    }
08074    if (vms->heard) {
08075       ast_free(vms->heard);
08076       vms->heard = NULL;
08077    }
08078    vms->dh_arraysize = 0;
08079 #ifdef IMAP_STORAGE
08080    ast_mutex_unlock(&vms->lock);
08081 #endif
08082 
08083    return 0;
08084 }

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

Definition at line 11158 of file app_voicemail_imapstorage.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11159 {
11160    int which = 0;
11161    int wordlen;
11162    struct ast_vm_user *vmu;
11163    const char *context = "";
11164 
11165    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11166    if (pos > 4)
11167       return NULL;
11168    if (pos == 3)
11169       return (state == 0) ? ast_strdup("for") : NULL;
11170    wordlen = strlen(word);
11171    AST_LIST_TRAVERSE(&users, vmu, list) {
11172       if (!strncasecmp(word, vmu->context, wordlen)) {
11173          if (context && strcmp(context, vmu->context) && ++which > state)
11174             return ast_strdup(vmu->context);
11175          /* ignore repeated contexts ? */
11176          context = vmu->context;
11177       }
11178    }
11179    return NULL;
11180 }

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 4094 of file app_voicemail_imapstorage.c.

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

Referenced by copy_plain_file(), and vm_forwardoptions().

04095 {
04096    int ifd;
04097    int ofd;
04098    int res;
04099    int len;
04100    char buf[4096];
04101 
04102 #ifdef HARDLINK_WHEN_POSSIBLE
04103    /* Hard link if possible; saves disk space & is faster */
04104    if (link(infile, outfile)) {
04105 #endif
04106       if ((ifd = open(infile, O_RDONLY)) < 0) {
04107          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04108          return -1;
04109       }
04110       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04111          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04112          close(ifd);
04113          return -1;
04114       }
04115       do {
04116          len = read(ifd, buf, sizeof(buf));
04117          if (len < 0) {
04118             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04119             close(ifd);
04120             close(ofd);
04121             unlink(outfile);
04122          } else if (len) {
04123             res = write(ofd, buf, len);
04124             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04125                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04126                close(ifd);
04127                close(ofd);
04128                unlink(outfile);
04129             }
04130          }
04131       } while (len);
04132       close(ifd);
04133       close(ofd);
04134       return 0;
04135 #ifdef HARDLINK_WHEN_POSSIBLE
04136    } else {
04137       /* Hard link succeeded */
04138       return 0;
04139    }
04140 #endif
04141 }

static int copy_message ( struct ast_channel chan,
struct ast_vm_user vmu,
int  imbox,
int  msgnum,
long  duration,
struct ast_vm_user recip,
char *  fmt,
char *  dir,
const char *  flag 
) [static]

Copies a message from one mailbox to another.

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

Definition at line 5330 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), ast_channel::caller, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), 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(), and leave_voicemail().

05331 {
05332    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05333    const char *frombox = mbox(vmu, imbox);
05334    const char *userfolder;
05335    int recipmsgnum;
05336    int res = 0;
05337 
05338    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05339 
05340    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05341       userfolder = "Urgent";
05342    } else {
05343       userfolder = "INBOX";
05344    }
05345 
05346    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05347 
05348    if (!dir)
05349       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05350    else
05351       ast_copy_string(fromdir, dir, sizeof(fromdir));
05352 
05353    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05354    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05355 
05356    if (vm_lock_path(todir))
05357       return ERROR_LOCK_PATH;
05358 
05359    recipmsgnum = last_message_index(recip, todir) + 1;
05360    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05361       make_file(topath, sizeof(topath), todir, recipmsgnum);
05362 #ifndef ODBC_STORAGE
05363       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05364          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05365       } else {
05366 #endif
05367          /* If we are prepending a message for ODBC, then the message already
05368           * exists in the database, but we want to force copying from the
05369           * filesystem (since only the FS contains the prepend). */
05370          copy_plain_file(frompath, topath);
05371          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05372          vm_delete(topath);
05373 #ifndef ODBC_STORAGE
05374       }
05375 #endif
05376    } else {
05377       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05378       res = -1;
05379    }
05380    ast_unlock_path(todir);
05381    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05382       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05383       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05384       flag);
05385    
05386    return res;
05387 }

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 4152 of file app_voicemail_imapstorage.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().

04153 {
04154    char frompath2[PATH_MAX], topath2[PATH_MAX];
04155    struct ast_variable *tmp,*var = NULL;
04156    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04157    ast_filecopy(frompath, topath, NULL);
04158    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04159    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04160    if (ast_check_realtime("voicemail_data")) {
04161       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04162       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04163       for (tmp = var; tmp; tmp = tmp->next) {
04164          if (!strcasecmp(tmp->name, "origmailbox")) {
04165             origmailbox = tmp->value;
04166          } else if (!strcasecmp(tmp->name, "context")) {
04167             context = tmp->value;
04168          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04169             macrocontext = tmp->value;
04170          } else if (!strcasecmp(tmp->name, "exten")) {
04171             exten = tmp->value;
04172          } else if (!strcasecmp(tmp->name, "priority")) {
04173             priority = tmp->value;
04174          } else if (!strcasecmp(tmp->name, "callerchan")) {
04175             callerchan = tmp->value;
04176          } else if (!strcasecmp(tmp->name, "callerid")) {
04177             callerid = tmp->value;
04178          } else if (!strcasecmp(tmp->name, "origdate")) {
04179             origdate = tmp->value;
04180          } else if (!strcasecmp(tmp->name, "origtime")) {
04181             origtime = tmp->value;
04182          } else if (!strcasecmp(tmp->name, "category")) {
04183             category = tmp->value;
04184          } else if (!strcasecmp(tmp->name, "duration")) {
04185             duration = tmp->value;
04186          }
04187       }
04188       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);
04189    }
04190    copy(frompath2, topath2);
04191    ast_variables_destroy(var);
04192 }

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 3989 of file app_voicemail_imapstorage.c.

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

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

03990 {
03991 
03992    int vmcount = 0;
03993    DIR *vmdir = NULL;
03994    struct dirent *vment = NULL;
03995 
03996    if (vm_lock_path(dir))
03997       return ERROR_LOCK_PATH;
03998 
03999    if ((vmdir = opendir(dir))) {
04000       while ((vment = readdir(vmdir))) {
04001          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
04002             vmcount++;
04003          }
04004       }
04005       closedir(vmdir);
04006    }
04007    ast_unlock_path(dir);
04008    
04009    return vmcount;
04010 }

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 1692 of file app_voicemail_imapstorage.c.

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

Referenced by add_email_attachment(), copy_message(), invent_message(), leave_voicemail(), open_mailbox(), and save_to_folder().

01693 {
01694    mode_t   mode = VOICEMAIL_DIR_MODE;
01695    int res;
01696 
01697    make_dir(dest, len, context, ext, folder);
01698    if ((res = ast_mkdir(dest, mode))) {
01699       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01700       return -1;
01701    }
01702    return 0;
01703 }

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

Definition at line 13186 of file app_voicemail_imapstorage.c.

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

Referenced by advanced_options(), and vm_execmain().

13187 {
13188    int cmd = 0;
13189    char destination[80] = "";
13190    int retries = 0;
13191 
13192    if (!num) {
13193       ast_verb(3, "Destination number will be entered manually\n");
13194       while (retries < 3 && cmd != 't') {
13195          destination[1] = '\0';
13196          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13197          if (!cmd)
13198             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13199          if (!cmd)
13200             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13201          if (!cmd) {
13202             cmd = ast_waitfordigit(chan, 6000);
13203             if (cmd)
13204                destination[0] = cmd;
13205          }
13206          if (!cmd) {
13207             retries++;
13208          } else {
13209 
13210             if (cmd < 0)
13211                return 0;
13212             if (cmd == '*') {
13213                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13214                return 0;
13215             }
13216             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13217                retries++;
13218             else
13219                cmd = 't';
13220          }
13221          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13222       }
13223       if (retries >= 3) {
13224          return 0;
13225       }
13226       
13227    } else {
13228       if (option_verbose > 2)
13229          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13230       ast_copy_string(destination, num, sizeof(destination));
13231    }
13232 
13233    if (!ast_strlen_zero(destination)) {
13234       if (destination[strlen(destination) -1 ] == '*')
13235          return 0; 
13236       if (option_verbose > 2)
13237          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13238       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13239       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13240       chan->priority = 0;
13241       return 9;
13242    }
13243    return 0;
13244 }

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

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

Referenced by actual_load_config(), and append_mailbox().

10742 {
10743    struct ast_vm_user *vmu;
10744 
10745    if (!ast_strlen_zero(box) && box[0] == '*') {
10746       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10747             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10748             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10749             "\n\tand will be ignored.\n", box, context);
10750       return NULL;
10751    }
10752 
10753    AST_LIST_TRAVERSE(&users, vmu, list) {
10754       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10755          if (strcasecmp(vmu->context, context)) {
10756             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10757                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10758                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10759                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10760          }
10761          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10762          return NULL;
10763       }
10764       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10765          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10766          return NULL;
10767       }
10768    }
10769    
10770    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10771       return NULL;
10772    
10773    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10774    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10775 
10776    AST_LIST_INSERT_TAIL(&users, vmu, list);
10777    
10778    return vmu;
10779 }

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 1444 of file app_voicemail_imapstorage.c.

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

Referenced by acf_mailbox_exists(), advanced_options(), forward_message(), leave_voicemail(), vm_authenticate(), vm_box_exists(), and vm_execmain().

01445 {
01446    /* This function could be made to generate one from a database, too */
01447    struct ast_vm_user *vmu = NULL, *cur;
01448    AST_LIST_LOCK(&users);
01449 
01450    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01451       context = "default";
01452 
01453    AST_LIST_TRAVERSE(&users, cur, list) {
01454 #ifdef IMAP_STORAGE
01455       if (cur->imapversion != imapversion) {
01456          continue;
01457       }
01458 #endif
01459       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01460          break;
01461       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01462          break;
01463    }
01464    if (cur) {
01465       /* Make a copy, so that on a reload, we have no race */
01466       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01467          *vmu = *cur;
01468          if (!ivm) {
01469             vmu->emailbody = ast_strdup(cur->emailbody);
01470             vmu->emailsubject = ast_strdup(cur->emailsubject);
01471          }
01472          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01473          AST_LIST_NEXT(vmu, list) = NULL;
01474       }
01475    } else
01476       vmu = find_user_realtime(ivm, context, mailbox);
01477    AST_LIST_UNLOCK(&users);
01478    return vmu;
01479 }

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 1403 of file app_voicemail_imapstorage.c.

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

Referenced by find_user().

01404 {
01405    struct ast_variable *var;
01406    struct ast_vm_user *retval;
01407 
01408    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01409       if (ivm) {
01410          memset(retval, 0, sizeof(*retval));
01411       }
01412       populate_defaults(retval);
01413       if (!ivm) {
01414          ast_set_flag(retval, VM_ALLOCED);
01415       }
01416       if (mailbox) {
01417          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01418       }
01419       if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
01420          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01421       } else {
01422          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01423       }
01424       if (var) {
01425          apply_options_full(retval, var);
01426          ast_variables_destroy(var);
01427       } else { 
01428          if (!ivm) 
01429             free_user(retval);
01430          retval = NULL;
01431       }  
01432    } 
01433    return retval;
01434 }

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

Sends a voicemail message to a mailbox recipient.

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

When in the leave message mode (is_new_message == 1):

  • allow the leaving of a message for ourselves. (Will not allow us to forward a message to ourselves, when is_new_message == 0).
  • attempt to determine the context and and mailbox, and then invoke leave_message() function to record and store the message.

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

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

Definition at line 7177 of file app_voicemail_imapstorage.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_waitfordigit(), ast_channel::caller, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), vm_state::fn, free_user(), ast_party_caller::id, inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), STORE, ast_party_name::str, ast_party_number::str, vm_state::username, ast_party_name::valid, ast_party_number::valid, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1747 of file app_voicemail_imapstorage.c.

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

Referenced by AST_TEST_DEFINE(), find_user_realtime(), forward_message(), free_vm_users(), leave_voicemail(), and vm_execmain().

01748 {
01749    if (ast_test_flag(vmu, VM_ALLOCED)) {
01750 
01751       ast_free(vmu->emailbody);
01752       vmu->emailbody = NULL;
01753 
01754       ast_free(vmu->emailsubject);
01755       vmu->emailsubject = NULL;
01756 
01757       ast_free(vmu);
01758    }
01759 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11770 of file app_voicemail_imapstorage.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().

11771 {
11772    struct ast_vm_user *current;
11773    AST_LIST_LOCK(&users);
11774    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11775       ast_set_flag(current, VM_ALLOCED);
11776       free_user(current);
11777    }
11778    AST_LIST_UNLOCK(&users);
11779 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11782 of file app_voicemail_imapstorage.c.

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

Referenced by actual_load_config(), and unload_module().

11783 {
11784    struct vm_zone *zcur;
11785    AST_LIST_LOCK(&zones);
11786    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11787       free_zone(zcur);
11788    AST_LIST_UNLOCK(&zones);
11789 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5098 of file app_voicemail_imapstorage.c.

References ast_free.

Referenced by free_vm_zones().

05099 {
05100    ast_free(z);
05101 }

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 5054 of file app_voicemail_imapstorage.c.

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

Referenced by leave_voicemail().

05055 {
05056    struct ast_tm tm;
05057    struct timeval t = ast_tvnow();
05058    
05059    ast_localtime(&t, &tm, "UTC");
05060 
05061    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05062 }

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 6786 of file app_voicemail_imapstorage.c.

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

Referenced by get_folder2().

06787 {
06788    int x;
06789    int d;
06790    char fn[PATH_MAX];
06791    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06792    if (d)
06793       return d;
06794    for (x = start; x < 5; x++) { /* For all folders */
06795       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06796          return d;
06797       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06798       if (d)
06799          return d;
06800       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06801 
06802       /* The inbox folder can have its name changed under certain conditions
06803        * so this checks if the sound file exists for the inbox folder name and
06804        * if it doesn't, plays the default name instead. */
06805       if (x == 0) {
06806          if (ast_fileexists(fn, NULL, NULL)) {
06807             d = vm_play_folder_name(chan, fn);
06808          } else {
06809             ast_verb(1, "failed to find %s\n", fn);
06810             d = vm_play_folder_name(chan, "vm-INBOX");
06811          }
06812       } else {
06813          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06814          d = vm_play_folder_name(chan, fn);
06815       }
06816 
06817       if (d)
06818          return d;
06819       d = ast_waitfordigit(chan, 500);
06820       if (d)
06821          return d;
06822    }
06823 
06824    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06825    if (d)
06826       return d;
06827    d = ast_waitfordigit(chan, 4000);
06828    return d;
06829 }

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

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

Referenced by vm_execmain().

06844 {
06845    int res = 0;
06846    int loops = 0;
06847 
06848    res = ast_play_and_wait(chan, fn);  /* Folder name */
06849    while (((res < '0') || (res > '9')) &&
06850          (res != '#') && (res >= 0) &&
06851          loops < 4) {
06852       res = get_folder(chan, 0);
06853       loops++;
06854    }
06855    if (loops == 4) { /* give up */
06856       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06857       return '#';
06858    }
06859    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06860    return res;
06861 }

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

Definition at line 1734 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

Referenced by vm_execmain().

01735 {
01736    size_t i;
01737 
01738    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01739       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01740          return i;
01741       }
01742    }
01743 
01744    return -1;
01745 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11540 of file app_voicemail_imapstorage.c.

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

Referenced by mwi_sub_event_cb().

11541 {
11542    unsigned int len;
11543    struct mwi_sub *mwi_sub;
11544    struct mwi_sub_task *p = datap;
11545 
11546    len = sizeof(*mwi_sub);
11547    if (!ast_strlen_zero(p->mailbox))
11548       len += strlen(p->mailbox);
11549 
11550    if (!ast_strlen_zero(p->context))
11551       len += strlen(p->context) + 1; /* Allow for seperator */
11552 
11553    if (!(mwi_sub = ast_calloc(1, len)))
11554       return -1;
11555 
11556    mwi_sub->uniqueid = p->uniqueid;
11557    if (!ast_strlen_zero(p->mailbox))
11558       strcpy(mwi_sub->mailbox, p->mailbox);
11559 
11560    if (!ast_strlen_zero(p->context)) {
11561       strcat(mwi_sub->mailbox, "@");
11562       strcat(mwi_sub->mailbox, p->context);
11563    }
11564 
11565    AST_RWLIST_WRLOCK(&mwi_subs);
11566    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11567    AST_RWLIST_UNLOCK(&mwi_subs);
11568    ast_free((void *) p->mailbox);
11569    ast_free((void *) p->context);
11570    ast_free(p);
11571    poll_subscribed_mailbox(mwi_sub);
11572    return 0;
11573 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11518 of file app_voicemail_imapstorage.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and mwi_sub_destroy().

Referenced by mwi_unsub_event_cb().

11519 {
11520    struct mwi_sub *mwi_sub;
11521    uint32_t *uniqueid = datap;
11522    
11523    AST_RWLIST_WRLOCK(&mwi_subs);
11524    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11525       if (mwi_sub->uniqueid == *uniqueid) {
11526          AST_LIST_REMOVE_CURRENT(entry);
11527          break;
11528       }
11529    }
11530    AST_RWLIST_TRAVERSE_SAFE_END
11531    AST_RWLIST_UNLOCK(&mwi_subs);
11532 
11533    if (mwi_sub)
11534       mwi_sub_destroy(mwi_sub);
11535 
11536    ast_free(uniqueid);  
11537    return 0;
11538 }

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 11295 of file app_voicemail_imapstorage.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.

11296 {
11297    switch (cmd) {
11298    case CLI_INIT:
11299       e->command = "voicemail reload";
11300       e->usage =
11301          "Usage: voicemail reload\n"
11302          "       Reload voicemail configuration\n";
11303       return NULL;
11304    case CLI_GENERATE:
11305       return NULL;
11306    }
11307 
11308    if (a->argc != 2)
11309       return CLI_SHOWUSAGE;
11310 
11311    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11312    load_config(1);
11313    
11314    return CLI_SUCCESS;
11315 }

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 11183 of file app_voicemail_imapstorage.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.

11184 {
11185    struct ast_vm_user *vmu;
11186 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11187    const char *context = NULL;
11188    int users_counter = 0;
11189 
11190    switch (cmd) {
11191    case CLI_INIT:
11192       e->command = "voicemail show users";
11193       e->usage =
11194          "Usage: voicemail show users [for <context>]\n"
11195          "       Lists all mailboxes currently set up\n";
11196       return NULL;
11197    case CLI_GENERATE:
11198       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11199    }  
11200 
11201    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11202       return CLI_SHOWUSAGE;
11203    if (a->argc == 5) {
11204       if (strcmp(a->argv[3],"for"))
11205          return CLI_SHOWUSAGE;
11206       context = a->argv[4];
11207    }
11208 
11209    if (ast_check_realtime("voicemail")) {
11210       if (!context) {
11211          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11212          return CLI_SHOWUSAGE;
11213       }
11214       return show_users_realtime(a->fd, context);
11215    }
11216 
11217    AST_LIST_LOCK(&users);
11218    if (AST_LIST_EMPTY(&users)) {
11219       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11220       AST_LIST_UNLOCK(&users);
11221       return CLI_FAILURE;
11222    }
11223    if (!context) {
11224       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11225    } else {
11226       int count = 0;
11227       AST_LIST_TRAVERSE(&users, vmu, list) {
11228          if (!strcmp(context, vmu->context)) {
11229             count++;
11230             break;
11231          }
11232       }
11233       if (count) {
11234          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11235       } else {
11236          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11237          AST_LIST_UNLOCK(&users);
11238          return CLI_FAILURE;
11239       }
11240    }
11241    AST_LIST_TRAVERSE(&users, vmu, list) {
11242       int newmsgs = 0, oldmsgs = 0;
11243       char count[12], tmp[256] = "";
11244 
11245       if (!context || !strcmp(context, vmu->context)) {
11246          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11247          inboxcount(tmp, &newmsgs, &oldmsgs);
11248          snprintf(count, sizeof(count), "%d", newmsgs);
11249          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11250          users_counter++;
11251       }
11252    }
11253    AST_LIST_UNLOCK(&users);
11254    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11255    return CLI_SUCCESS;
11256 }

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 11259 of file app_voicemail_imapstorage.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, and ast_cli_entry::usage.

11260 {
11261    struct vm_zone *zone;
11262 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11263    char *res = CLI_SUCCESS;
11264 
11265    switch (cmd) {
11266    case CLI_INIT:
11267       e->command = "voicemail show zones";
11268       e->usage =
11269          "Usage: voicemail show zones\n"
11270          "       Lists zone message formats\n";
11271       return NULL;
11272    case CLI_GENERATE:
11273       return NULL;
11274    }
11275 
11276    if (a->argc != 3)
11277       return CLI_SHOWUSAGE;
11278 
11279    AST_LIST_LOCK(&zones);
11280    if (!AST_LIST_EMPTY(&zones)) {
11281       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11282       AST_LIST_TRAVERSE(&zones, zone, list) {
11283          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11284       }
11285    } else {
11286       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11287       res = CLI_FAILURE;
11288    }
11289    AST_LIST_UNLOCK(&zones);
11290 
11291    return res;
11292 }

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

Determines if the given folder has messages.

Parameters:
mailbox The @ delimited string for user. If no context is found, uses 'default' for the context.
folder the folder to look in

This function is used when the mailbox is stored in a filesystem back end. This invokes the __has_voicemail(). Here we are interested in the presence of messages (> 0) only, not the actual count.

Returns:
1 if the folder has one or more messages. zero otherwise.

Definition at line 5442 of file app_voicemail_imapstorage.c.

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

Referenced by load_module(), and vm_execmain().

05443 {
05444    char tmp[256], *tmp2 = tmp, *box, *context;
05445    ast_copy_string(tmp, mailbox, sizeof(tmp));
05446    if (ast_strlen_zero(folder)) {
05447       folder = "INBOX";
05448    }
05449    while ((box = strsep(&tmp2, ",&"))) {
05450       if ((context = strchr(box, '@')))
05451          *context++ = '\0';
05452       else
05453          context = "default";
05454       if (__has_voicemail(context, box, folder, 1))
05455          return 1;
05456       /* If we are checking INBOX, we should check Urgent as well */
05457       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05458          return 1;
05459       }
05460    }
05461    return 0;
05462 }

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

Definition at line 5524 of file app_voicemail_imapstorage.c.

References inboxcount2().

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

05525 {
05526    int urgentmsgs = 0;
05527    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05528    if (newmsgs) {
05529       *newmsgs += urgentmsgs;
05530    }
05531    return res;
05532 }

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

Definition at line 5465 of file app_voicemail_imapstorage.c.

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

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

05466 {
05467    char tmp[256];
05468    char *context;
05469 
05470    /* If no mailbox, return immediately */
05471    if (ast_strlen_zero(mailbox))
05472       return 0;
05473 
05474    if (newmsgs)
05475       *newmsgs = 0;
05476    if (oldmsgs)
05477       *oldmsgs = 0;
05478    if (urgentmsgs)
05479       *urgentmsgs = 0;
05480 
05481    if (strchr(mailbox, ',')) {
05482       int tmpnew, tmpold, tmpurgent;
05483       char *mb, *cur;
05484 
05485       ast_copy_string(tmp, mailbox, sizeof(tmp));
05486       mb = tmp;
05487       while ((cur = strsep(&mb, ", "))) {
05488          if (!ast_strlen_zero(cur)) {
05489             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05490                return -1;
05491             else {
05492                if (newmsgs)
05493                   *newmsgs += tmpnew; 
05494                if (oldmsgs)
05495                   *oldmsgs += tmpold;
05496                if (urgentmsgs)
05497                   *urgentmsgs += tmpurgent;
05498             }
05499          }
05500       }
05501       return 0;
05502    }
05503 
05504    ast_copy_string(tmp, mailbox, sizeof(tmp));
05505    
05506    if ((context = strchr(tmp, '@')))
05507       *context++ = '\0';
05508    else
05509       context = "default";
05510 
05511    if (newmsgs)
05512       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05513    if (oldmsgs)
05514       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05515    if (urgentmsgs)
05516       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05517 
05518    return 0;
05519 }

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

utility used by inchar(), for base_encode()

Definition at line 4224 of file app_voicemail_imapstorage.c.

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

Referenced by inchar().

04225 {
04226    int l;
04227 
04228    if (bio->ateof)
04229       return 0;
04230 
04231    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04232       if (ferror(fi))
04233          return -1;
04234 
04235       bio->ateof = 1;
04236       return 0;
04237    }
04238 
04239    bio->iolen = l;
04240    bio->iocp = 0;
04241 
04242    return 1;
04243 }

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

utility used by base_encode()

Definition at line 4248 of file app_voicemail_imapstorage.c.

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

Referenced by base_encode().

04249 {
04250    if (bio->iocp>=bio->iolen) {
04251       if (!inbuf(bio, fi))
04252          return EOF;
04253    }
04254 
04255    return bio->iobuf[bio->iocp++];
04256 }

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

Definition at line 942 of file app_voicemail_imapstorage.c.

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

Referenced by load_module().

00943 {
00944    struct inprocess *i = obj, *j = arg;
00945    if (strcmp(i->mailbox, j->mailbox)) {
00946       return 0;
00947    }
00948    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00949 }

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

Definition at line 951 of file app_voicemail_imapstorage.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, LOG_WARNING, and inprocess::mailbox.

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

00952 {
00953    struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00954    arg->context = arg->mailbox + strlen(mailbox) + 1;
00955    strcpy(arg->mailbox, mailbox); /* SAFE */
00956    strcpy(arg->context, context); /* SAFE */
00957    ao2_lock(inprocess_container);
00958    if ((i = ao2_find(inprocess_container, arg, 0))) {
00959       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00960       ao2_unlock(inprocess_container);
00961       ao2_ref(i, -1);
00962       return ret;
00963    }
00964    if (delta < 0) {
00965       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00966    }
00967    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00968       ao2_unlock(inprocess_container);
00969       return 0;
00970    }
00971    i->context = i->mailbox + strlen(mailbox) + 1;
00972    strcpy(i->mailbox, mailbox); /* SAFE */
00973    strcpy(i->context, context); /* SAFE */
00974    i->count = delta;
00975    ao2_link(inprocess_container, i);
00976    ao2_unlock(inprocess_container);
00977    ao2_ref(i, -1);
00978    return 0;
00979 }

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

Definition at line 936 of file app_voicemail_imapstorage.c.

References inprocess::mailbox.

Referenced by load_module().

00937 {
00938    const struct inprocess *i = obj;
00939    return atoi(i->mailbox);
00940 }

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

Definition at line 5064 of file app_voicemail_imapstorage.c.

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

Referenced by leave_voicemail().

05065 {
05066    int res;
05067    char fn[PATH_MAX];
05068    char dest[PATH_MAX];
05069 
05070    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05071 
05072    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05073       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05074       return -1;
05075    }
05076 
05077    RETRIEVE(fn, -1, ext, context);
05078    if (ast_fileexists(fn, NULL, NULL) > 0) {
05079       res = ast_stream_and_wait(chan, fn, ecodes);
05080       if (res) {
05081          DISPOSE(fn, -1);
05082          return res;
05083       }
05084    } else {
05085       /* Dispose just in case */
05086       DISPOSE(fn, -1);
05087       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05088       if (res)
05089          return res;
05090       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05091       if (res)
05092          return res;
05093    }
05094    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05095    return res;
05096 }

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

Determines if a DTMF key entered is valid.

Parameters:
key The character to be compared. expects a single character. Though is capable of handling a string, this is internally copies using ast_strdupa.

Tests the character entered against the set of valid DTMF characters.

Returns:
1 if the character entered is a valid DTMF digit, 0 if the character is invalid.

Definition at line 1378 of file app_voicemail_imapstorage.c.

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

Referenced by actual_load_config().

01379 {
01380    int i;
01381    char *local_key = ast_strdupa(key);
01382 
01383    for (i = 0; i < strlen(key); ++i) {
01384       if (!strchr(VALID_DTMF, *local_key)) {
01385          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01386          return 0;
01387       }
01388       local_key++;
01389    }
01390    return 1;
01391 }

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

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

Parameters:
vmu 
dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.

This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP). Typical use to set the msgnum would be to take the value returned from this method and add one to it.

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

Definition at line 4043 of file app_voicemail_imapstorage.c.

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

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

04044 {
04045    int x;
04046    unsigned char map[MAXMSGLIMIT] = "";
04047    DIR *msgdir;
04048    struct dirent *msgdirent;
04049    int msgdirint;
04050    char extension[4];
04051    int stopcount = 0;
04052 
04053    /* Reading the entire directory into a file map scales better than
04054     * doing a stat repeatedly on a predicted sequence.  I suspect this
04055     * is partially due to stat(2) internally doing a readdir(2) itself to
04056     * find each file. */
04057    if (!(msgdir = opendir(dir))) {
04058       return -1;
04059    }
04060 
04061    while ((msgdirent = readdir(msgdir))) {
04062       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04063          map[msgdirint] = 1;
04064          stopcount++;
04065          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04066       }
04067    }
04068    closedir(msgdir);
04069 
04070    for (x = 0; x < vmu->maxmsg; x++) {
04071       if (map[x] == 1) {
04072          stopcount--;
04073       } else if (map[x] == 0 && !stopcount) {
04074          break;
04075       }
04076    }
04077 
04078    return x - 1;
04079 }

static int leave_voicemail ( struct ast_channel chan,
char *  ext,
struct leave_vm_options options 
) [static]

Prompts the user and records a voicemail to a mailbox.

Parameters:
chan 
ext 
options OPT_BUSY_GREETING, OPT_UNAVAIL_GREETING
Returns:
zero on success, -1 on error.

Definition at line 5597 of file app_voicemail_imapstorage.c.

References ast_callerid_merge(), ast_canmatch_extension(), ast_channel_lock, ast_channel_unlock, ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, ast_channel::exten, find_user(), free_user(), ast_party_redirecting::from, get_date(), ast_party_caller::id, inboxcount(), inprocess_count(), INTRO, invent_message(), last_message_index(), LOG_DEBUG, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_party_id::name, vm_state::newmessages, notify_new_message(), ast_party_id::number, OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, ast_channel::redirecting, RENAME, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, ast_party_name::str, ast_party_number::str, transfer, ast_party_name::valid, ast_party_number::valid, vm_lock_path(), VM_OPERATOR, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

Referenced by advanced_options(), forward_message(), and vm_exec().

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

static int load_config ( int  reload  )  [static]

Definition at line 11838 of file app_voicemail_imapstorage.c.

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

Referenced by handle_voicemail_reload(), load_module(), and reload().

11839 {
11840    struct ast_config *cfg, *ucfg;
11841    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11842    int res;
11843 
11844    ast_unload_realtime("voicemail");
11845    ast_unload_realtime("voicemail_data");
11846 
11847    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11848       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11849          return 0;
11850       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11851          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11852          ucfg = NULL;
11853       }
11854       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11855       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11856          ast_config_destroy(ucfg);
11857          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11858          return 0;
11859       }
11860    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11861       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11862       return 0;
11863    } else {
11864       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11865       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11866          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11867          ucfg = NULL;
11868       }
11869    }
11870 
11871    res = actual_load_config(reload, cfg, ucfg);
11872 
11873    ast_config_destroy(cfg);
11874    ast_config_destroy(ucfg);
11875 
11876    return res;
11877 }

static int load_module ( void   )  [static]

Definition at line 13138 of file app_voicemail_imapstorage.c.

References ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_data_register_multiple, ast_install_vm_functions(), ast_log(), AST_LOG_WARNING, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application_xml, ast_taskprocessor_get(), AST_TEST_REGISTER, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), inprocess_cmp_fn(), inprocess_hash_fn(), load_config(), manager_list_voicemail_users(), messagecount(), RQ_CHAR, RQ_UINTEGER3, sayname(), SENTINEL, vm_box_exists(), vm_exec(), vm_execmain(), vmauthenticate(), and vmsayname_exec().

13139 {
13140    int res;
13141    my_umask = umask(0);
13142    umask(my_umask);
13143 
13144    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13145       return AST_MODULE_LOAD_DECLINE;
13146    }
13147 
13148    /* compute the location of the voicemail spool directory */
13149    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13150    
13151    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13152       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13153    }
13154 
13155    if ((res = load_config(0)))
13156       return res;
13157 
13158    res = ast_register_application_xml(app, vm_exec);
13159    res |= ast_register_application_xml(app2, vm_execmain);
13160    res |= ast_register_application_xml(app3, vm_box_exists);
13161    res |= ast_register_application_xml(app4, vmauthenticate);
13162    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13163    res |= ast_custom_function_register(&mailbox_exists_acf);
13164    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13165 #ifdef TEST_FRAMEWORK
13166    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13167    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13168    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13169    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13170    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13171 #endif
13172 
13173    if (res)
13174       return res;
13175 
13176    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13177    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13178 
13179    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13180    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13181    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13182 
13183    return res;
13184 }

static int make_dir ( char *  dest,
int  len,
const char *  context,
const char *  ext,
const char *  folder 
) [static]

Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.

Parameters:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The length of the path string that was written out.
context 
ext 
folder 

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1646 of file app_voicemail_imapstorage.c.

Referenced by copy_message(), create_dirpath(), make_email_file(), manager_list_voicemail_users(), notify_new_message(), and prep_email_sub_vars().

01647 {
01648    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01649 }

static void make_email_file ( FILE *  p,
char *  srcemail,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  attach,
char *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
int  imap,
const char *  flag 
) [static]

Creates the email file to be sent to indicate a new voicemail exists for a user.

Parameters:
p The output file to generate the email contents into.
srcemail The email address to send the email to, presumably the email address for the owner of the mailbox.
vmu The voicemail user who is sending the voicemail.
msgnum The message index in the mailbox folder.
context 
mailbox The voicemail box to read the voicemail to be notified in this email.
fromfolder 
cidnum The caller ID number.
cidname The caller ID name.
attach the name of the sound file to be attached to the email, if attach_user_voicemail == 1.
attach2 
format The message sound file format. i.e. .wav
duration The time of the message content, in seconds.
attach_user_voicemail if 1, the sound file is attached to the email.
chan 
category 
imap if == 1, indicates the target folder for the email notification to be sent to will be an IMAP mailstore. This causes additional mailbox headers to be set, which would facilitate searching for the email in the destination IMAP folder.
flag The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.

Definition at line 4541 of file app_voicemail_imapstorage.c.

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

Referenced by sendmail().

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

static int make_file ( char *  dest,
const int  len,
const char *  dir,
const int  num 
) [static]

Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.

Parameters:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The length of the path string that was written out.
dir 
num 

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1663 of file app_voicemail_imapstorage.c.

Referenced by advanced_options(), close_mailbox(), copy_message(), forward_message(), leave_voicemail(), make_email_file(), notify_new_message(), play_message(), prep_email_sub_vars(), resequence_mailbox(), save_to_folder(), vm_execmain(), and vm_forwardoptions().

01664 {
01665    return snprintf(dest, len, "%s/msg%04d", dir, num);
01666 }

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

Manager list voicemail users command.

Definition at line 11669 of file app_voicemail_imapstorage.c.

References AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_ack(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::context, count_messages(), ast_vm_user::dialout, ast_vm_user::email, ast_vm_user::exit, ast_vm_user::fullname, inboxcount(), ast_vm_user::language, ast_vm_user::mailbox, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, ast_vm_user::saydurationm, ast_vm_user::serveremail, ast_vm_user::uniqueid, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_OPERATOR, VM_REVIEW, VM_SAYCID, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by load_module().

11670 {
11671    struct ast_vm_user *vmu = NULL;
11672    const char *id = astman_get_header(m, "ActionID");
11673    char actionid[128] = "";
11674 
11675    if (!ast_strlen_zero(id))
11676       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11677 
11678    AST_LIST_LOCK(&users);
11679 
11680    if (AST_LIST_EMPTY(&users)) {
11681       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11682       AST_LIST_UNLOCK(&users);
11683       return RESULT_SUCCESS;
11684    }
11685    
11686    astman_send_ack(s, m, "Voicemail user list will follow");
11687    
11688    AST_LIST_TRAVERSE(&users, vmu, list) {
11689       char dirname[256];
11690 
11691 #ifdef IMAP_STORAGE
11692       int new, old;
11693       inboxcount(vmu->mailbox, &new, &old);
11694 #endif
11695       
11696       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11697       astman_append(s,
11698          "%s"
11699          "Event: VoicemailUserEntry\r\n"
11700          "VMContext: %s\r\n"
11701          "VoiceMailbox: %s\r\n"
11702          "Fullname: %s\r\n"
11703          "Email: %s\r\n"
11704          "Pager: %s\r\n"
11705          "ServerEmail: %s\r\n"
11706          "MailCommand: %s\r\n"
11707          "Language: %s\r\n"
11708          "TimeZone: %s\r\n"
11709          "Callback: %s\r\n"
11710          "Dialout: %s\r\n"
11711          "UniqueID: %s\r\n"
11712          "ExitContext: %s\r\n"
11713          "SayDurationMinimum: %d\r\n"
11714          "SayEnvelope: %s\r\n"
11715          "SayCID: %s\r\n"
11716          "AttachMessage: %s\r\n"
11717          "AttachmentFormat: %s\r\n"
11718          "DeleteMessage: %s\r\n"
11719          "VolumeGain: %.2f\r\n"
11720          "CanReview: %s\r\n"
11721          "CallOperator: %s\r\n"
11722          "MaxMessageCount: %d\r\n"
11723          "MaxMessageLength: %d\r\n"
11724          "NewMessageCount: %d\r\n"
11725 #ifdef IMAP_STORAGE
11726          "OldMessageCount: %d\r\n"
11727          "IMAPUser: %s\r\n"
11728 #endif
11729          "\r\n",
11730          actionid,
11731          vmu->context,
11732          vmu->mailbox,
11733          vmu->fullname,
11734          vmu->email,
11735          vmu->pager,
11736          ast_strlen_zero(vmu->serveremail) ? serveremail : vmu->serveremail,
11737          mailcmd,
11738          vmu->language,
11739          vmu->zonetag,
11740          vmu->callback,
11741          vmu->dialout,
11742          vmu->uniqueid,
11743          vmu->exit,
11744          vmu->saydurationm,
11745          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11746          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11747          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11748          vmu->attachfmt,
11749          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11750          vmu->volgain,
11751          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11752          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11753          vmu->maxmsg,
11754          vmu->maxsecs,
11755 #ifdef IMAP_STORAGE
11756          new, old, vmu->imapuser
11757 #else
11758          count_messages(vmu, dirname)
11759 #endif
11760          );
11761    }     
11762    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11763 
11764    AST_LIST_UNLOCK(&users);
11765 
11766    return RESULT_SUCCESS;
11767 }

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

Definition at line 11490 of file app_voicemail_imapstorage.c.

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

Referenced by start_poll_thread().

11491 {
11492    while (poll_thread_run) {
11493       struct timespec ts = { 0, };
11494       struct timeval wait;
11495 
11496       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11497       ts.tv_sec = wait.tv_sec;
11498       ts.tv_nsec = wait.tv_usec * 1000;
11499 
11500       ast_mutex_lock(&poll_lock);
11501       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11502       ast_mutex_unlock(&poll_lock);
11503 
11504       if (!poll_thread_run)
11505          break;
11506 
11507       poll_subscribed_mailboxes();
11508    }
11509 
11510    return NULL;
11511 }

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

Definition at line 1724 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

Referenced by acf_mailbox_exists(), adsi_load_vmail(), copy_message(), get_folder(), notify_new_message(), open_mailbox(), save_to_folder(), vm_box_exists(), and vm_execmain().

01725 {
01726 #ifdef IMAP_STORAGE
01727    if (vmu && id == 0) {
01728       return vmu->imapfolder;
01729    }
01730 #endif
01731    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01732 }

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

Definition at line 5391 of file app_voicemail_imapstorage.c.

References __has_voicemail().

Referenced by load_module().

05392 {
05393    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05394 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11513 of file app_voicemail_imapstorage.c.

References ast_free.

Referenced by handle_unsubscribe().

11514 {
11515    ast_free(mwi_sub);
11516 }

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

Definition at line 11601 of file app_voicemail_imapstorage.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_SUB, ast_free, ast_log(), ast_strdup, ast_taskprocessor_push(), mwi_sub_task::context, handle_subscribe(), LOG_ERROR, mwi_sub_task::mailbox, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

11602 {
11603    struct mwi_sub_task *mwist;
11604    
11605    if (ast_event_get_type(event) != AST_EVENT_SUB)
11606       return;
11607 
11608    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11609       return;
11610 
11611    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11612       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11613       return;
11614    }
11615    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11616    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11617    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11618    
11619    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11620       ast_free(mwist);
11621    }
11622 }

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

Definition at line 11575 of file app_voicemail_imapstorage.c.

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

Referenced by start_poll_thread().

11576 {
11577    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11578 
11579    if (!uniqueid) {
11580       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11581       return;
11582    }
11583 
11584    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11585       ast_free(uniqueid);
11586       return;
11587    }
11588 
11589    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11590       ast_free(uniqueid);
11591       return;
11592    }
11593 
11594    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11595    *uniqueid = u;
11596    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11597       ast_free(uniqueid);
11598    }
11599 }

static int notify_new_message ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  msgnum,
long  duration,
char *  fmt,
char *  cidnum,
char *  cidname,
const char *  flag 
) [static]

Sends email notification that a user has a new voicemail waiting for them.

Parameters:
chan 
vmu 
vms 
msgnum 
duration 
fmt 
cidnum The Caller ID phone number value.
cidname The Caller ID name value.
flag 
Returns:
zero on success, -1 on error.

Definition at line 7074 of file app_voicemail_imapstorage.c.

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

Referenced by copy_message(), and leave_voicemail().

07075 {
07076    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07077    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07078    const char *category;
07079    char *myserveremail = serveremail;
07080 
07081    ast_channel_lock(chan);
07082    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07083       category = ast_strdupa(category);
07084    }
07085    ast_channel_unlock(chan);
07086 
07087 #ifndef IMAP_STORAGE
07088    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07089 #else
07090    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07091 #endif
07092    make_file(fn, sizeof(fn), todir, msgnum);
07093    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07094 
07095    if (!ast_strlen_zero(vmu->attachfmt)) {
07096       if (strstr(fmt, vmu->attachfmt))
07097          fmt = vmu->attachfmt;
07098       else
07099          ast_log(AST_LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'.  Falling back to default format for '%s@%s'.\n", vmu->attachfmt, fmt, vmu->mailbox, vmu->context);
07100    }
07101 
07102    /* Attach only the first format */
07103    fmt = ast_strdupa(fmt);
07104    stringp = fmt;
07105    strsep(&stringp, "|");
07106 
07107    if (!ast_strlen_zero(vmu->serveremail))
07108       myserveremail = vmu->serveremail;
07109 
07110    if (!ast_strlen_zero(vmu->email)) {
07111       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07112 
07113       if (attach_user_voicemail)
07114          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07115 
07116       /* XXX possible imap issue, should category be NULL XXX */
07117       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07118 
07119       if (attach_user_voicemail)
07120          DISPOSE(todir, msgnum);
07121    }
07122 
07123    if (!ast_strlen_zero(vmu->pager)) {
07124       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07125    }
07126 
07127    if (ast_test_flag(vmu, VM_DELETE))
07128       DELETE(todir, msgnum, fn, vmu);
07129 
07130    /* Leave voicemail for someone */
07131    if (ast_app_has_voicemail(ext_context, NULL)) 
07132       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07133 
07134    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07135 
07136    ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
07137    run_externnotify(vmu->context, vmu->mailbox, flag);
07138 
07139 #ifdef IMAP_STORAGE
07140    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07141    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07142       vm_imap_delete(NULL, vms->curmsg, vmu);
07143       vms->newmessages--;  /* Fix new message count */
07144    }
07145 #endif
07146 
07147    return 0;
07148 }

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

utility used by base_encode()

Definition at line 4261 of file app_voicemail_imapstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04262 {
04263    if (bio->linelength >= BASELINELEN) {
04264       if (fputs(ENDL, so) == EOF) {
04265          return -1;
04266       }
04267 
04268       bio->linelength = 0;
04269    }
04270 
04271    if (putc(((unsigned char) c), so) == EOF) {
04272       return -1;
04273    }
04274 
04275    bio->linelength++;
04276 
04277    return 1;
04278 }

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

Definition at line 7923 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

07924 {
07925    int count_msg, last_msg;
07926 
07927    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07928 
07929    /* Rename the member vmbox HERE so that we don't try to return before
07930     * we know what's going on.
07931     */
07932    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07933 
07934    /* Faster to make the directory than to check if it exists. */
07935    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07936 
07937    /* traverses directory using readdir (or select query for ODBC) */
07938    count_msg = count_messages(vmu, vms->curdir);
07939    if (count_msg < 0) {
07940       return count_msg;
07941    } else {
07942       vms->lastmsg = count_msg - 1;
07943    }
07944 
07945    if (vm_allocate_dh(vms, vmu, count_msg)) {
07946       return -1;
07947    }
07948 
07949    /*
07950    The following test is needed in case sequencing gets messed up.
07951    There appears to be more than one way to mess up sequence, so
07952    we will not try to find all of the root causes--just fix it when
07953    detected.
07954    */
07955 
07956    if (vm_lock_path(vms->curdir)) {
07957       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07958       return ERROR_LOCK_PATH;
07959    }
07960 
07961    /* for local storage, checks directory for messages up to maxmsg limit */
07962    last_msg = last_message_index(vmu, vms->curdir);
07963    ast_unlock_path(vms->curdir);
07964 
07965    if (last_msg < -1) {
07966       return last_msg;
07967    } else if (vms->lastmsg != last_msg) {
07968       ast_log(LOG_NOTICE, "Resequencing Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
07969       resequence_mailbox(vmu, vms->curdir, count_msg);
07970    }
07971 
07972    return 0;
07973 }

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

Definition at line 7697 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_vi(), vm_browse_messages_zh(), and vm_execmain().

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

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

Definition at line 7583 of file app_voicemail_imapstorage.c.

References ast_callerid_parse(), ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_say_digit_str(), ast_stream_and_wait(), ast_strlen_zero(), ast_verb, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

07584 {
07585    int res = 0;
07586    int i;
07587    char *callerid, *name;
07588    char prefile[PATH_MAX] = "";
07589    
07590 
07591    /* If voicemail cid is not enabled, or we didn't get cid or context from
07592     * the attribute file, leave now.
07593     *
07594     * TODO Still need to change this so that if this function is called by the
07595     * message envelope (and someone is explicitly requesting to hear the CID),
07596     * it does not check to see if CID is enabled in the config file.
07597     */
07598    if ((cid == NULL)||(context == NULL))
07599       return res;
07600 
07601    /* Strip off caller ID number from name */
07602    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07603    ast_callerid_parse(cid, &name, &callerid);
07604    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07605       /* Check for internal contexts and only */
07606       /* say extension when the call didn't come from an internal context in the list */
07607       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07608          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07609          if ((strcmp(cidinternalcontexts[i], context) == 0))
07610             break;
07611       }
07612       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07613          if (!res) {
07614             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07615             if (!ast_strlen_zero(prefile)) {
07616             /* See if we can find a recorded name for this person instead of their extension number */
07617                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07618                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07619                   if (!callback)
07620                      res = wait_file2(chan, vms, "vm-from");
07621                   res = ast_stream_and_wait(chan, prefile, "");
07622                } else {
07623                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07624                   /* Say "from extension" as one saying to sound smoother */
07625                   if (!callback)
07626                      res = wait_file2(chan, vms, "vm-from-extension");
07627                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07628                }
07629             }
07630          }
07631       } else if (!res) {
07632          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07633          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07634          if (!callback)
07635             res = wait_file2(chan, vms, "vm-from-phonenumber");
07636          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07637       }
07638    } else {
07639       /* Number unknown */
07640       ast_debug(1, "VM-CID: From an unknown number\n");
07641       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07642       res = wait_file2(chan, vms, "vm-unknown-caller");
07643    }
07644    return res;
07645 }

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

Definition at line 7494 of file app_voicemail_imapstorage.c.

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

Referenced by play_message().

07495 {
07496    int res = 0;
07497 
07498    if (!ast_strlen_zero(category))
07499       res = ast_play_and_wait(chan, category);
07500 
07501    if (res) {
07502       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07503       res = 0;
07504    }
07505 
07506    return res;
07507 }

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

Definition at line 7509 of file app_voicemail_imapstorage.c.

References AST_DIGIT_ANY, ast_get_time_t(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), AST_LOG_WARNING, ast_say_date_with_format, ast_strlen_zero(), ast_tvnow(), pbx_builtin_setvar_helper(), and ast_vm_user::zonetag.

Referenced by advanced_options(), and play_message().

07510 {
07511    int res = 0;
07512    struct vm_zone *the_zone = NULL;
07513    time_t t;
07514 
07515    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07516       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07517       return 0;
07518    }
07519 
07520    /* Does this user have a timezone specified? */
07521    if (!ast_strlen_zero(vmu->zonetag)) {
07522       /* Find the zone in the list */
07523       struct vm_zone *z;
07524       AST_LIST_LOCK(&zones);
07525       AST_LIST_TRAVERSE(&zones, z, list) {
07526          if (!strcmp(z->name, vmu->zonetag)) {
07527             the_zone = z;
07528             break;
07529          }
07530       }
07531       AST_LIST_UNLOCK(&zones);
07532    }
07533 
07534 /* No internal variable parsing for now, so we'll comment it out for the time being */
07535 #if 0
07536    /* Set the DIFF_* variables */
07537    ast_localtime(&t, &time_now, NULL);
07538    tv_now = ast_tvnow();
07539    ast_localtime(&tv_now, &time_then, NULL);
07540 
07541    /* Day difference */
07542    if (time_now.tm_year == time_then.tm_year)
07543       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07544    else
07545       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07546    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07547 
07548    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07549 #endif
07550    if (the_zone) {
07551       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07552    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07553       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07554    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07555       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07556    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07557       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
07558    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07559       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07560    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07561       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07562    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07563       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07564    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07565       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
07566    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07567       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07568    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07569       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07570    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07571       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL);
07572    } else {
07573       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07574    }
07575 #if 0
07576    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07577 #endif
07578    return res;
07579 }

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

Definition at line 7647 of file app_voicemail_imapstorage.c.

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

Referenced by play_message().

07648 {
07649    int res = 0;
07650    int durationm;
07651    int durations;
07652    /* Verify that we have a duration for the message */
07653    if (duration == NULL)
07654       return res;
07655 
07656    /* Convert from seconds to minutes */
07657    durations = atoi(duration);
07658    durationm = (durations / 60);
07659 
07660    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07661 
07662    if ((!res) && (durationm >= minduration)) {
07663       res = wait_file2(chan, vms, "vm-duration");
07664 
07665       /* POLISH syntax */
07666       if (!strncasecmp(chan->language, "pl", 2)) {
07667          div_t num = div(durationm, 10);
07668 
07669          if (durationm == 1) {
07670             res = ast_play_and_wait(chan, "digits/1z");
07671             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07672          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07673             if (num.rem == 2) {
07674                if (!num.quot) {
07675                   res = ast_play_and_wait(chan, "digits/2-ie");
07676                } else {
07677                   res = say_and_wait(chan, durationm - 2 , chan->language);
07678                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07679                }
07680             } else {
07681                res = say_and_wait(chan, durationm, chan->language);
07682             }
07683             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07684          } else {
07685             res = say_and_wait(chan, durationm, chan->language);
07686             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07687          }
07688       /* DEFAULT syntax */
07689       } else {
07690          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07691          res = wait_file2(chan, vms, "vm-minutes");
07692       }
07693    }
07694    return res;
07695 }

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

Definition at line 13451 of file app_voicemail_imapstorage.c.

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

Referenced by leave_voicemail(), vm_forwardoptions(), vm_newuser(), vm_options(), and vm_tempgreeting().

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11462 of file app_voicemail_imapstorage.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11463 {
11464    int new = 0, old = 0, urgent = 0;
11465 
11466    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11467 
11468    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11469       mwi_sub->old_urgent = urgent;
11470       mwi_sub->old_new = new;
11471       mwi_sub->old_old = old;
11472       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11473       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11474    }
11475 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11477 of file app_voicemail_imapstorage.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), and poll_subscribed_mailbox().

Referenced by mb_poll_thread().

11478 {
11479    struct mwi_sub *mwi_sub;
11480 
11481    AST_RWLIST_RDLOCK(&mwi_subs);
11482    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11483       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11484          poll_subscribed_mailbox(mwi_sub);
11485       }
11486    }
11487    AST_RWLIST_UNLOCK(&mwi_subs);
11488 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

  • all the globalflags
  • the saydurationminfo
  • the callcontext
  • the dialcontext
  • the exitcontext
  • vmmaxsecs, vmmaxmsg, maxdeletedmsg
  • volume gain
  • emailsubject, emailbody set to NULL

Definition at line 1021 of file app_voicemail_imapstorage.c.

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

Referenced by actual_load_config(), append_mailbox(), AST_TEST_DEFINE(), and find_user_realtime().

01022 {
01023    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
01024    vmu->passwordlocation = passwordlocation;
01025    if (saydurationminfo) {
01026       vmu->saydurationm = saydurationminfo;
01027    }
01028    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
01029    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
01030    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
01031    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
01032    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
01033    if (vmminsecs) {
01034       vmu->minsecs = vmminsecs;
01035    }
01036    if (vmmaxsecs) {
01037       vmu->maxsecs = vmmaxsecs;
01038    }
01039    if (maxmsg) {
01040       vmu->maxmsg = maxmsg;
01041    }
01042    if (maxdeletedmsg) {
01043       vmu->maxdeletedmsg = maxdeletedmsg;
01044    }
01045    vmu->volgain = volgain;
01046    ast_free(vmu->emailsubject);
01047    vmu->emailsubject = NULL;
01048    ast_free(vmu->emailbody);
01049    vmu->emailbody = NULL;
01050 #ifdef IMAP_STORAGE
01051    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
01052 #endif
01053 }

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

Definition at line 4349 of file app_voicemail_imapstorage.c.

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

Referenced by make_email_file(), and sendpage().

04350 {
04351    char callerid[256];
04352    char num[12];
04353    char fromdir[256], fromfile[256];
04354    struct ast_config *msg_cfg;
04355    const char *origcallerid, *origtime;
04356    char origcidname[80], origcidnum[80], origdate[80];
04357    int inttime;
04358    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04359 
04360    /* Prepare variables for substitution in email body and subject */
04361    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04362    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04363    snprintf(num, sizeof(num), "%d", msgnum);
04364    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04365    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04366    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04367    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04368       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04369    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04370    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04371    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04372    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04373    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04374 
04375    /* Retrieve info from VM attribute file */
04376    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04377    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04378    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04379       strcat(fromfile, ".txt");
04380    }
04381    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04382       if (option_debug > 0) {
04383          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04384       }
04385       return;
04386    }
04387 
04388    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04389       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04390       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04391       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04392       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04393    }
04394 
04395    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04396       struct timeval tv = { inttime, };
04397       struct ast_tm tm;
04398       ast_localtime(&tv, &tm, NULL);
04399       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04400       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04401    }
04402    ast_config_destroy(msg_cfg);
04403 }

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

Definition at line 7037 of file app_voicemail_imapstorage.c.

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_strdupa, and ast_strlen_zero().

Referenced by append_mailbox(), notify_new_message(), poll_subscribed_mailbox(), and vm_execmain().

07038 {
07039    struct ast_event *event;
07040    char *mailbox, *context;
07041 
07042    /* Strip off @default */
07043    context = mailbox = ast_strdupa(box);
07044    strsep(&context, "@");
07045    if (ast_strlen_zero(context))
07046       context = "default";
07047 
07048    if (!(event = ast_event_new(AST_EVENT_MWI,
07049          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07050          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07051          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07052          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07053          AST_EVENT_IE_END))) {
07054       return;
07055    }
07056 
07057    ast_event_queue_and_cache(event);
07058 }

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

Definition at line 12568 of file app_voicemail_imapstorage.c.

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

Referenced by actual_load_config(), and append_mailbox().

12568                                                                                            {
12569    struct ast_config *pwconf;
12570    struct ast_flags config_flags = { 0 };
12571 
12572    pwconf = ast_config_load(secretfn, config_flags);
12573    if (pwconf) {
12574       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12575       if (val) {
12576          ast_copy_string(password, val, passwordlen);
12577          ast_config_destroy(pwconf);
12578          return;
12579       }
12580       ast_config_destroy(pwconf);
12581    }
12582    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12583 }

static int reload ( void   )  [static]

Definition at line 13098 of file app_voicemail_imapstorage.c.

References load_config().

13099 {
13100    return load_config(1);
13101 }

static void rename_file ( char *  sfn,
char *  dfn 
) [static]

Renames a message in a mailbox folder.

Parameters:
sfn The path to the mailbox information and data file to be renamed.
dfn The path for where the message data and information files will be renamed to.

This method is used by the RENAME macro when mailboxes are stored on the filesystem. (not ODBC and not IMAP).

Definition at line 4019 of file app_voicemail_imapstorage.c.

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

04020 {
04021    char stxt[PATH_MAX];
04022    char dtxt[PATH_MAX];
04023    ast_filerename(sfn, dfn, NULL);
04024    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04025    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04026    if (ast_check_realtime("voicemail_data")) {
04027       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04028    }
04029    rename(stxt, dtxt);
04030 }

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

Definition at line 6163 of file app_voicemail_imapstorage.c.

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

Referenced by open_mailbox().

06164 {
06165    /* we know the actual number of messages, so stop process when number is hit */
06166 
06167    int x, dest;
06168    char sfn[PATH_MAX];
06169    char dfn[PATH_MAX];
06170 
06171    if (vm_lock_path(dir)) {
06172       return ERROR_LOCK_PATH;
06173    }
06174 
06175    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06176       make_file(sfn, sizeof(sfn), dir, x);
06177       if (EXISTS(dir, x, sfn, NULL)) {
06178 
06179          if (x != dest) {
06180             make_file(dfn, sizeof(dfn), dir, dest);
06181             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06182          }
06183 
06184          dest++;
06185       }
06186    }
06187    ast_unlock_path(dir);
06188 
06189    return dest;
06190 }

static int reset_user_pw ( const char *  context,
const char *  mailbox,
const char *  newpass 
) [static]

Resets a user password to a specified password.

Parameters:
context 
mailbox 
newpass This does the actual change password work, called by the vm_change_password() function.
Returns:
zero on success, -1 on error.

Definition at line 1491 of file app_voicemail_imapstorage.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::context, ast_vm_user::mailbox, and ast_vm_user::password.

Referenced by vm_change_password(), and vm_change_password_shell().

01492 {
01493    /* This function could be made to generate one from a database, too */
01494    struct ast_vm_user *cur;
01495    int res = -1;
01496    AST_LIST_LOCK(&users);
01497    AST_LIST_TRAVERSE(&users, cur, list) {
01498       if ((!context || !strcasecmp(context, cur->context)) &&
01499          (!strcasecmp(mailbox, cur->mailbox)))
01500             break;
01501    }
01502    if (cur) {
01503       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01504       res = 0;
01505    }
01506    AST_LIST_UNLOCK(&users);
01507    return res;
01508 }

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

Definition at line 5534 of file app_voicemail_imapstorage.c.

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

Referenced by forward_message(), notify_new_message(), poll_subscribed_mailbox(), and vm_execmain().

05535 {
05536    char arguments[255];
05537    char ext_context[256] = "";
05538    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05539    struct ast_smdi_mwi_message *mwi_msg;
05540 
05541    if (!ast_strlen_zero(context))
05542       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05543    else
05544       ast_copy_string(ext_context, extension, sizeof(ext_context));
05545 
05546    if (smdi_iface) {
05547       if (ast_app_has_voicemail(ext_context, NULL)) 
05548          ast_smdi_mwi_set(smdi_iface, extension);
05549       else
05550          ast_smdi_mwi_unset(smdi_iface, extension);
05551 
05552       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05553          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05554          if (!strncmp(mwi_msg->cause, "INV", 3))
05555             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05556          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05557             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05558          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05559          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05560       } else {
05561          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05562       }
05563    }
05564 
05565    if (!ast_strlen_zero(externnotify)) {
05566       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05567          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05568       } else {
05569          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05570          ast_debug(1, "Executing %s\n", arguments);
05571          ast_safe_system(arguments);
05572       }
05573    }
05574 }

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

Definition at line 6200 of file app_voicemail_imapstorage.c.

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

Referenced by close_mailbox(), and vm_execmain().

06201 {
06202 #ifdef IMAP_STORAGE
06203    /* we must use mbox(x) folder names, and copy the message there */
06204    /* simple. huh? */
06205    char sequence[10];
06206    char mailbox[256];
06207    int res;
06208 
06209    /* get the real IMAP message number for this message */
06210    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06211    
06212    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06213    ast_mutex_lock(&vms->lock);
06214    /* if save to Old folder, put in INBOX as read */
06215    if (box == OLD_FOLDER) {
06216       mail_setflag(vms->mailstream, sequence, "\\Seen");
06217       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06218    } else if (box == NEW_FOLDER) {
06219       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06220       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06221    }
06222    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06223       ast_mutex_unlock(&vms->lock);
06224       return 0;
06225    }
06226    /* Create the folder if it don't exist */
06227    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06228    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06229    if (mail_create(vms->mailstream, mailbox) == NIL) 
06230       ast_debug(5, "Folder exists.\n");
06231    else
06232       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06233    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06234    ast_mutex_unlock(&vms->lock);
06235    return res;
06236 #else
06237    char *dir = vms->curdir;
06238    char *username = vms->username;
06239    char *context = vmu->context;
06240    char sfn[PATH_MAX];
06241    char dfn[PATH_MAX];
06242    char ddir[PATH_MAX];
06243    const char *dbox = mbox(vmu, box);
06244    int x, i;
06245    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06246 
06247    if (vm_lock_path(ddir))
06248       return ERROR_LOCK_PATH;
06249 
06250    x = last_message_index(vmu, ddir) + 1;
06251 
06252    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06253       x--;
06254       for (i = 1; i <= x; i++) {
06255          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06256          make_file(sfn, sizeof(sfn), ddir, i);
06257          make_file(dfn, sizeof(dfn), ddir, i - 1);
06258          if (EXISTS(ddir, i, sfn, NULL)) {
06259             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06260          } else
06261             break;
06262       }
06263    } else {
06264       if (x >= vmu->maxmsg) {
06265          ast_unlock_path(ddir);
06266          return -1;
06267       }
06268    }
06269    make_file(sfn, sizeof(sfn), dir, msg);
06270    make_file(dfn, sizeof(dfn), ddir, x);
06271    if (strcmp(sfn, dfn)) {
06272       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06273    }
06274    ast_unlock_path(ddir);
06275 #endif
06276    return 0;
06277 }

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

Definition at line 12554 of file app_voicemail_imapstorage.c.

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

Referenced by load_module(), and vmsayname_exec().

12555 {
12556    int res = -1;
12557    char dir[PATH_MAX];
12558    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12559    ast_debug(2, "About to try retrieving name file %s\n", dir);
12560    RETRIEVE(dir, -1, mailbox, context);
12561    if (ast_fileexists(dir, NULL, NULL)) {
12562       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12563    }
12564    DISPOSE(dir, -1);
12565    return res;
12566 }

static int sendmail ( char *  srcemail,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  attach,
char *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
const char *  flag 
) [static]

Definition at line 4864 of file app_voicemail_imapstorage.c.

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

Referenced by forward_message(), and notify_new_message().

04865 {
04866    FILE *p = NULL;
04867    char tmp[80] = "/tmp/astmail-XXXXXX";
04868    char tmp2[256];
04869    char *stringp;
04870 
04871    if (vmu && ast_strlen_zero(vmu->email)) {
04872       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04873       return(0);
04874    }
04875 
04876    /* Mail only the first format */
04877    format = ast_strdupa(format);
04878    stringp = format;
04879    strsep(&stringp, "|");
04880 
04881    if (!strcmp(format, "wav49"))
04882       format = "WAV";
04883    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04884    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04885       command hangs */
04886    if ((p = vm_mkftemp(tmp)) == NULL) {
04887       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04888       return -1;
04889    } else {
04890       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04891       fclose(p);
04892       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04893       ast_safe_system(tmp2);
04894       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04895    }
04896    return 0;
04897 }

static int sendpage ( char *  srcemail,
char *  pager,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
int  duration,
struct ast_vm_user vmu,
const char *  category,
const char *  flag 
) [static]

Definition at line 4899 of file app_voicemail_imapstorage.c.

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

Referenced by notify_new_message().

04900 {
04901    char enc_cidnum[256], enc_cidname[256];
04902    char date[256];
04903    char host[MAXHOSTNAMELEN] = "";
04904    char who[256];
04905    char dur[PATH_MAX];
04906    char tmp[80] = "/tmp/astmail-XXXXXX";
04907    char tmp2[PATH_MAX];
04908    struct ast_tm tm;
04909    FILE *p;
04910    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04911 
04912    if (!str1 || !str2) {
04913       ast_free(str1);
04914       ast_free(str2);
04915       return -1;
04916    }
04917 
04918    if (cidnum) {
04919       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04920    }
04921    if (cidname) {
04922       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04923    }
04924 
04925    if ((p = vm_mkftemp(tmp)) == NULL) {
04926       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04927       ast_free(str1);
04928       ast_free(str2);
04929       return -1;
04930    }
04931    gethostname(host, sizeof(host)-1);
04932    if (strchr(srcemail, '@')) {
04933       ast_copy_string(who, srcemail, sizeof(who));
04934    } else {
04935       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04936    }
04937    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04938    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04939    fprintf(p, "Date: %s\n", date);
04940 
04941    /* Reformat for custom pager format */
04942    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04943 
04944    if (!ast_strlen_zero(pagerfromstring)) {
04945       struct ast_channel *ast;
04946       if ((ast = ast_dummy_channel_alloc())) {
04947          char *ptr;
04948          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04949          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04950 
04951          if (check_mime(ast_str_buffer(str1))) {
04952             int first_line = 1;
04953             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04954             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04955                *ptr = '\0';
04956                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04957                first_line = 0;
04958                /* Substring is smaller, so this will never grow */
04959                ast_str_set(&str2, 0, "%s", ptr + 1);
04960             }
04961             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04962          } else {
04963             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04964          }
04965          ast = ast_channel_unref(ast);
04966       } else {
04967          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04968       }
04969    } else {
04970       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04971    }
04972 
04973    if (check_mime(vmu->fullname)) {
04974       int first_line = 1;
04975       char *ptr;
04976       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04977       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04978          *ptr = '\0';
04979          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04980          first_line = 0;
04981          /* Substring is smaller, so this will never grow */
04982          ast_str_set(&str2, 0, "%s", ptr + 1);
04983       }
04984       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04985    } else {
04986       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
04987    }
04988 
04989    if (!ast_strlen_zero(pagersubject)) {
04990       struct ast_channel *ast;
04991       if ((ast = ast_dummy_channel_alloc())) {
04992          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04993          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
04994          if (check_mime(ast_str_buffer(str1))) {
04995             int first_line = 1;
04996             char *ptr;
04997             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04998             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04999                *ptr = '\0';
05000                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
05001                first_line = 0;
05002                /* Substring is smaller, so this will never grow */
05003                ast_str_set(&str2, 0, "%s", ptr + 1);
05004             }
05005             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
05006          } else {
05007             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
05008          }
05009          ast = ast_channel_unref(ast);
05010       } else {
05011          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05012       }
05013    } else {
05014       if (ast_strlen_zero(flag)) {
05015          fprintf(p, "Subject: New VM\n\n");
05016       } else {
05017          fprintf(p, "Subject: New %s VM\n\n", flag);
05018       }
05019    }
05020 
05021    if (pagerbody) {
05022       struct ast_channel *ast;
05023       if ((ast = ast_dummy_channel_alloc())) {
05024          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05025          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
05026          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
05027          ast = ast_channel_unref(ast);
05028       } else {
05029          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05030       }
05031    } else {
05032       fprintf(p, "New %s long %s msg in box %s\n"
05033             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
05034    }
05035 
05036    fclose(p);
05037    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
05038    ast_safe_system(tmp2);
05039    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
05040    ast_free(str1);
05041    ast_free(str2);
05042    return 0;
05043 }

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

Definition at line 11119 of file app_voicemail_imapstorage.c.

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, ast_variable::name, ast_variable::next, SENTINEL, and ast_variable::value.

Referenced by handle_voicemail_show_users().

11120 {
11121    struct ast_config *cfg;
11122    const char *cat = NULL;
11123 
11124    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11125       "context", context, SENTINEL))) {
11126       return CLI_FAILURE;
11127    }
11128 
11129    ast_cli(fd,
11130       "\n"
11131       "=============================================================\n"
11132       "=== Configured Voicemail Users ==============================\n"
11133       "=============================================================\n"
11134       "===\n");
11135 
11136    while ((cat = ast_category_browse(cfg, cat))) {
11137       struct ast_variable *var = NULL;
11138       ast_cli(fd,
11139          "=== Mailbox ...\n"
11140          "===\n");
11141       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11142          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11143       ast_cli(fd,
11144          "===\n"
11145          "=== ---------------------------------------------------------\n"
11146          "===\n");
11147    }
11148 
11149    ast_cli(fd,
11150       "=============================================================\n"
11151       "\n");
11152 
11153    ast_config_destroy(cfg);
11154 
11155    return CLI_SUCCESS;
11156 }

static void start_poll_thread ( void   )  [static]
static void stop_poll_thread ( void   )  [static]

Definition at line 11645 of file app_voicemail_imapstorage.c.

References ast_cond_signal, ast_event_unsubscribe(), ast_mutex_lock, ast_mutex_unlock, and AST_PTHREADT_NULL.

Referenced by actual_load_config(), and unload_module().

11646 {
11647    poll_thread_run = 0;
11648 
11649    if (mwi_sub_sub) {
11650       ast_event_unsubscribe(mwi_sub_sub);
11651       mwi_sub_sub = NULL;
11652    }
11653 
11654    if (mwi_unsub_sub) {
11655       ast_event_unsubscribe(mwi_unsub_sub);
11656       mwi_unsub_sub = NULL;
11657    }
11658 
11659    ast_mutex_lock(&poll_lock);
11660    ast_cond_signal(&poll_cond);
11661    ast_mutex_unlock(&poll_lock);
11662 
11663    pthread_join(poll_thread, NULL);
11664 
11665    poll_thread = AST_PTHREADT_NULL;
11666 }

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

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

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

Definition at line 991 of file app_voicemail_imapstorage.c.

Referenced by make_email_file(), and sendpage().

00992 {
00993    char *bufptr = buf;
00994    for (; *input; input++) {
00995       if (*input < 32) {
00996          continue;
00997       }
00998       *bufptr++ = *input;
00999       if (bufptr == buf + buflen - 1) {
01000          break;
01001       }
01002    }
01003    *bufptr = '\0';
01004    return buf;
01005 }

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

Definition at line 11791 of file app_voicemail_imapstorage.c.

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

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

11792 {
11793    char *current;
11794 
11795    /* Add 16 for fudge factor */
11796    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11797 
11798    ast_str_reset(str);
11799    
11800    /* Substitute strings \r, \n, and \t into the appropriate characters */
11801    for (current = (char *) value; *current; current++) {
11802       if (*current == '\\') {
11803          current++;
11804          if (!*current) {
11805             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11806             break;
11807          }
11808          switch (*current) {
11809          case '\\':
11810             ast_str_append(&str, 0, "\\");
11811             break;
11812          case 'r':
11813             ast_str_append(&str, 0, "\r");
11814             break;
11815          case 'n':
11816 #ifdef IMAP_STORAGE
11817             if (!str->used || str->str[str->used - 1] != '\r') {
11818                ast_str_append(&str, 0, "\r");
11819             }
11820 #endif
11821             ast_str_append(&str, 0, "\n");
11822             break;
11823          case 't':
11824             ast_str_append(&str, 0, "\t");
11825             break;
11826          default:
11827             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11828             break;
11829          }
11830       } else {
11831          ast_str_append(&str, 0, "%c", *current);
11832       }
11833    }
11834 
11835    return ast_str_buffer(str);
11836 }

static int unload_module ( void   )  [static]

Definition at line 13103 of file app_voicemail_imapstorage.c.

References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_manager_unregister(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), AST_TEST_UNREGISTER, ast_uninstall_vm_functions(), ast_unload_realtime(), ast_unregister_application(), free_vm_users(), free_vm_zones(), and stop_poll_thread().

13104 {
13105    int res;
13106 
13107    res = ast_unregister_application(app);
13108    res |= ast_unregister_application(app2);
13109    res |= ast_unregister_application(app3);
13110    res |= ast_unregister_application(app4);
13111    res |= ast_unregister_application(sayname_app);
13112    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13113    res |= ast_manager_unregister("VoicemailUsersList");
13114    res |= ast_data_unregister(NULL);
13115 #ifdef TEST_FRAMEWORK
13116    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13117    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13118    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13119    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13120    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13121 #endif
13122    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13123    ast_uninstall_vm_functions();
13124    ao2_ref(inprocess_container, -1);
13125 
13126    if (poll_thread != AST_PTHREADT_NULL)
13127       stop_poll_thread();
13128 
13129    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13130    ast_unload_realtime("voicemail");
13131    ast_unload_realtime("voicemail_data");
13132 
13133    free_vm_users();
13134    free_vm_zones();
13135    return res;
13136 }

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

Definition at line 1761 of file app_voicemail_imapstorage.c.

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

Referenced by open_mailbox().

01761                                                                                         {
01762 
01763    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01764 
01765    /* remove old allocation */
01766    if (vms->deleted) {
01767       ast_free(vms->deleted);
01768       vms->deleted = NULL;
01769    }
01770    if (vms->heard) {
01771       ast_free(vms->heard);
01772       vms->heard = NULL;
01773    }
01774    vms->dh_arraysize = 0;
01775 
01776    if (arraysize > 0) {
01777       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01778          return -1;
01779       }
01780       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01781          ast_free(vms->deleted);
01782          vms->deleted = NULL;
01783          return -1;
01784       }
01785       vms->dh_arraysize = arraysize;
01786    }
01787 
01788    return 0;
01789 }

static int vm_authenticate ( struct ast_channel chan,
char *  mailbox,
int  mailbox_size,
struct ast_vm_user res_vmu,
const char *  context,
const char *  prefix,
int  skipuser,
int  max_logins,
int  silent 
) [static]

Definition at line 9795 of file app_voicemail_imapstorage.c.

References adsi_begin(), adsi_login(), adsi_password(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, find_user(), ast_party_caller::id, ast_party_id::number, ast_vm_user::password, S_COR, ast_party_number::str, and ast_party_number::valid.

Referenced by vm_execmain(), and vmauthenticate().

09798 {
09799    int useadsi = 0, valid = 0, logretries = 0;
09800    char password[AST_MAX_EXTENSION]="", *passptr;
09801    struct ast_vm_user vmus, *vmu = NULL;
09802 
09803    /* If ADSI is supported, setup login screen */
09804    adsi_begin(chan, &useadsi);
09805    if (!skipuser && useadsi)
09806       adsi_login(chan);
09807    ast_test_suite_event_notify("PLAYBACK", "Message: vm-login");
09808    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09809       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09810       return -1;
09811    }
09812 
09813    /* Authenticate them and get their mailbox/password */
09814 
09815    while (!valid && (logretries < max_logins)) {
09816       /* Prompt for, and read in the username */
09817       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09818          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09819          return -1;
09820       }
09821       if (ast_strlen_zero(mailbox)) {
09822          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09823             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09824          } else {
09825             ast_verb(3, "Username not entered\n"); 
09826             return -1;
09827          }
09828       } else if (mailbox[0] == '*') {
09829          /* user entered '*' */
09830          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09831          if (ast_exists_extension(chan, chan->context, "a", 1,
09832             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09833             return -1;
09834          }
09835          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09836          mailbox[0] = '\0';
09837       }
09838 
09839       if (useadsi)
09840          adsi_password(chan);
09841 
09842       if (!ast_strlen_zero(prefix)) {
09843          char fullusername[80] = "";
09844          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09845          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09846          ast_copy_string(mailbox, fullusername, mailbox_size);
09847       }
09848 
09849       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09850       vmu = find_user(&vmus, context, mailbox);
09851       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09852          /* saved password is blank, so don't bother asking */
09853          password[0] = '\0';
09854       } else {
09855          ast_test_suite_event_notify("PLAYBACK", "Message: %s", vm_password);
09856          if (ast_streamfile(chan, vm_password, chan->language)) {
09857             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09858             return -1;
09859          }
09860          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09861             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09862             return -1;
09863          } else if (password[0] == '*') {
09864             /* user entered '*' */
09865             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09866             if (ast_exists_extension(chan, chan->context, "a", 1,
09867                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09868                mailbox[0] = '*';
09869                return -1;
09870             }
09871             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09872             mailbox[0] = '\0';
09873             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09874             vmu = NULL;
09875          }
09876       }
09877 
09878       if (vmu) {
09879          passptr = vmu->password;
09880          if (passptr[0] == '-') passptr++;
09881       }
09882       if (vmu && !strcmp(passptr, password))
09883          valid++;
09884       else {
09885          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09886          if (!ast_strlen_zero(prefix))
09887             mailbox[0] = '\0';
09888       }
09889       logretries++;
09890       if (!valid) {
09891          if (skipuser || logretries >= max_logins) {
09892             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect");
09893             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09894                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09895                return -1;
09896             }
09897          } else {
09898             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect-mailbox");
09899             if (useadsi)
09900                adsi_login(chan);
09901             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09902                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09903                return -1;
09904             }
09905          }
09906          if (ast_waitstream(chan, "")) /* Channel is hung up */
09907             return -1;
09908       }
09909    }
09910    if (!valid && (logretries >= max_logins)) {
09911       ast_stopstream(chan);
09912       ast_play_and_wait(chan, "vm-goodbye");
09913       return -1;
09914    }
09915    if (vmu && !skipuser) {
09916       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09917    }
09918    return 0;
09919 }

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

Definition at line 11014 of file app_voicemail_imapstorage.c.

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

Referenced by load_module().

11015 {
11016    struct ast_vm_user svm;
11017    char *context, *box;
11018    AST_DECLARE_APP_ARGS(args,
11019       AST_APP_ARG(mbox);
11020       AST_APP_ARG(options);
11021    );
11022    static int dep_warning = 0;
11023 
11024    if (ast_strlen_zero(data)) {
11025       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
11026       return -1;
11027    }
11028 
11029    if (!dep_warning) {
11030       dep_warning = 1;
11031       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
11032    }
11033 
11034    box = ast_strdupa(data);
11035 
11036    AST_STANDARD_APP_ARGS(args, box);
11037 
11038    if (args.options) {
11039    }
11040 
11041    if ((context = strchr(args.mbox, '@'))) {
11042       *context = '\0';
11043       context++;
11044    }
11045 
11046    if (find_user(&svm, context, args.mbox)) {
11047       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
11048    } else
11049       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
11050 
11051    return 0;
11052 }

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

Top level method to invoke the language variant vm_browse_messages_XX function.

Parameters:
chan The channel for the current user. We read the language property from this.
vms passed into the language-specific vm_browse_messages function.
vmu passed into the language-specific vm_browse_messages function.

The method to be invoked is determined by the value of language code property in the user's channel. The default (when unable to match) is to use english.

Returns:
zero on success, -1 on error.

Definition at line 9774 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

09775 {
09776    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09777       return vm_browse_messages_es(chan, vms, vmu);
09778    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09779       return vm_browse_messages_gr(chan, vms, vmu);
09780    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09781       return vm_browse_messages_he(chan, vms, vmu);
09782    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09783       return vm_browse_messages_it(chan, vms, vmu);
09784    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09785       return vm_browse_messages_pt(chan, vms, vmu);
09786    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09787       return vm_browse_messages_vi(chan, vms, vmu);
09788    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09789       return vm_browse_messages_zh(chan, vms, vmu);
09790    } else {                                             /* Default to English syntax */
09791       return vm_browse_messages_en(chan, vms, vmu);
09792    }
09793 }

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

Default English syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9613 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09614 {
09615    int cmd = 0;
09616 
09617    if (vms->lastmsg > -1) {
09618       cmd = play_message(chan, vmu, vms);
09619    } else {
09620       cmd = ast_play_and_wait(chan, "vm-youhave");
09621       if (!cmd) 
09622          cmd = ast_play_and_wait(chan, "vm-no");
09623       if (!cmd) {
09624          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09625          cmd = ast_play_and_wait(chan, vms->fn);
09626       }
09627       if (!cmd)
09628          cmd = ast_play_and_wait(chan, "vm-messages");
09629    }
09630    return cmd;
09631 }

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

Spanish syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9667 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09668 {
09669    int cmd;
09670 
09671    if (vms->lastmsg > -1) {
09672       cmd = play_message(chan, vmu, vms);
09673    } else {
09674       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09675       if (!cmd)
09676          cmd = ast_play_and_wait(chan, "vm-messages");
09677       if (!cmd) {
09678          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09679          cmd = ast_play_and_wait(chan, vms->fn);
09680       }
09681    }
09682    return cmd;
09683 }

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

Greek syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9561 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09562 {
09563    int cmd = 0;
09564 
09565    if (vms->lastmsg > -1) {
09566       cmd = play_message(chan, vmu, vms);
09567    } else {
09568       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09569       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09570          if (!cmd) {
09571             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09572             cmd = ast_play_and_wait(chan, vms->fn);
09573          }
09574          if (!cmd)
09575             cmd = ast_play_and_wait(chan, "vm-messages");
09576       } else {
09577          if (!cmd)
09578             cmd = ast_play_and_wait(chan, "vm-messages");
09579          if (!cmd) {
09580             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09581             cmd = ast_play_and_wait(chan, vms->fn);
09582          }
09583       }
09584    } 
09585    return cmd;
09586 }

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

Definition at line 9589 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09590 {
09591    int cmd = 0;
09592 
09593    if (vms->lastmsg > -1) {
09594       cmd = play_message(chan, vmu, vms);
09595    } else {
09596       if (!strcasecmp(vms->fn, "INBOX")) {
09597          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09598       } else {
09599          cmd = ast_play_and_wait(chan, "vm-nomessages");
09600       }
09601    }
09602    return cmd;
09603 }

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

Italian syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9641 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09642 {
09643    int cmd;
09644 
09645    if (vms->lastmsg > -1) {
09646       cmd = play_message(chan, vmu, vms);
09647    } else {
09648       cmd = ast_play_and_wait(chan, "vm-no");
09649       if (!cmd)
09650          cmd = ast_play_and_wait(chan, "vm-message");
09651       if (!cmd) {
09652          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09653          cmd = ast_play_and_wait(chan, vms->fn);
09654       }
09655    }
09656    return cmd;
09657 }

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

Portuguese syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9693 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09694 {
09695    int cmd;
09696 
09697    if (vms->lastmsg > -1) {
09698       cmd = play_message(chan, vmu, vms);
09699    } else {
09700       cmd = ast_play_and_wait(chan, "vm-no");
09701       if (!cmd) {
09702          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09703          cmd = ast_play_and_wait(chan, vms->fn);
09704       }
09705       if (!cmd)
09706          cmd = ast_play_and_wait(chan, "vm-messages");
09707    }
09708    return cmd;
09709 }

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

Vietnamese syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9747 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09748 {
09749    int cmd = 0;
09750 
09751    if (vms->lastmsg > -1) {
09752       cmd = play_message(chan, vmu, vms);
09753    } else {
09754       cmd = ast_play_and_wait(chan, "vm-no");
09755       if (!cmd) {
09756          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09757          cmd = ast_play_and_wait(chan, vms->fn);
09758       }
09759    }
09760    return cmd;
09761 }

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

Chinese (Taiwan)syntax for 'You have N messages' greeting.

Parameters:
chan 
vms 
vmu 
Returns:
zero on success, -1 on error.

Definition at line 9719 of file app_voicemail_imapstorage.c.

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

Referenced by vm_browse_messages().

09720 {
09721    int cmd;
09722 
09723    if (vms->lastmsg > -1) {
09724       cmd = play_message(chan, vmu, vms);
09725    } else {
09726       cmd = ast_play_and_wait(chan, "vm-you");
09727       if (!cmd) 
09728          cmd = ast_play_and_wait(chan, "vm-haveno");
09729       if (!cmd)
09730          cmd = ast_play_and_wait(chan, "vm-messages");
09731       if (!cmd) {
09732          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09733          cmd = ast_play_and_wait(chan, vms->fn);
09734       }
09735    }
09736    return cmd;
09737 }

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

The handler for the change password option.

Parameters:
vmu The voicemail user to work with.
newpassword The new password (that has been gathered from the appropriate prompting). This is called when a new user logs in for the first time and the option to force them to change their password is set. It is also called when the user wants to change their password from menu option '5' on the mailbox options menu.

Definition at line 1517 of file app_voicemail_imapstorage.c.

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

Referenced by vm_newuser(), and vm_options().

01518 {
01519    struct ast_config   *cfg = NULL;
01520    struct ast_variable *var = NULL;
01521    struct ast_category *cat = NULL;
01522    char *category = NULL, *value = NULL, *new = NULL;
01523    const char *tmp = NULL;
01524    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01525    char secretfn[PATH_MAX] = "";
01526    int found = 0;
01527 
01528    if (!change_password_realtime(vmu, newpassword))
01529       return;
01530 
01531    /* check if we should store the secret in the spool directory next to the messages */
01532    switch (vmu->passwordlocation) {
01533    case OPT_PWLOC_SPOOLDIR:
01534       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01535       if (write_password_to_file(secretfn, newpassword) == 0) {
01536          ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
01537          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01538          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01539          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01540          break;
01541       } else {
01542          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01543       }
01544       /* Fall-through */
01545    case OPT_PWLOC_VOICEMAILCONF:
01546       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01547          while ((category = ast_category_browse(cfg, category))) {
01548             if (!strcasecmp(category, vmu->context)) {
01549                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01550                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01551                   break;
01552                }
01553                value = strstr(tmp, ",");
01554                if (!value) {
01555                   new = ast_alloca(strlen(newpassword)+1);
01556                   sprintf(new, "%s", newpassword);
01557                } else {
01558                   new = ast_alloca((strlen(value) + strlen(newpassword) + 1));
01559                   sprintf(new, "%s%s", newpassword, value);
01560                }
01561                if (!(cat = ast_category_get(cfg, category))) {
01562                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01563                   break;
01564                }
01565                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01566                found = 1;
01567             }
01568          }
01569          /* save the results */
01570          if (found) {
01571             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
01572             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01573             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01574             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01575             break;
01576          }
01577       }
01578       /* Fall-through */
01579    case OPT_PWLOC_USERSCONF:
01580       /* check users.conf and update the password stored for the mailbox */
01581       /* if no vmsecret entry exists create one. */
01582       if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01583          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01584          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01585             ast_debug(4, "users.conf: %s\n", category);
01586             if (!strcasecmp(category, vmu->mailbox)) {
01587                if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
01588                   ast_debug(3, "looks like we need to make vmsecret!\n");
01589                   var = ast_variable_new("vmsecret", newpassword, "");
01590                } else {
01591                   var = NULL;
01592                }
01593                new = ast_alloca(strlen(newpassword) + 1);
01594                sprintf(new, "%s", newpassword);
01595                if (!(cat = ast_category_get(cfg, category))) {
01596                   ast_debug(4, "failed to get category!\n");
01597                   ast_free(var);
01598                   break;
01599                }
01600                if (!var) {
01601                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01602                } else {
01603                   ast_variable_append(cat, var);
01604                }
01605                found = 1;
01606                break;
01607             }
01608          }
01609          /* save the results and clean things up */
01610          if (found) {
01611             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
01612             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01613             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01614             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01615          }
01616       }
01617    }
01618 }

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

Definition at line 1620 of file app_voicemail_imapstorage.c.

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

Referenced by vm_newuser(), and vm_options().

01621 {
01622    char buf[255];
01623    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01624    ast_debug(1, "External password: %s\n",buf);
01625    if (!ast_safe_system(buf)) {
01626       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01627       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01628       /* Reset the password in memory, too */
01629       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01630    }
01631 }

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

Definition at line 1188 of file app_voicemail_imapstorage.c.

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

Referenced by check_password().

01189 {
01190    int fds[2], pid = 0;
01191 
01192    memset(buf, 0, len);
01193 
01194    if (pipe(fds)) {
01195       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01196    } else {
01197       /* good to go*/
01198       pid = ast_safe_fork(0);
01199 
01200       if (pid < 0) {
01201          /* ok maybe not */
01202          close(fds[0]);
01203          close(fds[1]);
01204          snprintf(buf, len, "FAILURE: Fork failed");
01205       } else if (pid) {
01206          /* parent */
01207          close(fds[1]);
01208          if (read(fds[0], buf, len) < 0) {
01209             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01210          }
01211          close(fds[0]);
01212       } else {
01213          /*  child */
01214          AST_DECLARE_APP_ARGS(arg,
01215             AST_APP_ARG(v)[20];
01216          );
01217          char *mycmd = ast_strdupa(command);
01218 
01219          close(fds[0]);
01220          dup2(fds[1], STDOUT_FILENO);
01221          close(fds[1]);
01222          ast_close_fds_above_n(STDOUT_FILENO);
01223 
01224          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01225 
01226          execv(arg.v[0], arg.v); 
01227          printf("FAILURE: %s", strerror(errno));
01228          _exit(0);
01229       }
01230    }
01231    return buf;
01232 }

static int vm_delete ( char *  file  )  [static]

Removes the voicemail sound and information file.

Parameters:
file The path to the sound file. This will be the the folder and message index, without the extension.

This is used by the DELETE macro when voicemails are stored on the file system.

Returns:
zero on success, -1 on error.

Definition at line 4203 of file app_voicemail_imapstorage.c.

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

Referenced by copy_message(), and notify_new_message().

04204 {
04205    char *txt;
04206    int txtsize = 0;
04207 
04208    txtsize = (strlen(file) + 5)*sizeof(char);
04209    txt = ast_alloca(txtsize);
04210    /* Sprintf here would safe because we alloca'd exactly the right length,
04211     * but trying to eliminate all sprintf's anyhow
04212     */
04213    if (ast_check_realtime("voicemail_data")) {
04214       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04215    }
04216    snprintf(txt, txtsize, "%s.txt", file);
04217    unlink(txt);
04218    return ast_filedelete(file, NULL);
04219 }

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

Definition at line 10673 of file app_voicemail_imapstorage.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), ast_copy_flags, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, ast_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_vm_options::exitcontext, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and leave_vm_options::record_gain.

Referenced by load_module(), and play_record_review().

10674 {
10675    int res = 0;
10676    char *tmp;
10677    struct leave_vm_options leave_options;
10678    struct ast_flags flags = { 0 };
10679    char *opts[OPT_ARG_ARRAY_SIZE];
10680    AST_DECLARE_APP_ARGS(args,
10681       AST_APP_ARG(argv0);
10682       AST_APP_ARG(argv1);
10683    );
10684    
10685    memset(&leave_options, 0, sizeof(leave_options));
10686 
10687    if (chan->_state != AST_STATE_UP)
10688       ast_answer(chan);
10689 
10690    if (!ast_strlen_zero(data)) {
10691       tmp = ast_strdupa(data);
10692       AST_STANDARD_APP_ARGS(args, tmp);
10693       if (args.argc == 2) {
10694          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10695             return -1;
10696          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10697          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10698             int gain;
10699 
10700             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10701                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10702                return -1;
10703             } else {
10704                leave_options.record_gain = (signed char) gain;
10705             }
10706          }
10707          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10708             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10709                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10710          }
10711       }
10712    } else {
10713       char temp[256];
10714       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10715       if (res < 0)
10716          return res;
10717       if (ast_strlen_zero(temp))
10718          return 0;
10719       args.argv0 = ast_strdupa(temp);
10720    }
10721 
10722    res = leave_voicemail(chan, args.argv0, &leave_options);
10723    if (res == 't') {
10724       ast_play_and_wait(chan, "vm-goodbye");
10725       res = 0;
10726    }
10727 
10728    if (res == OPERATOR_EXIT) {
10729       res = 0;
10730    }
10731 
10732    if (res == ERROR_LOCK_PATH) {
10733       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10734       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10735       res = 0;
10736    }
10737 
10738    return res;
10739 }

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

Definition at line 9921 of file app_voicemail_imapstorage.c.

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

Referenced by load_module().

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

static int vm_forwardoptions ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  curdir,
int  curmsg,
char *  vm_fmts,
char *  context,
signed char  record_gain,
long *  duration,
struct vm_state vms,
char *  flag 
) [static]

presents the option to prepend to an existing message when forwarding it.

Parameters:
chan 
vmu 
curdir 
curmsg 
vm_fmts 
context 
record_gain 
duration 
vms 
flag 

Presents a prompt for 1 to prepend the current message, 2 to forward the message without prepending, or * to return to the main menu.

This is invoked from forward_message() when performing a forward operation (option 8 from main menu).

Returns:
zero on success, -1 on error.

Definition at line 6881 of file app_voicemail_imapstorage.c.

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

Referenced by forward_message().

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

static int vm_instructions ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 9236 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

09237 {
09238    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09239       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09240    } else {             /* Default to ENGLISH */
09241       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09242    }
09243 }

static int vm_instructions_en ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 9124 of file app_voicemail_imapstorage.c.

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

Referenced by vm_instructions(), and vm_instructions_zh().

09125 {
09126    int res = 0;
09127    /* Play instructions and wait for new command */
09128    while (!res) {
09129       if (vms->starting) {
09130          if (vms->lastmsg > -1) {
09131             if (skipadvanced)
09132                res = ast_play_and_wait(chan, "vm-onefor-full");
09133             else
09134                res = ast_play_and_wait(chan, "vm-onefor");
09135             if (!res)
09136                res = vm_play_folder_name(chan, vms->vmbox);
09137          }
09138          if (!res) {
09139             if (skipadvanced)
09140                res = ast_play_and_wait(chan, "vm-opts-full");
09141             else
09142                res = ast_play_and_wait(chan, "vm-opts");
09143          }
09144       } else {
09145          /* Added for additional help */
09146          if (skipadvanced) {
09147             res = ast_play_and_wait(chan, "vm-onefor-full");
09148             if (!res)
09149                res = vm_play_folder_name(chan, vms->vmbox);
09150             res = ast_play_and_wait(chan, "vm-opts-full");
09151          }
09152          /* Logic:
09153           * If the current message is not the first OR
09154           * if we're listening to the first new message and there are
09155           * also urgent messages, then prompt for navigation to the
09156           * previous message
09157           */
09158          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09159             res = ast_play_and_wait(chan, "vm-prev");
09160          }
09161          if (!res && !skipadvanced)
09162             res = ast_play_and_wait(chan, "vm-advopts");
09163          if (!res)
09164             res = ast_play_and_wait(chan, "vm-repeat");
09165          /* Logic:
09166           * If we're not listening to the last message OR
09167           * we're listening to the last urgent message and there are
09168           * also new non-urgent messages, then prompt for navigation
09169           * to the next message
09170           */
09171          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09172             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09173             res = ast_play_and_wait(chan, "vm-next");
09174          }
09175          if (!res) {
09176             int curmsg_deleted;
09177 #ifdef IMAP_STORAGE
09178             ast_mutex_lock(&vms->lock);
09179 #endif
09180             curmsg_deleted = vms->deleted[vms->curmsg];
09181 #ifdef IMAP_STORAGE
09182             ast_mutex_unlock(&vms->lock);
09183 #endif
09184             if (!curmsg_deleted) {
09185                res = ast_play_and_wait(chan, "vm-delete");
09186             } else {
09187                res = ast_play_and_wait(chan, "vm-undelete");
09188             }
09189             if (!res) {
09190                res = ast_play_and_wait(chan, "vm-toforward");
09191             }
09192             if (!res) {
09193                res = ast_play_and_wait(chan, "vm-savemessage");
09194             }
09195          }
09196       }
09197       if (!res) {
09198          res = ast_play_and_wait(chan, "vm-helpexit");
09199       }
09200       if (!res)
09201          res = ast_waitfordigit(chan, 6000);
09202       if (!res) {
09203          vms->repeats++;
09204          if (vms->repeats > 2) {
09205             res = 't';
09206          }
09207       }
09208    }
09209    return res;
09210 }

static int vm_instructions_zh ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 9212 of file app_voicemail_imapstorage.c.

References ast_play_and_wait(), vm_state::lastmsg, vm_state::starting, vm_instructions_en(), vm_play_folder_name(), and vm_state::vmbox.

Referenced by vm_instructions().

09213 {
09214    int res = 0;
09215    /* Play instructions and wait for new command */
09216    while (!res) {
09217       if (vms->lastmsg > -1) {
09218          res = ast_play_and_wait(chan, "vm-listen");
09219          if (!res)
09220             res = vm_play_folder_name(chan, vms->vmbox);
09221          if (!res)
09222             res = ast_play_and_wait(chan, "press");
09223          if (!res)
09224             res = ast_play_and_wait(chan, "digits/1");
09225       }
09226       if (!res)
09227          res = ast_play_and_wait(chan, "vm-opts");
09228       if (!res) {
09229          vms->starting = 0;
09230          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09231       }
09232    }
09233    return res;
09234 }

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

Definition at line 9062 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

09063 {
09064    char prefile[256];
09065    
09066    /* Notify the user that the temp greeting is set and give them the option to remove it */
09067    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09068    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09069       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09070       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09071          ast_play_and_wait(chan, "vm-tempgreetactive");
09072       }
09073       DISPOSE(prefile, -1);
09074    }
09075 
09076    /* Play voicemail intro - syntax is different for different languages */
09077    if (0) {
09078       return 0;
09079    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09080       return vm_intro_cs(chan, vms);
09081    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09082       static int deprecation_warning = 0;
09083       if (deprecation_warning++ % 10 == 0) {
09084          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09085       }
09086       return vm_intro_cs(chan, vms);
09087    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09088       return vm_intro_de(chan, vms);
09089    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09090       return vm_intro_es(chan, vms);
09091    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09092       return vm_intro_fr(chan, vms);
09093    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09094       return vm_intro_gr(chan, vms);
09095    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09096       return vm_intro_he(chan, vms);
09097    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09098       return vm_intro_it(chan, vms);
09099    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09100       return vm_intro_nl(chan, vms);
09101    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09102       return vm_intro_no(chan, vms);
09103    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09104       return vm_intro_pl(chan, vms);
09105    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09106       return vm_intro_pt_BR(chan, vms);
09107    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09108       return vm_intro_pt(chan, vms);
09109    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09110       return vm_intro_multilang(chan, vms, "n");
09111    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09112       return vm_intro_se(chan, vms);
09113    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09114       return vm_intro_multilang(chan, vms, "n");
09115    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09116       return vm_intro_vi(chan, vms);
09117    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09118       return vm_intro_zh(chan, vms);
09119    } else {                                             /* Default to ENGLISH */
09120       return vm_intro_en(chan, vms);
09121    }
09122 }

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

Definition at line 8932 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08933 {
08934    int res;
08935    res = ast_play_and_wait(chan, "vm-youhave");
08936    if (!res) {
08937       if (vms->newmessages) {
08938          if (vms->newmessages == 1) {
08939             res = ast_play_and_wait(chan, "digits/jednu");
08940          } else {
08941             res = say_and_wait(chan, vms->newmessages, chan->language);
08942          }
08943          if (!res) {
08944             if ((vms->newmessages == 1))
08945                res = ast_play_and_wait(chan, "vm-novou");
08946             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08947                res = ast_play_and_wait(chan, "vm-nove");
08948             if (vms->newmessages > 4)
08949                res = ast_play_and_wait(chan, "vm-novych");
08950          }
08951          if (vms->oldmessages && !res)
08952             res = ast_play_and_wait(chan, "vm-and");
08953          else if (!res) {
08954             if ((vms->newmessages == 1))
08955                res = ast_play_and_wait(chan, "vm-zpravu");
08956             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08957                res = ast_play_and_wait(chan, "vm-zpravy");
08958             if (vms->newmessages > 4)
08959                res = ast_play_and_wait(chan, "vm-zprav");
08960          }
08961       }
08962       if (!res && vms->oldmessages) {
08963          res = say_and_wait(chan, vms->oldmessages, chan->language);
08964          if (!res) {
08965             if ((vms->oldmessages == 1))
08966                res = ast_play_and_wait(chan, "vm-starou");
08967             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08968                res = ast_play_and_wait(chan, "vm-stare");
08969             if (vms->oldmessages > 4)
08970                res = ast_play_and_wait(chan, "vm-starych");
08971          }
08972          if (!res) {
08973             if ((vms->oldmessages == 1))
08974                res = ast_play_and_wait(chan, "vm-zpravu");
08975             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08976                res = ast_play_and_wait(chan, "vm-zpravy");
08977             if (vms->oldmessages > 4)
08978                res = ast_play_and_wait(chan, "vm-zprav");
08979          }
08980       }
08981       if (!res) {
08982          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08983             res = ast_play_and_wait(chan, "vm-no");
08984             if (!res)
08985                res = ast_play_and_wait(chan, "vm-zpravy");
08986          }
08987       }
08988    }
08989    return res;
08990 }

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

Definition at line 8628 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08629 {
08630    /* Introduce messages they have */
08631    int res;
08632    res = ast_play_and_wait(chan, "vm-youhave");
08633    if (!res) {
08634       if (vms->newmessages) {
08635          if ((vms->newmessages == 1))
08636             res = ast_play_and_wait(chan, "digits/1F");
08637          else
08638             res = say_and_wait(chan, vms->newmessages, chan->language);
08639          if (!res)
08640             res = ast_play_and_wait(chan, "vm-INBOX");
08641          if (vms->oldmessages && !res)
08642             res = ast_play_and_wait(chan, "vm-and");
08643          else if (!res) {
08644             if ((vms->newmessages == 1))
08645                res = ast_play_and_wait(chan, "vm-message");
08646             else
08647                res = ast_play_and_wait(chan, "vm-messages");
08648          }
08649             
08650       }
08651       if (!res && vms->oldmessages) {
08652          if (vms->oldmessages == 1)
08653             res = ast_play_and_wait(chan, "digits/1F");
08654          else
08655             res = say_and_wait(chan, vms->oldmessages, chan->language);
08656          if (!res)
08657             res = ast_play_and_wait(chan, "vm-Old");
08658          if (!res) {
08659             if (vms->oldmessages == 1)
08660                res = ast_play_and_wait(chan, "vm-message");
08661             else
08662                res = ast_play_and_wait(chan, "vm-messages");
08663          }
08664       }
08665       if (!res) {
08666          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08667             res = ast_play_and_wait(chan, "vm-no");
08668             if (!res)
08669                res = ast_play_and_wait(chan, "vm-messages");
08670          }
08671       }
08672    }
08673    return res;
08674 }

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

Definition at line 8377 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08378 {
08379    int res;
08380 
08381    /* Introduce messages they have */
08382    res = ast_play_and_wait(chan, "vm-youhave");
08383    if (!res) {
08384       if (vms->urgentmessages) {
08385          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08386          if (!res)
08387             res = ast_play_and_wait(chan, "vm-Urgent");
08388          if ((vms->oldmessages || vms->newmessages) && !res) {
08389             res = ast_play_and_wait(chan, "vm-and");
08390          } else if (!res) {
08391             if ((vms->urgentmessages == 1))
08392                res = ast_play_and_wait(chan, "vm-message");
08393             else
08394                res = ast_play_and_wait(chan, "vm-messages");
08395          }
08396       }
08397       if (vms->newmessages) {
08398          res = say_and_wait(chan, vms->newmessages, chan->language);
08399          if (!res)
08400             res = ast_play_and_wait(chan, "vm-INBOX");
08401          if (vms->oldmessages && !res)
08402             res = ast_play_and_wait(chan, "vm-and");
08403          else if (!res) {
08404             if ((vms->newmessages == 1))
08405                res = ast_play_and_wait(chan, "vm-message");
08406             else
08407                res = ast_play_and_wait(chan, "vm-messages");
08408          }
08409             
08410       }
08411       if (!res && vms->oldmessages) {
08412          res = say_and_wait(chan, vms->oldmessages, chan->language);
08413          if (!res)
08414             res = ast_play_and_wait(chan, "vm-Old");
08415          if (!res) {
08416             if (vms->oldmessages == 1)
08417                res = ast_play_and_wait(chan, "vm-message");
08418             else
08419                res = ast_play_and_wait(chan, "vm-messages");
08420          }
08421       }
08422       if (!res) {
08423          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08424             res = ast_play_and_wait(chan, "vm-no");
08425             if (!res)
08426                res = ast_play_and_wait(chan, "vm-messages");
08427          }
08428       }
08429    }
08430    return res;
08431 }

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

Definition at line 8677 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08678 {
08679    /* Introduce messages they have */
08680    int res;
08681    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08682       res = ast_play_and_wait(chan, "vm-youhaveno");
08683       if (!res)
08684          res = ast_play_and_wait(chan, "vm-messages");
08685    } else {
08686       res = ast_play_and_wait(chan, "vm-youhave");
08687    }
08688    if (!res) {
08689       if (vms->newmessages) {
08690          if (!res) {
08691             if ((vms->newmessages == 1)) {
08692                res = ast_play_and_wait(chan, "digits/1M");
08693                if (!res)
08694                   res = ast_play_and_wait(chan, "vm-message");
08695                if (!res)
08696                   res = ast_play_and_wait(chan, "vm-INBOXs");
08697             } else {
08698                res = say_and_wait(chan, vms->newmessages, chan->language);
08699                if (!res)
08700                   res = ast_play_and_wait(chan, "vm-messages");
08701                if (!res)
08702                   res = ast_play_and_wait(chan, "vm-INBOX");
08703             }
08704          }
08705          if (vms->oldmessages && !res)
08706             res = ast_play_and_wait(chan, "vm-and");
08707       }
08708       if (vms->oldmessages) {
08709          if (!res) {
08710             if (vms->oldmessages == 1) {
08711                res = ast_play_and_wait(chan, "digits/1M");
08712                if (!res)
08713                   res = ast_play_and_wait(chan, "vm-message");
08714                if (!res)
08715                   res = ast_play_and_wait(chan, "vm-Olds");
08716             } else {
08717                res = say_and_wait(chan, vms->oldmessages, chan->language);
08718                if (!res)
08719                   res = ast_play_and_wait(chan, "vm-messages");
08720                if (!res)
08721                   res = ast_play_and_wait(chan, "vm-Old");
08722             }
08723          }
08724       }
08725    }
08726 return res;
08727 }

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

Definition at line 8775 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08776 {
08777    /* Introduce messages they have */
08778    int res;
08779    res = ast_play_and_wait(chan, "vm-youhave");
08780    if (!res) {
08781       if (vms->newmessages) {
08782          res = say_and_wait(chan, vms->newmessages, chan->language);
08783          if (!res)
08784             res = ast_play_and_wait(chan, "vm-INBOX");
08785          if (vms->oldmessages && !res)
08786             res = ast_play_and_wait(chan, "vm-and");
08787          else if (!res) {
08788             if ((vms->newmessages == 1))
08789                res = ast_play_and_wait(chan, "vm-message");
08790             else
08791                res = ast_play_and_wait(chan, "vm-messages");
08792          }
08793             
08794       }
08795       if (!res && vms->oldmessages) {
08796          res = say_and_wait(chan, vms->oldmessages, chan->language);
08797          if (!res)
08798             res = ast_play_and_wait(chan, "vm-Old");
08799          if (!res) {
08800             if (vms->oldmessages == 1)
08801                res = ast_play_and_wait(chan, "vm-message");
08802             else
08803                res = ast_play_and_wait(chan, "vm-messages");
08804          }
08805       }
08806       if (!res) {
08807          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08808             res = ast_play_and_wait(chan, "vm-no");
08809             if (!res)
08810                res = ast_play_and_wait(chan, "vm-messages");
08811          }
08812       }
08813    }
08814    return res;
08815 }

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

Definition at line 8176 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08177 {
08178    int res = 0;
08179 
08180    if (vms->newmessages) {
08181       res = ast_play_and_wait(chan, "vm-youhave");
08182       if (!res) 
08183          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08184       if (!res) {
08185          if ((vms->newmessages == 1)) {
08186             res = ast_play_and_wait(chan, "vm-INBOX");
08187             if (!res)
08188                res = ast_play_and_wait(chan, "vm-message");
08189          } else {
08190             res = ast_play_and_wait(chan, "vm-INBOXs");
08191             if (!res)
08192                res = ast_play_and_wait(chan, "vm-messages");
08193          }
08194       }
08195    } else if (vms->oldmessages){
08196       res = ast_play_and_wait(chan, "vm-youhave");
08197       if (!res)
08198          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08199       if ((vms->oldmessages == 1)){
08200          res = ast_play_and_wait(chan, "vm-Old");
08201          if (!res)
08202             res = ast_play_and_wait(chan, "vm-message");
08203       } else {
08204          res = ast_play_and_wait(chan, "vm-Olds");
08205          if (!res)
08206             res = ast_play_and_wait(chan, "vm-messages");
08207       }
08208    } else if (!vms->oldmessages && !vms->newmessages) 
08209       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08210    return res;
08211 }

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

Definition at line 8310 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08311 {
08312    int res = 0;
08313 
08314    /* Introduce messages they have */
08315    if (!res) {
08316       if ((vms->newmessages) || (vms->oldmessages)) {
08317          res = ast_play_and_wait(chan, "vm-youhave");
08318       }
08319       /*
08320        * The word "shtei" refers to the number 2 in hebrew when performing a count
08321        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08322        * an element, this is one of them.
08323        */
08324       if (vms->newmessages) {
08325          if (!res) {
08326             if (vms->newmessages == 1) {
08327                res = ast_play_and_wait(chan, "vm-INBOX1");
08328             } else {
08329                if (vms->newmessages == 2) {
08330                   res = ast_play_and_wait(chan, "vm-shtei");
08331                } else {
08332                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08333                }
08334                res = ast_play_and_wait(chan, "vm-INBOX");
08335             }
08336          }
08337          if (vms->oldmessages && !res) {
08338             res = ast_play_and_wait(chan, "vm-and");
08339             if (vms->oldmessages == 1) {
08340                res = ast_play_and_wait(chan, "vm-Old1");
08341             } else {
08342                if (vms->oldmessages == 2) {
08343                   res = ast_play_and_wait(chan, "vm-shtei");
08344                } else {
08345                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08346                }
08347                res = ast_play_and_wait(chan, "vm-Old");
08348             }
08349          }
08350       }
08351       if (!res && vms->oldmessages && !vms->newmessages) {
08352          if (!res) {
08353             if (vms->oldmessages == 1) {
08354                res = ast_play_and_wait(chan, "vm-Old1");
08355             } else {
08356                if (vms->oldmessages == 2) {
08357                   res = ast_play_and_wait(chan, "vm-shtei");
08358                } else {
08359                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08360                }
08361                res = ast_play_and_wait(chan, "vm-Old");
08362             }
08363          }
08364       }
08365       if (!res) {
08366          if (!vms->oldmessages && !vms->newmessages) {
08367             if (!res) {
08368                res = ast_play_and_wait(chan, "vm-nomessages");
08369             }
08370          }
08371       }
08372    }
08373    return res;
08374 }

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

Definition at line 8434 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08435 {
08436    /* Introduce messages they have */
08437    int res;
08438    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08439       res = ast_play_and_wait(chan, "vm-no") ||
08440          ast_play_and_wait(chan, "vm-message");
08441    else
08442       res = ast_play_and_wait(chan, "vm-youhave");
08443    if (!res && vms->newmessages) {
08444       res = (vms->newmessages == 1) ?
08445          ast_play_and_wait(chan, "digits/un") ||
08446          ast_play_and_wait(chan, "vm-nuovo") ||
08447          ast_play_and_wait(chan, "vm-message") :
08448          /* 2 or more new messages */
08449          say_and_wait(chan, vms->newmessages, chan->language) ||
08450          ast_play_and_wait(chan, "vm-nuovi") ||
08451          ast_play_and_wait(chan, "vm-messages");
08452       if (!res && vms->oldmessages)
08453          res = ast_play_and_wait(chan, "vm-and");
08454    }
08455    if (!res && vms->oldmessages) {
08456       res = (vms->oldmessages == 1) ?
08457          ast_play_and_wait(chan, "digits/un") ||
08458          ast_play_and_wait(chan, "vm-vecchio") ||
08459          ast_play_and_wait(chan, "vm-message") :
08460          /* 2 or more old messages */
08461          say_and_wait(chan, vms->oldmessages, chan->language) ||
08462          ast_play_and_wait(chan, "vm-vecchi") ||
08463          ast_play_and_wait(chan, "vm-messages");
08464    }
08465    return res;
08466 }

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

Definition at line 8270 of file app_voicemail_imapstorage.c.

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_counted_adjective(), ast_say_counted_noun(), ast_say_number(), vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_intro().

08271 {
08272    int res;
08273    int lastnum = 0;
08274 
08275    res = ast_play_and_wait(chan, "vm-youhave");
08276 
08277    if (!res && vms->newmessages) {
08278       lastnum = vms->newmessages;
08279 
08280       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08281          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08282       }
08283 
08284       if (!res && vms->oldmessages) {
08285          res = ast_play_and_wait(chan, "vm-and");
08286       }
08287    }
08288 
08289    if (!res && vms->oldmessages) {
08290       lastnum = vms->oldmessages;
08291 
08292       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08293          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08294       }
08295    }
08296 
08297    if (!res) {
08298       if (lastnum == 0) {
08299          res = ast_play_and_wait(chan, "vm-no");
08300       }
08301       if (!res) {
08302          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08303       }
08304    }
08305 
08306    return res;
08307 }

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

Definition at line 8818 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08819 {
08820    /* Introduce messages they have */
08821    int res;
08822    res = ast_play_and_wait(chan, "vm-youhave");
08823    if (!res) {
08824       if (vms->newmessages) {
08825          res = say_and_wait(chan, vms->newmessages, chan->language);
08826          if (!res) {
08827             if (vms->newmessages == 1)
08828                res = ast_play_and_wait(chan, "vm-INBOXs");
08829             else
08830                res = ast_play_and_wait(chan, "vm-INBOX");
08831          }
08832          if (vms->oldmessages && !res)
08833             res = ast_play_and_wait(chan, "vm-and");
08834          else if (!res) {
08835             if ((vms->newmessages == 1))
08836                res = ast_play_and_wait(chan, "vm-message");
08837             else
08838                res = ast_play_and_wait(chan, "vm-messages");
08839          }
08840             
08841       }
08842       if (!res && vms->oldmessages) {
08843          res = say_and_wait(chan, vms->oldmessages, chan->language);
08844          if (!res) {
08845             if (vms->oldmessages == 1)
08846                res = ast_play_and_wait(chan, "vm-Olds");
08847             else
08848                res = ast_play_and_wait(chan, "vm-Old");
08849          }
08850          if (!res) {
08851             if (vms->oldmessages == 1)
08852                res = ast_play_and_wait(chan, "vm-message");
08853             else
08854                res = ast_play_and_wait(chan, "vm-messages");
08855          }
08856       }
08857       if (!res) {
08858          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08859             res = ast_play_and_wait(chan, "vm-no");
08860             if (!res)
08861                res = ast_play_and_wait(chan, "vm-messages");
08862          }
08863       }
08864    }
08865    return res;
08866 }

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

Definition at line 8584 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08585 {
08586    /* Introduce messages they have */
08587    int res;
08588 
08589    res = ast_play_and_wait(chan, "vm-youhave");
08590    if (res)
08591       return res;
08592 
08593    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08594       res = ast_play_and_wait(chan, "vm-no");
08595       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08596       return res;
08597    }
08598 
08599    if (vms->newmessages) {
08600       if ((vms->newmessages == 1)) {
08601          res = ast_play_and_wait(chan, "digits/1");
08602          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08603          res = res ? res : ast_play_and_wait(chan, "vm-message");
08604       } else {
08605          res = say_and_wait(chan, vms->newmessages, chan->language);
08606          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08607          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08608       }
08609       if (!res && vms->oldmessages)
08610          res = ast_play_and_wait(chan, "vm-and");
08611    }
08612    if (!res && vms->oldmessages) {
08613       if (vms->oldmessages == 1) {
08614          res = ast_play_and_wait(chan, "digits/1");
08615          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08616          res = res ? res : ast_play_and_wait(chan, "vm-message");
08617       } else {
08618          res = say_and_wait(chan, vms->oldmessages, chan->language);
08619          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08620          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08621       }
08622    }
08623 
08624    return res;
08625 }

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

Definition at line 8469 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08470 {
08471    /* Introduce messages they have */
08472    int res;
08473    div_t num;
08474 
08475    if (!vms->oldmessages && !vms->newmessages) {
08476       res = ast_play_and_wait(chan, "vm-no");
08477       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08478       return res;
08479    } else {
08480       res = ast_play_and_wait(chan, "vm-youhave");
08481    }
08482 
08483    if (vms->newmessages) {
08484       num = div(vms->newmessages, 10);
08485       if (vms->newmessages == 1) {
08486          res = ast_play_and_wait(chan, "digits/1-a");
08487          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08488          res = res ? res : ast_play_and_wait(chan, "vm-message");
08489       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08490          if (num.rem == 2) {
08491             if (!num.quot) {
08492                res = ast_play_and_wait(chan, "digits/2-ie");
08493             } else {
08494                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08495                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08496             }
08497          } else {
08498             res = say_and_wait(chan, vms->newmessages, chan->language);
08499          }
08500          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08501          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08502       } else {
08503          res = say_and_wait(chan, vms->newmessages, chan->language);
08504          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08505          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08506       }
08507       if (!res && vms->oldmessages)
08508          res = ast_play_and_wait(chan, "vm-and");
08509    }
08510    if (!res && vms->oldmessages) {
08511       num = div(vms->oldmessages, 10);
08512       if (vms->oldmessages == 1) {
08513          res = ast_play_and_wait(chan, "digits/1-a");
08514          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08515          res = res ? res : ast_play_and_wait(chan, "vm-message");
08516       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08517          if (num.rem == 2) {
08518             if (!num.quot) {
08519                res = ast_play_and_wait(chan, "digits/2-ie");
08520             } else {
08521                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08522                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08523             }
08524          } else {
08525             res = say_and_wait(chan, vms->oldmessages, chan->language);
08526          }
08527          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08528          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08529       } else {
08530          res = say_and_wait(chan, vms->oldmessages, chan->language);
08531          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08532          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08533       }
08534    }
08535 
08536    return res;
08537 }

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

Definition at line 8869 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08870 {
08871    /* Introduce messages they have */
08872    int res;
08873    res = ast_play_and_wait(chan, "vm-youhave");
08874    if (!res) {
08875       if (vms->newmessages) {
08876          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08877          if (!res) {
08878             if ((vms->newmessages == 1)) {
08879                res = ast_play_and_wait(chan, "vm-message");
08880                if (!res)
08881                   res = ast_play_and_wait(chan, "vm-INBOXs");
08882             } else {
08883                res = ast_play_and_wait(chan, "vm-messages");
08884                if (!res)
08885                   res = ast_play_and_wait(chan, "vm-INBOX");
08886             }
08887          }
08888          if (vms->oldmessages && !res)
08889             res = ast_play_and_wait(chan, "vm-and");
08890       }
08891       if (!res && vms->oldmessages) {
08892          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08893          if (!res) {
08894             if (vms->oldmessages == 1) {
08895                res = ast_play_and_wait(chan, "vm-message");
08896                if (!res)
08897                   res = ast_play_and_wait(chan, "vm-Olds");
08898             } else {
08899                res = ast_play_and_wait(chan, "vm-messages");
08900                if (!res)
08901                   res = ast_play_and_wait(chan, "vm-Old");
08902             }
08903          }
08904       }
08905       if (!res) {
08906          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08907             res = ast_play_and_wait(chan, "vm-no");
08908             if (!res)
08909                res = ast_play_and_wait(chan, "vm-messages");
08910          }
08911       }
08912    }
08913    return res;
08914 }

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

Definition at line 8730 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08730                                                                           {
08731    /* Introduce messages they have */
08732    int res;
08733    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08734       res = ast_play_and_wait(chan, "vm-nomessages");
08735       return res;
08736    } else {
08737       res = ast_play_and_wait(chan, "vm-youhave");
08738    }
08739    if (vms->newmessages) {
08740       if (!res)
08741          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08742       if ((vms->newmessages == 1)) {
08743          if (!res)
08744             res = ast_play_and_wait(chan, "vm-message");
08745          if (!res)
08746             res = ast_play_and_wait(chan, "vm-INBOXs");
08747       } else {
08748          if (!res)
08749             res = ast_play_and_wait(chan, "vm-messages");
08750          if (!res)
08751             res = ast_play_and_wait(chan, "vm-INBOX");
08752       }
08753       if (vms->oldmessages && !res)
08754          res = ast_play_and_wait(chan, "vm-and");
08755    }
08756    if (vms->oldmessages) {
08757       if (!res)
08758          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08759       if (vms->oldmessages == 1) {
08760          if (!res)
08761             res = ast_play_and_wait(chan, "vm-message");
08762          if (!res)
08763             res = ast_play_and_wait(chan, "vm-Olds");
08764       } else {
08765          if (!res)
08766             res = ast_play_and_wait(chan, "vm-messages");
08767          if (!res)
08768             res = ast_play_and_wait(chan, "vm-Old");
08769       }
08770    }
08771    return res;
08772 }

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

Definition at line 8540 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

08541 {
08542    /* Introduce messages they have */
08543    int res;
08544 
08545    res = ast_play_and_wait(chan, "vm-youhave");
08546    if (res)
08547       return res;
08548 
08549    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08550       res = ast_play_and_wait(chan, "vm-no");
08551       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08552       return res;
08553    }
08554 
08555    if (vms->newmessages) {
08556       if ((vms->newmessages == 1)) {
08557          res = ast_play_and_wait(chan, "digits/ett");
08558          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08559          res = res ? res : ast_play_and_wait(chan, "vm-message");
08560       } else {
08561          res = say_and_wait(chan, vms->newmessages, chan->language);
08562          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08563          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08564       }
08565       if (!res && vms->oldmessages)
08566          res = ast_play_and_wait(chan, "vm-and");
08567    }
08568    if (!res && vms->oldmessages) {
08569       if (vms->oldmessages == 1) {
08570          res = ast_play_and_wait(chan, "digits/ett");
08571          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08572          res = res ? res : ast_play_and_wait(chan, "vm-message");
08573       } else {
08574          res = say_and_wait(chan, vms->oldmessages, chan->language);
08575          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08576          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08577       }
08578    }
08579 
08580    return res;
08581 }

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

Definition at line 9032 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

09033 {
09034    int res;
09035 
09036    /* Introduce messages they have */
09037    res = ast_play_and_wait(chan, "vm-youhave");
09038    if (!res) {
09039       if (vms->newmessages) {
09040          res = say_and_wait(chan, vms->newmessages, chan->language);
09041          if (!res)
09042             res = ast_play_and_wait(chan, "vm-INBOX");
09043          if (vms->oldmessages && !res)
09044             res = ast_play_and_wait(chan, "vm-and");
09045       }
09046       if (!res && vms->oldmessages) {
09047          res = say_and_wait(chan, vms->oldmessages, chan->language);
09048          if (!res)
09049             res = ast_play_and_wait(chan, "vm-Old");        
09050       }
09051       if (!res) {
09052          if (!vms->oldmessages && !vms->newmessages) {
09053             res = ast_play_and_wait(chan, "vm-no");
09054             if (!res)
09055                res = ast_play_and_wait(chan, "vm-message");
09056          }
09057       }
09058    }
09059    return res;
09060 }

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

Definition at line 8993 of file app_voicemail_imapstorage.c.

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

Referenced by vm_intro().

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

static int vm_lock_path ( const char *  path  )  [static]

Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.

Definition at line 3278 of file app_voicemail_imapstorage.c.

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

03279 {
03280    switch (ast_lock_path(path)) {
03281    case AST_LOCK_TIMEOUT:
03282       return -1;
03283    default:
03284       return 0;
03285    }
03286 }

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

Definition at line 1669 of file app_voicemail_imapstorage.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01670 {
01671    FILE *p = NULL;
01672    int pfd = mkstemp(template);
01673    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01674    if (pfd > -1) {
01675       p = fdopen(pfd, "w+");
01676       if (!p) {
01677          close(pfd);
01678          pfd = -1;
01679       }
01680    }
01681    return p;
01682 }

static int vm_newuser ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
) [static]

Definition at line 9246 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, check_password(), ast_vm_user::context, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, and VM_FORCENAME.

Referenced by vm_execmain().

09247 {
09248    int cmd = 0;
09249    int duration = 0;
09250    int tries = 0;
09251    char newpassword[80] = "";
09252    char newpassword2[80] = "";
09253    char prefile[PATH_MAX] = "";
09254    unsigned char buf[256];
09255    int bytes = 0;
09256 
09257    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09258    if (ast_adsi_available(chan)) {
09259       bytes += adsi_logo(buf + bytes);
09260       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09261       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09262       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09263       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09264       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09265    }
09266 
09267    /* If forcename is set, have the user record their name */
09268    if (ast_test_flag(vmu, VM_FORCENAME)) {
09269       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09270       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09271          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09272          if (cmd < 0 || cmd == 't' || cmd == '#')
09273             return cmd;
09274       }
09275    }
09276 
09277    /* If forcegreetings is set, have the user record their greetings */
09278    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09279       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09280       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09281          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09282          if (cmd < 0 || cmd == 't' || cmd == '#')
09283             return cmd;
09284       }
09285 
09286       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09287       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09288          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09289          if (cmd < 0 || cmd == 't' || cmd == '#')
09290             return cmd;
09291       }
09292    }
09293 
09294    /*
09295     * Change the password last since new users will be able to skip over any steps this one comes before
09296     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09297     */
09298    for (;;) {
09299       newpassword[1] = '\0';
09300       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09301       if (cmd == '#')
09302          newpassword[0] = '\0';
09303       if (cmd < 0 || cmd == 't' || cmd == '#')
09304          return cmd;
09305       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09306       if (cmd < 0 || cmd == 't' || cmd == '#')
09307          return cmd;
09308       cmd = check_password(vmu, newpassword); /* perform password validation */
09309       if (cmd != 0) {
09310          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09311          cmd = ast_play_and_wait(chan, vm_invalid_password);
09312       } else {
09313          newpassword2[1] = '\0';
09314          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09315          if (cmd == '#')
09316             newpassword2[0] = '\0';
09317          if (cmd < 0 || cmd == 't' || cmd == '#')
09318             return cmd;
09319          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09320          if (cmd < 0 || cmd == 't' || cmd == '#')
09321             return cmd;
09322          if (!strcmp(newpassword, newpassword2))
09323             break;
09324          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09325          cmd = ast_play_and_wait(chan, vm_mismatch);
09326       }
09327       if (++tries == 3)
09328          return -1;
09329       if (cmd != 0) {
09330          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09331       }
09332    }
09333    if (pwdchange & PWDCHANGE_INTERNAL)
09334       vm_change_password(vmu, newpassword);
09335    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09336       vm_change_password_shell(vmu, newpassword);
09337 
09338    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09339    cmd = ast_play_and_wait(chan, vm_passchanged);
09340 
09341    return cmd;
09342 }

static int vm_options ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
) [static]

Definition at line 9344 of file app_voicemail_imapstorage.c.

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

Referenced by vm_execmain().

09345 {
09346    int cmd = 0;
09347    int retries = 0;
09348    int duration = 0;
09349    char newpassword[80] = "";
09350    char newpassword2[80] = "";
09351    char prefile[PATH_MAX] = "";
09352    unsigned char buf[256];
09353    int bytes = 0;
09354 
09355    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09356    if (ast_adsi_available(chan)) {
09357       bytes += adsi_logo(buf + bytes);
09358       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09359       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09360       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09361       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09362       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09363    }
09364    while ((cmd >= 0) && (cmd != 't')) {
09365       if (cmd)
09366          retries = 0;
09367       switch (cmd) {
09368       case '1': /* Record your unavailable message */
09369          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09370          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09371          break;
09372       case '2':  /* Record your busy message */
09373          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09374          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09375          break;
09376       case '3': /* Record greeting */
09377          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09378          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09379          break;
09380       case '4':  /* manage the temporary greeting */
09381          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09382          break;
09383       case '5': /* change password */
09384          if (vmu->password[0] == '-') {
09385             cmd = ast_play_and_wait(chan, "vm-no");
09386             break;
09387          }
09388          newpassword[1] = '\0';
09389          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09390          if (cmd == '#')
09391             newpassword[0] = '\0';
09392          else {
09393             if (cmd < 0)
09394                break;
09395             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09396                break;
09397             }
09398          }
09399          cmd = check_password(vmu, newpassword); /* perform password validation */
09400          if (cmd != 0) {
09401             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09402             cmd = ast_play_and_wait(chan, vm_invalid_password);
09403             if (!cmd) {
09404                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09405             }
09406             break;
09407          }
09408          newpassword2[1] = '\0';
09409          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09410          if (cmd == '#')
09411             newpassword2[0] = '\0';
09412          else {
09413             if (cmd < 0)
09414                break;
09415 
09416             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09417                break;
09418             }
09419          }
09420          if (strcmp(newpassword, newpassword2)) {
09421             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09422             cmd = ast_play_and_wait(chan, vm_mismatch);
09423             if (!cmd) {
09424                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09425             }
09426             break;
09427          }
09428 
09429          if (pwdchange & PWDCHANGE_INTERNAL) {
09430             vm_change_password(vmu, newpassword);
09431          }
09432          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09433             vm_change_password_shell(vmu, newpassword);
09434          }
09435 
09436          ast_debug(1, "User %s set password to %s of length %d\n",
09437             vms->username, newpassword, (int) strlen(newpassword));
09438          cmd = ast_play_and_wait(chan, vm_passchanged);
09439          break;
09440       case '*': 
09441          cmd = 't';
09442          break;
09443       default: 
09444          cmd = 0;
09445          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09446          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09447          if (ast_fileexists(prefile, NULL, NULL)) {
09448             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09449          }
09450          DISPOSE(prefile, -1);
09451          if (!cmd) {
09452             cmd = ast_play_and_wait(chan, "vm-options");
09453          }
09454          if (!cmd) {
09455             cmd = ast_waitfordigit(chan, 6000);
09456          }
09457          if (!cmd) {
09458             retries++;
09459          }
09460          if (retries > 3) {
09461             cmd = 't';
09462          }
09463          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09464       }
09465    }
09466    if (cmd == 't')
09467       cmd = 0;
09468    return cmd;
09469 }

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

Definition at line 8139 of file app_voicemail_imapstorage.c.

References ast_play_and_wait(), vm_play_folder_name_gr(), vm_play_folder_name_pl(), and vm_play_folder_name_ua().

Referenced by get_folder(), vm_execmain(), vm_instructions_en(), and vm_instructions_zh().

08140 {
08141    int cmd;
08142 
08143    if (  !strncasecmp(chan->language, "it", 2) ||
08144         !strncasecmp(chan->language, "es", 2) ||
08145         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08146       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08147       return cmd ? cmd : ast_play_and_wait(chan, box);
08148    } else if (!strncasecmp(chan->language, "gr", 2)) {
08149       return vm_play_folder_name_gr(chan, box);
08150    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08151       return ast_play_and_wait(chan, box);
08152    } else if (!strncasecmp(chan->language, "pl", 2)) {
08153       return vm_play_folder_name_pl(chan, box);
08154    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08155       return vm_play_folder_name_ua(chan, box);
08156    } else if (!strncasecmp(chan->language, "vi", 2)) {
08157       return ast_play_and_wait(chan, box);
08158    } else {  /* Default English */
08159       cmd = ast_play_and_wait(chan, box);
08160       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08161    }
08162 }

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

Definition at line 8092 of file app_voicemail_imapstorage.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

08093 {
08094    int cmd;
08095    char *buf;
08096 
08097    buf = ast_alloca(strlen(box) + 2);
08098    strcpy(buf, box);
08099    strcat(buf, "s");
08100 
08101    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08102       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08103       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08104    } else {
08105       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08106       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08107    }
08108 }

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

Definition at line 8110 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08111 {
08112    int cmd;
08113 
08114    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08115       if (!strcasecmp(box, "vm-INBOX"))
08116          cmd = ast_play_and_wait(chan, "vm-new-e");
08117       else
08118          cmd = ast_play_and_wait(chan, "vm-old-e");
08119       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08120    } else {
08121       cmd = ast_play_and_wait(chan, "vm-messages");
08122       return cmd ? cmd : ast_play_and_wait(chan, box);
08123    }
08124 }

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

Definition at line 8126 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08127 {
08128    int cmd;
08129 
08130    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08131       cmd = ast_play_and_wait(chan, "vm-messages");
08132       return cmd ? cmd : ast_play_and_wait(chan, box);
08133    } else {
08134       cmd = ast_play_and_wait(chan, box);
08135       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08136    }
08137 }

static int vm_tempgreeting ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
) [static]

The handler for 'record a temporary greeting'.

Parameters:
chan 
vmu 
vms 
fmtc 
record_gain This is option 4 from the mailbox options menu. This function manages the following promptings: 1: play / record / review the temporary greeting. : invokes play_record_review(). 2: remove (delete) the temporary greeting. *: return to the main menu.
Returns:
zero on success, -1 on error.

Definition at line 9487 of file app_voicemail_imapstorage.c.

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

Referenced by vm_options().

09488 {
09489    int cmd = 0;
09490    int retries = 0;
09491    int duration = 0;
09492    char prefile[PATH_MAX] = "";
09493    unsigned char buf[256];
09494    int bytes = 0;
09495 
09496    if (ast_adsi_available(chan)) {
09497       bytes += adsi_logo(buf + bytes);
09498       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09499       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09500       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09501       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09502       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09503    }
09504 
09505    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09506    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09507    while ((cmd >= 0) && (cmd != 't')) {
09508       if (cmd)
09509          retries = 0;
09510       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09511       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09512          cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09513          if (cmd == -1) {
09514             break;
09515          }
09516          cmd = 't';  
09517       } else {
09518          switch (cmd) {
09519          case '1':
09520             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09521             break;
09522          case '2':
09523             DELETE(prefile, -1, prefile, vmu);
09524             ast_play_and_wait(chan, "vm-tempremoved");
09525             cmd = 't';  
09526             break;
09527          case '*': 
09528             cmd = 't';
09529             break;
09530          default:
09531             cmd = ast_play_and_wait(chan,
09532                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09533                   "vm-tempgreeting2" : "vm-tempgreeting");
09534             if (!cmd) {
09535                cmd = ast_waitfordigit(chan, 6000);
09536             }
09537             if (!cmd) {
09538                retries++;
09539             }
09540             if (retries > 3) {
09541                cmd = 't';
09542             }
09543             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09544          }
09545       }
09546       DISPOSE(prefile, -1);
09547    }
09548    if (cmd == 't')
09549       cmd = 0;
09550    return cmd;
09551 }

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

Definition at line 11439 of file app_voicemail_imapstorage.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and vm_users_data_provider_get_helper().

11441 {
11442    struct ast_vm_user *user;
11443 
11444    AST_LIST_LOCK(&users);
11445    AST_LIST_TRAVERSE(&users, user, list) {
11446       vm_users_data_provider_get_helper(search, data_root, user);
11447    }
11448    AST_LIST_UNLOCK(&users);
11449 
11450    return 0;
11451 }

static int vm_users_data_provider_get_helper ( const struct ast_data_search search,
struct ast_data data_root,
struct ast_vm_user user 
) [static]

Definition at line 11392 of file app_voicemail_imapstorage.c.

References ast_data_add_int(), ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::context, inboxcount2(), ast_vm_user::mailbox, and ast_vm_user::zonetag.

Referenced by vm_users_data_provider_get().

11394 {
11395    struct ast_data *data_user, *data_zone;
11396    struct ast_data *data_state;
11397    struct vm_zone *zone = NULL;
11398    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11399    char ext_context[256] = "";
11400 
11401    data_user = ast_data_add_node(data_root, "user");
11402    if (!data_user) {
11403       return -1;
11404    }
11405 
11406    ast_data_add_structure(ast_vm_user, data_user, user);
11407 
11408    AST_LIST_LOCK(&zones);
11409    AST_LIST_TRAVERSE(&zones, zone, list) {
11410       if (!strcmp(zone->name, user->zonetag)) {
11411          break;
11412       }
11413    }
11414    AST_LIST_UNLOCK(&zones);
11415 
11416    /* state */
11417    data_state = ast_data_add_node(data_user, "state");
11418    if (!data_state) {
11419       return -1;
11420    }
11421    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11422    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11423    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11424    ast_data_add_int(data_state, "newmsg", newmsg);
11425    ast_data_add_int(data_state, "oldmsg", oldmsg);
11426 
11427    if (zone) {
11428       data_zone = ast_data_add_node(data_user, "zone");
11429       ast_data_add_structure(vm_zone, data_zone, zone);
11430    }
11431 
11432    if (!ast_data_search_match(search, data_user)) {
11433       ast_data_remove_node(data_root, data_user);
11434    }
11435 
11436    return 0;
11437 }

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

Definition at line 11078 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_goto_if_exists(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_vm_user::context, pbx_builtin_setvar_helper(), and vm_authenticate().

Referenced by load_module().

11079 {
11080    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11081    struct ast_vm_user vmus;
11082    char *options = NULL;
11083    int silent = 0, skipuser = 0;
11084    int res = -1;
11085    
11086    if (data) {
11087       s = ast_strdupa(data);
11088       user = strsep(&s, ",");
11089       options = strsep(&s, ",");
11090       if (user) {
11091          s = user;
11092          user = strsep(&s, "@");
11093          context = strsep(&s, "");
11094          if (!ast_strlen_zero(user))
11095             skipuser++;
11096          ast_copy_string(mailbox, user, sizeof(mailbox));
11097       }
11098    }
11099 
11100    if (options) {
11101       silent = (strchr(options, 's')) != NULL;
11102    }
11103 
11104    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11105       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11106       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11107       ast_play_and_wait(chan, "auth-thankyou");
11108       res = 0;
11109    } else if (mailbox[0] == '*') {
11110       /* user entered '*' */
11111       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11112          res = 0; /* prevent hangup */
11113       }
11114    }
11115 
11116    return res;
11117 }

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

Definition at line 12618 of file app_voicemail_imapstorage.c.

References ast_debug, AST_DIGIT_ANY, ast_log(), ast_say_character_str(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), LOG_WARNING, and sayname().

Referenced by load_module().

12619 {
12620    char *context;
12621    char *args_copy;
12622    int res;
12623 
12624    if (ast_strlen_zero(data)) {
12625       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12626       return -1;
12627    }
12628 
12629    args_copy = ast_strdupa(data);
12630    if ((context = strchr(args_copy, '@'))) {
12631       *context++ = '\0';
12632    } else {
12633       context = "default";
12634    }
12635 
12636    if ((res = sayname(chan, args_copy, context) < 0)) {
12637       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12638       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12639       if (!res) {
12640          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12641       }
12642    }
12643 
12644    return res;
12645 }

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

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

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

Definition at line 4435 of file app_voicemail_imapstorage.c.

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

Referenced by make_email_file(), and sendpage().

04436 {
04437    const struct vm_zone *z = NULL;
04438    struct timeval t = ast_tvnow();
04439 
04440    /* Does this user have a timezone specified? */
04441    if (!ast_strlen_zero(vmu->zonetag)) {
04442       /* Find the zone in the list */
04443       AST_LIST_LOCK(&zones);
04444       AST_LIST_TRAVERSE(&zones, z, list) {
04445          if (!strcmp(z->name, vmu->zonetag))
04446             break;
04447       }
04448       AST_LIST_UNLOCK(&zones);
04449    }
04450    ast_localtime(&t, tm, z ? z->timezone : NULL);
04451    return tm;
04452 }

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

Definition at line 7480 of file app_voicemail_imapstorage.c.

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

Referenced by play_message(), play_message_callerid(), and play_message_duration().

07481 {
07482    int res;
07483    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07484       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07485    return res;
07486 }

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

Definition at line 12585 of file app_voicemail_imapstorage.c.

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

Referenced by vm_change_password().

12585                                                                               {
12586    struct ast_config *conf;
12587    struct ast_category *cat;
12588    struct ast_variable *var;
12589    int res = -1;
12590 
12591    if (!(conf = ast_config_new())) {
12592       ast_log(LOG_ERROR, "Error creating new config structure\n");
12593       return res;
12594    }
12595    if (!(cat = ast_category_new("general", "", 1))) {
12596       ast_log(LOG_ERROR, "Error creating new category structure\n");
12597       ast_config_destroy(conf);
12598       return res;
12599    }
12600    if (!(var = ast_variable_new("password", password, ""))) {
12601       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12602       ast_config_destroy(conf);
12603       ast_category_destroy(cat);
12604       return res;
12605    }
12606    ast_category_append(conf, cat);
12607    ast_variable_append(cat, var);
12608    if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12609       res = 0;
12610    } else {
12611       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12612    }
12613 
12614    ast_config_destroy(conf);
12615    return res;
12616 }


Variable Documentation

char* addesc = "Comedian Mail" [static]

Definition at line 776 of file app_voicemail_imapstorage.c.

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

Definition at line 903 of file app_voicemail_imapstorage.c.

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

Definition at line 904 of file app_voicemail_imapstorage.c.

int adsiver = 1 [static]

Definition at line 905 of file app_voicemail_imapstorage.c.

char* app = "VoiceMail" [static]

Definition at line 779 of file app_voicemail_imapstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 782 of file app_voicemail_imapstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 784 of file app_voicemail_imapstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 785 of file app_voicemail_imapstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 889 of file app_voicemail_imapstorage.c.

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

Definition at line 901 of file app_voicemail_imapstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 892 of file app_voicemail_imapstorage.c.

struct ast_cli_entry cli_voicemail[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_voicemail_show_users, "List defined voicemail boxes"),
   AST_CLI_DEFINE(handle_voicemail_show_zones, "List zone message formats"),
   AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"),
}

Definition at line 11317 of file app_voicemail_imapstorage.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 888 of file app_voicemail_imapstorage.c.

char* emailbody = NULL [static]

Definition at line 895 of file app_voicemail_imapstorage.c.

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

Definition at line 906 of file app_voicemail_imapstorage.c.

char* emailsubject = NULL [static]

Definition at line 896 of file app_voicemail_imapstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 890 of file app_voicemail_imapstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 756 of file app_voicemail_imapstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 755 of file app_voicemail_imapstorage.c.

char externnotify[160] [static]

Definition at line 799 of file app_voicemail_imapstorage.c.

char fromstring[100] [static]

Definition at line 899 of file app_voicemail_imapstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 884 of file app_voicemail_imapstorage.c.

Definition at line 928 of file app_voicemail_imapstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 857 of file app_voicemail_imapstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 859 of file app_voicemail_imapstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 860 of file app_voicemail_imapstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 858 of file app_voicemail_imapstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 861 of file app_voicemail_imapstorage.c.

char locale[20] [static]

Definition at line 792 of file app_voicemail_imapstorage.c.

Initial value:
 {
   .name = "MAILBOX_EXISTS",
   .read = acf_mailbox_exists,
}

Definition at line 11073 of file app_voicemail_imapstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1705 of file app_voicemail_imapstorage.c.

char mailcmd[160] [static]

Definition at line 798 of file app_voicemail_imapstorage.c.

int maxdeletedmsg [static]

Definition at line 795 of file app_voicemail_imapstorage.c.

int maxgreet [static]

Definition at line 805 of file app_voicemail_imapstorage.c.

int maxlogins [static]

Definition at line 807 of file app_voicemail_imapstorage.c.

int maxmsg [static]

Definition at line 794 of file app_voicemail_imapstorage.c.

int maxsilence [static]

Definition at line 793 of file app_voicemail_imapstorage.c.

int minpassword [static]

Definition at line 808 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 826 of file app_voicemail_imapstorage.c.

Definition at line 852 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 828 of file app_voicemail_imapstorage.c.

int my_umask [static]

Definition at line 758 of file app_voicemail_imapstorage.c.

char* pagerbody = NULL [static]

Definition at line 897 of file app_voicemail_imapstorage.c.

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

Definition at line 907 of file app_voicemail_imapstorage.c.

char pagerfromstring[100] [static]

Definition at line 900 of file app_voicemail_imapstorage.c.

char* pagersubject = NULL [static]

Definition at line 898 of file app_voicemail_imapstorage.c.

int passwordlocation [static]

Definition at line 809 of file app_voicemail_imapstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 821 of file app_voicemail_imapstorage.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 816 of file app_voicemail_imapstorage.c.

unsigned int poll_mailboxes [static]

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

Definition at line 813 of file app_voicemail_imapstorage.c.

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 822 of file app_voicemail_imapstorage.c.

unsigned char poll_thread_run [static]

Definition at line 823 of file app_voicemail_imapstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 762 of file app_voicemail_imapstorage.c.

int saydurationminfo [static]

Definition at line 886 of file app_voicemail_imapstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 787 of file app_voicemail_imapstorage.c.

char serveremail[80] [static]

Definition at line 797 of file app_voicemail_imapstorage.c.

int silencethreshold = 128 [static]

Definition at line 796 of file app_voicemail_imapstorage.c.

int skipms [static]

Definition at line 806 of file app_voicemail_imapstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 800 of file app_voicemail_imapstorage.c.

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

Definition at line 774 of file app_voicemail_imapstorage.c.

struct ast_data_entry vm_data_providers[] [static]
Initial value:
 {

}

Definition at line 11458 of file app_voicemail_imapstorage.c.

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

Definition at line 869 of file app_voicemail_imapstorage.c.

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

Definition at line 868 of file app_voicemail_imapstorage.c.

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

Definition at line 865 of file app_voicemail_imapstorage.c.

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

Definition at line 866 of file app_voicemail_imapstorage.c.

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

Definition at line 864 of file app_voicemail_imapstorage.c.

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

Definition at line 870 of file app_voicemail_imapstorage.c.

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

Definition at line 882 of file app_voicemail_imapstorage.c.

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

Definition at line 867 of file app_voicemail_imapstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 753 of file app_voicemail_imapstorage.c.

Initial value:

Definition at line 11453 of file app_voicemail_imapstorage.c.

char vmfmts[80] [static]

Definition at line 801 of file app_voicemail_imapstorage.c.

int vmmaxsecs [static]

Definition at line 804 of file app_voicemail_imapstorage.c.

int vmminsecs [static]

Definition at line 803 of file app_voicemail_imapstorage.c.

double volgain [static]

Definition at line 802 of file app_voicemail_imapstorage.c.

char zonetag[80] [static]

Definition at line 791 of file app_voicemail_imapstorage.c.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1