Wed Aug 7 17:15:49 2019

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 valid_config (const struct ast_config *cfg)
 Check if configuration file is valid.
static int vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
static int vm_box_exists (struct ast_channel *chan, const char *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_latin (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Common LATIN languages 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 749 of file app_voicemail_imapstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11304 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 11331 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 819 of file app_voicemail_imapstorage.c.

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

Definition at line 750 of file app_voicemail_imapstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 745 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 747 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 762 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 761 of file app_voicemail_imapstorage.c.

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

Definition at line 748 of file app_voicemail_imapstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

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

#define tdesc   "Comedian Mail (Voicemail System)"

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

References ast_strlen_zero().

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

05431 {
05432    DIR *dir;
05433    struct dirent *de;
05434    char fn[256];
05435    int ret = 0;
05436 
05437    /* If no mailbox, return immediately */
05438    if (ast_strlen_zero(mailbox))
05439       return 0;
05440 
05441    if (ast_strlen_zero(folder))
05442       folder = "INBOX";
05443    if (ast_strlen_zero(context))
05444       context = "default";
05445 
05446    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05447 
05448    if (!(dir = opendir(fn)))
05449       return 0;
05450 
05451    while ((de = readdir(dir))) {
05452       if (!strncasecmp(de->d_name, "msg", 3)) {
05453          if (shortcircuit) {
05454             ret = 1;
05455             break;
05456          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05457             ret++;
05458          }
05459       }
05460    }
05461 
05462    closedir(dir);
05463 
05464    return ret;
05465 }

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

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

11008 {
11009    struct ast_vm_user svm;
11010    AST_DECLARE_APP_ARGS(arg,
11011       AST_APP_ARG(mbox);
11012       AST_APP_ARG(context);
11013    );
11014 
11015    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11016 
11017    if (ast_strlen_zero(arg.mbox)) {
11018       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11019       return -1;
11020    }
11021 
11022    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11023    return 0;
11024 }

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

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

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

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

04845 {
04846    char tmpdir[256], newtmp[256];
04847    char fname[256];
04848    char tmpcmd[256];
04849    int tmpfd = -1;
04850    int soxstatus = 0;
04851 
04852    /* Eww. We want formats to tell us their own MIME type */
04853    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04854 
04855    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04856       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04857       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04858       tmpfd = mkstemp(newtmp);
04859       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04860       ast_debug(3, "newtmp: %s\n", newtmp);
04861       if (tmpfd > -1) {
04862          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04863          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04864             attach = newtmp;
04865             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04866          } else {
04867             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04868                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04869             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04870          }
04871       }
04872    }
04873    fprintf(p, "--%s" ENDL, bound);
04874    if (msgnum > -1)
04875       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04876    else
04877       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04878    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04879    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04880    if (msgnum > -1)
04881       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04882    else
04883       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04884    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04885    base_encode(fname, p);
04886    if (last)
04887       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04888    if (tmpfd > -1) {
04889       if (soxstatus == 0) {
04890          unlink(fname);
04891       }
04892       close(tmpfd);
04893       unlink(newtmp);
04894    }
04895    return 0;
04896 }

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

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

06454 {
06455    int x;
06456    if (!ast_adsi_available(chan))
06457       return;
06458    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06459    if (x < 0)
06460       return;
06461    if (!x) {
06462       if (adsi_load_vmail(chan, useadsi)) {
06463          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06464          return;
06465       }
06466    } else
06467       *useadsi = 1;
06468 }

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

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

06649 {
06650    int bytes = 0;
06651    unsigned char buf[256];
06652    unsigned char keys[8];
06653 
06654    int x;
06655 
06656    if (!ast_adsi_available(chan))
06657       return;
06658 
06659    /* New meaning for keys */
06660    for (x = 0; x < 5; x++)
06661       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06662 
06663    keys[6] = 0x0;
06664    keys[7] = 0x0;
06665 
06666    if (!vms->curmsg) {
06667       /* No prev key, provide "Folder" instead */
06668       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06669    }
06670    if (vms->curmsg >= vms->lastmsg) {
06671       /* If last message ... */
06672       if (vms->curmsg) {
06673          /* but not only message, provide "Folder" instead */
06674          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06675       } else {
06676          /* Otherwise if only message, leave blank */
06677          keys[3] = 1;
06678       }
06679    }
06680 
06681    /* If deleted, show "undeleted" */
06682 #ifdef IMAP_STORAGE
06683    ast_mutex_lock(&vms->lock);
06684 #endif
06685    if (vms->deleted[vms->curmsg]) {
06686       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06687    }
06688 #ifdef IMAP_STORAGE
06689    ast_mutex_unlock(&vms->lock);
06690 #endif
06691 
06692    /* Except "Exit" */
06693    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06694    bytes += ast_adsi_set_keys(buf + bytes, keys);
06695    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06696 
06697    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06698 }

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

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

06519 {
06520    unsigned char buf[256];
06521    int bytes = 0;
06522    unsigned char keys[8];
06523    int x, y;
06524 
06525    if (!ast_adsi_available(chan))
06526       return;
06527 
06528    for (x = 0; x < 5; x++) {
06529       y = ADSI_KEY_APPS + 12 + start + x;
06530       if (y > ADSI_KEY_APPS + 12 + 4)
06531          y = 0;
06532       keys[x] = ADSI_KEY_SKT | y;
06533    }
06534    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06535    keys[6] = 0;
06536    keys[7] = 0;
06537 
06538    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06539    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06540    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06541    bytes += ast_adsi_set_keys(buf + bytes, keys);
06542    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06543 
06544    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06545 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06804 {
06805    unsigned char buf[256];
06806    int bytes = 0;
06807 
06808    if (!ast_adsi_available(chan))
06809       return;
06810    bytes += adsi_logo(buf + bytes);
06811    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06812    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06813    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06814    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06815 
06816    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06817 }

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

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

06325 {
06326    unsigned char buf[256];
06327    int bytes = 0;
06328    int x;
06329    char num[5];
06330 
06331    *useadsi = 0;
06332    bytes += ast_adsi_data_mode(buf + bytes);
06333    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06334 
06335    bytes = 0;
06336    bytes += adsi_logo(buf);
06337    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06338 #ifdef DISPLAY
06339    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06340 #endif
06341    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06342    bytes += ast_adsi_data_mode(buf + bytes);
06343    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06344 
06345    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06346       bytes = 0;
06347       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06348       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06349       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06350       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06351       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06352       return 0;
06353    }
06354 
06355 #ifdef DISPLAY
06356    /* Add a dot */
06357    bytes = 0;
06358    bytes += ast_adsi_logo(buf);
06359    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06360    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06361    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06362    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06363 #endif
06364    bytes = 0;
06365    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06366    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06367    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06368    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06369    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06370    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06371    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06372 
06373 #ifdef DISPLAY
06374    /* Add another dot */
06375    bytes = 0;
06376    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06377    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06378 
06379    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06380    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06381 #endif
06382 
06383    bytes = 0;
06384    /* These buttons we load but don't use yet */
06385    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06386    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06387    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06388    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06389    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06390    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06391    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06392 
06393 #ifdef DISPLAY
06394    /* Add another dot */
06395    bytes = 0;
06396    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06397    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06398    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06399 #endif
06400 
06401    bytes = 0;
06402    for (x = 0; x < 5; x++) {
06403       snprintf(num, sizeof(num), "%d", x);
06404       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06405    }
06406    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06407    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06408 
06409 #ifdef DISPLAY
06410    /* Add another dot */
06411    bytes = 0;
06412    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06413    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06414    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06415 #endif
06416 
06417    if (ast_adsi_end_download(chan)) {
06418       bytes = 0;
06419       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06420       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06421       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06422       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06423       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06424       return 0;
06425    }
06426    bytes = 0;
06427    bytes += ast_adsi_download_disconnect(buf + bytes);
06428    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06429    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06430 
06431    ast_debug(1, "Done downloading scripts...\n");
06432 
06433 #ifdef DISPLAY
06434    /* Add last dot */
06435    bytes = 0;
06436    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06437    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06438 #endif
06439    ast_debug(1, "Restarting session...\n");
06440 
06441    bytes = 0;
06442    /* Load the session now */
06443    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06444       *useadsi = 1;
06445       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06446    } else
06447       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06448 
06449    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06450    return 0;
06451 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06471 {
06472    unsigned char buf[256];
06473    int bytes = 0;
06474    unsigned char keys[8];
06475    int x;
06476    if (!ast_adsi_available(chan))
06477       return;
06478 
06479    for (x = 0; x < 8; x++)
06480       keys[x] = 0;
06481    /* Set one key for next */
06482    keys[3] = ADSI_KEY_APPS + 3;
06483 
06484    bytes += adsi_logo(buf + bytes);
06485    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06486    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06487    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06488    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06489    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06490    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06491    bytes += ast_adsi_set_keys(buf + bytes, keys);
06492    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06493    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06494 }

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

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

06317 {
06318    int bytes = 0;
06319    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06320    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06321    return bytes;
06322 }

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

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

06548 {
06549    int bytes = 0;
06550    unsigned char buf[256]; 
06551    char buf1[256], buf2[256];
06552    char fn2[PATH_MAX];
06553 
06554    char cid[256] = "";
06555    char *val;
06556    char *name, *num;
06557    char datetime[21] = "";
06558    FILE *f;
06559 
06560    unsigned char keys[8];
06561 
06562    int x;
06563 
06564    if (!ast_adsi_available(chan))
06565       return;
06566 
06567    /* Retrieve important info */
06568    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06569    f = fopen(fn2, "r");
06570    if (f) {
06571       while (!feof(f)) {   
06572          if (!fgets((char *) buf, sizeof(buf), f)) {
06573             continue;
06574          }
06575          if (!feof(f)) {
06576             char *stringp = NULL;
06577             stringp = (char *) buf;
06578             strsep(&stringp, "=");
06579             val = strsep(&stringp, "=");
06580             if (!ast_strlen_zero(val)) {
06581                if (!strcmp((char *) buf, "callerid"))
06582                   ast_copy_string(cid, val, sizeof(cid));
06583                if (!strcmp((char *) buf, "origdate"))
06584                   ast_copy_string(datetime, val, sizeof(datetime));
06585             }
06586          }
06587       }
06588       fclose(f);
06589    }
06590    /* New meaning for keys */
06591    for (x = 0; x < 5; x++)
06592       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06593    keys[6] = 0x0;
06594    keys[7] = 0x0;
06595 
06596    if (!vms->curmsg) {
06597       /* No prev key, provide "Folder" instead */
06598       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06599    }
06600    if (vms->curmsg >= vms->lastmsg) {
06601       /* If last message ... */
06602       if (vms->curmsg) {
06603          /* but not only message, provide "Folder" instead */
06604          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06605          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06606 
06607       } else {
06608          /* Otherwise if only message, leave blank */
06609          keys[3] = 1;
06610       }
06611    }
06612 
06613    if (!ast_strlen_zero(cid)) {
06614       ast_callerid_parse(cid, &name, &num);
06615       if (!name)
06616          name = num;
06617    } else
06618       name = "Unknown Caller";
06619 
06620    /* If deleted, show "undeleted" */
06621 #ifdef IMAP_STORAGE
06622    ast_mutex_lock(&vms->lock);
06623 #endif
06624    if (vms->deleted[vms->curmsg]) {
06625       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06626    }
06627 #ifdef IMAP_STORAGE
06628    ast_mutex_unlock(&vms->lock);
06629 #endif
06630 
06631    /* Except "Exit" */
06632    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06633    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06634       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06635    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06636 
06637    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06638    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06639    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06640    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06641    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06642    bytes += ast_adsi_set_keys(buf + bytes, keys);
06643    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06644 
06645    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06646 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06497 {
06498    unsigned char buf[256];
06499    int bytes = 0;
06500    unsigned char keys[8];
06501    int x;
06502    if (!ast_adsi_available(chan))
06503       return;
06504 
06505    for (x = 0; x < 8; x++)
06506       keys[x] = 0;
06507    /* Set one key for next */
06508    keys[3] = ADSI_KEY_APPS + 3;
06509 
06510    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06511    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06512    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06513    bytes += ast_adsi_set_keys(buf + bytes, keys);
06514    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06515    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06516 }

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

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

06701 {
06702    unsigned char buf[256] = "";
06703    char buf1[256] = "", buf2[256] = "";
06704    int bytes = 0;
06705    unsigned char keys[8];
06706    int x;
06707 
06708    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06709    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06710    if (!ast_adsi_available(chan))
06711       return;
06712    if (vms->newmessages) {
06713       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06714       if (vms->oldmessages) {
06715          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06716          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06717       } else {
06718          snprintf(buf2, sizeof(buf2), "%s.", newm);
06719       }
06720    } else if (vms->oldmessages) {
06721       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06722       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06723    } else {
06724       strcpy(buf1, "You have no messages.");
06725       buf2[0] = ' ';
06726       buf2[1] = '\0';
06727    }
06728    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06729    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06730    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06731 
06732    for (x = 0; x < 6; x++)
06733       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06734    keys[6] = 0;
06735    keys[7] = 0;
06736 
06737    /* Don't let them listen if there are none */
06738    if (vms->lastmsg < 0)
06739       keys[0] = 1;
06740    bytes += ast_adsi_set_keys(buf + bytes, keys);
06741 
06742    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06743 
06744    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06745 }

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

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

06748 {
06749    unsigned char buf[256] = "";
06750    char buf1[256] = "", buf2[256] = "";
06751    int bytes = 0;
06752    unsigned char keys[8];
06753    int x;
06754 
06755    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06756 
06757    if (!ast_adsi_available(chan))
06758       return;
06759 
06760    /* Original command keys */
06761    for (x = 0; x < 6; x++)
06762       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06763 
06764    keys[6] = 0;
06765    keys[7] = 0;
06766 
06767    if ((vms->lastmsg + 1) < 1)
06768       keys[0] = 0;
06769 
06770    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06771       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06772 
06773    if (vms->lastmsg + 1)
06774       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06775    else
06776       strcpy(buf2, "no messages.");
06777    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06778    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06779    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06780    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06781    bytes += ast_adsi_set_keys(buf + bytes, keys);
06782 
06783    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06784 
06785    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06786    
06787 }

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

Referenced by vm_execmain().

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

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

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

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

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

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

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

Destructively Parse options and apply.

Definition at line 1305 of file app_voicemail_imapstorage.c.

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

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

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

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

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

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

04520 {
04521    struct ast_str *tmp = ast_str_alloca(80);
04522    int first_section = 1;
04523 
04524    ast_str_reset(*end);
04525    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04526    for (; *start; start++) {
04527       int need_encoding = 0;
04528       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04529          need_encoding = 1;
04530       }
04531       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04532          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04533          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04534          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04535          /* Start new line */
04536          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04537          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04538          first_section = 0;
04539       }
04540       if (need_encoding && *start == ' ') {
04541          ast_str_append(&tmp, -1, "_");
04542       } else if (need_encoding) {
04543          ast_str_append(&tmp, -1, "=%hhX", *start);
04544       } else {
04545          ast_str_append(&tmp, -1, "%c", *start);
04546       }
04547    }
04548    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04549    return ast_str_buffer(*end);
04550 }

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

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

Referenced by make_email_file(), and sendpage().

04448 {
04449    const char *ptr;
04450 
04451    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04452    ast_str_set(buf, maxlen, "\"");
04453    for (ptr = from; *ptr; ptr++) {
04454       if (*ptr == '"' || *ptr == '\\') {
04455          ast_str_append(buf, maxlen, "\\%c", *ptr);
04456       } else {
04457          ast_str_append(buf, maxlen, "%c", *ptr);
04458       }
04459    }
04460    ast_str_append(buf, maxlen, "\"");
04461 
04462    return ast_str_buffer(*buf);
04463 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

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

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

04324 {
04325    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04326       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04327       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04328       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04329    int i, hiteof = 0;
04330    FILE *fi;
04331    struct baseio bio;
04332 
04333    memset(&bio, 0, sizeof(bio));
04334    bio.iocp = BASEMAXINLINE;
04335 
04336    if (!(fi = fopen(filename, "rb"))) {
04337       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04338       return -1;
04339    }
04340 
04341    while (!hiteof){
04342       unsigned char igroup[3], ogroup[4];
04343       int c, n;
04344 
04345       memset(igroup, 0, sizeof(igroup));
04346 
04347       for (n = 0; n < 3; n++) {
04348          if ((c = inchar(&bio, fi)) == EOF) {
04349             hiteof = 1;
04350             break;
04351          }
04352 
04353          igroup[n] = (unsigned char) c;
04354       }
04355 
04356       if (n > 0) {
04357          ogroup[0]= dtable[igroup[0] >> 2];
04358          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04359          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04360          ogroup[3]= dtable[igroup[2] & 0x3F];
04361 
04362          if (n < 3) {
04363             ogroup[3] = '=';
04364 
04365             if (n < 2)
04366                ogroup[2] = '=';
04367          }
04368 
04369          for (i = 0; i < 4; i++)
04370             ochar(&bio, ogroup[i], so);
04371       }
04372    }
04373 
04374    fclose(fi);
04375    
04376    if (fputs(ENDL, so) == EOF) {
04377       return 0;
04378    }
04379 
04380    return 1;
04381 }

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

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

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

Referenced by make_email_file(), and sendpage().

04493 {
04494    for (; *str; str++) {
04495       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04496          return 1;
04497       }
04498    }
04499    return 0;
04500 }

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

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

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

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

08013 {
08014    int x = 0;
08015    int last_msg_idx = 0;
08016 
08017 #ifndef IMAP_STORAGE
08018    int res = 0, nummsg;
08019    char fn2[PATH_MAX];
08020 #endif
08021 
08022    if (vms->lastmsg <= -1) {
08023       goto done;
08024    }
08025 
08026    vms->curmsg = -1;
08027 #ifndef IMAP_STORAGE
08028    /* Get the deleted messages fixed */
08029    if (vm_lock_path(vms->curdir)) {
08030       return ERROR_LOCK_PATH;
08031    }
08032 
08033    /* update count as message may have arrived while we've got mailbox open */
08034    last_msg_idx = last_message_index(vmu, vms->curdir);
08035    if (last_msg_idx != vms->lastmsg) {
08036       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
08037    }
08038 
08039    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
08040    for (x = 0; x < last_msg_idx + 1; x++) {
08041       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
08042          /* Save this message.  It's not in INBOX or hasn't been heard */
08043          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08044          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
08045             break;
08046          }
08047          vms->curmsg++;
08048          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
08049          if (strcmp(vms->fn, fn2)) {
08050             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
08051          }
08052       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
08053          /* Move to old folder before deleting */
08054          res = save_to_folder(vmu, vms, x, 1);
08055          if (res == ERROR_LOCK_PATH) {
08056             /* If save failed do not delete the message */
08057             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08058             vms->deleted[x] = 0;
08059             vms->heard[x] = 0;
08060             --x;
08061          }
08062       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08063          /* Move to deleted folder */
08064          res = save_to_folder(vmu, vms, x, 10);
08065          if (res == ERROR_LOCK_PATH) {
08066             /* If save failed do not delete the message */
08067             vms->deleted[x] = 0;
08068             vms->heard[x] = 0;
08069             --x;
08070          }
08071       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08072          /* If realtime storage enabled - we should explicitly delete this message,
08073          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08074          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08075          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08076             DELETE(vms->curdir, x, vms->fn, vmu);
08077          }
08078       }
08079    }
08080 
08081    /* Delete ALL remaining messages */
08082    nummsg = x - 1;
08083    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08084       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08085       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08086          DELETE(vms->curdir, x, vms->fn, vmu);
08087       }
08088    }
08089    ast_unlock_path(vms->curdir);
08090 #else /* defined(IMAP_STORAGE) */
08091    ast_mutex_lock(&vms->lock);
08092    if (vms->deleted) {
08093       /* Since we now expunge after each delete, deleting in reverse order
08094        * ensures that no reordering occurs between each step. */
08095       last_msg_idx = vms->dh_arraysize;
08096       for (x = last_msg_idx - 1; x >= 0; x--) {
08097          if (vms->deleted[x]) {
08098             ast_debug(3, "IMAP delete of %d\n", x);
08099             DELETE(vms->curdir, x, vms->fn, vmu);
08100          }
08101       }
08102    }
08103 #endif
08104 
08105 done:
08106    if (vms->deleted) {
08107       ast_free(vms->deleted);
08108       vms->deleted = NULL;
08109    }
08110    if (vms->heard) {
08111       ast_free(vms->heard);
08112       vms->heard = NULL;
08113    }
08114    vms->dh_arraysize = 0;
08115 #ifdef IMAP_STORAGE
08116    ast_mutex_unlock(&vms->lock);
08117 #endif
08118 
08119    return 0;
08120 }

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

Definition at line 11111 of file app_voicemail_imapstorage.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11112 {
11113    int which = 0;
11114    int wordlen;
11115    struct ast_vm_user *vmu;
11116    const char *context = "";
11117 
11118    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11119    if (pos > 4)
11120       return NULL;
11121    if (pos == 3)
11122       return (state == 0) ? ast_strdup("for") : NULL;
11123    wordlen = strlen(word);
11124    AST_LIST_TRAVERSE(&users, vmu, list) {
11125       if (!strncasecmp(word, vmu->context, wordlen)) {
11126          if (context && strcmp(context, vmu->context) && ++which > state)
11127             return ast_strdup(vmu->context);
11128          /* ignore repeated contexts ? */
11129          context = vmu->context;
11130       }
11131    }
11132    return NULL;
11133 }

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

04129 {
04130    int ifd;
04131    int ofd;
04132    int res;
04133    int len;
04134    char buf[4096];
04135 
04136 #ifdef HARDLINK_WHEN_POSSIBLE
04137    /* Hard link if possible; saves disk space & is faster */
04138    if (link(infile, outfile)) {
04139 #endif
04140       if ((ifd = open(infile, O_RDONLY)) < 0) {
04141          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04142          return -1;
04143       }
04144       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04145          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04146          close(ifd);
04147          return -1;
04148       }
04149       do {
04150          len = read(ifd, buf, sizeof(buf));
04151          if (len < 0) {
04152             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04153             close(ifd);
04154             close(ofd);
04155             unlink(outfile);
04156          } else if (len) {
04157             res = write(ofd, buf, len);
04158             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04159                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04160                close(ifd);
04161                close(ofd);
04162                unlink(outfile);
04163             }
04164          }
04165       } while (len);
04166       close(ifd);
04167       close(ofd);
04168       return 0;
04169 #ifdef HARDLINK_WHEN_POSSIBLE
04170    } else {
04171       /* Hard link succeeded */
04172       return 0;
04173    }
04174 #endif
04175 }

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

05365 {
05366    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05367    const char *frombox = mbox(vmu, imbox);
05368    const char *userfolder;
05369    int recipmsgnum;
05370    int res = 0;
05371 
05372    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05373 
05374    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05375       userfolder = "Urgent";
05376    } else {
05377       userfolder = "INBOX";
05378    }
05379 
05380    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05381 
05382    if (!dir)
05383       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05384    else
05385       ast_copy_string(fromdir, dir, sizeof(fromdir));
05386 
05387    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05388    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05389 
05390    if (vm_lock_path(todir))
05391       return ERROR_LOCK_PATH;
05392 
05393    recipmsgnum = last_message_index(recip, todir) + 1;
05394    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05395       make_file(topath, sizeof(topath), todir, recipmsgnum);
05396 #ifndef ODBC_STORAGE
05397       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05398          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05399       } else {
05400 #endif
05401          /* If we are prepending a message for ODBC, then the message already
05402           * exists in the database, but we want to force copying from the
05403           * filesystem (since only the FS contains the prepend). */
05404          copy_plain_file(frompath, topath);
05405          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05406          vm_delete(topath);
05407 #ifndef ODBC_STORAGE
05408       }
05409 #endif
05410    } else {
05411       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05412       res = -1;
05413    }
05414    ast_unlock_path(todir);
05415    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05416       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05417       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05418       flag);
05419    
05420    return res;
05421 }

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

04187 {
04188    char frompath2[PATH_MAX], topath2[PATH_MAX];
04189    struct ast_variable *tmp,*var = NULL;
04190    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04191    ast_filecopy(frompath, topath, NULL);
04192    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04193    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04194    if (ast_check_realtime("voicemail_data")) {
04195       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04196       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04197       for (tmp = var; tmp; tmp = tmp->next) {
04198          if (!strcasecmp(tmp->name, "origmailbox")) {
04199             origmailbox = tmp->value;
04200          } else if (!strcasecmp(tmp->name, "context")) {
04201             context = tmp->value;
04202          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04203             macrocontext = tmp->value;
04204          } else if (!strcasecmp(tmp->name, "exten")) {
04205             exten = tmp->value;
04206          } else if (!strcasecmp(tmp->name, "priority")) {
04207             priority = tmp->value;
04208          } else if (!strcasecmp(tmp->name, "callerchan")) {
04209             callerchan = tmp->value;
04210          } else if (!strcasecmp(tmp->name, "callerid")) {
04211             callerid = tmp->value;
04212          } else if (!strcasecmp(tmp->name, "origdate")) {
04213             origdate = tmp->value;
04214          } else if (!strcasecmp(tmp->name, "origtime")) {
04215             origtime = tmp->value;
04216          } else if (!strcasecmp(tmp->name, "category")) {
04217             category = tmp->value;
04218          } else if (!strcasecmp(tmp->name, "duration")) {
04219             duration = tmp->value;
04220          }
04221       }
04222       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);
04223    }
04224    copy(frompath2, topath2);
04225    ast_variables_destroy(var);
04226 }

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

04024 {
04025 
04026    int vmcount = 0;
04027    DIR *vmdir = NULL;
04028    struct dirent *vment = NULL;
04029 
04030    if (vm_lock_path(dir))
04031       return ERROR_LOCK_PATH;
04032 
04033    if ((vmdir = opendir(dir))) {
04034       while ((vment = readdir(vmdir))) {
04035          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
04036             vmcount++;
04037          }
04038       }
04039       closedir(vmdir);
04040    }
04041    ast_unlock_path(dir);
04042    
04043    return vmcount;
04044 }

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

01707 {
01708    mode_t   mode = VOICEMAIL_DIR_MODE;
01709    int res;
01710 
01711    make_dir(dest, len, context, ext, folder);
01712    if ((res = ast_mkdir(dest, mode))) {
01713       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01714       return -1;
01715    }
01716    return 0;
01717 }

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

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

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

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

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

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

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

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

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

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

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

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

static void free_user ( struct ast_vm_user vmu  )  [static]

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

01762 {
01763    if (ast_test_flag(vmu, VM_ALLOCED)) {
01764 
01765       ast_free(vmu->emailbody);
01766       vmu->emailbody = NULL;
01767 
01768       ast_free(vmu->emailsubject);
01769       vmu->emailsubject = NULL;
01770 
01771       ast_free(vmu);
01772    }
01773 }

static void free_vm_users ( void   )  [static]

Free the users structure.

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

11724 {
11725    struct ast_vm_user *current;
11726    AST_LIST_LOCK(&users);
11727    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11728       ast_set_flag(current, VM_ALLOCED);
11729       free_user(current);
11730    }
11731    AST_LIST_UNLOCK(&users);
11732 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

11736 {
11737    struct vm_zone *zcur;
11738    AST_LIST_LOCK(&zones);
11739    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11740       free_zone(zcur);
11741    AST_LIST_UNLOCK(&zones);
11742 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5132 of file app_voicemail_imapstorage.c.

References ast_free.

Referenced by free_vm_zones().

05133 {
05134    ast_free(z);
05135 }

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

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

Referenced by leave_voicemail().

05089 {
05090    struct ast_tm tm;
05091    struct timeval t = ast_tvnow();
05092    
05093    ast_localtime(&t, &tm, "UTC");
05094 
05095    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05096 }

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

06824 {
06825    int x;
06826    int d;
06827    char fn[PATH_MAX];
06828    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06829    if (d)
06830       return d;
06831    for (x = start; x < 5; x++) { /* For all folders */
06832       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06833          return d;
06834       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06835       if (d)
06836          return d;
06837       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06838 
06839       /* The inbox folder can have its name changed under certain conditions
06840        * so this checks if the sound file exists for the inbox folder name and
06841        * if it doesn't, plays the default name instead. */
06842       if (x == 0) {
06843          if (ast_fileexists(fn, NULL, NULL)) {
06844             d = vm_play_folder_name(chan, fn);
06845          } else {
06846             ast_verb(1, "failed to find %s\n", fn);
06847             d = vm_play_folder_name(chan, "vm-INBOX");
06848          }
06849       } else {
06850          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06851          d = vm_play_folder_name(chan, fn);
06852       }
06853 
06854       if (d)
06855          return d;
06856       d = ast_waitfordigit(chan, 500);
06857       if (d)
06858          return d;
06859    }
06860 
06861    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06862    if (d)
06863       return d;
06864    d = ast_waitfordigit(chan, 4000);
06865    return d;
06866 }

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

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

Referenced by vm_execmain().

06881 {
06882    int res = 0;
06883    int loops = 0;
06884 
06885    res = ast_play_and_wait(chan, fn);  /* Folder name */
06886    while (((res < '0') || (res > '9')) &&
06887          (res != '#') && (res >= 0) &&
06888          loops < 4) {
06889       res = get_folder(chan, 0);
06890       loops++;
06891    }
06892    if (loops == 4) { /* give up */
06893       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06894       return '#';
06895    }
06896    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06897    return res;
06898 }

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

Definition at line 1748 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

Referenced by vm_execmain().

01749 {
01750    size_t i;
01751 
01752    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01753       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01754          return i;
01755       }
01756    }
01757 
01758    return -1;
01759 }

static int handle_subscribe ( void *  datap  )  [static]

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

11494 {
11495    unsigned int len;
11496    struct mwi_sub *mwi_sub;
11497    struct mwi_sub_task *p = datap;
11498 
11499    len = sizeof(*mwi_sub);
11500    if (!ast_strlen_zero(p->mailbox))
11501       len += strlen(p->mailbox);
11502 
11503    if (!ast_strlen_zero(p->context))
11504       len += strlen(p->context) + 1; /* Allow for seperator */
11505 
11506    if (!(mwi_sub = ast_calloc(1, len)))
11507       return -1;
11508 
11509    mwi_sub->uniqueid = p->uniqueid;
11510    if (!ast_strlen_zero(p->mailbox))
11511       strcpy(mwi_sub->mailbox, p->mailbox);
11512 
11513    if (!ast_strlen_zero(p->context)) {
11514       strcat(mwi_sub->mailbox, "@");
11515       strcat(mwi_sub->mailbox, p->context);
11516    }
11517 
11518    AST_RWLIST_WRLOCK(&mwi_subs);
11519    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11520    AST_RWLIST_UNLOCK(&mwi_subs);
11521    ast_free((void *) p->mailbox);
11522    ast_free((void *) p->context);
11523    ast_free(p);
11524    poll_subscribed_mailbox(mwi_sub);
11525    return 0;
11526 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

11472 {
11473    struct mwi_sub *mwi_sub;
11474    uint32_t *uniqueid = datap;
11475    
11476    AST_RWLIST_WRLOCK(&mwi_subs);
11477    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11478       if (mwi_sub->uniqueid == *uniqueid) {
11479          AST_LIST_REMOVE_CURRENT(entry);
11480          break;
11481       }
11482    }
11483    AST_RWLIST_TRAVERSE_SAFE_END
11484    AST_RWLIST_UNLOCK(&mwi_subs);
11485 
11486    if (mwi_sub)
11487       mwi_sub_destroy(mwi_sub);
11488 
11489    ast_free(uniqueid);  
11490    return 0;
11491 }

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

11249 {
11250    switch (cmd) {
11251    case CLI_INIT:
11252       e->command = "voicemail reload";
11253       e->usage =
11254          "Usage: voicemail reload\n"
11255          "       Reload voicemail configuration\n";
11256       return NULL;
11257    case CLI_GENERATE:
11258       return NULL;
11259    }
11260 
11261    if (a->argc != 2)
11262       return CLI_SHOWUSAGE;
11263 
11264    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11265    load_config(1);
11266    
11267    return CLI_SUCCESS;
11268 }

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

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

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

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

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

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

Referenced by load_module(), and vm_execmain().

05477 {
05478    char tmp[256], *tmp2 = tmp, *box, *context;
05479    ast_copy_string(tmp, mailbox, sizeof(tmp));
05480    if (ast_strlen_zero(folder)) {
05481       folder = "INBOX";
05482    }
05483    while ((box = strsep(&tmp2, ",&"))) {
05484       if ((context = strchr(box, '@')))
05485          *context++ = '\0';
05486       else
05487          context = "default";
05488       if (__has_voicemail(context, box, folder, 1))
05489          return 1;
05490       /* If we are checking INBOX, we should check Urgent as well */
05491       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05492          return 1;
05493       }
05494    }
05495    return 0;
05496 }

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

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

05559 {
05560    int urgentmsgs = 0;
05561    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05562    if (newmsgs) {
05563       *newmsgs += urgentmsgs;
05564    }
05565    return res;
05566 }

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

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

05500 {
05501    char tmp[256];
05502    char *context;
05503 
05504    /* If no mailbox, return immediately */
05505    if (ast_strlen_zero(mailbox))
05506       return 0;
05507 
05508    if (newmsgs)
05509       *newmsgs = 0;
05510    if (oldmsgs)
05511       *oldmsgs = 0;
05512    if (urgentmsgs)
05513       *urgentmsgs = 0;
05514 
05515    if (strchr(mailbox, ',')) {
05516       int tmpnew, tmpold, tmpurgent;
05517       char *mb, *cur;
05518 
05519       ast_copy_string(tmp, mailbox, sizeof(tmp));
05520       mb = tmp;
05521       while ((cur = strsep(&mb, ", "))) {
05522          if (!ast_strlen_zero(cur)) {
05523             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05524                return -1;
05525             else {
05526                if (newmsgs)
05527                   *newmsgs += tmpnew; 
05528                if (oldmsgs)
05529                   *oldmsgs += tmpold;
05530                if (urgentmsgs)
05531                   *urgentmsgs += tmpurgent;
05532             }
05533          }
05534       }
05535       return 0;
05536    }
05537 
05538    ast_copy_string(tmp, mailbox, sizeof(tmp));
05539    
05540    if ((context = strchr(tmp, '@')))
05541       *context++ = '\0';
05542    else
05543       context = "default";
05544 
05545    if (newmsgs)
05546       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05547    if (oldmsgs)
05548       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05549    if (urgentmsgs)
05550       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05551 
05552    return 0;
05553 }

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

utility used by inchar(), for base_encode()

Definition at line 4258 of file app_voicemail_imapstorage.c.

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

Referenced by inchar().

04259 {
04260    int l;
04261 
04262    if (bio->ateof)
04263       return 0;
04264 
04265    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04266       if (ferror(fi))
04267          return -1;
04268 
04269       bio->ateof = 1;
04270       return 0;
04271    }
04272 
04273    bio->iolen = l;
04274    bio->iocp = 0;
04275 
04276    return 1;
04277 }

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

utility used by base_encode()

Definition at line 4282 of file app_voicemail_imapstorage.c.

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

Referenced by base_encode().

04283 {
04284    if (bio->iocp>=bio->iolen) {
04285       if (!inbuf(bio, fi))
04286          return EOF;
04287    }
04288 
04289    return bio->iobuf[bio->iocp++];
04290 }

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

Definition at line 943 of file app_voicemail_imapstorage.c.

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

Referenced by load_module().

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

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

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

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

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

Definition at line 937 of file app_voicemail_imapstorage.c.

References inprocess::mailbox.

Referenced by load_module().

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

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

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

05099 {
05100    int res;
05101    char fn[PATH_MAX];
05102    char dest[PATH_MAX];
05103 
05104    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05105 
05106    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05107       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05108       return -1;
05109    }
05110 
05111    RETRIEVE(fn, -1, ext, context);
05112    if (ast_fileexists(fn, NULL, NULL) > 0) {
05113       res = ast_stream_and_wait(chan, fn, ecodes);
05114       if (res) {
05115          DISPOSE(fn, -1);
05116          return res;
05117       }
05118    } else {
05119       /* Dispose just in case */
05120       DISPOSE(fn, -1);
05121       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05122       if (res)
05123          return res;
05124       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05125       if (res)
05126          return res;
05127    }
05128    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05129    return res;
05130 }

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

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

Referenced by actual_load_config().

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

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

04078 {
04079    int x;
04080    unsigned char map[MAXMSGLIMIT] = "";
04081    DIR *msgdir;
04082    struct dirent *msgdirent;
04083    int msgdirint;
04084    char extension[4];
04085    int stopcount = 0;
04086 
04087    /* Reading the entire directory into a file map scales better than
04088     * doing a stat repeatedly on a predicted sequence.  I suspect this
04089     * is partially due to stat(2) internally doing a readdir(2) itself to
04090     * find each file. */
04091    if (!(msgdir = opendir(dir))) {
04092       return -1;
04093    }
04094 
04095    while ((msgdirent = readdir(msgdir))) {
04096       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04097          map[msgdirint] = 1;
04098          stopcount++;
04099          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04100       }
04101    }
04102    closedir(msgdir);
04103 
04104    for (x = 0; x < vmu->maxmsg; x++) {
04105       if (map[x] == 1) {
04106          stopcount--;
04107       } else if (map[x] == 0 && !stopcount) {
04108          break;
04109       }
04110    }
04111 
04112    return x - 1;
04113 }

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

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

static int load_config ( int  reload  )  [static]

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

11792 {
11793    struct ast_config *cfg, *ucfg;
11794    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11795    int res;
11796 
11797    ast_unload_realtime("voicemail");
11798    ast_unload_realtime("voicemail_data");
11799 
11800    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11801       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11802          return 0;
11803       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11804          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11805          ucfg = NULL;
11806       }
11807       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11808       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11809          ast_config_destroy(ucfg);
11810          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11811          return 0;
11812       }
11813    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11814       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11815       return 0;
11816    } else {
11817       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11818       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11819          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11820          ucfg = NULL;
11821       }
11822    }
11823 
11824    res = actual_load_config(reload, cfg, ucfg);
11825 
11826    ast_config_destroy(cfg);
11827    ast_config_destroy(ucfg);
11828 
11829    return res;
11830 }

static int load_module ( void   )  [static]

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

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

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

01661 {
01662    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01663 }

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 4575 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(), valid_config(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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

01678 {
01679    return snprintf(dest, len, "%s/msg%04d", dir, num);
01680 }

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

Manager list voicemail users command.

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

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

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

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

11444 {
11445    while (poll_thread_run) {
11446       struct timespec ts = { 0, };
11447       struct timeval wait;
11448 
11449       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11450       ts.tv_sec = wait.tv_sec;
11451       ts.tv_nsec = wait.tv_usec * 1000;
11452 
11453       ast_mutex_lock(&poll_lock);
11454       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11455       ast_mutex_unlock(&poll_lock);
11456 
11457       if (!poll_thread_run)
11458          break;
11459 
11460       poll_subscribed_mailboxes();
11461    }
11462 
11463    return NULL;
11464 }

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

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

01739 {
01740 #ifdef IMAP_STORAGE
01741    if (vmu && id == 0) {
01742       return vmu->imapfolder;
01743    }
01744 #endif
01745    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01746 }

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

Definition at line 5425 of file app_voicemail_imapstorage.c.

References __has_voicemail().

Referenced by load_module().

05426 {
05427    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05428 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11466 of file app_voicemail_imapstorage.c.

References ast_free.

Referenced by handle_unsubscribe().

11467 {
11468    ast_free(mwi_sub);
11469 }

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

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

11555 {
11556    struct mwi_sub_task *mwist;
11557    
11558    if (ast_event_get_type(event) != AST_EVENT_SUB)
11559       return;
11560 
11561    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11562       return;
11563 
11564    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11565       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11566       return;
11567    }
11568    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11569    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11570    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11571    
11572    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11573       ast_free(mwist);
11574    }
11575 }

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

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

11529 {
11530    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11531 
11532    if (!uniqueid) {
11533       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11534       return;
11535    }
11536 
11537    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11538       ast_free(uniqueid);
11539       return;
11540    }
11541 
11542    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11543       ast_free(uniqueid);
11544       return;
11545    }
11546 
11547    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11548    *uniqueid = u;
11549    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11550       ast_free(uniqueid);
11551    }
11552 }

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

07112 {
07113    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07114    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07115    const char *category;
07116    char *myserveremail = serveremail;
07117 
07118    ast_channel_lock(chan);
07119    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07120       category = ast_strdupa(category);
07121    }
07122    ast_channel_unlock(chan);
07123 
07124 #ifndef IMAP_STORAGE
07125    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07126 #else
07127    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07128 #endif
07129    make_file(fn, sizeof(fn), todir, msgnum);
07130    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07131 
07132    if (!ast_strlen_zero(vmu->attachfmt)) {
07133       if (strstr(fmt, vmu->attachfmt))
07134          fmt = vmu->attachfmt;
07135       else
07136          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);
07137    }
07138 
07139    /* Attach only the first format */
07140    fmt = ast_strdupa(fmt);
07141    stringp = fmt;
07142    strsep(&stringp, "|");
07143 
07144    if (!ast_strlen_zero(vmu->serveremail))
07145       myserveremail = vmu->serveremail;
07146 
07147    if (!ast_strlen_zero(vmu->email)) {
07148       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07149 
07150       if (attach_user_voicemail)
07151          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07152 
07153       /* XXX possible imap issue, should category be NULL XXX */
07154       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07155 
07156       if (attach_user_voicemail)
07157          DISPOSE(todir, msgnum);
07158    }
07159 
07160    if (!ast_strlen_zero(vmu->pager)) {
07161       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07162    }
07163 
07164    if (ast_test_flag(vmu, VM_DELETE))
07165       DELETE(todir, msgnum, fn, vmu);
07166 
07167    /* Leave voicemail for someone */
07168    if (ast_app_has_voicemail(ext_context, NULL)) 
07169       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07170 
07171    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07172 
07173    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);
07174    run_externnotify(vmu->context, vmu->mailbox, flag);
07175 
07176 #ifdef IMAP_STORAGE
07177    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07178    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07179       vm_imap_delete(NULL, vms->curmsg, vmu);
07180       vms->newmessages--;  /* Fix new message count */
07181    }
07182 #endif
07183 
07184    return 0;
07185 }

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

utility used by base_encode()

Definition at line 4295 of file app_voicemail_imapstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04296 {
04297    if (bio->linelength >= BASELINELEN) {
04298       if (fputs(ENDL, so) == EOF) {
04299          return -1;
04300       }
04301 
04302       bio->linelength = 0;
04303    }
04304 
04305    if (putc(((unsigned char) c), so) == EOF) {
04306       return -1;
04307    }
04308 
04309    bio->linelength++;
04310 
04311    return 1;
04312 }

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

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

07960 {
07961    int count_msg, last_msg;
07962 
07963    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07964 
07965    /* Rename the member vmbox HERE so that we don't try to return before
07966     * we know what's going on.
07967     */
07968    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07969 
07970    /* Faster to make the directory than to check if it exists. */
07971    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07972 
07973    /* traverses directory using readdir (or select query for ODBC) */
07974    count_msg = count_messages(vmu, vms->curdir);
07975    if (count_msg < 0) {
07976       return count_msg;
07977    } else {
07978       vms->lastmsg = count_msg - 1;
07979    }
07980 
07981    if (vm_allocate_dh(vms, vmu, count_msg)) {
07982       return -1;
07983    }
07984 
07985    /*
07986    The following test is needed in case sequencing gets messed up.
07987    There appears to be more than one way to mess up sequence, so
07988    we will not try to find all of the root causes--just fix it when
07989    detected.
07990    */
07991 
07992    if (vm_lock_path(vms->curdir)) {
07993       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07994       return ERROR_LOCK_PATH;
07995    }
07996 
07997    /* for local storage, checks directory for messages up to maxmsg limit */
07998    last_msg = last_message_index(vmu, vms->curdir);
07999    ast_unlock_path(vms->curdir);
08000 
08001    if (last_msg < -1) {
08002       return last_msg;
08003    } else if (vms->lastmsg != last_msg) {
08004       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);
08005       resequence_mailbox(vmu, vms->curdir, count_msg);
08006    }
08007 
08008    return 0;
08009 }

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

Definition at line 7733 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, 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, valid_config(), VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

Referenced by vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_browse_messages_vi(), vm_browse_messages_zh(), and vm_execmain().

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

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

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

07620 {
07621    int res = 0;
07622    int i;
07623    char *callerid, *name;
07624    char prefile[PATH_MAX] = "";
07625    
07626 
07627    /* If voicemail cid is not enabled, or we didn't get cid or context from
07628     * the attribute file, leave now.
07629     *
07630     * TODO Still need to change this so that if this function is called by the
07631     * message envelope (and someone is explicitly requesting to hear the CID),
07632     * it does not check to see if CID is enabled in the config file.
07633     */
07634    if ((cid == NULL)||(context == NULL))
07635       return res;
07636 
07637    /* Strip off caller ID number from name */
07638    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07639    ast_callerid_parse(cid, &name, &callerid);
07640    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07641       /* Check for internal contexts and only */
07642       /* say extension when the call didn't come from an internal context in the list */
07643       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07644          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07645          if ((strcmp(cidinternalcontexts[i], context) == 0))
07646             break;
07647       }
07648       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07649          if (!res) {
07650             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07651             if (!ast_strlen_zero(prefile)) {
07652             /* See if we can find a recorded name for this person instead of their extension number */
07653                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07654                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07655                   if (!callback)
07656                      res = wait_file2(chan, vms, "vm-from");
07657                   res = ast_stream_and_wait(chan, prefile, "");
07658                } else {
07659                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07660                   /* Say "from extension" as one saying to sound smoother */
07661                   if (!callback)
07662                      res = wait_file2(chan, vms, "vm-from-extension");
07663                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07664                }
07665             }
07666          }
07667       } else if (!res) {
07668          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07669          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07670          if (!callback)
07671             res = wait_file2(chan, vms, "vm-from-phonenumber");
07672          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07673       }
07674    } else {
07675       /* Number unknown */
07676       ast_debug(1, "VM-CID: From an unknown number\n");
07677       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07678       res = wait_file2(chan, vms, "vm-unknown-caller");
07679    }
07680    return res;
07681 }

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

Definition at line 7530 of file app_voicemail_imapstorage.c.

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

Referenced by play_message().

07531 {
07532    int res = 0;
07533 
07534    if (!ast_strlen_zero(category))
07535       res = ast_play_and_wait(chan, category);
07536 
07537    if (res) {
07538       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07539       res = 0;
07540    }
07541 
07542    return res;
07543 }

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

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

07546 {
07547    int res = 0;
07548    struct vm_zone *the_zone = NULL;
07549    time_t t;
07550 
07551    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07552       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07553       return 0;
07554    }
07555 
07556    /* Does this user have a timezone specified? */
07557    if (!ast_strlen_zero(vmu->zonetag)) {
07558       /* Find the zone in the list */
07559       struct vm_zone *z;
07560       AST_LIST_LOCK(&zones);
07561       AST_LIST_TRAVERSE(&zones, z, list) {
07562          if (!strcmp(z->name, vmu->zonetag)) {
07563             the_zone = z;
07564             break;
07565          }
07566       }
07567       AST_LIST_UNLOCK(&zones);
07568    }
07569 
07570 /* No internal variable parsing for now, so we'll comment it out for the time being */
07571 #if 0
07572    /* Set the DIFF_* variables */
07573    ast_localtime(&t, &time_now, NULL);
07574    tv_now = ast_tvnow();
07575    ast_localtime(&tv_now, &time_then, NULL);
07576 
07577    /* Day difference */
07578    if (time_now.tm_year == time_then.tm_year)
07579       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07580    else
07581       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07582    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07583 
07584    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07585 #endif
07586    if (the_zone) {
07587       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07588    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07589       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07590    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07591       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07592    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07593       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);
07594    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07595       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07596    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07597       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07598    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07599       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07600    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07601       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);
07602    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07603       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07604    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07605       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07606    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07607       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);
07608    } else {
07609       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07610    }
07611 #if 0
07612    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07613 #endif
07614    return res;
07615 }

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

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

07684 {
07685    int res = 0;
07686    int durationm;
07687    int durations;
07688    /* Verify that we have a duration for the message */
07689    if (duration == NULL)
07690       return res;
07691 
07692    /* Convert from seconds to minutes */
07693    durations = atoi(duration);
07694    durationm = (durations / 60);
07695 
07696    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07697 
07698    if ((!res) && (durationm >= minduration)) {
07699       res = wait_file2(chan, vms, "vm-duration");
07700 
07701       /* POLISH syntax */
07702       if (!strncasecmp(chan->language, "pl", 2)) {
07703          div_t num = div(durationm, 10);
07704 
07705          if (durationm == 1) {
07706             res = ast_play_and_wait(chan, "digits/1z");
07707             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07708          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07709             if (num.rem == 2) {
07710                if (!num.quot) {
07711                   res = ast_play_and_wait(chan, "digits/2-ie");
07712                } else {
07713                   res = say_and_wait(chan, durationm - 2 , chan->language);
07714                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07715                }
07716             } else {
07717                res = say_and_wait(chan, durationm, chan->language);
07718             }
07719             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07720          } else {
07721             res = say_and_wait(chan, durationm, chan->language);
07722             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07723          }
07724       /* DEFAULT syntax */
07725       } else {
07726          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07727          res = wait_file2(chan, vms, "vm-minutes");
07728       }
07729    }
07730    return res;
07731 }

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11415 of file app_voicemail_imapstorage.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11416 {
11417    int new = 0, old = 0, urgent = 0;
11418 
11419    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11420 
11421    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11422       mwi_sub->old_urgent = urgent;
11423       mwi_sub->old_new = new;
11424       mwi_sub->old_old = old;
11425       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11426       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11427    }
11428 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11431 {
11432    struct mwi_sub *mwi_sub;
11433 
11434    AST_RWLIST_RDLOCK(&mwi_subs);
11435    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11436       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11437          poll_subscribed_mailbox(mwi_sub);
11438       }
11439    }
11440    AST_RWLIST_UNLOCK(&mwi_subs);
11441 }

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

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

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 4383 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(), S_OR, and valid_config().

Referenced by make_email_file(), and sendpage().

04384 {
04385    char callerid[256];
04386    char num[12];
04387    char fromdir[256], fromfile[256];
04388    struct ast_config *msg_cfg;
04389    const char *origcallerid, *origtime;
04390    char origcidname[80], origcidnum[80], origdate[80];
04391    int inttime;
04392    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04393 
04394    /* Prepare variables for substitution in email body and subject */
04395    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04396    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04397    snprintf(num, sizeof(num), "%d", msgnum);
04398    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04399    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04400    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04401    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04402       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04403    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04404    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04405    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04406    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04407    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04408 
04409    /* Retrieve info from VM attribute file */
04410    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04411    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04412    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04413       strcat(fromfile, ".txt");
04414    }
04415    if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
04416       if (option_debug > 0) {
04417          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04418       }
04419       return;
04420    }
04421 
04422    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04423       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04424       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04425       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04426       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04427    }
04428 
04429    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04430       struct timeval tv = { inttime, };
04431       struct ast_tm tm;
04432       ast_localtime(&tv, &tm, NULL);
04433       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04434       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04435    }
04436    ast_config_destroy(msg_cfg);
04437 }

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

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

07075 {
07076    struct ast_event *event;
07077    char *mailbox, *context;
07078 
07079    /* Strip off @default */
07080    context = mailbox = ast_strdupa(box);
07081    strsep(&context, "@");
07082    if (ast_strlen_zero(context))
07083       context = "default";
07084 
07085    if (!(event = ast_event_new(AST_EVENT_MWI,
07086          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07087          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07088          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07089          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07090          AST_EVENT_IE_END))) {
07091       return;
07092    }
07093 
07094    ast_event_queue_and_cache(event);
07095 }

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

Definition at line 12521 of file app_voicemail_imapstorage.c.

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

Referenced by actual_load_config(), and append_mailbox().

12521                                                                                            {
12522    struct ast_config *pwconf;
12523    struct ast_flags config_flags = { 0 };
12524 
12525    pwconf = ast_config_load(secretfn, config_flags);
12526    if (valid_config(pwconf)) {
12527       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12528       if (val) {
12529          ast_copy_string(password, val, passwordlen);
12530          ast_config_destroy(pwconf);
12531          return;
12532       }
12533       ast_config_destroy(pwconf);
12534    }
12535    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12536 }

static int reload ( void   )  [static]

Definition at line 13052 of file app_voicemail_imapstorage.c.

References load_config().

13053 {
13054    return load_config(1);
13055 }

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

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

04054 {
04055    char stxt[PATH_MAX];
04056    char dtxt[PATH_MAX];
04057    ast_filerename(sfn, dfn, NULL);
04058    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04059    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04060    if (ast_check_realtime("voicemail_data")) {
04061       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04062    }
04063    rename(stxt, dtxt);
04064 }

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

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

06201 {
06202    /* we know the actual number of messages, so stop process when number is hit */
06203 
06204    int x, dest;
06205    char sfn[PATH_MAX];
06206    char dfn[PATH_MAX];
06207 
06208    if (vm_lock_path(dir)) {
06209       return ERROR_LOCK_PATH;
06210    }
06211 
06212    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06213       make_file(sfn, sizeof(sfn), dir, x);
06214       if (EXISTS(dir, x, sfn, NULL)) {
06215 
06216          if (x != dest) {
06217             make_file(dfn, sizeof(dfn), dir, dest);
06218             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06219          }
06220 
06221          dest++;
06222       }
06223    }
06224    ast_unlock_path(dir);
06225 
06226    return dest;
06227 }

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

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

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

Definition at line 5568 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(), S_OR, and SMDI_MWI_WAIT_TIMEOUT.

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

05569 {
05570    char arguments[255];
05571    char ext_context[256] = "";
05572    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05573    struct ast_smdi_mwi_message *mwi_msg;
05574 
05575    if (!ast_strlen_zero(context))
05576       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05577    else
05578       ast_copy_string(ext_context, extension, sizeof(ext_context));
05579 
05580    if (smdi_iface) {
05581       if (ast_app_has_voicemail(ext_context, NULL)) 
05582          ast_smdi_mwi_set(smdi_iface, extension);
05583       else
05584          ast_smdi_mwi_unset(smdi_iface, extension);
05585 
05586       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05587          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05588          if (!strncmp(mwi_msg->cause, "INV", 3))
05589             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05590          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05591             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05592          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05593          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05594       } else {
05595          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05596       }
05597    }
05598 
05599    if (!ast_strlen_zero(externnotify)) {
05600       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05601          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05602       } else {
05603          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
05604             externnotify, S_OR(context, "\"\""),
05605             extension, newvoicemails,
05606             oldvoicemails, urgentvoicemails);
05607          ast_debug(1, "Executing %s\n", arguments);
05608          ast_safe_system(arguments);
05609       }
05610    }
05611 }

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

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

06238 {
06239 #ifdef IMAP_STORAGE
06240    /* we must use mbox(x) folder names, and copy the message there */
06241    /* simple. huh? */
06242    char sequence[10];
06243    char mailbox[256];
06244    int res;
06245 
06246    /* get the real IMAP message number for this message */
06247    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06248    
06249    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06250    ast_mutex_lock(&vms->lock);
06251    /* if save to Old folder, put in INBOX as read */
06252    if (box == OLD_FOLDER) {
06253       mail_setflag(vms->mailstream, sequence, "\\Seen");
06254       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06255    } else if (box == NEW_FOLDER) {
06256       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06257       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06258    }
06259    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06260       ast_mutex_unlock(&vms->lock);
06261       return 0;
06262    }
06263    /* Create the folder if it don't exist */
06264    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06265    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06266    if (mail_create(vms->mailstream, mailbox) == NIL) 
06267       ast_debug(5, "Folder exists.\n");
06268    else
06269       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06270    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06271    ast_mutex_unlock(&vms->lock);
06272    return res;
06273 #else
06274    char *dir = vms->curdir;
06275    char *username = vms->username;
06276    char *context = vmu->context;
06277    char sfn[PATH_MAX];
06278    char dfn[PATH_MAX];
06279    char ddir[PATH_MAX];
06280    const char *dbox = mbox(vmu, box);
06281    int x, i;
06282    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06283 
06284    if (vm_lock_path(ddir))
06285       return ERROR_LOCK_PATH;
06286 
06287    x = last_message_index(vmu, ddir) + 1;
06288 
06289    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06290       x--;
06291       for (i = 1; i <= x; i++) {
06292          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06293          make_file(sfn, sizeof(sfn), ddir, i);
06294          make_file(dfn, sizeof(dfn), ddir, i - 1);
06295          if (EXISTS(ddir, i, sfn, NULL)) {
06296             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06297          } else
06298             break;
06299       }
06300    } else {
06301       if (x >= vmu->maxmsg) {
06302          ast_unlock_path(ddir);
06303          return -1;
06304       }
06305    }
06306    make_file(sfn, sizeof(sfn), dir, msg);
06307    make_file(dfn, sizeof(dfn), ddir, x);
06308    if (strcmp(sfn, dfn)) {
06309       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06310    }
06311    ast_unlock_path(ddir);
06312 #endif
06313    return 0;
06314 }

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

12508 {
12509    int res = -1;
12510    char dir[PATH_MAX];
12511    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12512    ast_debug(2, "About to try retrieving name file %s\n", dir);
12513    RETRIEVE(dir, -1, mailbox, context);
12514    if (ast_fileexists(dir, NULL, NULL)) {
12515       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12516    }
12517    DISPOSE(dir, -1);
12518    return res;
12519 }

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

04899 {
04900    FILE *p = NULL;
04901    char tmp[80] = "/tmp/astmail-XXXXXX";
04902    char tmp2[256];
04903    char *stringp;
04904 
04905    if (vmu && ast_strlen_zero(vmu->email)) {
04906       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04907       return(0);
04908    }
04909 
04910    /* Mail only the first format */
04911    format = ast_strdupa(format);
04912    stringp = format;
04913    strsep(&stringp, "|");
04914 
04915    if (!strcmp(format, "wav49"))
04916       format = "WAV";
04917    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %u\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04918    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04919       command hangs */
04920    if ((p = vm_mkftemp(tmp)) == NULL) {
04921       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04922       return -1;
04923    } else {
04924       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04925       fclose(p);
04926       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04927       ast_safe_system(tmp2);
04928       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04929    }
04930    return 0;
04931 }

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

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

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

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

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

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

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

11599 {
11600    poll_thread_run = 0;
11601 
11602    if (mwi_sub_sub) {
11603       ast_event_unsubscribe(mwi_sub_sub);
11604       mwi_sub_sub = NULL;
11605    }
11606 
11607    if (mwi_unsub_sub) {
11608       ast_event_unsubscribe(mwi_unsub_sub);
11609       mwi_unsub_sub = NULL;
11610    }
11611 
11612    ast_mutex_lock(&poll_lock);
11613    ast_cond_signal(&poll_cond);
11614    ast_mutex_unlock(&poll_lock);
11615 
11616    pthread_join(poll_thread, NULL);
11617 
11618    poll_thread = AST_PTHREADT_NULL;
11619 }

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

Referenced by make_email_file(), and sendpage().

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

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

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

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

static int unload_module ( void   )  [static]

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

13058 {
13059    int res;
13060 
13061    res = ast_unregister_application(app);
13062    res |= ast_unregister_application(app2);
13063    res |= ast_unregister_application(app3);
13064    res |= ast_unregister_application(app4);
13065    res |= ast_unregister_application(sayname_app);
13066    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13067    res |= ast_manager_unregister("VoicemailUsersList");
13068    res |= ast_data_unregister(NULL);
13069 #ifdef TEST_FRAMEWORK
13070    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13071    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13072    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13073    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13074    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13075 #endif
13076    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13077    ast_uninstall_vm_functions();
13078    ao2_ref(inprocess_container, -1);
13079 
13080    if (poll_thread != AST_PTHREADT_NULL)
13081       stop_poll_thread();
13082 
13083    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13084    ast_unload_realtime("voicemail");
13085    ast_unload_realtime("voicemail_data");
13086 
13087    free_vm_users();
13088    free_vm_zones();
13089    return res;
13090 }

static int valid_config ( const struct ast_config cfg  )  [inline, static]

Check if configuration file is valid.

Definition at line 1514 of file app_voicemail_imapstorage.c.

References CONFIG_STATUS_FILEINVALID.

Referenced by advanced_options(), make_email_file(), play_message(), prep_email_sub_vars(), read_password_from_file(), vm_change_password(), and vm_forwardoptions().

01515 {
01516    return cfg && cfg != CONFIG_STATUS_FILEINVALID;
01517 }

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

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

01775                                                                                         {
01776 
01777    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01778 
01779    /* remove old allocation */
01780    if (vms->deleted) {
01781       ast_free(vms->deleted);
01782       vms->deleted = NULL;
01783    }
01784    if (vms->heard) {
01785       ast_free(vms->heard);
01786       vms->heard = NULL;
01787    }
01788    vms->dh_arraysize = 0;
01789 
01790    if (arraysize > 0) {
01791       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01792          return -1;
01793       }
01794       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01795          ast_free(vms->deleted);
01796          vms->deleted = NULL;
01797          return -1;
01798       }
01799       vms->dh_arraysize = arraysize;
01800    }
01801 
01802    return 0;
01803 }

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

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

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

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

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

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

References vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

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

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

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

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

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

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

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

Common LATIN languages syntax for 'You have N messages' greeting.

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

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

09645 {
09646    int cmd;
09647 
09648    if (vms->lastmsg > -1) {
09649       cmd = play_message(chan, vmu, vms);
09650    } else {
09651       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09652       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09653          if (!cmd) {
09654             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09655             cmd = ast_play_and_wait(chan, vms->fn);
09656          }
09657          if (!cmd)
09658             cmd = ast_play_and_wait(chan, "vm-messages");
09659       } else {
09660          if (!cmd)
09661             cmd = ast_play_and_wait(chan, "vm-messages");
09662          if (!cmd) {
09663             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09664             cmd = ast_play_and_wait(chan, vms->fn);
09665          }
09666       }
09667    }
09668    return cmd;
09669 }

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

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

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

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

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

References ast_alloca, ast_category_browse(), ast_category_get(), ast_config_destroy(), 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, 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(), valid_config(), value, var, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser(), and vm_options().

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

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

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

01635 {
01636    char buf[255];
01637    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01638    ast_debug(1, "External password: %s\n",buf);
01639    if (!ast_safe_system(buf)) {
01640       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01641       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01642       /* Reset the password in memory, too */
01643       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01644    }
01645 }

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

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

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

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

04238 {
04239    char *txt;
04240    int txtsize = 0;
04241 
04242    txtsize = (strlen(file) + 5)*sizeof(char);
04243    txt = ast_alloca(txtsize);
04244    /* Sprintf here would safe because we alloca'd exactly the right length,
04245     * but trying to eliminate all sprintf's anyhow
04246     */
04247    if (ast_check_realtime("voicemail_data")) {
04248       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04249    }
04250    snprintf(txt, txtsize, "%s.txt", file);
04251    unlink(txt);
04252    return ast_filedelete(file, NULL);
04253 }

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

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

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

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

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

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

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 6918 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, copy(), INTRO, make_file(), ast_vm_user::maxsecs, play_record_review(), and valid_config().

Referenced by forward_message().

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

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

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

Referenced by vm_execmain().

09273 {
09274    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09275       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09276    } else {             /* Default to ENGLISH */
09277       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09278    }
09279 }

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

09161 {
09162    int res = 0;
09163    /* Play instructions and wait for new command */
09164    while (!res) {
09165       if (vms->starting) {
09166          if (vms->lastmsg > -1) {
09167             if (skipadvanced)
09168                res = ast_play_and_wait(chan, "vm-onefor-full");
09169             else
09170                res = ast_play_and_wait(chan, "vm-onefor");
09171             if (!res)
09172                res = vm_play_folder_name(chan, vms->vmbox);
09173          }
09174          if (!res) {
09175             if (skipadvanced)
09176                res = ast_play_and_wait(chan, "vm-opts-full");
09177             else
09178                res = ast_play_and_wait(chan, "vm-opts");
09179          }
09180       } else {
09181          /* Added for additional help */
09182          if (skipadvanced) {
09183             res = ast_play_and_wait(chan, "vm-onefor-full");
09184             if (!res)
09185                res = vm_play_folder_name(chan, vms->vmbox);
09186             res = ast_play_and_wait(chan, "vm-opts-full");
09187          }
09188          /* Logic:
09189           * If the current message is not the first OR
09190           * if we're listening to the first new message and there are
09191           * also urgent messages, then prompt for navigation to the
09192           * previous message
09193           */
09194          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09195             res = ast_play_and_wait(chan, "vm-prev");
09196          }
09197          if (!res && !skipadvanced)
09198             res = ast_play_and_wait(chan, "vm-advopts");
09199          if (!res)
09200             res = ast_play_and_wait(chan, "vm-repeat");
09201          /* Logic:
09202           * If we're not listening to the last message OR
09203           * we're listening to the last urgent message and there are
09204           * also new non-urgent messages, then prompt for navigation
09205           * to the next message
09206           */
09207          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09208             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09209             res = ast_play_and_wait(chan, "vm-next");
09210          }
09211          if (!res) {
09212             int curmsg_deleted;
09213 #ifdef IMAP_STORAGE
09214             ast_mutex_lock(&vms->lock);
09215 #endif
09216             curmsg_deleted = vms->deleted[vms->curmsg];
09217 #ifdef IMAP_STORAGE
09218             ast_mutex_unlock(&vms->lock);
09219 #endif
09220             if (!curmsg_deleted) {
09221                res = ast_play_and_wait(chan, "vm-delete");
09222             } else {
09223                res = ast_play_and_wait(chan, "vm-undelete");
09224             }
09225             if (!res) {
09226                res = ast_play_and_wait(chan, "vm-toforward");
09227             }
09228             if (!res) {
09229                res = ast_play_and_wait(chan, "vm-savemessage");
09230             }
09231          }
09232       }
09233       if (!res) {
09234          res = ast_play_and_wait(chan, "vm-helpexit");
09235       }
09236       if (!res)
09237          res = ast_waitfordigit(chan, 6000);
09238       if (!res) {
09239          vms->repeats++;
09240          if (vms->repeats > 2) {
09241             res = 't';
09242          }
09243       }
09244    }
09245    return res;
09246 }

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

09249 {
09250    int res = 0;
09251    /* Play instructions and wait for new command */
09252    while (!res) {
09253       if (vms->lastmsg > -1) {
09254          res = ast_play_and_wait(chan, "vm-listen");
09255          if (!res)
09256             res = vm_play_folder_name(chan, vms->vmbox);
09257          if (!res)
09258             res = ast_play_and_wait(chan, "press");
09259          if (!res)
09260             res = ast_play_and_wait(chan, "digits/1");
09261       }
09262       if (!res)
09263          res = ast_play_and_wait(chan, "vm-opts");
09264       if (!res) {
09265          vms->starting = 0;
09266          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09267       }
09268    }
09269    return res;
09270 }

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

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

09099 {
09100    char prefile[256];
09101    
09102    /* Notify the user that the temp greeting is set and give them the option to remove it */
09103    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09104    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09105       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09106       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09107          ast_play_and_wait(chan, "vm-tempgreetactive");
09108       }
09109       DISPOSE(prefile, -1);
09110    }
09111 
09112    /* Play voicemail intro - syntax is different for different languages */
09113    if (0) {
09114       return 0;
09115    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09116       return vm_intro_cs(chan, vms);
09117    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09118       static int deprecation_warning = 0;
09119       if (deprecation_warning++ % 10 == 0) {
09120          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09121       }
09122       return vm_intro_cs(chan, vms);
09123    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09124       return vm_intro_de(chan, vms);
09125    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09126       return vm_intro_es(chan, vms);
09127    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09128       return vm_intro_fr(chan, vms);
09129    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09130       return vm_intro_gr(chan, vms);
09131    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09132       return vm_intro_he(chan, vms);
09133    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09134       return vm_intro_it(chan, vms);
09135    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09136       return vm_intro_nl(chan, vms);
09137    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09138       return vm_intro_no(chan, vms);
09139    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09140       return vm_intro_pl(chan, vms);
09141    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09142       return vm_intro_pt_BR(chan, vms);
09143    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09144       return vm_intro_pt(chan, vms);
09145    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09146       return vm_intro_multilang(chan, vms, "n");
09147    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09148       return vm_intro_se(chan, vms);
09149    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09150       return vm_intro_multilang(chan, vms, "n");
09151    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09152       return vm_intro_vi(chan, vms);
09153    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09154       return vm_intro_zh(chan, vms);
09155    } else {                                             /* Default to ENGLISH */
09156       return vm_intro_en(chan, vms);
09157    }
09158 }

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

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

08969 {
08970    int res;
08971    res = ast_play_and_wait(chan, "vm-youhave");
08972    if (!res) {
08973       if (vms->newmessages) {
08974          if (vms->newmessages == 1) {
08975             res = ast_play_and_wait(chan, "digits/jednu");
08976          } else {
08977             res = say_and_wait(chan, vms->newmessages, chan->language);
08978          }
08979          if (!res) {
08980             if ((vms->newmessages == 1))
08981                res = ast_play_and_wait(chan, "vm-novou");
08982             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08983                res = ast_play_and_wait(chan, "vm-nove");
08984             if (vms->newmessages > 4)
08985                res = ast_play_and_wait(chan, "vm-novych");
08986          }
08987          if (vms->oldmessages && !res)
08988             res = ast_play_and_wait(chan, "vm-and");
08989          else if (!res) {
08990             if ((vms->newmessages == 1))
08991                res = ast_play_and_wait(chan, "vm-zpravu");
08992             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08993                res = ast_play_and_wait(chan, "vm-zpravy");
08994             if (vms->newmessages > 4)
08995                res = ast_play_and_wait(chan, "vm-zprav");
08996          }
08997       }
08998       if (!res && vms->oldmessages) {
08999          res = say_and_wait(chan, vms->oldmessages, chan->language);
09000          if (!res) {
09001             if ((vms->oldmessages == 1))
09002                res = ast_play_and_wait(chan, "vm-starou");
09003             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
09004                res = ast_play_and_wait(chan, "vm-stare");
09005             if (vms->oldmessages > 4)
09006                res = ast_play_and_wait(chan, "vm-starych");
09007          }
09008          if (!res) {
09009             if ((vms->oldmessages == 1))
09010                res = ast_play_and_wait(chan, "vm-zpravu");
09011             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
09012                res = ast_play_and_wait(chan, "vm-zpravy");
09013             if (vms->oldmessages > 4)
09014                res = ast_play_and_wait(chan, "vm-zprav");
09015          }
09016       }
09017       if (!res) {
09018          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
09019             res = ast_play_and_wait(chan, "vm-no");
09020             if (!res)
09021                res = ast_play_and_wait(chan, "vm-zpravy");
09022          }
09023       }
09024    }
09025    return res;
09026 }

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

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

08665 {
08666    /* Introduce messages they have */
08667    int res;
08668    res = ast_play_and_wait(chan, "vm-youhave");
08669    if (!res) {
08670       if (vms->newmessages) {
08671          if ((vms->newmessages == 1))
08672             res = ast_play_and_wait(chan, "digits/1F");
08673          else
08674             res = say_and_wait(chan, vms->newmessages, chan->language);
08675          if (!res)
08676             res = ast_play_and_wait(chan, "vm-INBOX");
08677          if (vms->oldmessages && !res)
08678             res = ast_play_and_wait(chan, "vm-and");
08679          else if (!res) {
08680             if ((vms->newmessages == 1))
08681                res = ast_play_and_wait(chan, "vm-message");
08682             else
08683                res = ast_play_and_wait(chan, "vm-messages");
08684          }
08685             
08686       }
08687       if (!res && vms->oldmessages) {
08688          if (vms->oldmessages == 1)
08689             res = ast_play_and_wait(chan, "digits/1F");
08690          else
08691             res = say_and_wait(chan, vms->oldmessages, chan->language);
08692          if (!res)
08693             res = ast_play_and_wait(chan, "vm-Old");
08694          if (!res) {
08695             if (vms->oldmessages == 1)
08696                res = ast_play_and_wait(chan, "vm-message");
08697             else
08698                res = ast_play_and_wait(chan, "vm-messages");
08699          }
08700       }
08701       if (!res) {
08702          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08703             res = ast_play_and_wait(chan, "vm-no");
08704             if (!res)
08705                res = ast_play_and_wait(chan, "vm-messages");
08706          }
08707       }
08708    }
08709    return res;
08710 }

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

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

08414 {
08415    int res;
08416 
08417    /* Introduce messages they have */
08418    res = ast_play_and_wait(chan, "vm-youhave");
08419    if (!res) {
08420       if (vms->urgentmessages) {
08421          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08422          if (!res)
08423             res = ast_play_and_wait(chan, "vm-Urgent");
08424          if ((vms->oldmessages || vms->newmessages) && !res) {
08425             res = ast_play_and_wait(chan, "vm-and");
08426          } else if (!res) {
08427             if ((vms->urgentmessages == 1))
08428                res = ast_play_and_wait(chan, "vm-message");
08429             else
08430                res = ast_play_and_wait(chan, "vm-messages");
08431          }
08432       }
08433       if (vms->newmessages) {
08434          res = say_and_wait(chan, vms->newmessages, chan->language);
08435          if (!res)
08436             res = ast_play_and_wait(chan, "vm-INBOX");
08437          if (vms->oldmessages && !res)
08438             res = ast_play_and_wait(chan, "vm-and");
08439          else if (!res) {
08440             if ((vms->newmessages == 1))
08441                res = ast_play_and_wait(chan, "vm-message");
08442             else
08443                res = ast_play_and_wait(chan, "vm-messages");
08444          }
08445             
08446       }
08447       if (!res && vms->oldmessages) {
08448          res = say_and_wait(chan, vms->oldmessages, chan->language);
08449          if (!res)
08450             res = ast_play_and_wait(chan, "vm-Old");
08451          if (!res) {
08452             if (vms->oldmessages == 1)
08453                res = ast_play_and_wait(chan, "vm-message");
08454             else
08455                res = ast_play_and_wait(chan, "vm-messages");
08456          }
08457       }
08458       if (!res) {
08459          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08460             res = ast_play_and_wait(chan, "vm-no");
08461             if (!res)
08462                res = ast_play_and_wait(chan, "vm-messages");
08463          }
08464       }
08465    }
08466    return res;
08467 }

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

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

08714 {
08715    /* Introduce messages they have */
08716    int res;
08717    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08718       res = ast_play_and_wait(chan, "vm-youhaveno");
08719       if (!res)
08720          res = ast_play_and_wait(chan, "vm-messages");
08721    } else {
08722       res = ast_play_and_wait(chan, "vm-youhave");
08723    }
08724    if (!res) {
08725       if (vms->newmessages) {
08726          if (!res) {
08727             if ((vms->newmessages == 1)) {
08728                res = ast_play_and_wait(chan, "digits/1");
08729                if (!res)
08730                   res = ast_play_and_wait(chan, "vm-message");
08731                if (!res)
08732                   res = ast_play_and_wait(chan, "vm-INBOXs");
08733             } else {
08734                res = say_and_wait(chan, vms->newmessages, chan->language);
08735                if (!res)
08736                   res = ast_play_and_wait(chan, "vm-messages");
08737                if (!res)
08738                   res = ast_play_and_wait(chan, "vm-INBOX");
08739             }
08740          }
08741          if (vms->oldmessages && !res)
08742             res = ast_play_and_wait(chan, "vm-and");
08743       }
08744       if (vms->oldmessages) {
08745          if (!res) {
08746             if (vms->oldmessages == 1) {
08747                res = ast_play_and_wait(chan, "digits/1");
08748                if (!res)
08749                   res = ast_play_and_wait(chan, "vm-message");
08750                if (!res)
08751                   res = ast_play_and_wait(chan, "vm-Olds");
08752             } else {
08753                res = say_and_wait(chan, vms->oldmessages, chan->language);
08754                if (!res)
08755                   res = ast_play_and_wait(chan, "vm-messages");
08756                if (!res)
08757                   res = ast_play_and_wait(chan, "vm-Old");
08758             }
08759          }
08760       }
08761    }
08762 return res;
08763 }

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

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

08812 {
08813    /* Introduce messages they have */
08814    int res;
08815    res = ast_play_and_wait(chan, "vm-youhave");
08816    if (!res) {
08817       if (vms->newmessages) {
08818          res = say_and_wait(chan, vms->newmessages, chan->language);
08819          if (!res)
08820             res = ast_play_and_wait(chan, "vm-INBOX");
08821          if (vms->oldmessages && !res)
08822             res = ast_play_and_wait(chan, "vm-and");
08823          else if (!res) {
08824             if ((vms->newmessages == 1))
08825                res = ast_play_and_wait(chan, "vm-message");
08826             else
08827                res = ast_play_and_wait(chan, "vm-messages");
08828          }
08829             
08830       }
08831       if (!res && vms->oldmessages) {
08832          res = say_and_wait(chan, vms->oldmessages, chan->language);
08833          if (!res)
08834             res = ast_play_and_wait(chan, "vm-Old");
08835          if (!res) {
08836             if (vms->oldmessages == 1)
08837                res = ast_play_and_wait(chan, "vm-message");
08838             else
08839                res = ast_play_and_wait(chan, "vm-messages");
08840          }
08841       }
08842       if (!res) {
08843          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08844             res = ast_play_and_wait(chan, "vm-no");
08845             if (!res)
08846                res = ast_play_and_wait(chan, "vm-messages");
08847          }
08848       }
08849    }
08850    return res;
08851 }

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

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

08213 {
08214    int res = 0;
08215 
08216    if (vms->newmessages) {
08217       res = ast_play_and_wait(chan, "vm-youhave");
08218       if (!res) 
08219          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08220       if (!res) {
08221          if ((vms->newmessages == 1)) {
08222             res = ast_play_and_wait(chan, "vm-INBOX");
08223             if (!res)
08224                res = ast_play_and_wait(chan, "vm-message");
08225          } else {
08226             res = ast_play_and_wait(chan, "vm-INBOXs");
08227             if (!res)
08228                res = ast_play_and_wait(chan, "vm-messages");
08229          }
08230       }
08231    } else if (vms->oldmessages){
08232       res = ast_play_and_wait(chan, "vm-youhave");
08233       if (!res)
08234          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08235       if ((vms->oldmessages == 1)){
08236          res = ast_play_and_wait(chan, "vm-Old");
08237          if (!res)
08238             res = ast_play_and_wait(chan, "vm-message");
08239       } else {
08240          res = ast_play_and_wait(chan, "vm-Olds");
08241          if (!res)
08242             res = ast_play_and_wait(chan, "vm-messages");
08243       }
08244    } else if (!vms->oldmessages && !vms->newmessages) 
08245       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08246    return res;
08247 }

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

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

08347 {
08348    int res = 0;
08349 
08350    /* Introduce messages they have */
08351    if (!res) {
08352       if ((vms->newmessages) || (vms->oldmessages)) {
08353          res = ast_play_and_wait(chan, "vm-youhave");
08354       }
08355       /*
08356        * The word "shtei" refers to the number 2 in hebrew when performing a count
08357        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08358        * an element, this is one of them.
08359        */
08360       if (vms->newmessages) {
08361          if (!res) {
08362             if (vms->newmessages == 1) {
08363                res = ast_play_and_wait(chan, "vm-INBOX1");
08364             } else {
08365                if (vms->newmessages == 2) {
08366                   res = ast_play_and_wait(chan, "vm-shtei");
08367                } else {
08368                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08369                }
08370                res = ast_play_and_wait(chan, "vm-INBOX");
08371             }
08372          }
08373          if (vms->oldmessages && !res) {
08374             res = ast_play_and_wait(chan, "vm-and");
08375             if (vms->oldmessages == 1) {
08376                res = ast_play_and_wait(chan, "vm-Old1");
08377             } else {
08378                if (vms->oldmessages == 2) {
08379                   res = ast_play_and_wait(chan, "vm-shtei");
08380                } else {
08381                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08382                }
08383                res = ast_play_and_wait(chan, "vm-Old");
08384             }
08385          }
08386       }
08387       if (!res && vms->oldmessages && !vms->newmessages) {
08388          if (!res) {
08389             if (vms->oldmessages == 1) {
08390                res = ast_play_and_wait(chan, "vm-Old1");
08391             } else {
08392                if (vms->oldmessages == 2) {
08393                   res = ast_play_and_wait(chan, "vm-shtei");
08394                } else {
08395                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08396                }
08397                res = ast_play_and_wait(chan, "vm-Old");
08398             }
08399          }
08400       }
08401       if (!res) {
08402          if (!vms->oldmessages && !vms->newmessages) {
08403             if (!res) {
08404                res = ast_play_and_wait(chan, "vm-nomessages");
08405             }
08406          }
08407       }
08408    }
08409    return res;
08410 }

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

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

08471 {
08472    /* Introduce messages they have */
08473    int res;
08474    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08475       res = ast_play_and_wait(chan, "vm-no") ||
08476          ast_play_and_wait(chan, "vm-message");
08477    else
08478       res = ast_play_and_wait(chan, "vm-youhave");
08479    if (!res && vms->newmessages) {
08480       res = (vms->newmessages == 1) ?
08481          ast_play_and_wait(chan, "digits/un") ||
08482          ast_play_and_wait(chan, "vm-nuovo") ||
08483          ast_play_and_wait(chan, "vm-message") :
08484          /* 2 or more new messages */
08485          say_and_wait(chan, vms->newmessages, chan->language) ||
08486          ast_play_and_wait(chan, "vm-nuovi") ||
08487          ast_play_and_wait(chan, "vm-messages");
08488       if (!res && vms->oldmessages)
08489          res = ast_play_and_wait(chan, "vm-and");
08490    }
08491    if (!res && vms->oldmessages) {
08492       res = (vms->oldmessages == 1) ?
08493          ast_play_and_wait(chan, "digits/un") ||
08494          ast_play_and_wait(chan, "vm-vecchio") ||
08495          ast_play_and_wait(chan, "vm-message") :
08496          /* 2 or more old messages */
08497          say_and_wait(chan, vms->oldmessages, chan->language) ||
08498          ast_play_and_wait(chan, "vm-vecchi") ||
08499          ast_play_and_wait(chan, "vm-messages");
08500    }
08501    return res;
08502 }

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

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

08307 {
08308    int res;
08309    int lastnum = 0;
08310 
08311    res = ast_play_and_wait(chan, "vm-youhave");
08312 
08313    if (!res && vms->newmessages) {
08314       lastnum = vms->newmessages;
08315 
08316       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08317          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08318       }
08319 
08320       if (!res && vms->oldmessages) {
08321          res = ast_play_and_wait(chan, "vm-and");
08322       }
08323    }
08324 
08325    if (!res && vms->oldmessages) {
08326       lastnum = vms->oldmessages;
08327 
08328       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08329          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08330       }
08331    }
08332 
08333    if (!res) {
08334       if (lastnum == 0) {
08335          res = ast_play_and_wait(chan, "vm-no");
08336       }
08337       if (!res) {
08338          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08339       }
08340    }
08341 
08342    return res;
08343 }

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

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

08855 {
08856    /* Introduce messages they have */
08857    int res;
08858    res = ast_play_and_wait(chan, "vm-youhave");
08859    if (!res) {
08860       if (vms->newmessages) {
08861          res = say_and_wait(chan, vms->newmessages, chan->language);
08862          if (!res) {
08863             if (vms->newmessages == 1)
08864                res = ast_play_and_wait(chan, "vm-INBOXs");
08865             else
08866                res = ast_play_and_wait(chan, "vm-INBOX");
08867          }
08868          if (vms->oldmessages && !res)
08869             res = ast_play_and_wait(chan, "vm-and");
08870          else if (!res) {
08871             if ((vms->newmessages == 1))
08872                res = ast_play_and_wait(chan, "vm-message");
08873             else
08874                res = ast_play_and_wait(chan, "vm-messages");
08875          }
08876             
08877       }
08878       if (!res && vms->oldmessages) {
08879          res = say_and_wait(chan, vms->oldmessages, chan->language);
08880          if (!res) {
08881             if (vms->oldmessages == 1)
08882                res = ast_play_and_wait(chan, "vm-Olds");
08883             else
08884                res = ast_play_and_wait(chan, "vm-Old");
08885          }
08886          if (!res) {
08887             if (vms->oldmessages == 1)
08888                res = ast_play_and_wait(chan, "vm-message");
08889             else
08890                res = ast_play_and_wait(chan, "vm-messages");
08891          }
08892       }
08893       if (!res) {
08894          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08895             res = ast_play_and_wait(chan, "vm-no");
08896             if (!res)
08897                res = ast_play_and_wait(chan, "vm-messages");
08898          }
08899       }
08900    }
08901    return res;
08902 }

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

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

08621 {
08622    /* Introduce messages they have */
08623    int res;
08624 
08625    res = ast_play_and_wait(chan, "vm-youhave");
08626    if (res)
08627       return res;
08628 
08629    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08630       res = ast_play_and_wait(chan, "vm-no");
08631       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08632       return res;
08633    }
08634 
08635    if (vms->newmessages) {
08636       if ((vms->newmessages == 1)) {
08637          res = ast_play_and_wait(chan, "digits/1");
08638          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08639          res = res ? res : ast_play_and_wait(chan, "vm-message");
08640       } else {
08641          res = say_and_wait(chan, vms->newmessages, chan->language);
08642          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08643          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08644       }
08645       if (!res && vms->oldmessages)
08646          res = ast_play_and_wait(chan, "vm-and");
08647    }
08648    if (!res && vms->oldmessages) {
08649       if (vms->oldmessages == 1) {
08650          res = ast_play_and_wait(chan, "digits/1");
08651          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08652          res = res ? res : ast_play_and_wait(chan, "vm-message");
08653       } else {
08654          res = say_and_wait(chan, vms->oldmessages, chan->language);
08655          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08656          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08657       }
08658    }
08659 
08660    return res;
08661 }

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

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

08506 {
08507    /* Introduce messages they have */
08508    int res;
08509    div_t num;
08510 
08511    if (!vms->oldmessages && !vms->newmessages) {
08512       res = ast_play_and_wait(chan, "vm-no");
08513       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08514       return res;
08515    } else {
08516       res = ast_play_and_wait(chan, "vm-youhave");
08517    }
08518 
08519    if (vms->newmessages) {
08520       num = div(vms->newmessages, 10);
08521       if (vms->newmessages == 1) {
08522          res = ast_play_and_wait(chan, "digits/1-a");
08523          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08524          res = res ? res : ast_play_and_wait(chan, "vm-message");
08525       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08526          if (num.rem == 2) {
08527             if (!num.quot) {
08528                res = ast_play_and_wait(chan, "digits/2-ie");
08529             } else {
08530                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08531                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08532             }
08533          } else {
08534             res = say_and_wait(chan, vms->newmessages, chan->language);
08535          }
08536          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08537          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08538       } else {
08539          res = say_and_wait(chan, vms->newmessages, chan->language);
08540          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08541          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08542       }
08543       if (!res && vms->oldmessages)
08544          res = ast_play_and_wait(chan, "vm-and");
08545    }
08546    if (!res && vms->oldmessages) {
08547       num = div(vms->oldmessages, 10);
08548       if (vms->oldmessages == 1) {
08549          res = ast_play_and_wait(chan, "digits/1-a");
08550          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08551          res = res ? res : ast_play_and_wait(chan, "vm-message");
08552       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08553          if (num.rem == 2) {
08554             if (!num.quot) {
08555                res = ast_play_and_wait(chan, "digits/2-ie");
08556             } else {
08557                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08558                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08559             }
08560          } else {
08561             res = say_and_wait(chan, vms->oldmessages, chan->language);
08562          }
08563          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08564          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08565       } else {
08566          res = say_and_wait(chan, vms->oldmessages, chan->language);
08567          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08568          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08569       }
08570    }
08571 
08572    return res;
08573 }

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

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

08906 {
08907    /* Introduce messages they have */
08908    int res;
08909    res = ast_play_and_wait(chan, "vm-youhave");
08910    if (!res) {
08911       if (vms->newmessages) {
08912          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08913          if (!res) {
08914             if ((vms->newmessages == 1)) {
08915                res = ast_play_and_wait(chan, "vm-message");
08916                if (!res)
08917                   res = ast_play_and_wait(chan, "vm-INBOXs");
08918             } else {
08919                res = ast_play_and_wait(chan, "vm-messages");
08920                if (!res)
08921                   res = ast_play_and_wait(chan, "vm-INBOX");
08922             }
08923          }
08924          if (vms->oldmessages && !res)
08925             res = ast_play_and_wait(chan, "vm-and");
08926       }
08927       if (!res && vms->oldmessages) {
08928          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08929          if (!res) {
08930             if (vms->oldmessages == 1) {
08931                res = ast_play_and_wait(chan, "vm-message");
08932                if (!res)
08933                   res = ast_play_and_wait(chan, "vm-Olds");
08934             } else {
08935                res = ast_play_and_wait(chan, "vm-messages");
08936                if (!res)
08937                   res = ast_play_and_wait(chan, "vm-Old");
08938             }
08939          }
08940       }
08941       if (!res) {
08942          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08943             res = ast_play_and_wait(chan, "vm-no");
08944             if (!res)
08945                res = ast_play_and_wait(chan, "vm-messages");
08946          }
08947       }
08948    }
08949    return res;
08950 }

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

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

08766                                                                           {
08767    /* Introduce messages they have */
08768    int res;
08769    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08770       res = ast_play_and_wait(chan, "vm-nomessages");
08771       return res;
08772    } else {
08773       res = ast_play_and_wait(chan, "vm-youhave");
08774    }
08775    if (vms->newmessages) {
08776       if (!res)
08777          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08778       if ((vms->newmessages == 1)) {
08779          if (!res)
08780             res = ast_play_and_wait(chan, "vm-message");
08781          if (!res)
08782             res = ast_play_and_wait(chan, "vm-INBOXs");
08783       } else {
08784          if (!res)
08785             res = ast_play_and_wait(chan, "vm-messages");
08786          if (!res)
08787             res = ast_play_and_wait(chan, "vm-INBOX");
08788       }
08789       if (vms->oldmessages && !res)
08790          res = ast_play_and_wait(chan, "vm-and");
08791    }
08792    if (vms->oldmessages) {
08793       if (!res)
08794          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08795       if (vms->oldmessages == 1) {
08796          if (!res)
08797             res = ast_play_and_wait(chan, "vm-message");
08798          if (!res)
08799             res = ast_play_and_wait(chan, "vm-Olds");
08800       } else {
08801          if (!res)
08802             res = ast_play_and_wait(chan, "vm-messages");
08803          if (!res)
08804             res = ast_play_and_wait(chan, "vm-Old");
08805       }
08806    }
08807    return res;
08808 }

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

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

08577 {
08578    /* Introduce messages they have */
08579    int res;
08580 
08581    res = ast_play_and_wait(chan, "vm-youhave");
08582    if (res)
08583       return res;
08584 
08585    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08586       res = ast_play_and_wait(chan, "vm-no");
08587       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08588       return res;
08589    }
08590 
08591    if (vms->newmessages) {
08592       if ((vms->newmessages == 1)) {
08593          res = ast_play_and_wait(chan, "digits/ett");
08594          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08595          res = res ? res : ast_play_and_wait(chan, "vm-message");
08596       } else {
08597          res = say_and_wait(chan, vms->newmessages, chan->language);
08598          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08599          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08600       }
08601       if (!res && vms->oldmessages)
08602          res = ast_play_and_wait(chan, "vm-and");
08603    }
08604    if (!res && vms->oldmessages) {
08605       if (vms->oldmessages == 1) {
08606          res = ast_play_and_wait(chan, "digits/ett");
08607          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08608          res = res ? res : ast_play_and_wait(chan, "vm-message");
08609       } else {
08610          res = say_and_wait(chan, vms->oldmessages, chan->language);
08611          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08612          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08613       }
08614    }
08615 
08616    return res;
08617 }

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

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

09069 {
09070    int res;
09071 
09072    /* Introduce messages they have */
09073    res = ast_play_and_wait(chan, "vm-youhave");
09074    if (!res) {
09075       if (vms->newmessages) {
09076          res = say_and_wait(chan, vms->newmessages, chan->language);
09077          if (!res)
09078             res = ast_play_and_wait(chan, "vm-INBOX");
09079          if (vms->oldmessages && !res)
09080             res = ast_play_and_wait(chan, "vm-and");
09081       }
09082       if (!res && vms->oldmessages) {
09083          res = say_and_wait(chan, vms->oldmessages, chan->language);
09084          if (!res)
09085             res = ast_play_and_wait(chan, "vm-Old");        
09086       }
09087       if (!res) {
09088          if (!vms->oldmessages && !vms->newmessages) {
09089             res = ast_play_and_wait(chan, "vm-no");
09090             if (!res)
09091                res = ast_play_and_wait(chan, "vm-message");
09092          }
09093       }
09094    }
09095    return res;
09096 }

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

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

09030 {
09031    int res;
09032    /* Introduce messages they have */
09033    res = ast_play_and_wait(chan, "vm-you");
09034 
09035    if (!res && vms->newmessages) {
09036       res = ast_play_and_wait(chan, "vm-have");
09037       if (!res)
09038          res = say_and_wait(chan, vms->newmessages, chan->language);
09039       if (!res)
09040          res = ast_play_and_wait(chan, "vm-tong");
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       else if (!res) 
09046          res = ast_play_and_wait(chan, "vm-messages");
09047    }
09048    if (!res && vms->oldmessages) {
09049       res = ast_play_and_wait(chan, "vm-have");
09050       if (!res)
09051          res = say_and_wait(chan, vms->oldmessages, chan->language);
09052       if (!res)
09053          res = ast_play_and_wait(chan, "vm-tong");
09054       if (!res)
09055          res = ast_play_and_wait(chan, "vm-Old");
09056       if (!res)
09057          res = ast_play_and_wait(chan, "vm-messages");
09058    }
09059    if (!res && !vms->oldmessages && !vms->newmessages) {
09060       res = ast_play_and_wait(chan, "vm-haveno");
09061       if (!res)
09062          res = ast_play_and_wait(chan, "vm-messages");
09063    }
09064    return res;
09065 }

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

03313 {
03314    switch (ast_lock_path(path)) {
03315    case AST_LOCK_TIMEOUT:
03316       return -1;
03317    default:
03318       return 0;
03319    }
03320 }

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

Definition at line 1683 of file app_voicemail_imapstorage.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01684 {
01685    FILE *p = NULL;
01686    int pfd = mkstemp(template);
01687    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01688    if (pfd > -1) {
01689       p = fdopen(pfd, "w+");
01690       if (!p) {
01691          close(pfd);
01692          pfd = -1;
01693       }
01694    }
01695    return p;
01696 }

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

09283 {
09284    int cmd = 0;
09285    int duration = 0;
09286    int tries = 0;
09287    char newpassword[80] = "";
09288    char newpassword2[80] = "";
09289    char prefile[PATH_MAX] = "";
09290    unsigned char buf[256];
09291    int bytes = 0;
09292 
09293    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09294    if (ast_adsi_available(chan)) {
09295       bytes += adsi_logo(buf + bytes);
09296       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09297       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09298       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09299       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09300       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09301    }
09302 
09303    /* If forcename is set, have the user record their name */
09304    if (ast_test_flag(vmu, VM_FORCENAME)) {
09305       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09306       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09307          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09308          if (cmd < 0 || cmd == 't' || cmd == '#')
09309             return cmd;
09310       }
09311    }
09312 
09313    /* If forcegreetings is set, have the user record their greetings */
09314    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09315       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09316       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09317          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09318          if (cmd < 0 || cmd == 't' || cmd == '#')
09319             return cmd;
09320       }
09321 
09322       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09323       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09324          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09325          if (cmd < 0 || cmd == 't' || cmd == '#')
09326             return cmd;
09327       }
09328    }
09329 
09330    /*
09331     * Change the password last since new users will be able to skip over any steps this one comes before
09332     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09333     */
09334    for (;;) {
09335       newpassword[1] = '\0';
09336       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09337       if (cmd == '#')
09338          newpassword[0] = '\0';
09339       if (cmd < 0 || cmd == 't' || cmd == '#')
09340          return cmd;
09341       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09342       if (cmd < 0 || cmd == 't' || cmd == '#')
09343          return cmd;
09344       cmd = check_password(vmu, newpassword); /* perform password validation */
09345       if (cmd != 0) {
09346          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09347          cmd = ast_play_and_wait(chan, vm_invalid_password);
09348       } else {
09349          newpassword2[1] = '\0';
09350          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09351          if (cmd == '#')
09352             newpassword2[0] = '\0';
09353          if (cmd < 0 || cmd == 't' || cmd == '#')
09354             return cmd;
09355          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09356          if (cmd < 0 || cmd == 't' || cmd == '#')
09357             return cmd;
09358          if (!strcmp(newpassword, newpassword2))
09359             break;
09360          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09361          cmd = ast_play_and_wait(chan, vm_mismatch);
09362       }
09363       if (++tries == 3)
09364          return -1;
09365       if (cmd != 0) {
09366          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09367       }
09368    }
09369    if (pwdchange & PWDCHANGE_INTERNAL)
09370       vm_change_password(vmu, newpassword);
09371    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09372       vm_change_password_shell(vmu, newpassword);
09373 
09374    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09375    cmd = ast_play_and_wait(chan, vm_passchanged);
09376 
09377    return cmd;
09378 }

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

09381 {
09382    int cmd = 0;
09383    int retries = 0;
09384    int duration = 0;
09385    char newpassword[80] = "";
09386    char newpassword2[80] = "";
09387    char prefile[PATH_MAX] = "";
09388    unsigned char buf[256];
09389    int bytes = 0;
09390 
09391    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09392    if (ast_adsi_available(chan)) {
09393       bytes += adsi_logo(buf + bytes);
09394       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09395       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09396       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09397       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09398       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09399    }
09400    while ((cmd >= 0) && (cmd != 't')) {
09401       if (cmd)
09402          retries = 0;
09403       switch (cmd) {
09404       case '1': /* Record your unavailable message */
09405          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09406          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09407          break;
09408       case '2':  /* Record your busy message */
09409          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09410          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09411          break;
09412       case '3': /* Record greeting */
09413          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09414          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09415          break;
09416       case '4':  /* manage the temporary greeting */
09417          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09418          break;
09419       case '5': /* change password */
09420          if (vmu->password[0] == '-') {
09421             cmd = ast_play_and_wait(chan, "vm-no");
09422             break;
09423          }
09424          newpassword[1] = '\0';
09425          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09426          if (cmd == '#')
09427             newpassword[0] = '\0';
09428          else {
09429             if (cmd < 0)
09430                break;
09431             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09432                break;
09433             }
09434          }
09435          cmd = check_password(vmu, newpassword); /* perform password validation */
09436          if (cmd != 0) {
09437             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09438             cmd = ast_play_and_wait(chan, vm_invalid_password);
09439             if (!cmd) {
09440                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09441             }
09442             break;
09443          }
09444          newpassword2[1] = '\0';
09445          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09446          if (cmd == '#')
09447             newpassword2[0] = '\0';
09448          else {
09449             if (cmd < 0)
09450                break;
09451 
09452             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09453                break;
09454             }
09455          }
09456          if (strcmp(newpassword, newpassword2)) {
09457             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09458             cmd = ast_play_and_wait(chan, vm_mismatch);
09459             if (!cmd) {
09460                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09461             }
09462             break;
09463          }
09464 
09465          if (pwdchange & PWDCHANGE_INTERNAL) {
09466             vm_change_password(vmu, newpassword);
09467          }
09468          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09469             vm_change_password_shell(vmu, newpassword);
09470          }
09471 
09472          ast_debug(1, "User %s set password to %s of length %d\n",
09473             vms->username, newpassword, (int) strlen(newpassword));
09474          cmd = ast_play_and_wait(chan, vm_passchanged);
09475          break;
09476       case '*': 
09477          cmd = 't';
09478          break;
09479       default: 
09480          cmd = 0;
09481          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09482          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09483          if (ast_fileexists(prefile, NULL, NULL)) {
09484             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09485          }
09486          DISPOSE(prefile, -1);
09487          if (!cmd) {
09488             cmd = ast_play_and_wait(chan, "vm-options");
09489          }
09490          if (!cmd) {
09491             cmd = ast_waitfordigit(chan, 6000);
09492          }
09493          if (!cmd) {
09494             retries++;
09495          }
09496          if (retries > 3) {
09497             cmd = 't';
09498          }
09499          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09500       }
09501    }
09502    if (cmd == 't')
09503       cmd = 0;
09504    return cmd;
09505 }

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

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

08176 {
08177    int cmd;
08178 
08179    if (  !strncasecmp(chan->language, "it", 2) ||
08180         !strncasecmp(chan->language, "es", 2) ||
08181         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08182       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08183       return cmd ? cmd : ast_play_and_wait(chan, box);
08184    } else if (!strncasecmp(chan->language, "gr", 2)) {
08185       return vm_play_folder_name_gr(chan, box);
08186    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08187       return ast_play_and_wait(chan, box);
08188    } else if (!strncasecmp(chan->language, "pl", 2)) {
08189       return vm_play_folder_name_pl(chan, box);
08190    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08191       return vm_play_folder_name_ua(chan, box);
08192    } else if (!strncasecmp(chan->language, "vi", 2)) {
08193       return ast_play_and_wait(chan, box);
08194    } else {  /* Default English */
08195       cmd = ast_play_and_wait(chan, box);
08196       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08197    }
08198 }

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

Definition at line 8128 of file app_voicemail_imapstorage.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

08129 {
08130    int cmd;
08131    char *buf;
08132 
08133    buf = ast_alloca(strlen(box) + 2);
08134    strcpy(buf, box);
08135    strcat(buf, "s");
08136 
08137    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08138       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08139       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08140    } else {
08141       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08142       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08143    }
08144 }

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

Definition at line 8146 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08147 {
08148    int cmd;
08149 
08150    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08151       if (!strcasecmp(box, "vm-INBOX"))
08152          cmd = ast_play_and_wait(chan, "vm-new-e");
08153       else
08154          cmd = ast_play_and_wait(chan, "vm-old-e");
08155       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08156    } else {
08157       cmd = ast_play_and_wait(chan, "vm-messages");
08158       return cmd ? cmd : ast_play_and_wait(chan, box);
08159    }
08160 }

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

Definition at line 8162 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08163 {
08164    int cmd;
08165 
08166    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08167       cmd = ast_play_and_wait(chan, "vm-messages");
08168       return cmd ? cmd : ast_play_and_wait(chan, box);
08169    } else {
08170       cmd = ast_play_and_wait(chan, box);
08171       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08172    }
08173 }

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

09524 {
09525    int cmd = 0;
09526    int retries = 0;
09527    int duration = 0;
09528    char prefile[PATH_MAX] = "";
09529    unsigned char buf[256];
09530    int bytes = 0;
09531 
09532    if (ast_adsi_available(chan)) {
09533       bytes += adsi_logo(buf + bytes);
09534       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09535       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09536       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09537       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09538       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09539    }
09540 
09541    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09542    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09543    while ((cmd >= 0) && (cmd != 't')) {
09544       if (cmd)
09545          retries = 0;
09546       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09547       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09548          cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09549          if (cmd == -1) {
09550             break;
09551          }
09552          cmd = 't';  
09553       } else {
09554          switch (cmd) {
09555          case '1':
09556             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09557             break;
09558          case '2':
09559             DELETE(prefile, -1, prefile, vmu);
09560             ast_play_and_wait(chan, "vm-tempremoved");
09561             cmd = 't';  
09562             break;
09563          case '*': 
09564             cmd = 't';
09565             break;
09566          default:
09567             cmd = ast_play_and_wait(chan,
09568                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09569                   "vm-tempgreeting2" : "vm-tempgreeting");
09570             if (!cmd) {
09571                cmd = ast_waitfordigit(chan, 6000);
09572             }
09573             if (!cmd) {
09574                retries++;
09575             }
09576             if (retries > 3) {
09577                cmd = 't';
09578             }
09579             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09580          }
09581       }
09582       DISPOSE(prefile, -1);
09583    }
09584    if (cmd == 't')
09585       cmd = 0;
09586    return cmd;
09587 }

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

Definition at line 11392 of file app_voicemail_imapstorage.c.

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

11394 {
11395    struct ast_vm_user *user;
11396 
11397    AST_LIST_LOCK(&users);
11398    AST_LIST_TRAVERSE(&users, user, list) {
11399       vm_users_data_provider_get_helper(search, data_root, user);
11400    }
11401    AST_LIST_UNLOCK(&users);
11402 
11403    return 0;
11404 }

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

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

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

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

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

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

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

12572 {
12573    char *context;
12574    char *args_copy;
12575    int res;
12576 
12577    if (ast_strlen_zero(data)) {
12578       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12579       return -1;
12580    }
12581 
12582    args_copy = ast_strdupa(data);
12583    if ((context = strchr(args_copy, '@'))) {
12584       *context++ = '\0';
12585    } else {
12586       context = "default";
12587    }
12588 
12589    if ((res = sayname(chan, args_copy, context) < 0)) {
12590       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12591       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12592       if (!res) {
12593          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12594       }
12595    }
12596 
12597    return res;
12598 }

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

04470 {
04471    const struct vm_zone *z = NULL;
04472    struct timeval t = ast_tvnow();
04473 
04474    /* Does this user have a timezone specified? */
04475    if (!ast_strlen_zero(vmu->zonetag)) {
04476       /* Find the zone in the list */
04477       AST_LIST_LOCK(&zones);
04478       AST_LIST_TRAVERSE(&zones, z, list) {
04479          if (!strcmp(z->name, vmu->zonetag))
04480             break;
04481       }
04482       AST_LIST_UNLOCK(&zones);
04483    }
04484    ast_localtime(&t, tm, z ? z->timezone : NULL);
04485    return tm;
04486 }

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

07517 {
07518    int res;
07519    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07520       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07521    return res;
07522 }

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

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

12538                                                                               {
12539    struct ast_config *conf;
12540    struct ast_category *cat;
12541    struct ast_variable *var;
12542    int res = -1;
12543 
12544    if (!(conf = ast_config_new())) {
12545       ast_log(LOG_ERROR, "Error creating new config structure\n");
12546       return res;
12547    }
12548    if (!(cat = ast_category_new("general", "", 1))) {
12549       ast_log(LOG_ERROR, "Error creating new category structure\n");
12550       ast_config_destroy(conf);
12551       return res;
12552    }
12553    if (!(var = ast_variable_new("password", password, ""))) {
12554       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12555       ast_config_destroy(conf);
12556       ast_category_destroy(cat);
12557       return res;
12558    }
12559    ast_category_append(conf, cat);
12560    ast_variable_append(cat, var);
12561    if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12562       res = 0;
12563    } else {
12564       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12565    }
12566 
12567    ast_config_destroy(conf);
12568    return res;
12569 }


Variable Documentation

char* addesc = "Comedian Mail" [static]

Definition at line 777 of file app_voicemail_imapstorage.c.

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

Definition at line 904 of file app_voicemail_imapstorage.c.

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

Definition at line 905 of file app_voicemail_imapstorage.c.

int adsiver = 1 [static]

Definition at line 906 of file app_voicemail_imapstorage.c.

char* app = "VoiceMail" [static]

Definition at line 780 of file app_voicemail_imapstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 783 of file app_voicemail_imapstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 785 of file app_voicemail_imapstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 786 of file app_voicemail_imapstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 890 of file app_voicemail_imapstorage.c.

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

Definition at line 902 of file app_voicemail_imapstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

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

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 889 of file app_voicemail_imapstorage.c.

char* emailbody = NULL [static]

Definition at line 896 of file app_voicemail_imapstorage.c.

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

Definition at line 907 of file app_voicemail_imapstorage.c.

char* emailsubject = NULL [static]

Definition at line 897 of file app_voicemail_imapstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 891 of file app_voicemail_imapstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 757 of file app_voicemail_imapstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 756 of file app_voicemail_imapstorage.c.

char externnotify[160] [static]

Definition at line 800 of file app_voicemail_imapstorage.c.

char fromstring[100] [static]

Definition at line 900 of file app_voicemail_imapstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 885 of file app_voicemail_imapstorage.c.

Definition at line 929 of file app_voicemail_imapstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 858 of file app_voicemail_imapstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 860 of file app_voicemail_imapstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 861 of file app_voicemail_imapstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 859 of file app_voicemail_imapstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 862 of file app_voicemail_imapstorage.c.

char locale[20] [static]

Definition at line 793 of file app_voicemail_imapstorage.c.

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

Definition at line 11026 of file app_voicemail_imapstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1719 of file app_voicemail_imapstorage.c.

char mailcmd[160] [static]

Definition at line 799 of file app_voicemail_imapstorage.c.

int maxdeletedmsg [static]

Definition at line 796 of file app_voicemail_imapstorage.c.

int maxgreet [static]

Definition at line 806 of file app_voicemail_imapstorage.c.

int maxlogins [static]

Definition at line 808 of file app_voicemail_imapstorage.c.

int maxmsg [static]

Definition at line 795 of file app_voicemail_imapstorage.c.

int maxsilence [static]

Definition at line 794 of file app_voicemail_imapstorage.c.

int minpassword [static]

Definition at line 809 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 827 of file app_voicemail_imapstorage.c.

Definition at line 853 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 829 of file app_voicemail_imapstorage.c.

int my_umask [static]

Definition at line 759 of file app_voicemail_imapstorage.c.

char* pagerbody = NULL [static]

Definition at line 898 of file app_voicemail_imapstorage.c.

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

Definition at line 908 of file app_voicemail_imapstorage.c.

char pagerfromstring[100] [static]

Definition at line 901 of file app_voicemail_imapstorage.c.

char* pagersubject = NULL [static]

Definition at line 899 of file app_voicemail_imapstorage.c.

int passwordlocation [static]

Definition at line 810 of file app_voicemail_imapstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 822 of file app_voicemail_imapstorage.c.

unsigned int poll_freq [static]

Polling frequency

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 823 of file app_voicemail_imapstorage.c.

unsigned char poll_thread_run [static]

Definition at line 824 of file app_voicemail_imapstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 763 of file app_voicemail_imapstorage.c.

int saydurationminfo [static]

Definition at line 887 of file app_voicemail_imapstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 788 of file app_voicemail_imapstorage.c.

char serveremail[80] [static]

Definition at line 798 of file app_voicemail_imapstorage.c.

int silencethreshold = 128 [static]

Definition at line 797 of file app_voicemail_imapstorage.c.

int skipms [static]

Definition at line 807 of file app_voicemail_imapstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 801 of file app_voicemail_imapstorage.c.

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

Definition at line 775 of file app_voicemail_imapstorage.c.

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

}

Definition at line 11411 of file app_voicemail_imapstorage.c.

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

Definition at line 870 of file app_voicemail_imapstorage.c.

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

Definition at line 869 of file app_voicemail_imapstorage.c.

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

Definition at line 866 of file app_voicemail_imapstorage.c.

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

Definition at line 867 of file app_voicemail_imapstorage.c.

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

Definition at line 865 of file app_voicemail_imapstorage.c.

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

Definition at line 871 of file app_voicemail_imapstorage.c.

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

Definition at line 883 of file app_voicemail_imapstorage.c.

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

Definition at line 868 of file app_voicemail_imapstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 754 of file app_voicemail_imapstorage.c.

Initial value:

Definition at line 11406 of file app_voicemail_imapstorage.c.

char vmfmts[80] [static]

Definition at line 802 of file app_voicemail_imapstorage.c.

int vmmaxsecs [static]

Definition at line 805 of file app_voicemail_imapstorage.c.

int vmminsecs [static]

Definition at line 804 of file app_voicemail_imapstorage.c.

double volgain [static]

Definition at line 803 of file app_voicemail_imapstorage.c.

char zonetag[80] [static]

Definition at line 792 of file app_voicemail_imapstorage.c.


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1