Wed Aug 18 22:34:02 2010

Asterisk developer's documentation


app_voicemail.c File Reference

Comedian Mail - Voicemail System. More...

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

Go to the source code of this file.

Data Structures

struct  ast_vm_user
struct  baseio
struct  inprocess
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  mwi_sub
 An MWI subscription. More...
struct  mwi_sub_task
struct  mwi_subs
struct  users
 list of users found in the config file More...
struct  vm_state
struct  vm_zone
struct  zones

Defines

#define ASTERISK_USERNAME   "asterisk"
#define BASELINELEN   72
#define BASEMAXINLINE   256
#define CHUNKSIZE   65536
#define COMMAND_TIMEOUT   5000
#define COPY(a, b, c, d, e, f, g, h)   (copy_plain_file(g,h));
#define 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  {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER
}
enum  {
  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  { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int 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.
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 char * encode_mime_str (const char *start, char *end, size_t endsize, 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 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 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 (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, 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, char *passdata, size_t passdatasize, const char *category, const char *flag)
static void queue_mwi_event (const char *box, int urgent, int new, int old)
static char * quote (const char *from, char *to, size_t len)
 Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
static int reload (void)
static void rename_file (char *sfn, char *dfn)
 Renames a message in a mailbox folder.
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 char * substitute_escapes (const char *value)
static int unload_module (void)
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, void *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Spanish syntax for 'You have N messages' greeting.
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_it (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Italian syntax for 'You have N messages' greeting.
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Portuguese syntax for 'You have N messages' greeting.
static int vm_browse_messages_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, void *data)
static int vm_execmain (struct ast_channel *chan, void *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_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 vmauthenticate (struct ast_channel *chan, void *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. Return tm so it can be used as a function argument.
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)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static char * addesc = "Comedian Mail"
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
static int adsiver = 1
static char * app = "VoiceMail"
static char * app2 = "VoiceMailMain"
static char * app3 = "MailboxExists"
static char * app4 = "VMAuthenticate"
static struct ast_module_infoast_module_info = &__mod_info
static char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char * descrip_vm
static char * descrip_vm_box_exists
static char * descrip_vmain
static char * descrip_vmauthenticate
static char dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_check_cmd [128]
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static struct ast_custom_function mailbox_exists_acf
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 pagerfromstring [100]
static char * pagersubject = NULL
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
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 serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char * synopsis_vm = "Leave a Voicemail message"
static char * synopsis_vm_box_exists
static char * synopsis_vmain = "Check Voicemail messages"
static char * synopsis_vmauthenticate = "Authenticate with Voicemail passwords"
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_app_option vm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }}
enum { ... }  vm_box
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
enum { ... }  vm_option_args
enum { ... }  vm_option_flags
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_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
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, read doc/imapstorage.txt

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


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 192 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 215 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 216 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 189 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 185 of file app_voicemail.c.

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

Definition at line 485 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 197 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 199 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 200 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 198 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 201 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 633 of file app_voicemail.c.

Referenced by load_config().

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

Definition at line 486 of file app_voicemail.c.

Referenced by notify_new_message(), play_record_review(), and vm_tempgreeting().

#define DISPOSE ( a,
 ) 

Definition at line 481 of file app_voicemail.c.

Referenced by advanced_options(), forward_message(), invent_message(), leave_voicemail(), notify_new_message(), play_message(), play_record_review(), sayname(), vm_intro(), vm_options(), and vm_tempgreeting().

#define ENDL   "\n"

Definition at line 220 of file app_voicemail.c.

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

#define ERROR_LOCK_PATH   -100

Definition at line 245 of file app_voicemail.c.

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

Definition at line 483 of file app_voicemail.c.

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

#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"

Referenced by handle_voicemail_show_users().

#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"

Referenced by handle_voicemail_show_zones().

#define INTRO   "vm-intro"

Definition at line 208 of file app_voicemail.c.

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

#define MAX_DATETIME_FORMAT   512

Definition at line 223 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 224 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 210 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

Definition at line 211 of file app_voicemail.c.

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

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 213 of file app_voicemail.c.

Referenced by load_config().

#define OPERATOR_EXIT   300

Definition at line 246 of file app_voicemail.c.

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

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 498 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 497 of file app_voicemail.c.

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

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

Definition at line 484 of file app_voicemail.c.

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

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 480 of file app_voicemail.c.

Referenced by advanced_options(), forward_message(), invent_message(), leave_voicemail(), notify_new_message(), play_message(), sayname(), vm_intro(), vm_options(), and vm_tempgreeting().

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

Definition at line 206 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 183 of file app_voicemail.c.

Referenced by run_externnotify().

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

Definition at line 482 of file app_voicemail.c.

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

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 507 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 202 of file app_voicemail.c.

Referenced by is_valid_dtmf().

#define VM_ALLOCED   (1 << 13)

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

Definition at line 239 of file app_voicemail.c.

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

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 237 of file app_voicemail.c.

Referenced by apply_option(), forward_message(), load_config(), manager_list_voicemail_users(), notify_new_message(), and sendmail().

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 238 of file app_voicemail.c.

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

#define VM_DIRECFORWARD   (1 << 10)

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

Definition at line 236 of file app_voicemail.c.

Referenced by forward_message(), and load_config().

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 230 of file app_voicemail.c.

Referenced by apply_option(), load_config(), manager_list_voicemail_users(), and play_message().

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 234 of file app_voicemail.c.

Referenced by apply_option(), load_config(), vm_execmain(), and vm_newuser().

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 233 of file app_voicemail.c.

Referenced by apply_option(), load_config(), vm_execmain(), and vm_newuser().

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 244 of file app_voicemail.c.

Referenced by forward_message(), and load_config().

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 243 of file app_voicemail.c.

Referenced by apply_option(), load_config(), vm_execmain(), and vm_instructions_en().

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 242 of file app_voicemail.c.

Referenced by apply_option(), close_mailbox(), and load_config().

#define VM_OPERATOR   (1 << 1)

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

Definition at line 227 of file app_voicemail.c.

Referenced by apply_option(), leave_voicemail(), load_config(), manager_list_voicemail_users(), and play_record_review().

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 235 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

#define VM_REVIEW   (1 << 0)

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

Definition at line 226 of file app_voicemail.c.

Referenced by apply_option(), load_config(), manager_list_voicemail_users(), and play_record_review().

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 228 of file app_voicemail.c.

Referenced by apply_option(), load_config(), manager_list_voicemail_users(), and play_message().

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 231 of file app_voicemail.c.

Referenced by apply_option(), load_config(), and play_message().

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 240 of file app_voicemail.c.

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

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 232 of file app_voicemail.c.

Referenced by load_config(), and vm_execmain().

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 229 of file app_voicemail.c.

Referenced by apply_option(), load_config(), and vm_execmain().

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 241 of file app_voicemail.c.

Referenced by apply_option(), load_config(), and vm_intro().

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 424 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 191 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 187 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 188 of file app_voicemail.c.

Referenced by add_email_attachment(), copy(), leave_voicemail(), and vm_mkftemp().


Enumeration Type Documentation

anonymous enum

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 249 of file app_voicemail.c.

00249      {
00250    NEW_FOLDER,
00251    OLD_FOLDER,
00252    WORK_FOLDER,
00253    FAMILY_FOLDER,
00254    FRIENDS_FOLDER,
00255    GREETINGS_FOLDER
00256 } vm_box;

anonymous enum

Enumerator:
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 

Definition at line 258 of file app_voicemail.c.

00258      {
00259    OPT_SILENT =           (1 << 0),
00260    OPT_BUSY_GREETING =    (1 << 1),
00261    OPT_UNAVAIL_GREETING = (1 << 2),
00262    OPT_RECORDGAIN =       (1 << 3),
00263    OPT_PREPEND_MAILBOX =  (1 << 4),
00264    OPT_AUTOPLAY =         (1 << 6),
00265    OPT_DTMFEXIT =         (1 << 7),
00266    OPT_MESSAGE_Urgent =   (1 << 8),
00267    OPT_MESSAGE_PRIORITY = (1 << 9)
00268 } vm_option_flags;

anonymous enum

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 270 of file app_voicemail.c.

00270      {
00271    OPT_ARG_RECORDGAIN = 0,
00272    OPT_ARG_PLAYFOLDER = 1,
00273    OPT_ARG_DTMFEXIT   = 2,
00274    /* This *must* be the last value in this enum! */
00275    OPT_ARG_ARRAY_SIZE = 3,
00276 } vm_option_args;


Function Documentation

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

Definition at line 4860 of file app_voicemail.c.

References ast_strlen_zero().

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

04861 {
04862    DIR *dir;
04863    struct dirent *de;
04864    char fn[256];
04865    int ret = 0;
04866 
04867    /* If no mailbox, return immediately */
04868    if (ast_strlen_zero(mailbox))
04869       return 0;
04870 
04871    if (ast_strlen_zero(folder))
04872       folder = "INBOX";
04873    if (ast_strlen_zero(context))
04874       context = "default";
04875 
04876    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
04877 
04878    if (!(dir = opendir(fn)))
04879       return 0;
04880 
04881    while ((de = readdir(dir))) {
04882       if (!strncasecmp(de->d_name, "msg", 3)) {
04883          if (shortcircuit) {
04884             ret = 1;
04885             break;
04886          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
04887             ret++;
04888          }
04889       }
04890    }
04891 
04892    closedir(dir);
04893 
04894    return ret;
04895 }

static void __reg_module ( void   )  [static]

Definition at line 11759 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

Definition at line 11759 of file app_voicemail.c.

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

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

09910 {
09911    struct ast_vm_user svm;
09912    AST_DECLARE_APP_ARGS(arg,
09913       AST_APP_ARG(mbox);
09914       AST_APP_ARG(context);
09915    );
09916 
09917    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
09918 
09919    if (ast_strlen_zero(arg.mbox)) {
09920       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
09921       return -1;
09922    }
09923 
09924    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
09925    return 0;
09926 }

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

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

Referenced by make_email_file().

04351 {
04352    char tmpdir[256], newtmp[256];
04353    char fname[256];
04354    char tmpcmd[256];
04355    int tmpfd = -1;
04356 
04357    /* Eww. We want formats to tell us their own MIME type */
04358    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04359 
04360    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04361       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04362       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04363       tmpfd = mkstemp(newtmp);
04364       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04365       ast_debug(3, "newtmp: %s\n", newtmp);
04366       if (tmpfd > -1) {
04367          int soxstatus;
04368          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04369          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04370             attach = newtmp;
04371             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04372          } else {
04373             ast_log(LOG_WARNING, "Sox failed to reencode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04374                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04375             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04376          }
04377       }
04378    }
04379    fprintf(p, "--%s" ENDL, bound);
04380    if (msgnum > -1)
04381       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04382    else
04383       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04384    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04385    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04386    if (msgnum > -1)
04387       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04388    else
04389       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04390    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04391    base_encode(fname, p);
04392    if (last)
04393       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04394    if (tmpfd > -1) {
04395       unlink(fname);
04396       close(tmpfd);
04397       unlink(newtmp);
04398    }
04399    return 0;
04400 }

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

Definition at line 5793 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

05794 {
05795    int x;
05796    if (!ast_adsi_available(chan))
05797       return;
05798    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05799    if (x < 0)
05800       return;
05801    if (!x) {
05802       if (adsi_load_vmail(chan, useadsi)) {
05803          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
05804          return;
05805       }
05806    } else
05807       *useadsi = 1;
05808 }

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

Definition at line 5982 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available, chan, and vm_state::curmsg.

Referenced by vm_execmain().

05983 {
05984    int bytes=0;
05985    unsigned char buf[256];
05986    unsigned char keys[8];
05987 
05988    int x;
05989 
05990    if (!ast_adsi_available(chan))
05991       return;
05992 
05993    /* New meaning for keys */
05994    for (x=0;x<5;x++)
05995       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05996 
05997    keys[6] = 0x0;
05998    keys[7] = 0x0;
05999 
06000    if (!vms->curmsg) {
06001       /* No prev key, provide "Folder" instead */
06002       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06003    }
06004    if (vms->curmsg >= vms->lastmsg) {
06005       /* If last message ... */
06006       if (vms->curmsg) {
06007          /* but not only message, provide "Folder" instead */
06008          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06009       } else {
06010          /* Otherwise if only message, leave blank */
06011          keys[3] = 1;
06012       }
06013    }
06014 
06015    /* If deleted, show "undeleted" */
06016    if (vms->deleted[vms->curmsg]) 
06017       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06018 
06019    /* Except "Exit" */
06020    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06021    bytes += ast_adsi_set_keys(buf + bytes, keys);
06022    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06023 
06024    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06025 }

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

Definition at line 5858 of file app_voicemail.c.

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

Referenced by vm_execmain().

05859 {
05860    unsigned char buf[256];
05861    int bytes=0;
05862    unsigned char keys[8];
05863    int x,y;
05864 
05865    if (!ast_adsi_available(chan))
05866       return;
05867 
05868    for (x=0;x<5;x++) {
05869       y = ADSI_KEY_APPS + 12 + start + x;
05870       if (y > ADSI_KEY_APPS + 12 + 4)
05871          y = 0;
05872       keys[x] = ADSI_KEY_SKT | y;
05873    }
05874    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05875    keys[6] = 0;
05876    keys[7] = 0;
05877 
05878    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05879    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05880    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05881    bytes += ast_adsi_set_keys(buf + bytes, keys);
05882    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05883 
05884    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05885 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 6130 of file app_voicemail.c.

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

Referenced by vm_execmain().

06131 {
06132    unsigned char buf[256];
06133    int bytes=0;
06134 
06135    if (!ast_adsi_available(chan))
06136       return;
06137    bytes += adsi_logo(buf + bytes);
06138    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06139    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06140    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06141    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06142 
06143    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06144 }

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

Definition at line 5664 of file app_voicemail.c.

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

Referenced by adsi_begin().

05665 {
05666    unsigned char buf[256];
05667    int bytes=0;
05668    int x;
05669    char num[5];
05670 
05671    *useadsi = 0;
05672    bytes += ast_adsi_data_mode(buf + bytes);
05673    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05674 
05675    bytes = 0;
05676    bytes += adsi_logo(buf);
05677    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05678 #ifdef DISPLAY
05679    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
05680 #endif
05681    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05682    bytes += ast_adsi_data_mode(buf + bytes);
05683    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05684 
05685    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
05686       bytes = 0;
05687       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
05688       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05689       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05690       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05691       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05692       return 0;
05693    }
05694 
05695 #ifdef DISPLAY
05696    /* Add a dot */
05697    bytes = 0;
05698    bytes += ast_adsi_logo(buf);
05699    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05700    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
05701    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05702    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05703 #endif
05704    bytes = 0;
05705    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
05706    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
05707    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
05708    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
05709    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
05710    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
05711    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05712 
05713 #ifdef DISPLAY
05714    /* Add another dot */
05715    bytes = 0;
05716    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
05717    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05718 
05719    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05720    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05721 #endif
05722 
05723    bytes = 0;
05724    /* These buttons we load but don't use yet */
05725    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
05726    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
05727    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
05728    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
05729    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
05730    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
05731    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05732 
05733 #ifdef DISPLAY
05734    /* Add another dot */
05735    bytes = 0;
05736    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
05737    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05738    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05739 #endif
05740 
05741    bytes = 0;
05742    for (x=0;x<5;x++) {
05743       snprintf(num, sizeof(num), "%d", x);
05744       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
05745    }
05746    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
05747    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05748 
05749 #ifdef DISPLAY
05750    /* Add another dot */
05751    bytes = 0;
05752    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
05753    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05754    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05755 #endif
05756 
05757    if (ast_adsi_end_download(chan)) {
05758       bytes = 0;
05759       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
05760       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05761       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05762       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05763       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05764       return 0;
05765    }
05766    bytes = 0;
05767    bytes += ast_adsi_download_disconnect(buf + bytes);
05768    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05769    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05770 
05771    ast_debug(1, "Done downloading scripts...\n");
05772 
05773 #ifdef DISPLAY
05774    /* Add last dot */
05775    bytes = 0;
05776    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
05777    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05778 #endif
05779    ast_debug(1, "Restarting session...\n");
05780 
05781    bytes = 0;
05782    /* Load the session now */
05783    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
05784       *useadsi = 1;
05785       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
05786    } else
05787       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
05788 
05789    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05790    return 0;
05791 }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 5810 of file app_voicemail.c.

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

Referenced by vm_authenticate().

05811 {
05812    unsigned char buf[256];
05813    int bytes=0;
05814    unsigned char keys[8];
05815    int x;
05816    if (!ast_adsi_available(chan))
05817       return;
05818 
05819    for (x=0;x<8;x++)
05820       keys[x] = 0;
05821    /* Set one key for next */
05822    keys[3] = ADSI_KEY_APPS + 3;
05823 
05824    bytes += adsi_logo(buf + bytes);
05825    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05826    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
05827    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05828    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
05829    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05830    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05831    bytes += ast_adsi_set_keys(buf + bytes, keys);
05832    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05833    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05834 }

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

Definition at line 5656 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display.

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

05657 {
05658    int bytes = 0;
05659    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
05660    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
05661    return bytes;
05662 }

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

Definition at line 5887 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available, ast_copy_string(), ast_strlen_zero(), chan, vm_state::curmsg, vm_state::fn, num, and strsep().

Referenced by play_message(), and vm_execmain().

05888 {
05889    int bytes=0;
05890    unsigned char buf[256]; 
05891    char buf1[256], buf2[256];
05892    char fn2[PATH_MAX];
05893 
05894    char cid[256]="";
05895    char *val;
05896    char *name, *num;
05897    char datetime[21]="";
05898    FILE *f;
05899 
05900    unsigned char keys[8];
05901 
05902    int x;
05903 
05904    if (!ast_adsi_available(chan))
05905       return;
05906 
05907    /* Retrieve important info */
05908    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
05909    f = fopen(fn2, "r");
05910    if (f) {
05911       while (!feof(f)) {   
05912          if (!fgets((char *)buf, sizeof(buf), f)) {
05913             continue;
05914          }
05915          if (!feof(f)) {
05916             char *stringp=NULL;
05917             stringp = (char *)buf;
05918             strsep(&stringp, "=");
05919             val = strsep(&stringp, "=");
05920             if (!ast_strlen_zero(val)) {
05921                if (!strcmp((char *)buf, "callerid"))
05922                   ast_copy_string(cid, val, sizeof(cid));
05923                if (!strcmp((char *)buf, "origdate"))
05924                   ast_copy_string(datetime, val, sizeof(datetime));
05925             }
05926          }
05927       }
05928       fclose(f);
05929    }
05930    /* New meaning for keys */
05931    for (x=0;x<5;x++)
05932       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05933    keys[6] = 0x0;
05934    keys[7] = 0x0;
05935 
05936    if (!vms->curmsg) {
05937       /* No prev key, provide "Folder" instead */
05938       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05939    }
05940    if (vms->curmsg >= vms->lastmsg) {
05941       /* If last message ... */
05942       if (vms->curmsg) {
05943          /* but not only message, provide "Folder" instead */
05944          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05945          bytes += ast_adsi_voice_mode(buf + bytes, 0);
05946 
05947       } else {
05948          /* Otherwise if only message, leave blank */
05949          keys[3] = 1;
05950       }
05951    }
05952 
05953    if (!ast_strlen_zero(cid)) {
05954       ast_callerid_parse(cid, &name, &num);
05955       if (!name)
05956          name = num;
05957    } else
05958       name = "Unknown Caller";
05959 
05960    /* If deleted, show "undeleted" */
05961 
05962    if (vms->deleted[vms->curmsg])
05963       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05964 
05965    /* Except "Exit" */
05966    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05967    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
05968       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
05969    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
05970 
05971    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05972    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05973    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
05974    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
05975    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05976    bytes += ast_adsi_set_keys(buf + bytes, keys);
05977    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05978 
05979    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05980 }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 5836 of file app_voicemail.c.

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

Referenced by vm_authenticate().

05837 {
05838    unsigned char buf[256];
05839    int bytes=0;
05840    unsigned char keys[8];
05841    int x;
05842    if (!ast_adsi_available(chan))
05843       return;
05844 
05845    for (x=0;x<8;x++)
05846       keys[x] = 0;
05847    /* Set one key for next */
05848    keys[3] = ADSI_KEY_APPS + 3;
05849 
05850    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05851    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05852    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05853    bytes += ast_adsi_set_keys(buf + bytes, keys);
05854    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05855    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05856 }

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

Definition at line 6027 of file app_voicemail.c.

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

Referenced by vm_execmain().

06028 {
06029    unsigned char buf[256] = "";
06030    char buf1[256] = "", buf2[256] = "";
06031    int bytes=0;
06032    unsigned char keys[8];
06033    int x;
06034 
06035    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06036    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06037    if (!ast_adsi_available(chan))
06038       return;
06039    if (vms->newmessages) {
06040       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06041       if (vms->oldmessages) {
06042          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06043          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06044       } else {
06045          snprintf(buf2, sizeof(buf2), "%s.", newm);
06046       }
06047    } else if (vms->oldmessages) {
06048       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06049       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06050    } else {
06051       strcpy(buf1, "You have no messages.");
06052       buf2[0] = ' ';
06053       buf2[1] = '\0';
06054    }
06055    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06056    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06057    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06058 
06059    for (x=0;x<6;x++)
06060       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06061    keys[6] = 0;
06062    keys[7] = 0;
06063 
06064    /* Don't let them listen if there are none */
06065    if (vms->lastmsg < 0)
06066       keys[0] = 1;
06067    bytes += ast_adsi_set_keys(buf + bytes, keys);
06068 
06069    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06070 
06071    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06072 }

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

Definition at line 6074 of file app_voicemail.c.

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

Referenced by vm_execmain().

06075 {
06076    unsigned char buf[256] = "";
06077    char buf1[256] = "", buf2[256] = "";
06078    int bytes=0;
06079    unsigned char keys[8];
06080    int x;
06081 
06082    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06083 
06084    if (!ast_adsi_available(chan))
06085       return;
06086 
06087    /* Original command keys */
06088    for (x=0;x<6;x++)
06089       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06090 
06091    keys[6] = 0;
06092    keys[7] = 0;
06093 
06094    if ((vms->lastmsg + 1) < 1)
06095       keys[0] = 0;
06096 
06097    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06098       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06099 
06100    if (vms->lastmsg + 1)
06101       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06102    else
06103       strcpy(buf2, "no messages.");
06104    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06105    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06106    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06107    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06108    bytes += ast_adsi_set_keys(buf + bytes, keys);
06109 
06110    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06111 
06112    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06113    
06114 }

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

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, chan, CONFIG_FLAG_NOCACHE, config_flags, 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(), num, play_message_callerid(), play_message_datetime(), RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

11336 {
11337    int res = 0;
11338    char filename[PATH_MAX];
11339    struct ast_config *msg_cfg = NULL;
11340    const char *origtime, *context;
11341    char *name, *num;
11342    int retries = 0;
11343    char *cid;
11344    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
11345 
11346    vms->starting = 0; 
11347 
11348    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11349 
11350    /* Retrieve info from VM attribute file */
11351    snprintf(filename,sizeof(filename), "%s.txt", vms->fn);
11352    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
11353    msg_cfg = ast_config_load(filename, config_flags);
11354    DISPOSE(vms->curdir, vms->curmsg);
11355    if (!msg_cfg) {
11356       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
11357       return 0;
11358    }
11359 
11360    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
11361       ast_config_destroy(msg_cfg);
11362       return 0;
11363    }
11364 
11365    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
11366 
11367    context = ast_variable_retrieve(msg_cfg, "message", "context");
11368    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
11369       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
11370    switch (option) {
11371    case 3: /* Play message envelope */
11372       if (!res)
11373          res = play_message_datetime(chan, vmu, origtime, filename);
11374       if (!res)
11375          res = play_message_callerid(chan, vms, cid, context, 0);
11376 
11377       res = 't';
11378       break;
11379 
11380    case 2:  /* Call back */
11381 
11382       if (ast_strlen_zero(cid))
11383          break;
11384 
11385       ast_callerid_parse(cid, &name, &num);
11386       while ((res > -1) && (res != 't')) {
11387          switch (res) {
11388          case '1':
11389             if (num) {
11390                /* Dial the CID number */
11391                res = dialout(chan, vmu, num, vmu->callback);
11392                if (res) {
11393                   ast_config_destroy(msg_cfg);
11394                   return 9;
11395                }
11396             } else {
11397                res = '2';
11398             }
11399             break;
11400 
11401          case '2':
11402             /* Want to enter a different number, can only do this if there's a dialout context for this user */
11403             if (!ast_strlen_zero(vmu->dialout)) {
11404                res = dialout(chan, vmu, NULL, vmu->dialout);
11405                if (res) {
11406                   ast_config_destroy(msg_cfg);
11407                   return 9;
11408                }
11409             } else {
11410                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
11411                res = ast_play_and_wait(chan, "vm-sorry");
11412             }
11413             ast_config_destroy(msg_cfg);
11414             return res;
11415          case '*':
11416             res = 't';
11417             break;
11418          case '3':
11419          case '4':
11420          case '5':
11421          case '6':
11422          case '7':
11423          case '8':
11424          case '9':
11425          case '0':
11426 
11427             res = ast_play_and_wait(chan, "vm-sorry");
11428             retries++;
11429             break;
11430          default:
11431             if (num) {
11432                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
11433                res = ast_play_and_wait(chan, "vm-num-i-have");
11434                if (!res)
11435                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
11436                if (!res)
11437                   res = ast_play_and_wait(chan, "vm-tocallnum");
11438                /* Only prompt for a caller-specified number if there is a dialout context specified */
11439                if (!ast_strlen_zero(vmu->dialout)) {
11440                   if (!res)
11441                      res = ast_play_and_wait(chan, "vm-calldiffnum");
11442                }
11443             } else {
11444                res = ast_play_and_wait(chan, "vm-nonumber");
11445                if (!ast_strlen_zero(vmu->dialout)) {
11446                   if (!res)
11447                      res = ast_play_and_wait(chan, "vm-toenternumber");
11448                }
11449             }
11450             if (!res)
11451                res = ast_play_and_wait(chan, "vm-star-cancel");
11452             if (!res)
11453                res = ast_waitfordigit(chan, 6000);
11454             if (!res) {
11455                retries++;
11456                if (retries > 3)
11457                   res = 't';
11458             }
11459             break; 
11460             
11461          }
11462          if (res == 't')
11463             res = 0;
11464          else if (res == '*')
11465             res = -1;
11466       }
11467       break;
11468       
11469    case 1:  /* Reply */
11470       /* Send reply directly to sender */
11471       if (ast_strlen_zero(cid))
11472          break;
11473 
11474       ast_callerid_parse(cid, &name, &num);
11475       if (!num) {
11476          ast_verb(3, "No CID number available, no reply sent\n");
11477          if (!res)
11478             res = ast_play_and_wait(chan, "vm-nonumber");
11479          ast_config_destroy(msg_cfg);
11480          return res;
11481       } else {
11482          struct ast_vm_user vmu2;
11483          if (find_user(&vmu2, vmu->context, num)) {
11484             struct leave_vm_options leave_options;
11485             char mailbox[AST_MAX_EXTENSION * 2 + 2];
11486             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
11487 
11488             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
11489             
11490             memset(&leave_options, 0, sizeof(leave_options));
11491             leave_options.record_gain = record_gain;
11492             res = leave_voicemail(chan, mailbox, &leave_options);
11493             if (!res)
11494                res = 't';
11495             ast_config_destroy(msg_cfg);
11496             return res;
11497          } else {
11498             /* Sender has no mailbox, can't reply */
11499             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
11500             ast_play_and_wait(chan, "vm-nobox");
11501             res = 't';
11502             ast_config_destroy(msg_cfg);
11503             return res;
11504          }
11505       } 
11506       res = 0;
11507 
11508       break;
11509    }
11510 
11511 #ifndef IMAP_STORAGE
11512    ast_config_destroy(msg_cfg);
11513 
11514    if (!res) {
11515       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11516       vms->heard[msg] = 1;
11517       res = wait_file(chan, vms, vms->fn);
11518    }
11519 #endif
11520    return res;
11521 }

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

Definition at line 9829 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_strdupa, ast_vm_user::email, find_or_create(), ast_vm_user::fullname, inboxcount2(), ast_vm_user::pager, ast_vm_user::password, populate_defaults(), queue_mwi_event(), s, and strsep().

Referenced by load_config().

09830 {
09831    /* Assumes lock is already held */
09832    char *tmp;
09833    char *stringp;
09834    char *s;
09835    struct ast_vm_user *vmu;
09836    char *mailbox_full;
09837    int new = 0, old = 0, urgent = 0;
09838 
09839    tmp = ast_strdupa(data);
09840 
09841    if (!(vmu = find_or_create(context, box)))
09842       return -1;
09843    
09844    populate_defaults(vmu);
09845 
09846    stringp = tmp;
09847    if ((s = strsep(&stringp, ","))) 
09848       ast_copy_string(vmu->password, s, sizeof(vmu->password));
09849    if (stringp && (s = strsep(&stringp, ","))) 
09850       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
09851    if (stringp && (s = strsep(&stringp, ","))) 
09852       ast_copy_string(vmu->email, s, sizeof(vmu->email));
09853    if (stringp && (s = strsep(&stringp, ","))) 
09854       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
09855    if (stringp && (s = strsep(&stringp, ","))) 
09856       apply_options(vmu, s);
09857 
09858    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
09859    strcpy(mailbox_full, box);
09860    strcat(mailbox_full, "@");
09861    strcat(mailbox_full, context);
09862 
09863    inboxcount2(mailbox_full, &urgent, &new, &old);
09864    queue_mwi_event(mailbox_full, urgent, new, old);
09865 
09866    return 0;
09867 }

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

References apply_options(), ast_copy_string(), ast_log(), AST_LOG_WARNING, ast_set2_flag, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::exit, ast_vm_user::language, ast_vm_user::maxdeletedmsg, MAXMSG, ast_vm_user::maxmsg, MAXMSGLIMIT, ast_vm_user::maxsecs, ast_vm_user::saydurationm, ast_vm_user::serveremail, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SVMAIL, VM_TEMPGREETWARN, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by apply_options(), and apply_options_full().

00842 {
00843    int x;
00844    if (!strcasecmp(var, "attach")) {
00845       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00846    } else if (!strcasecmp(var, "attachfmt")) {
00847       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00848    } else if (!strcasecmp(var, "serveremail")) {
00849       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00850    } else if (!strcasecmp(var, "language")) {
00851       ast_copy_string(vmu->language, value, sizeof(vmu->language));
00852    } else if (!strcasecmp(var, "tz")) {
00853       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00854 #ifdef IMAP_STORAGE
00855    } else if (!strcasecmp(var, "imapuser")) {
00856       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00857       vmu->imapversion = imapversion;
00858    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
00859       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00860       vmu->imapversion = imapversion;
00861    } else if (!strcasecmp(var, "imapvmshareid")) {
00862       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
00863       vmu->imapversion = imapversion;
00864 #endif
00865    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00866       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
00867    } else if (!strcasecmp(var, "saycid")){
00868       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
00869    } else if (!strcasecmp(var,"sendvoicemail")){
00870       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
00871    } else if (!strcasecmp(var, "review")){
00872       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00873    } else if (!strcasecmp(var, "tempgreetwarn")){
00874       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
00875    } else if (!strcasecmp(var, "messagewrap")){
00876       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
00877    } else if (!strcasecmp(var, "operator")) {
00878       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
00879    } else if (!strcasecmp(var, "envelope")){
00880       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
00881    } else if (!strcasecmp(var, "moveheard")){
00882       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
00883    } else if (!strcasecmp(var, "sayduration")){
00884       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
00885    } else if (!strcasecmp(var, "saydurationm")){
00886       if (sscanf(value, "%30d", &x) == 1) {
00887          vmu->saydurationm = x;
00888       } else {
00889          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
00890       }
00891    } else if (!strcasecmp(var, "forcename")){
00892       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
00893    } else if (!strcasecmp(var, "forcegreetings")){
00894       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
00895    } else if (!strcasecmp(var, "callback")) {
00896       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00897    } else if (!strcasecmp(var, "dialout")) {
00898       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00899    } else if (!strcasecmp(var, "exitcontext")) {
00900       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00901    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
00902       vmu->maxsecs = atoi(value);
00903       if (vmu->maxsecs <= 0) {
00904          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
00905          vmu->maxsecs = vmmaxsecs;
00906       } else {
00907          vmu->maxsecs = atoi(value);
00908       }
00909       if (!strcasecmp(var, "maxmessage"))
00910          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
00911    } else if (!strcasecmp(var, "maxmsg")) {
00912       vmu->maxmsg = atoi(value);
00913       if (vmu->maxmsg <= 0) {
00914          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
00915          vmu->maxmsg = MAXMSG;
00916       } else if (vmu->maxmsg > MAXMSGLIMIT) {
00917          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00918          vmu->maxmsg = MAXMSGLIMIT;
00919       }
00920    } else if (!strcasecmp(var, "backupdeleted")) {
00921       if (sscanf(value, "%30d", &x) == 1)
00922          vmu->maxdeletedmsg = x;
00923       else if (ast_true(value))
00924          vmu->maxdeletedmsg = MAXMSG;
00925       else
00926          vmu->maxdeletedmsg = 0;
00927 
00928       if (vmu->maxdeletedmsg < 0) {
00929          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
00930          vmu->maxdeletedmsg = MAXMSG;
00931       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
00932          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
00933          vmu->maxdeletedmsg = MAXMSGLIMIT;
00934       }
00935    } else if (!strcasecmp(var, "volgain")) {
00936       sscanf(value, "%30lf", &vmu->volgain);
00937    } else if (!strcasecmp(var, "options")) {
00938       apply_options(vmu, value);
00939    }
00940 }

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

Destructively Parse options and apply.

Definition at line 1054 of file app_voicemail.c.

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

Referenced by append_mailbox(), and apply_option().

01055 {  
01056    char *stringp;
01057    char *s;
01058    char *var, *value;
01059    stringp = ast_strdupa(options);
01060    while ((s = strsep(&stringp, "|"))) {
01061       value = s;
01062       if ((var = strsep(&value, "=")) && value) {
01063          apply_option(vmu, var, value);
01064       }
01065    }  
01066 }

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

References apply_option(), ast_copy_string(), ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, ast_vm_user::fullname, ast_variable::name, ast_variable::next, ast_vm_user::pager, ast_vm_user::password, ast_vm_user::uniqueid, ast_variable::value, and var.

Referenced by find_user_realtime(), and load_config().

01074 {
01075    struct ast_variable *tmp;
01076    tmp = var;
01077    while (tmp) {
01078       if (!strcasecmp(tmp->name, "vmsecret")) {
01079          ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
01080       } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) { /* don't overwrite vmsecret if it exists */
01081          if (ast_strlen_zero(retval->password))
01082             ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
01083       } else if (!strcasecmp(tmp->name, "uniqueid")) {
01084          ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
01085       } else if (!strcasecmp(tmp->name, "pager")) {
01086          ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
01087       } else if (!strcasecmp(tmp->name, "email")) {
01088          ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
01089       } else if (!strcasecmp(tmp->name, "fullname")) {
01090          ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
01091       } else if (!strcasecmp(tmp->name, "context")) {
01092          ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
01093 #ifdef IMAP_STORAGE
01094       } else if (!strcasecmp(tmp->name, "imapuser")) {
01095          ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
01096          retval->imapversion = imapversion;
01097       } else if (!strcasecmp(tmp->name, "imappassword") || !strcasecmp(tmp->name, "imapsecret")) {
01098          ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
01099          retval->imapversion = imapversion;
01100       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01101          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01102          retval->imapversion = imapversion;
01103 #endif
01104       } else
01105          apply_option(retval, tmp->name, tmp->value);
01106       tmp = tmp->next;
01107    } 
01108 }

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

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

03828 {
03829    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
03830       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
03831       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
03832       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
03833    int i,hiteof= 0;
03834    FILE *fi;
03835    struct baseio bio;
03836 
03837    memset(&bio, 0, sizeof(bio));
03838    bio.iocp = BASEMAXINLINE;
03839 
03840    if (!(fi = fopen(filename, "rb"))) {
03841       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
03842       return -1;
03843    }
03844 
03845    while (!hiteof){
03846       unsigned char igroup[3], ogroup[4];
03847       int c,n;
03848 
03849       igroup[0]= igroup[1]= igroup[2]= 0;
03850 
03851       for (n= 0;n<3;n++) {
03852          if ((c = inchar(&bio, fi)) == EOF) {
03853             hiteof= 1;
03854             break;
03855          }
03856 
03857          igroup[n]= (unsigned char)c;
03858       }
03859 
03860       if (n> 0) {
03861          ogroup[0]= dtable[igroup[0]>>2];
03862          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
03863          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
03864          ogroup[3]= dtable[igroup[2]&0x3F];
03865 
03866          if (n<3) {
03867             ogroup[3]= '=';
03868 
03869             if (n<2)
03870                ogroup[2]= '=';
03871          }
03872 
03873          for (i= 0;i<4;i++)
03874             ochar(&bio, ogroup[i], so);
03875       }
03876    }
03877 
03878    fclose(fi);
03879    
03880    if (fputs(ENDL, so) == EOF) {
03881       return 0;
03882    }
03883 
03884    return 1;
03885 }

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

References ast_copy_string(), ast_realtime_require_field(), ast_strlen_zero(), ast_update_realtime(), ast_vm_user::password, RQ_CHAR, SENTINEL, and ast_vm_user::uniqueid.

Referenced by vm_change_password().

01034 {
01035    int res = -1;
01036    if (!strcmp(vmu->password, password)) {
01037       /* No change (but an update would return 0 rows updated, so we opt out here) */
01038       res = 0;
01039    } else if (!ast_strlen_zero(vmu->uniqueid)) {
01040       if (strlen(password) > 10) {
01041          ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01042       }
01043       if (ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, SENTINEL) > 0) {
01044          ast_copy_string(vmu->password, password, sizeof(vmu->password));
01045          res = 0;
01046       }
01047    }
01048    return res;
01049 }

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

Referenced by make_email_file().

03994 {
03995    for (; *str; str++) {
03996       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
03997          return 1;
03998       }
03999    }
04000    return 0;
04001 }

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

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

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

00996 {
00997    /* check minimum length */
00998    if (strlen(password) < minpassword)
00999       return 1;
01000    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01001       char cmd[255], buf[255];
01002 
01003       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01004 
01005       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01006       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01007          ast_debug(5, "Result: %s\n", buf);
01008          if (!strncasecmp(buf, "VALID", 5)) {
01009             ast_debug(3, "Passed password check: '%s'\n", buf);
01010             return 0;
01011          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01012             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01013             return 0;
01014          } else {
01015             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01016             return 1;
01017          }
01018       }
01019    }
01020    return 0;
01021 }

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

Definition at line 7219 of file app_voicemail.c.

References ast_log(), ast_test_flag, ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, vm_state::deleted, ERROR_LOCK_PATH, EXISTS, vm_state::fn, vm_state::heard, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by vm_execmain().

07220 {
07221    int x = 0;
07222 #ifndef IMAP_STORAGE
07223    int res = 0, nummsg;
07224    char fn2[PATH_MAX];
07225 #endif
07226 
07227    if (vms->lastmsg <= -1)
07228       goto done;
07229 
07230    vms->curmsg = -1; 
07231 #ifndef IMAP_STORAGE
07232    /* Get the deleted messages fixed */ 
07233    if (vm_lock_path(vms->curdir))
07234       return ERROR_LOCK_PATH;
07235 
07236    for (x = 0; x < vmu->maxmsg; x++) { 
07237       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) { 
07238          /* Save this message.  It's not in INBOX or hasn't been heard */ 
07239          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
07240          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
07241             break;
07242          vms->curmsg++; 
07243          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg); 
07244          if (strcmp(vms->fn, fn2)) { 
07245             RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07246          } 
07247       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { 
07248          /* Move to old folder before deleting */ 
07249          res = save_to_folder(vmu, vms, x, 1);
07250          if (res == ERROR_LOCK_PATH) {
07251             /* If save failed do not delete the message */
07252             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07253             vms->deleted[x] = 0;
07254             vms->heard[x] = 0;
07255             --x;
07256          }
07257       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07258          /* Move to deleted folder */ 
07259          res = save_to_folder(vmu, vms, x, 10);
07260          if (res == ERROR_LOCK_PATH) {
07261             /* If save failed do not delete the message */
07262             vms->deleted[x] = 0;
07263             vms->heard[x] = 0;
07264             --x;
07265          }
07266       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07267          /* If realtime storage enabled - we should explicitly delete this message,
07268          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07269          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07270          if (EXISTS(vms->curdir, x, vms->fn, NULL))
07271             DELETE(vms->curdir, x, vms->fn, vmu);
07272       }
07273    } 
07274 
07275    /* Delete ALL remaining messages */
07276    nummsg = x - 1;
07277    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07278       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07279       if (EXISTS(vms->curdir, x, vms->fn, NULL))
07280          DELETE(vms->curdir, x, vms->fn, vmu);
07281    }
07282    ast_unlock_path(vms->curdir);
07283 #else
07284    if (vms->deleted) {
07285       for (x=0;x < vmu->maxmsg;x++) { 
07286          if (vms->deleted[x]) { 
07287             ast_debug(3,"IMAP delete of %d\n",x);
07288             DELETE(vms->curdir, x, vms->fn, vmu);
07289          }
07290       }
07291    }
07292 #endif
07293 
07294 done:
07295    if (vms->deleted)
07296       memset(vms->deleted, 0, vmu->maxmsg * sizeof(int)); 
07297    if (vms->heard)
07298       memset(vms->heard, 0, vmu->maxmsg * sizeof(int)); 
07299 
07300    return 0;
07301 }

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

Definition at line 10013 of file app_voicemail.c.

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

Referenced by handle_voicemail_show_users().

10014 {
10015    int which = 0;
10016    int wordlen;
10017    struct ast_vm_user *vmu;
10018    const char *context = "";
10019 
10020    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
10021    if (pos > 4)
10022       return NULL;
10023    if (pos == 3)
10024       return (state == 0) ? ast_strdup("for") : NULL;
10025    wordlen = strlen(word);
10026    AST_LIST_TRAVERSE(&users, vmu, list) {
10027       if (!strncasecmp(word, vmu->context, wordlen)) {
10028          if (context && strcmp(context, vmu->context) && ++which > state)
10029             return ast_strdup(vmu->context);
10030          /* ignore repeated contexts ? */
10031          context = vmu->context;
10032       }
10033    }
10034    return NULL;
10035 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

03632 {
03633    int ifd;
03634    int ofd;
03635    int res;
03636    int len;
03637    char buf[4096];
03638 
03639 #ifdef HARDLINK_WHEN_POSSIBLE
03640    /* Hard link if possible; saves disk space & is faster */
03641    if (link(infile, outfile)) {
03642 #endif
03643       if ((ifd = open(infile, O_RDONLY)) < 0) {
03644          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03645          return -1;
03646       }
03647       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03648          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03649          close(ifd);
03650          return -1;
03651       }
03652       do {
03653          len = read(ifd, buf, sizeof(buf));
03654          if (len < 0) {
03655             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03656             close(ifd);
03657             close(ofd);
03658             unlink(outfile);
03659          }
03660          if (len) {
03661             res = write(ofd, buf, len);
03662             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03663                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03664                close(ifd);
03665                close(ofd);
03666                unlink(outfile);
03667             }
03668          }
03669       } while (len);
03670       close(ifd);
03671       close(ofd);
03672       return 0;
03673 #ifdef HARDLINK_WHEN_POSSIBLE
03674    } else {
03675       /* Hard link succeeded */
03676       return 0;
03677    }
03678 #endif
03679 }

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 This is only used by file storage based mailboxes.
Returns:
zero on success, -1 on error.

Definition at line 4802 of file app_voicemail.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, inprocess_count(), ast_channel::language, last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), mbox(), notify_new_message(), S_OR, STORE, vm_delete(), and vm_lock_path().

Referenced by forward_message(), and leave_voicemail().

04803 {
04804    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
04805    const char *frombox = mbox(imbox);
04806    int recipmsgnum;
04807    int res = 0;
04808 
04809    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
04810 
04811    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
04812       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
04813    } else {
04814       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04815    }
04816    
04817    if (!dir)
04818       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
04819    else
04820       ast_copy_string(fromdir, dir, sizeof(fromdir));
04821 
04822    make_file(frompath, sizeof(frompath), fromdir, msgnum);
04823    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04824 
04825    if (vm_lock_path(todir))
04826       return ERROR_LOCK_PATH;
04827 
04828    recipmsgnum = last_message_index(recip, todir) + 1;
04829    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
04830       make_file(topath, sizeof(topath), todir, recipmsgnum);
04831       if (EXISTS(fromdir, msgnum, frompath, chan->language)) {
04832          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
04833       } else {
04834          /* For ODBC storage, if the file we want to copy isn't yet in the database, then the SQL
04835           * copy will fail. Instead, we need to create a local copy, store it, and delete the local
04836           * copy. We don't have to #ifdef this because if file storage reaches this point, there's a
04837           * much worse problem happening and IMAP storage doesn't call this function
04838           */
04839          copy_plain_file(frompath, topath);
04840          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
04841          vm_delete(topath);
04842       }
04843    } else {
04844       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
04845       res = -1;
04846    }
04847    ast_unlock_path(todir);
04848    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
04849    
04850    return res;
04851 }

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

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

Referenced by copy_message().

03691 {
03692    char frompath2[PATH_MAX], topath2[PATH_MAX];
03693    struct ast_variable *tmp,*var = NULL;
03694    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
03695    ast_filecopy(frompath, topath, NULL);
03696    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
03697    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
03698    if (ast_check_realtime("voicemail_data")) {
03699       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
03700       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
03701       for (tmp = var; tmp; tmp = tmp->next) {
03702          if (!strcasecmp(tmp->name, "origmailbox")) {
03703             origmailbox = tmp->value;
03704          } else if (!strcasecmp(tmp->name, "context")) {
03705             context = tmp->value;
03706          } else if (!strcasecmp(tmp->name, "macrocontext")) {
03707             macrocontext = tmp->value;
03708          } else if (!strcasecmp(tmp->name, "exten")) {
03709             exten = tmp->value;
03710          } else if (!strcasecmp(tmp->name, "priority")) {
03711             priority = tmp->value;
03712          } else if (!strcasecmp(tmp->name, "callerchan")) {
03713             callerchan = tmp->value;
03714          } else if (!strcasecmp(tmp->name, "callerid")) {
03715             callerid = tmp->value;
03716          } else if (!strcasecmp(tmp->name, "origdate")) {
03717             origdate = tmp->value;
03718          } else if (!strcasecmp(tmp->name, "origtime")) {
03719             origtime = tmp->value;
03720          } else if (!strcasecmp(tmp->name, "category")) {
03721             category = tmp->value;
03722          } else if (!strcasecmp(tmp->name, "duration")) {
03723             duration = tmp->value;
03724          }
03725       }
03726       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);
03727    }
03728    copy(frompath2, topath2);
03729    ast_variables_destroy(var);
03730 }

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

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

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

03535 {
03536 
03537    int vmcount = 0;
03538    DIR *vmdir = NULL;
03539    struct dirent *vment = NULL;
03540 
03541    if (vm_lock_path(dir))
03542       return ERROR_LOCK_PATH;
03543 
03544    if ((vmdir = opendir(dir))) {
03545       while ((vment = readdir(vmdir))) {
03546          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03547             vmcount++;
03548          }
03549       }
03550       closedir(vmdir);
03551    }
03552    ast_unlock_path(dir);
03553    
03554    return vmcount;
03555 }

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

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

01384 {
01385    mode_t   mode = VOICEMAIL_DIR_MODE;
01386    int res;
01387 
01388    make_dir(dest, len, context, ext, folder);
01389    if ((res = ast_mkdir(dest, mode))) {
01390       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01391       return -1;
01392    }
01393    return 0;
01394 }

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

Definition at line 11263 of file app_voicemail.c.

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

Referenced by advanced_options(), and vm_execmain().

11264 {
11265    int cmd = 0;
11266    char destination[80] = "";
11267    int retries = 0;
11268 
11269    if (!num) {
11270       ast_verb(3, "Destination number will be entered manually\n");
11271       while (retries < 3 && cmd != 't') {
11272          destination[1] = '\0';
11273          destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
11274          if (!cmd)
11275             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
11276          if (!cmd)
11277             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
11278          if (!cmd) {
11279             cmd = ast_waitfordigit(chan, 6000);
11280             if (cmd)
11281                destination[0] = cmd;
11282          }
11283          if (!cmd) {
11284             retries++;
11285          } else {
11286 
11287             if (cmd < 0)
11288                return 0;
11289             if (cmd == '*') {
11290                ast_verb(3, "User hit '*' to cancel outgoing call\n");
11291                return 0;
11292             }
11293             if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0) 
11294                retries++;
11295             else
11296                cmd = 't';
11297          }
11298       }
11299       if (retries >= 3) {
11300          return 0;
11301       }
11302       
11303    } else {
11304       if (option_verbose > 2)
11305          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
11306       ast_copy_string(destination, num, sizeof(destination));
11307    }
11308 
11309    if (!ast_strlen_zero(destination)) {
11310       if (destination[strlen(destination) -1 ] == '*')
11311          return 0; 
11312       if (option_verbose > 2)
11313          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
11314       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
11315       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
11316       chan->priority = 0;
11317       return 9;
11318    }
11319    return 0;
11320 }

static char* encode_mime_str ( const char *  start,
char *  end,
size_t  endsize,
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:
start A string to be encoded
end An expandable buffer for holding the result
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 4019 of file app_voicemail.c.

References charset.

Referenced by make_email_file().

04020 {
04021    char tmp[80];
04022    int first_section = 1;
04023    size_t endlen = 0, tmplen = 0;
04024    *end = '\0';
04025 
04026    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
04027    for (; *start; start++) {
04028       int need_encoding = 0;
04029       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04030          need_encoding = 1;
04031       }
04032       if ((first_section && need_encoding && preamble + tmplen > 70) ||
04033          (first_section && !need_encoding && preamble + tmplen > 72) ||
04034          (!first_section && need_encoding && tmplen > 70) ||
04035          (!first_section && !need_encoding && tmplen > 72)) {
04036          /* Start new line */
04037          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
04038          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
04039          first_section = 0;
04040       }
04041       if (need_encoding && *start == ' ') {
04042          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
04043       } else if (need_encoding) {
04044          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
04045       } else {
04046          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
04047       }
04048    }
04049    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
04050    return end;
04051 }

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

Definition at line 9797 of file app_voicemail.c.

References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_test_flag, ast_vm_user::context, globalflags, ast_vm_user::list, LOG_WARNING, ast_vm_user::mailbox, and VM_SEARCH.

Referenced by append_mailbox(), and load_config().

09798 {
09799    struct ast_vm_user *vmu;
09800 
09801    AST_LIST_TRAVERSE(&users, vmu, list) {
09802       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
09803          if (strcasecmp(vmu->context, context)) {
09804             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
09805                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
09806                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
09807                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
09808          }
09809          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
09810          return NULL;
09811       }
09812       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
09813          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
09814          return NULL;
09815       }
09816    }
09817    
09818    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
09819       return NULL;
09820    
09821    ast_copy_string(vmu->context, context, sizeof(vmu->context));
09822    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
09823 
09824    AST_LIST_INSERT_TAIL(&users, vmu, list);
09825    
09826    return vmu;
09827 }

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

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

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

Definition at line 1179 of file app_voicemail.c.

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

01180 {
01181    /* This function could be made to generate one from a database, too */
01182    struct ast_vm_user *vmu=NULL, *cur;
01183    AST_LIST_LOCK(&users);
01184 
01185    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01186       context = "default";
01187 
01188    AST_LIST_TRAVERSE(&users, cur, list) {
01189 #ifdef IMAP_STORAGE
01190       if (cur->imapversion != imapversion) {
01191          continue;
01192       }
01193 #endif
01194       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01195          break;
01196       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01197          break;
01198    }
01199    if (cur) {
01200       /* Make a copy, so that on a reload, we have no race */
01201       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01202          memcpy(vmu, cur, sizeof(*vmu));
01203          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01204          AST_LIST_NEXT(vmu, list) = NULL;
01205       }
01206    } else
01207       vmu = find_user_realtime(ivm, context, mailbox);
01208    AST_LIST_UNLOCK(&users);
01209    return vmu;
01210 }

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

Finds a voicemail user from the realtime engine.

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

Definition at line 1142 of file app_voicemail.c.

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

01143 {
01144    struct ast_variable *var;
01145    struct ast_vm_user *retval;
01146 
01147    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01148       if (!ivm)
01149          ast_set_flag(retval, VM_ALLOCED);   
01150       else
01151          memset(retval, 0, sizeof(*retval));
01152       if (mailbox) 
01153          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01154       populate_defaults(retval);
01155       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01156          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01157       else
01158          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01159       if (var) {
01160          apply_options_full(retval, var);
01161          ast_variables_destroy(var);
01162       } else { 
01163          if (!ivm) 
01164             ast_free(retval);
01165          retval = NULL;
01166       }  
01167    } 
01168    return retval;
01169 }

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:
ast_channel 
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 
Reads the destination mailbox(es) from keypad input for CID, or if use_directory feature is enabled, the Directory.

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

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

Returns:
zero on success, -1 on error.

Definition at line 6498 of file app_voicemail.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), free_user(), globalflags, ast_channel::language, leave_voicemail(), ast_app::list, LOG_NOTICE, ast_vm_user::mailbox, make_file(), pbx_exec(), pbx_findapp(), ast_channel::priority, RETRIEVE, run_externnotify(), s, S_OR, sendmail(), STORE, strsep(), vm_state::username, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

06499 {
06500 #ifdef IMAP_STORAGE
06501    int todircount=0;
06502    struct vm_state *dstvms;
06503 #endif
06504    char username[70]="";
06505    char fn[PATH_MAX]; /* for playback of name greeting */
06506    char ecodes[16] = "#";
06507    int res = 0, cmd = 0;
06508    struct ast_vm_user *receiver = NULL, *vmtmp;
06509    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06510    char *stringp;
06511    const char *s;
06512    int saved_messages = 0, found = 0;
06513    int valid_extensions = 0;
06514    char *dir;
06515    int curmsg;
06516    char urgent_str[7] = "";
06517    char tmptxtfile[PATH_MAX];
06518    int prompt_played = 0;
06519 #ifndef IMAP_STORAGE
06520    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06521 #endif
06522    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
06523       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
06524    }
06525 
06526    if (vms == NULL) return -1;
06527    dir = vms->curdir;
06528    curmsg = vms->curmsg;
06529 
06530    tmptxtfile[0] = '\0';
06531    while (!res && !valid_extensions) {
06532       int use_directory = 0;
06533       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
06534          int done = 0;
06535          int retries = 0;
06536          cmd=0;
06537          while ((cmd >= 0) && !done ){
06538             if (cmd)
06539                retries = 0;
06540             switch (cmd) {
06541             case '1': 
06542                use_directory = 0;
06543                done = 1;
06544                break;
06545             case '2': 
06546                use_directory = 1;
06547                done=1;
06548                break;
06549             case '*': 
06550                cmd = 't';
06551                done = 1;
06552                break;
06553             default: 
06554                /* Press 1 to enter an extension press 2 to use the directory */
06555                cmd = ast_play_and_wait(chan,"vm-forward");
06556                if (!cmd)
06557                   cmd = ast_waitfordigit(chan,3000);
06558                if (!cmd)
06559                   retries++;
06560                if (retries > 3) {
06561                   cmd = 't';
06562                   done = 1;
06563                }
06564                
06565             }
06566          }
06567          if (cmd < 0 || cmd == 't')
06568             break;
06569       }
06570       
06571       if (use_directory) {
06572          /* use app_directory */
06573          
06574          char old_context[sizeof(chan->context)];
06575          char old_exten[sizeof(chan->exten)];
06576          int old_priority;
06577          struct ast_app* directory_app;
06578 
06579          directory_app = pbx_findapp("Directory");
06580          if (directory_app) {
06581             char vmcontext[256];
06582             /* make backup copies */
06583             memcpy(old_context, chan->context, sizeof(chan->context));
06584             memcpy(old_exten, chan->exten, sizeof(chan->exten));
06585             old_priority = chan->priority;
06586             
06587             /* call the the Directory, changes the channel */
06588             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
06589             res = pbx_exec(chan, directory_app, vmcontext);
06590             
06591             ast_copy_string(username, chan->exten, sizeof(username));
06592             
06593             /* restore the old context, exten, and priority */
06594             memcpy(chan->context, old_context, sizeof(chan->context));
06595             memcpy(chan->exten, old_exten, sizeof(chan->exten));
06596             chan->priority = old_priority;
06597          } else {
06598             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
06599             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
06600          }
06601       } else {
06602          /* Ask for an extension */
06603          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
06604          prompt_played++;
06605          if (res || prompt_played > 4)
06606             break;
06607          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
06608             break;
06609       }
06610       
06611       /* start all over if no username */
06612       if (ast_strlen_zero(username))
06613          continue;
06614       stringp = username;
06615       s = strsep(&stringp, "*");
06616       /* start optimistic */
06617       valid_extensions = 1;
06618       while (s) {
06619          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
06620             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
06621             found++;
06622          } else {
06623             /* XXX Optimization for the future.  When we encounter a single bad extension,
06624              * bailing out on all of the extensions may not be the way to go.  We should
06625              * probably just bail on that single extension, then allow the user to enter
06626              * several more. XXX
06627              */
06628             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
06629                free_user(receiver);
06630             }
06631             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
06632             valid_extensions = 0;
06633             break;
06634          }
06635 
06636          /* play name if available, else play extension number */
06637          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
06638          RETRIEVE(fn, -1, s, receiver->context);
06639          if (ast_fileexists(fn, NULL, NULL) > 0) {
06640             res = ast_stream_and_wait(chan, fn, ecodes);
06641             if (res) {
06642                DISPOSE(fn, -1);
06643                return res;
06644             }
06645          } else {
06646             res = ast_say_digit_str(chan, s, ecodes, chan->language);
06647          }
06648          DISPOSE(fn, -1);
06649 
06650          s = strsep(&stringp, "*");
06651       }
06652       /* break from the loop of reading the extensions */
06653       if (valid_extensions)
06654          break;
06655       /* "I am sorry, that's not a valid extension.  Please try again." */
06656       res = ast_play_and_wait(chan, "pbx-invalid");
06657    }
06658    /* check if we're clear to proceed */
06659    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
06660       return res;
06661    if (is_new_message == 1) {
06662       struct leave_vm_options leave_options;
06663       char mailbox[AST_MAX_EXTENSION * 2 + 2];
06664       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
06665 
06666       /* Send VoiceMail */
06667       memset(&leave_options, 0, sizeof(leave_options));
06668       leave_options.record_gain = record_gain;
06669       cmd = leave_voicemail(chan, mailbox, &leave_options);
06670    } else {
06671       /* Forward VoiceMail */
06672       long duration = 0;
06673       struct vm_state vmstmp;
06674       int copy_msg_result = 0;
06675       memcpy(&vmstmp, vms, sizeof(vmstmp));
06676 
06677       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
06678 
06679       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
06680       if (!cmd) {
06681          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
06682 #ifdef IMAP_STORAGE
06683             int attach_user_voicemail;
06684             char *myserveremail = serveremail;
06685             
06686             /* get destination mailbox */
06687             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
06688             if (!dstvms) {
06689                dstvms = create_vm_state_from_user(vmtmp);
06690             }
06691             if (dstvms) {
06692                init_mailstream(dstvms, 0);
06693                if (!dstvms->mailstream) {
06694                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
06695                } else {
06696                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
06697                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
06698                }
06699             } else {
06700                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
06701             }
06702             if (!ast_strlen_zero(vmtmp->serveremail))
06703                myserveremail = vmtmp->serveremail;
06704             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
06705             /* NULL category for IMAP storage */
06706             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, dstvms->curbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, NULL, urgent_str);
06707 #else
06708             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
06709 #endif
06710             saved_messages++;
06711             AST_LIST_REMOVE_CURRENT(list);
06712             free_user(vmtmp);
06713             if (res)
06714                break;
06715          }
06716          AST_LIST_TRAVERSE_SAFE_END;
06717          if (saved_messages > 0 && !copy_msg_result) {
06718             /* give confirmation that the message was saved */
06719             /* commented out since we can't forward batches yet
06720             if (saved_messages == 1)
06721                res = ast_play_and_wait(chan, "vm-message");
06722             else
06723                res = ast_play_and_wait(chan, "vm-messages");
06724             if (!res)
06725                res = ast_play_and_wait(chan, "vm-saved"); */
06726 #ifdef IMAP_STORAGE
06727             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
06728             if (ast_strlen_zero(vmstmp.introfn))
06729 #endif
06730             res = ast_play_and_wait(chan, "vm-msgsaved");
06731          }
06732 #ifndef IMAP_STORAGE
06733          else {
06734             /* with IMAP, mailbox full warning played by imap_check_limits */
06735             res = ast_play_and_wait(chan, "vm-mailboxfull");
06736          }
06737          /* Restore original message without prepended message if backup exists */
06738          make_file(msgfile, sizeof(msgfile), dir, curmsg);
06739          strcpy(textfile, msgfile);
06740          strcpy(backup, msgfile);
06741          strcpy(backup_textfile, msgfile);
06742          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06743          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06744          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06745          if (ast_fileexists(backup, NULL, NULL) > 0) {
06746             ast_filerename(backup, msgfile, NULL);
06747             rename(backup_textfile, textfile);
06748          }
06749 #endif
06750       }
06751       DISPOSE(dir, curmsg);
06752    }
06753 
06754    /* If anything failed above, we still have this list to free */
06755    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
06756       free_user(vmtmp);
06757    return res ? res : cmd;
06758 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1419 of file app_voicemail.c.

References ast_free, ast_test_flag, and VM_ALLOCED.

01420 {
01421    if (ast_test_flag(vmu, VM_ALLOCED))
01422       ast_free(vmu);
01423 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 10470 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10471 {
10472    struct ast_vm_user *current;
10473    AST_LIST_LOCK(&users);
10474    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
10475       ast_set_flag(current, VM_ALLOCED);
10476       free_user(current);
10477    }
10478    AST_LIST_UNLOCK(&users);
10479 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 10482 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10483 {
10484    struct vm_zone *zcur;
10485    AST_LIST_LOCK(&zones);
10486    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
10487       free_zone(zcur);
10488    AST_LIST_UNLOCK(&zones);
10489 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4570 of file app_voicemail.c.

References ast_free.

04571 {
04572    ast_free(z);
04573 }

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

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

04527 {
04528    struct ast_tm tm;
04529    struct timeval t = ast_tvnow();
04530    
04531    ast_localtime(&t, &tm, "UTC");
04532 
04533    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04534 }

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

References AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_waitfordigit(), chan, ast_channel::language, mbox(), and vm_play_folder_name().

Referenced by get_folder2().

06151 {
06152    int x;
06153    int d;
06154    char fn[PATH_MAX];
06155    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06156    if (d)
06157       return d;
06158    for (x = start; x< 5; x++) {  /* For all folders */
06159       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06160          return d;
06161       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06162       if (d)
06163          return d;
06164       snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
06165       d = vm_play_folder_name(chan, fn);
06166       if (d)
06167          return d;
06168       d = ast_waitfordigit(chan, 500);
06169       if (d)
06170          return d;
06171    }
06172    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06173    if (d)
06174       return d;
06175    d = ast_waitfordigit(chan, 4000);
06176    return d;
06177 }

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

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

Referenced by vm_execmain().

06192 {
06193    int res = 0;
06194    int loops = 0;
06195    res = ast_play_and_wait(chan, fn);  /* Folder name */
06196    while (((res < '0') || (res > '9')) &&
06197          (res != '#') && (res >= 0) &&
06198          loops < 4) {
06199       res = get_folder(chan, 0);
06200       loops++;
06201    }
06202    if (loops == 4) { /* give up */
06203       return '#';
06204    }
06205    return res;
06206 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 10253 of file app_voicemail.c.

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

Referenced by mwi_sub_event_cb().

10254 {
10255    unsigned int len;
10256    struct mwi_sub *mwi_sub;
10257    struct mwi_sub_task *p = datap;
10258 
10259    len = sizeof(*mwi_sub);
10260    if (!ast_strlen_zero(p->mailbox))
10261       len += strlen(p->mailbox);
10262 
10263    if (!ast_strlen_zero(p->context))
10264       len += strlen(p->context) + 1; /* Allow for seperator */
10265 
10266    if (!(mwi_sub = ast_calloc(1, len)))
10267       return -1;
10268 
10269    mwi_sub->uniqueid = p->uniqueid;
10270    if (!ast_strlen_zero(p->mailbox))
10271       strcpy(mwi_sub->mailbox, p->mailbox);
10272 
10273    if (!ast_strlen_zero(p->context)) {
10274       strcat(mwi_sub->mailbox, "@");
10275       strcat(mwi_sub->mailbox, p->context);
10276    }
10277 
10278    AST_RWLIST_WRLOCK(&mwi_subs);
10279    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
10280    AST_RWLIST_UNLOCK(&mwi_subs);
10281    ast_free((void *) p->mailbox);
10282    ast_free((void *) p->context);
10283    ast_free(p);
10284    poll_subscribed_mailbox(mwi_sub);
10285    return 0;
10286 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 10231 of file app_voicemail.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, mwi_sub::entry, mwi_sub_destroy(), and mwi_sub::uniqueid.

Referenced by mwi_unsub_event_cb().

10232 {
10233    struct mwi_sub *mwi_sub;
10234    uint32_t *uniqueid = datap;
10235    
10236    AST_RWLIST_WRLOCK(&mwi_subs);
10237    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
10238       if (mwi_sub->uniqueid == *uniqueid) {
10239          AST_LIST_REMOVE_CURRENT(entry);
10240          break;
10241       }
10242    }
10243    AST_RWLIST_TRAVERSE_SAFE_END
10244    AST_RWLIST_UNLOCK(&mwi_subs);
10245 
10246    if (mwi_sub)
10247       mwi_sub_destroy(mwi_sub);
10248 
10249    ast_free(uniqueid);  
10250    return 0;
10251 }

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

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, load_config(), and ast_cli_entry::usage.

10149 {
10150    switch (cmd) {
10151    case CLI_INIT:
10152       e->command = "voicemail reload";
10153       e->usage =
10154          "Usage: voicemail reload\n"
10155          "       Reload voicemail configuration\n";
10156       return NULL;
10157    case CLI_GENERATE:
10158       return NULL;
10159    }
10160 
10161    if (a->argc != 2)
10162       return CLI_SHOWUSAGE;
10163 
10164    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
10165    load_config(1);
10166    
10167    return CLI_SUCCESS;
10168 }

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

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

10039 {
10040    struct ast_vm_user *vmu;
10041 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
10042    const char *context = NULL;
10043    int users_counter = 0;
10044 
10045    switch (cmd) {
10046    case CLI_INIT:
10047       e->command = "voicemail show users";
10048       e->usage =
10049          "Usage: voicemail show users [for <context>]\n"
10050          "       Lists all mailboxes currently set up\n";
10051       return NULL;
10052    case CLI_GENERATE:
10053       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10054    }  
10055 
10056    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10057       return CLI_SHOWUSAGE;
10058    if (a->argc == 5) {
10059       if (strcmp(a->argv[3],"for"))
10060          return CLI_SHOWUSAGE;
10061       context = a->argv[4];
10062    }
10063 
10064    if (ast_check_realtime("voicemail")) {
10065       if (!context) {
10066          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10067          return CLI_SHOWUSAGE;
10068       }
10069       return show_users_realtime(a->fd, context);
10070    }
10071 
10072    AST_LIST_LOCK(&users);
10073    if (AST_LIST_EMPTY(&users)) {
10074       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10075       AST_LIST_UNLOCK(&users);
10076       return CLI_FAILURE;
10077    }
10078    if (a->argc == 3)
10079       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10080    else {
10081       int count = 0;
10082       AST_LIST_TRAVERSE(&users, vmu, list) {
10083          if (!strcmp(context, vmu->context))
10084             count++;
10085       }
10086       if (count) {
10087          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10088       } else {
10089          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10090          AST_LIST_UNLOCK(&users);
10091          return CLI_FAILURE;
10092       }
10093    }
10094    AST_LIST_TRAVERSE(&users, vmu, list) {
10095       int newmsgs = 0, oldmsgs = 0;
10096       char count[12], tmp[256] = "";
10097 
10098       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10099          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10100          inboxcount(tmp, &newmsgs, &oldmsgs);
10101          snprintf(count, sizeof(count), "%d", newmsgs);
10102          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10103          users_counter++;
10104       }
10105    }
10106    AST_LIST_UNLOCK(&users);
10107    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10108    return CLI_SUCCESS;
10109 }

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

References ast_cli_args::argc, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HVSZ_OUTPUT_FORMAT, vm_zone::list, vm_zone::msg_format, vm_zone::name, vm_zone::timezone, and ast_cli_entry::usage.

10113 {
10114    struct vm_zone *zone;
10115 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10116    char *res = CLI_SUCCESS;
10117 
10118    switch (cmd) {
10119    case CLI_INIT:
10120       e->command = "voicemail show zones";
10121       e->usage =
10122          "Usage: voicemail show zones\n"
10123          "       Lists zone message formats\n";
10124       return NULL;
10125    case CLI_GENERATE:
10126       return NULL;
10127    }
10128 
10129    if (a->argc != 3)
10130       return CLI_SHOWUSAGE;
10131 
10132    AST_LIST_LOCK(&zones);
10133    if (!AST_LIST_EMPTY(&zones)) {
10134       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10135       AST_LIST_TRAVERSE(&zones, zone, list) {
10136          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10137       }
10138    } else {
10139       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10140       res = CLI_FAILURE;
10141    }
10142    AST_LIST_UNLOCK(&zones);
10143 
10144    return res;
10145 }

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

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

04907 {
04908    char tmp[256], *tmp2 = tmp, *box, *context;
04909    ast_copy_string(tmp, mailbox, sizeof(tmp));
04910    if (ast_strlen_zero(folder)) {
04911       folder = "INBOX";
04912    }
04913    while ((box = strsep(&tmp2, ",&"))) {
04914       if ((context = strchr(box, '@')))
04915          *context++ = '\0';
04916       else
04917          context = "default";
04918       if (__has_voicemail(context, box, folder, 1))
04919          return 1;
04920       /* If we are checking INBOX, we should check Urgent as well */
04921       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
04922          return 1;
04923       }
04924    }
04925    return 0;
04926 }

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

Definition at line 4988 of file app_voicemail.c.

References inboxcount2().

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

04989 {
04990    int urgentmsgs = 0;
04991    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
04992    if (newmsgs) {
04993       *newmsgs += urgentmsgs;
04994    }
04995    return res;
04996 }

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

Definition at line 4929 of file app_voicemail.c.

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

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

04930 {
04931    char tmp[256];
04932    char *context;
04933 
04934    /* If no mailbox, return immediately */
04935    if (ast_strlen_zero(mailbox))
04936       return 0;
04937 
04938    if (newmsgs)
04939       *newmsgs = 0;
04940    if (oldmsgs)
04941       *oldmsgs = 0;
04942    if (urgentmsgs)
04943       *urgentmsgs = 0;
04944 
04945    if (strchr(mailbox, ',')) {
04946       int tmpnew, tmpold, tmpurgent;
04947       char *mb, *cur;
04948 
04949       ast_copy_string(tmp, mailbox, sizeof(tmp));
04950       mb = tmp;
04951       while ((cur = strsep(&mb, ", "))) {
04952          if (!ast_strlen_zero(cur)) {
04953             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
04954                return -1;
04955             else {
04956                if (newmsgs)
04957                   *newmsgs += tmpnew; 
04958                if (oldmsgs)
04959                   *oldmsgs += tmpold;
04960                if (urgentmsgs)
04961                   *urgentmsgs += tmpurgent;
04962             }
04963          }
04964       }
04965       return 0;
04966    }
04967 
04968    ast_copy_string(tmp, mailbox, sizeof(tmp));
04969    
04970    if ((context = strchr(tmp, '@')))
04971       *context++ = '\0';
04972    else
04973       context = "default";
04974 
04975    if (newmsgs)
04976       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
04977    if (oldmsgs)
04978       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
04979    if (urgentmsgs)
04980       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
04981 
04982    return 0;
04983 }

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

utility used by inchar(), for base_encode()

Definition at line 3762 of file app_voicemail.c.

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

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

03763 {
03764    int l;
03765 
03766    if (bio->ateof)
03767       return 0;
03768 
03769    if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
03770       if (ferror(fi))
03771          return -1;
03772 
03773       bio->ateof = 1;
03774       return 0;
03775    }
03776 
03777    bio->iolen= l;
03778    bio->iocp= 0;
03779 
03780    return 1;
03781 }

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

utility used by base_encode()

Definition at line 3786 of file app_voicemail.c.

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

Referenced by base_encode().

03787 {
03788    if (bio->iocp>=bio->iolen) {
03789       if (!inbuf(bio, fi))
03790          return EOF;
03791    }
03792 
03793    return bio->iobuf[bio->iocp++];
03794 }

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

Definition at line 740 of file app_voicemail.c.

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

Referenced by load_module().

00741 {
00742    struct inprocess *i = obj, *j = arg;
00743    if (!strcmp(i->mailbox, j->mailbox)) {
00744       return 0;
00745    }
00746    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00747 }

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

Definition at line 749 of file app_voicemail.c.

References ao2_alloc, ao2_find, ao2_link, ao2_lock(), ao2_ref, ao2_unlock(), ast_atomic_fetchadd_int(), inprocess::count, and inprocess_container.

Referenced by copy_message(), and leave_voicemail().

00750 {
00751    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00752    arg->context = arg->mailbox + strlen(mailbox) + 1;
00753    strcpy(arg->mailbox, mailbox); /* SAFE */
00754    strcpy(arg->context, context); /* SAFE */
00755    ao2_lock(inprocess_container);
00756    if ((i = ao2_find(inprocess_container, arg, 0))) {
00757       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00758       ao2_unlock(inprocess_container);
00759       ao2_ref(i, -1);
00760       return ret;
00761    }
00762    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00763       ao2_unlock(inprocess_container);
00764       return 0;
00765    }
00766    i->context = i->mailbox + strlen(mailbox) + 1;
00767    strcpy(i->mailbox, mailbox); /* SAFE */
00768    strcpy(i->context, context); /* SAFE */
00769    i->count = delta;
00770    ao2_link(inprocess_container, i);
00771    ao2_unlock(inprocess_container);
00772    ao2_ref(i, -1);
00773    return 0;
00774 }

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

Definition at line 734 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

00735 {
00736    const struct inprocess *i = obj;
00737    return atoi(i->mailbox);
00738 }

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

Definition at line 4536 of file app_voicemail.c.

References ast_fileexists(), ast_log(), ast_say_digit_str(), ast_stream_and_wait(), chan, create_dirpath(), DISPOSE, ast_channel::language, and RETRIEVE.

04537 {
04538    int res;
04539    char fn[PATH_MAX];
04540    char dest[PATH_MAX];
04541 
04542    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04543 
04544    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04545       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04546       return -1;
04547    }
04548 
04549    RETRIEVE(fn, -1, ext, context);
04550    if (ast_fileexists(fn, NULL, NULL) > 0) {
04551       res = ast_stream_and_wait(chan, fn, ecodes);
04552       if (res) {
04553          DISPOSE(fn, -1);
04554          return res;
04555       }
04556    } else {
04557       /* Dispose just in case */
04558       DISPOSE(fn, -1);
04559       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04560       if (res)
04561          return res;
04562       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04563       if (res)
04564          return res;
04565    }
04566    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04567    return res;
04568 }

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

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

Referenced by load_config().

01118 {
01119    int i;
01120    char *local_key = ast_strdupa(key);
01121 
01122    for (i = 0; i < strlen(key); ++i) {
01123       if (!strchr(VALID_DTMF, *local_key)) {
01124          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01125          return 0;
01126       }
01127       local_key++;
01128    }
01129    return 1;
01130 }

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

References map, ast_vm_user::maxmsg, and MAXMSGLIMIT.

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

03589 {
03590    int x;
03591    unsigned char map[MAXMSGLIMIT] = "";
03592    DIR *msgdir;
03593    struct dirent *msgdirent;
03594    int msgdirint;
03595 
03596    /* Reading the entire directory into a file map scales better than
03597     * doing a stat repeatedly on a predicted sequence.  I suspect this
03598     * is partially due to stat(2) internally doing a readdir(2) itself to
03599     * find each file. */
03600    if (!(msgdir = opendir(dir))) {
03601       return -1;
03602    }
03603 
03604    while ((msgdirent = readdir(msgdir))) {
03605       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03606          map[msgdirint] = 1;
03607    }
03608    closedir(msgdir);
03609 
03610    for (x = 0; x < vmu->maxmsg; x++) {
03611       if (map[x] == 0)
03612          break;
03613    }
03614 
03615    return x - 1;
03616 }

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 5061 of file app_voicemail.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_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_verbose, ast_waitstream(), chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, 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(), get_date(), inboxcount(), inprocess_count(), INTRO, invent_message(), ast_channel::language, last_message_index(), ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_channel::name, vm_state::newmessages, notify_new_message(), OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, RENAME, RETRIEVE, S_OR, SENTINEL, STORE, strsep(), transfer, VERBOSE_PREFIX_3, vm_lock_path(), VM_OPERATOR, and VOICEMAIL_FILE_MODE.

05062 {
05063 #ifdef IMAP_STORAGE
05064    int newmsgs, oldmsgs;
05065 #else
05066    char urgdir[PATH_MAX];
05067 #endif
05068    char txtfile[PATH_MAX];
05069    char tmptxtfile[PATH_MAX];
05070    struct vm_state *vms = NULL;
05071    char callerid[256];
05072    FILE *txt;
05073    char date[256];
05074    int txtdes;
05075    int res = 0;
05076    int msgnum;
05077    int duration = 0;
05078    int ausemacro = 0;
05079    int ousemacro = 0;
05080    int ouseexten = 0;
05081    int rtmsgid = 0;
05082    char tmpid[16];
05083    char tmpdur[16];
05084    char priority[16];
05085    char origtime[16];
05086    char dir[PATH_MAX];
05087    char tmpdir[PATH_MAX];
05088    char fn[PATH_MAX];
05089    char prefile[PATH_MAX] = "";
05090    char tempfile[PATH_MAX] = "";
05091    char ext_context[256] = "";
05092    char fmt[80];
05093    char *context;
05094    char ecodes[17] = "#";
05095    struct ast_str *tmp = ast_str_create(16);
05096    char *tmpptr;
05097    struct ast_vm_user *vmu;
05098    struct ast_vm_user svm;
05099    const char *category = NULL;
05100    const char *code;
05101    const char *alldtmf = "0123456789ABCD*#";
05102    char flag[80];
05103 
05104    ast_str_set(&tmp, 0, "%s", ext);
05105    ext = ast_str_buffer(tmp);
05106    if ((context = strchr(ext, '@'))) {
05107       *context++ = '\0';
05108       tmpptr = strchr(context, '&');
05109    } else {
05110       tmpptr = strchr(ext, '&');
05111    }
05112 
05113    if (tmpptr)
05114       *tmpptr++ = '\0';
05115 
05116    ast_channel_lock(chan);
05117    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
05118       category = ast_strdupa(category);
05119    }
05120    ast_channel_unlock(chan);
05121 
05122    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
05123       ast_copy_string(flag, "Urgent", sizeof(flag));
05124    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
05125       ast_copy_string(flag, "PRIORITY", sizeof(flag));
05126    } else {
05127       flag[0] = '\0';
05128    }
05129 
05130    ast_debug(3, "Before find_user\n");
05131    if (!(vmu = find_user(&svm, context, ext))) {
05132       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
05133       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05134       ast_free(tmp);
05135       return res;
05136    }
05137    /* Setup pre-file if appropriate */
05138    if (strcmp(vmu->context, "default"))
05139       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
05140    else
05141       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
05142 
05143    /* Set the path to the prefile. Will be one of 
05144       VM_SPOOL_DIRcontext/ext/busy
05145       VM_SPOOL_DIRcontext/ext/unavail
05146       Depending on the flag set in options.
05147    */
05148    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
05149       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
05150    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
05151       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
05152    }
05153    /* Set the path to the tmpfile as
05154       VM_SPOOL_DIR/context/ext/temp
05155       and attempt to create the folder structure.
05156    */
05157    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
05158    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
05159       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
05160       ast_free(tmp);
05161       return -1;
05162    }
05163    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
05164    if (ast_fileexists(tempfile, NULL, NULL) > 0)
05165       ast_copy_string(prefile, tempfile, sizeof(prefile));
05166 
05167    DISPOSE(tempfile, -1);
05168    /* It's easier just to try to make it than to check for its existence */
05169    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
05170 
05171    /* Check current or macro-calling context for special extensions */
05172    if (ast_test_flag(vmu, VM_OPERATOR)) {
05173       if (!ast_strlen_zero(vmu->exit)) {
05174          if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
05175             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05176             ouseexten = 1;
05177          }
05178       } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
05179          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05180          ouseexten = 1;
05181       } else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
05182          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05183          ousemacro = 1;
05184       }
05185    }
05186 
05187    if (!ast_strlen_zero(vmu->exit)) {
05188       if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
05189          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05190    } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
05191       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05192    else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
05193       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05194       ausemacro = 1;
05195    }
05196 
05197    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05198       for (code = alldtmf; *code; code++) {
05199          char e[2] = "";
05200          e[0] = *code;
05201          if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num))
05202             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05203       }
05204    }
05205 
05206    /* Play the beginning intro if desired */
05207    if (!ast_strlen_zero(prefile)) {
05208 #ifdef ODBC_STORAGE
05209       int success = 
05210 #endif
05211          RETRIEVE(prefile, -1, ext, context);
05212       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05213          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05214             res = ast_waitstream(chan, ecodes);
05215 #ifdef ODBC_STORAGE
05216          if (success == -1) {
05217             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05218             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05219             store_file(prefile, vmu->mailbox, vmu->context, -1);
05220          }
05221 #endif
05222       } else {
05223          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05224          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05225       }
05226       DISPOSE(prefile, -1);
05227       if (res < 0) {
05228          ast_debug(1, "Hang up during prefile playback\n");
05229          free_user(vmu);
05230          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05231          ast_free(tmp);
05232          return -1;
05233       }
05234    }
05235    if (res == '#') {
05236       /* On a '#' we skip the instructions */
05237       ast_set_flag(options, OPT_SILENT);
05238       res = 0;
05239    }
05240    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05241       res = ast_stream_and_wait(chan, INTRO, ecodes);
05242       if (res == '#') {
05243          ast_set_flag(options, OPT_SILENT);
05244          res = 0;
05245       }
05246    }
05247    if (res > 0)
05248       ast_stopstream(chan);
05249    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05250     other than the operator -- an automated attendant or mailbox login for example */
05251    if (res == '*') {
05252       chan->exten[0] = 'a';
05253       chan->exten[1] = '\0';
05254       if (!ast_strlen_zero(vmu->exit)) {
05255          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05256       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05257          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05258       }
05259       chan->priority = 0;
05260       free_user(vmu);
05261       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05262       ast_free(tmp);
05263       return 0;
05264    }
05265 
05266    /* Check for a '0' here */
05267    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05268    transfer:
05269       if (ouseexten || ousemacro) {
05270          chan->exten[0] = 'o';
05271          chan->exten[1] = '\0';
05272          if (!ast_strlen_zero(vmu->exit)) {
05273             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05274          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05275             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05276          }
05277          ast_play_and_wait(chan, "transfer");
05278          chan->priority = 0;
05279          free_user(vmu);
05280          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05281       }
05282       ast_free(tmp);
05283       return OPERATOR_EXIT;
05284    }
05285 
05286    /* Allow all other digits to exit Voicemail and return to the dialplan */
05287    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05288       if (!ast_strlen_zero(options->exitcontext))
05289          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05290       free_user(vmu);
05291       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05292       ast_free(tmp);
05293       return res;
05294    }
05295 
05296    if (res < 0) {
05297       free_user(vmu);
05298       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05299       ast_free(tmp);
05300       return -1;
05301    }
05302    /* The meat of recording the message...  All the announcements and beeps have been played*/
05303    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05304    if (!ast_strlen_zero(fmt)) {
05305       msgnum = 0;
05306 
05307 #ifdef IMAP_STORAGE
05308       /* Is ext a mailbox? */
05309       /* must open stream for this user to get info! */
05310       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05311       if (res < 0) {
05312          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05313          ast_free(tmp);
05314          return -1;
05315       }
05316       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05317       /* It is possible under certain circumstances that inboxcount did not
05318        * create a vm_state when it was needed. This is a catchall which will
05319        * rarely be used.
05320        */
05321          if (!(vms = create_vm_state_from_user(vmu))) {
05322             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05323             ast_free(tmp);
05324             return -1;
05325          }
05326       }
05327       vms->newmessages++;
05328       
05329       /* here is a big difference! We add one to it later */
05330       msgnum = newmsgs + oldmsgs;
05331       ast_debug(3, "Messagecount set to %d\n",msgnum);
05332       snprintf(fn, sizeof(fn), "%s/imap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05333       /* set variable for compatibility */
05334       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05335 
05336       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
05337          goto leave_vm_out;
05338       }
05339 #else
05340       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
05341          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05342          if (!res)
05343             res = ast_waitstream(chan, "");
05344          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05345          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05346          inprocess_count(vmu->mailbox, vmu->context, -1);
05347          goto leave_vm_out;
05348       }
05349 
05350 #endif
05351       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05352       txtdes = mkstemp(tmptxtfile);
05353       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05354       if (txtdes < 0) {
05355          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05356          if (!res)
05357             res = ast_waitstream(chan, "");
05358          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05359          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05360          inprocess_count(vmu->mailbox, vmu->context, -1);
05361          goto leave_vm_out;
05362       }
05363 
05364       /* Now play the beep once we have the message number for our next message. */
05365       if (res >= 0) {
05366          /* Unless we're *really* silent, try to send the beep */
05367          res = ast_stream_and_wait(chan, "beep", "");
05368       }
05369             
05370       /* Store information in real-time storage */
05371       if (ast_check_realtime("voicemail_data")) {
05372          snprintf(priority, sizeof(priority), "%d", chan->priority);
05373          snprintf(origtime, sizeof(origtime), "%ld", (long)time(NULL));
05374          get_date(date, sizeof(date));
05375          rtmsgid = ast_store_realtime("voicemail_data", "origmailbox", ext, "context", chan->context, "macrocontext", chan->macrocontext, "exten", chan->exten, "priority", priority, "callerchan", chan->name, "callerid", ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"), "origdate", date, "origtime", origtime, "category", S_OR(category,""), SENTINEL);
05376       }
05377 
05378       /* Store information */
05379       txt = fdopen(txtdes, "w+");
05380       if (txt) {
05381          get_date(date, sizeof(date));
05382          fprintf(txt, 
05383             ";\n"
05384             "; Message Information file\n"
05385             ";\n"
05386             "[message]\n"
05387             "origmailbox=%s\n"
05388             "context=%s\n"
05389             "macrocontext=%s\n"
05390             "exten=%s\n"
05391             "priority=%d\n"
05392             "callerchan=%s\n"
05393             "callerid=%s\n"
05394             "origdate=%s\n"
05395             "origtime=%ld\n"
05396             "category=%s\n",
05397             ext,
05398             chan->context,
05399             chan->macrocontext, 
05400             chan->exten,
05401             chan->priority,
05402             chan->name,
05403             ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
05404             date, (long)time(NULL),
05405             category ? category : "");
05406       } else {
05407          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
05408          inprocess_count(vmu->mailbox, vmu->context, -1);
05409          if (ast_check_realtime("voicemail_data")) {
05410             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05411          }
05412          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05413          goto leave_vm_out;
05414       }
05415       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms, flag);
05416 
05417       if (txt) {
05418          fprintf(txt, "flag=%s\n", flag);
05419          if (duration < vmminsecs) {
05420             fclose(txt);
05421             if (option_verbose > 2) 
05422                ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminsecs);
05423             ast_filedelete(tmptxtfile, NULL);
05424             unlink(tmptxtfile);
05425             if (ast_check_realtime("voicemail_data")) {
05426                snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
05427                ast_destroy_realtime("voicemail_data", "id", tmpid, SENTINEL);
05428             }
05429             inprocess_count(vmu->mailbox, vmu->context, -1);
05430          } else {
05431             fprintf(txt, "duration=%d\n", duration);
05432             fclose(txt);
05433             if (vm_lock_path(dir)) {
05434                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
05435                /* Delete files */
05436                ast_filedelete(tmptxtfile, NULL);
05437                unlink(tmptxtfile);
05438                inprocess_count(vmu->mailbox, vmu->context, -1);
05439             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
05440                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
05441                unlink(tmptxtfile);
05442                ast_unlock_path(dir);
05443                inprocess_count(vmu->mailbox, vmu->context, -1);
05444                if (ast_check_realtime("voicemail_data")) {
05445                   snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
05446                   ast_destroy_realtime("voicemail_data", "id", tmpid, SENTINEL);
05447                }
05448             } else {
05449 #ifndef IMAP_STORAGE
05450                msgnum = last_message_index(vmu, dir) + 1;
05451 #endif
05452                make_file(fn, sizeof(fn), dir, msgnum);
05453 
05454                /* assign a variable with the name of the voicemail file */ 
05455 #ifndef IMAP_STORAGE
05456                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
05457 #else
05458                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05459 #endif
05460 
05461                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
05462                ast_filerename(tmptxtfile, fn, NULL);
05463                rename(tmptxtfile, txtfile);
05464                inprocess_count(vmu->mailbox, vmu->context, -1);
05465 
05466                /* Properly set permissions on voicemail text descriptor file.
05467                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
05468                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
05469                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
05470 
05471                ast_unlock_path(dir);
05472                if (ast_check_realtime("voicemail_data")) {
05473                   snprintf(tmpid, sizeof(tmpid), "%d", rtmsgid);
05474                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
05475                   ast_update_realtime("voicemail_data", "id", tmpid, "filename", fn, "duration", tmpdur, SENTINEL);
05476                }
05477                /* We must store the file first, before copying the message, because
05478                 * ODBC storage does the entire copy with SQL.
05479                 */
05480                if (ast_fileexists(fn, NULL, NULL) > 0) {
05481                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
05482                }
05483 
05484                /* Are there to be more recipients of this message? */
05485                while (tmpptr) {
05486                   struct ast_vm_user recipu, *recip;
05487                   char *exten, *cntx;
05488                
05489                   exten = strsep(&tmpptr, "&");
05490                   cntx = strchr(exten, '@');
05491                   if (cntx) {
05492                      *cntx = '\0';
05493                      cntx++;
05494                   }
05495                   if ((recip = find_user(&recipu, cntx, exten))) {
05496                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
05497                      free_user(recip);
05498                   }
05499                }
05500 #ifndef IMAP_STORAGE
05501                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
05502                   /* Move the message from INBOX to Urgent folder if this is urgent! */
05503                   char sfn[PATH_MAX];
05504                   char dfn[PATH_MAX];
05505                   int x;
05506                   /* It's easier just to try to make it than to check for its existence */
05507                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
05508                   x = last_message_index(vmu, urgdir) + 1;
05509                   make_file(sfn, sizeof(sfn), dir, msgnum);
05510                   make_file(dfn, sizeof(dfn), urgdir, x);
05511                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
05512                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
05513                   /* Notification must happen for this new message in Urgent folder, not INBOX */
05514                   ast_copy_string(fn, dfn, sizeof(fn));
05515                   msgnum = x;
05516                }
05517 #endif
05518                /* Notification needs to happen after the copy, though. */
05519                if (ast_fileexists(fn, NULL, NULL)) {
05520 #ifdef IMAP_STORAGE
05521                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
05522 #else
05523                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
05524 #endif
05525                }
05526 
05527                /* Disposal needs to happen after the optional move and copy */
05528                if (ast_fileexists(fn, NULL, NULL)) {
05529                   DISPOSE(dir, msgnum);
05530                }
05531             }
05532          }
05533       } else {
05534          inprocess_count(vmu->mailbox, vmu->context, -1);
05535       }
05536       if (res == '0') {
05537          goto transfer;
05538       } else if (res > 0)
05539          res = 0;
05540 
05541       if (duration < vmminsecs)
05542          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
05543          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05544       else
05545          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05546    } else
05547       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
05548 leave_vm_out:
05549    free_user(vmu);
05550 
05551 #ifdef IMAP_STORAGE
05552    /* expunge message - use UID Expunge if supported on IMAP server*/
05553    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n",expungeonhangup);
05554    if (expungeonhangup == 1) {
05555       ast_mutex_lock(&vms->lock);
05556 #ifdef HAVE_IMAP_TK2006
05557       if (LEVELUIDPLUS (vms->mailstream)) {
05558          mail_expunge_full(vms->mailstream,NIL,EX_UID);
05559       } else 
05560 #endif
05561          mail_expunge(vms->mailstream);
05562       ast_mutex_unlock(&vms->lock);
05563    }
05564 #endif
05565 
05566    ast_free(tmp);
05567    return res;
05568 }

static int load_config ( int  reload  )  [static]

Definition at line 10536 of file app_voicemail.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_unload_realtime(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), vm_zone::list, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, LOG_ERROR, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, pagerbody, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, saydurationminfo, SENDMAIL, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, var, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, and VOICEMAIL_CONFIG.

10537 {
10538    struct ast_vm_user *current;
10539    struct ast_config *cfg, *ucfg;
10540    char *cat;
10541    struct ast_variable *var;
10542    const char *val;
10543    char *q, *stringp, *tmp;
10544    int x;
10545    int tmpadsi[4];
10546    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10547 
10548    ast_unload_realtime("voicemail");
10549    ast_unload_realtime("voicemail_data");
10550 
10551    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
10552       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
10553          return 0;
10554       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
10555       cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
10556    } else {
10557       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
10558       ucfg = ast_config_load("users.conf", config_flags);
10559    }
10560 #ifdef IMAP_STORAGE
10561    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
10562 #endif
10563    /* set audio control prompts */
10564    strcpy(listen_control_forward_key,DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
10565    strcpy(listen_control_reverse_key,DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
10566    strcpy(listen_control_pause_key,DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
10567    strcpy(listen_control_restart_key,DEFAULT_LISTEN_CONTROL_RESTART_KEY);
10568    strcpy(listen_control_stop_key,DEFAULT_LISTEN_CONTROL_STOP_KEY);
10569 
10570    /* Free all the users structure */  
10571    free_vm_users();
10572 
10573    /* Free all the zones structure */
10574    free_vm_zones();
10575 
10576    AST_LIST_LOCK(&users);  
10577 
10578    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
10579    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
10580 
10581    if (cfg) {
10582       /* General settings */
10583 
10584       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
10585          val = "default";
10586       ast_copy_string(userscontext, val, sizeof(userscontext));
10587       /* Attach voice message to mail message ? */
10588       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
10589          val = "yes";
10590       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
10591 
10592       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
10593          val = "no";
10594       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
10595 
10596       volgain = 0.0;
10597       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
10598          sscanf(val, "%30lf", &volgain);
10599 
10600 #ifdef ODBC_STORAGE
10601       strcpy(odbc_database, "asterisk");
10602       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
10603          ast_copy_string(odbc_database, val, sizeof(odbc_database));
10604       }
10605       strcpy(odbc_table, "voicemessages");
10606       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
10607          ast_copy_string(odbc_table, val, sizeof(odbc_table));
10608       }
10609 #endif      
10610       /* Mail command */
10611       strcpy(mailcmd, SENDMAIL);
10612       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
10613          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
10614 
10615       maxsilence = 0;
10616       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
10617          maxsilence = atoi(val);
10618          if (maxsilence > 0)
10619             maxsilence *= 1000;
10620       }
10621       
10622       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
10623          maxmsg = MAXMSG;
10624       } else {
10625          maxmsg = atoi(val);
10626          if (maxmsg <= 0) {
10627             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
10628             maxmsg = MAXMSG;
10629          } else if (maxmsg > MAXMSGLIMIT) {
10630             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
10631             maxmsg = MAXMSGLIMIT;
10632          }
10633       }
10634 
10635       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
10636          maxdeletedmsg = 0;
10637       } else {
10638          if (sscanf(val, "%30d", &x) == 1)
10639             maxdeletedmsg = x;
10640          else if (ast_true(val))
10641             maxdeletedmsg = MAXMSG;
10642          else
10643             maxdeletedmsg = 0;
10644 
10645          if (maxdeletedmsg < 0) {
10646             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
10647             maxdeletedmsg = MAXMSG;
10648          } else if (maxdeletedmsg > MAXMSGLIMIT) {
10649             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
10650             maxdeletedmsg = MAXMSGLIMIT;
10651          }
10652       }
10653 
10654       /* Load date format config for voicemail mail */
10655       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
10656          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
10657       }
10658 
10659       /* External password changing command */
10660       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
10661          ast_copy_string(ext_pass_cmd,val,sizeof(ext_pass_cmd));
10662          pwdchange = PWDCHANGE_EXTERNAL;
10663       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
10664          ast_copy_string(ext_pass_cmd,val,sizeof(ext_pass_cmd));
10665          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
10666       }
10667  
10668       /* External password validation command */
10669       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
10670          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
10671          ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
10672       }
10673 
10674 #ifdef IMAP_STORAGE
10675       /* IMAP server address */
10676       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
10677          ast_copy_string(imapserver, val, sizeof(imapserver));
10678       } else {
10679          ast_copy_string(imapserver,"localhost", sizeof(imapserver));
10680       }
10681       /* IMAP server port */
10682       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
10683          ast_copy_string(imapport, val, sizeof(imapport));
10684       } else {
10685          ast_copy_string(imapport,"143", sizeof(imapport));
10686       }
10687       /* IMAP server flags */
10688       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
10689          ast_copy_string(imapflags, val, sizeof(imapflags));
10690       }
10691       /* IMAP server master username */
10692       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
10693          ast_copy_string(authuser, val, sizeof(authuser));
10694       }
10695       /* IMAP server master password */
10696       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
10697          ast_copy_string(authpassword, val, sizeof(authpassword));
10698       }
10699       /* Expunge on exit */
10700       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
10701          if (ast_false(val))
10702             expungeonhangup = 0;
10703          else
10704             expungeonhangup = 1;
10705       } else {
10706          expungeonhangup = 1;
10707       }
10708       /* IMAP voicemail folder */
10709       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
10710          ast_copy_string(imapfolder, val, sizeof(imapfolder));
10711       } else {
10712          ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder));
10713       }
10714       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
10715          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
10716       }
10717       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
10718          imapgreetings = ast_true(val);
10719       } else {
10720          imapgreetings = 0;
10721       }
10722       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
10723          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
10724       } else {
10725          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
10726       }
10727 
10728       /* There is some very unorthodox casting done here. This is due
10729        * to the way c-client handles the argument passed in. It expects a 
10730        * void pointer and casts the pointer directly to a long without
10731        * first dereferencing it. */
10732       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
10733          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
10734       } else {
10735          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
10736       }
10737 
10738       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
10739          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
10740       } else {
10741          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
10742       }
10743 
10744       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
10745          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
10746       } else {
10747          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
10748       }
10749 
10750       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
10751          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
10752       } else {
10753          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
10754       }
10755 
10756       /* Increment configuration version */
10757       imapversion++;
10758 #endif
10759       /* External voicemail notify application */
10760       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
10761          ast_copy_string(externnotify, val, sizeof(externnotify));
10762          ast_debug(1, "found externnotify: %s\n", externnotify);
10763       } else {
10764          externnotify[0] = '\0';
10765       }
10766 
10767       /* SMDI voicemail notification */
10768       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
10769          ast_debug(1, "Enabled SMDI voicemail notification\n");
10770          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
10771             smdi_iface = ast_smdi_interface_find ? ast_smdi_interface_find(val) : NULL;
10772          } else {
10773             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
10774             smdi_iface = ast_smdi_interface_find ? ast_smdi_interface_find("/dev/ttyS0") : NULL;
10775          }
10776          if (!smdi_iface) {
10777             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
10778          } 
10779       }
10780 
10781       /* Silence treshold */
10782       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
10783       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
10784          silencethreshold = atoi(val);
10785       
10786       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
10787          val = ASTERISK_USERNAME;
10788       ast_copy_string(serveremail, val, sizeof(serveremail));
10789       
10790       vmmaxsecs = 0;
10791       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
10792          if (sscanf(val, "%30d", &x) == 1) {
10793             vmmaxsecs = x;
10794          } else {
10795             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
10796          }
10797       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
10798          static int maxmessage_deprecate = 0;
10799          if (maxmessage_deprecate == 0) {
10800             maxmessage_deprecate = 1;
10801             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
10802          }
10803          if (sscanf(val, "%30d", &x) == 1) {
10804             vmmaxsecs = x;
10805          } else {
10806             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
10807          }
10808       }
10809 
10810       vmminsecs = 0;
10811       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
10812          if (sscanf(val, "%30d", &x) == 1) {
10813             vmminsecs = x;
10814             if (maxsilence / 1000 >= vmminsecs) {
10815                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
10816             }
10817          } else {
10818             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
10819          }
10820       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
10821          static int maxmessage_deprecate = 0;
10822          if (maxmessage_deprecate == 0) {
10823             maxmessage_deprecate = 1;
10824             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
10825          }
10826          if (sscanf(val, "%30d", &x) == 1) {
10827             vmminsecs = x;
10828             if (maxsilence / 1000 >= vmminsecs) {
10829                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
10830             }
10831          } else {
10832             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
10833          }
10834       }
10835 
10836       val = ast_variable_retrieve(cfg, "general", "format");
10837       if (!val) {
10838          val = "wav";   
10839       } else {
10840          tmp = ast_strdupa(val);
10841          val = ast_format_str_reduce(tmp);
10842          if (!val) {
10843             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
10844             val = "wav";
10845          }
10846       }
10847       ast_copy_string(vmfmts, val, sizeof(vmfmts));
10848 
10849       skipms = 3000;
10850       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
10851          if (sscanf(val, "%30d", &x) == 1) {
10852             maxgreet = x;
10853          } else {
10854             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
10855          }
10856       }
10857 
10858       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
10859          if (sscanf(val, "%30d", &x) == 1) {
10860             skipms = x;
10861          } else {
10862             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
10863          }
10864       }
10865 
10866       maxlogins = 3;
10867       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
10868          if (sscanf(val, "%30d", &x) == 1) {
10869             maxlogins = x;
10870          } else {
10871             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
10872          }
10873       }
10874 
10875       minpassword = MINPASSWORD;
10876       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
10877          if (sscanf(val, "%30d", &x) == 1) {
10878             minpassword = x;
10879          } else {
10880             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
10881          }
10882       }
10883 
10884       /* Force new user to record name ? */
10885       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
10886          val = "no";
10887       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
10888 
10889       /* Force new user to record greetings ? */
10890       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
10891          val = "no";
10892       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
10893 
10894       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
10895          ast_debug(1, "VM_CID Internal context string: %s\n", val);
10896          stringp = ast_strdupa(val);
10897          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
10898             if (!ast_strlen_zero(stringp)) {
10899                q = strsep(&stringp, ",");
10900                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
10901                   q++;
10902                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
10903                ast_debug(1,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
10904             } else {
10905                cidinternalcontexts[x][0] = '\0';
10906             }
10907          }
10908       }
10909       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
10910          ast_debug(1,"VM Review Option disabled globally\n");
10911          val = "no";
10912       }
10913       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
10914 
10915       /* Temporary greeting reminder */
10916       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
10917          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
10918          val = "no";
10919       } else {
10920          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
10921       }
10922       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
10923       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
10924          ast_debug(1, "VM next message wrap disabled globally\n");
10925          val = "no";
10926       }
10927       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);  
10928 
10929       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
10930          ast_debug(1,"VM Operator break disabled globally\n");
10931          val = "no";
10932       }
10933       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
10934 
10935       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
10936          ast_debug(1,"VM CID Info before msg disabled globally\n");
10937          val = "no";
10938       } 
10939       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
10940 
10941       if (!(val = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
10942          ast_debug(1,"Send Voicemail msg disabled globally\n");
10943          val = "no";
10944       }
10945       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
10946    
10947       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
10948          ast_debug(1,"ENVELOPE before msg enabled globally\n");
10949          val = "yes";
10950       }
10951       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
10952 
10953       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
10954          ast_debug(1,"Move Heard enabled globally\n");
10955          val = "yes";
10956       }
10957       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
10958 
10959       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
10960          ast_debug(1,"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
10961          val = "no";
10962       }
10963       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);   
10964 
10965       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
10966          ast_debug(1,"Duration info before msg enabled globally\n");
10967          val = "yes";
10968       }
10969       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
10970 
10971       saydurationminfo = 2;
10972       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
10973          if (sscanf(val, "%30d", &x) == 1) {
10974             saydurationminfo = x;
10975          } else {
10976             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
10977          }
10978       }
10979 
10980       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
10981          ast_debug(1,"We are not going to skip to the next msg after save/delete\n");
10982          val = "no";
10983       }
10984       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
10985 
10986       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
10987          ast_copy_string(dialcontext, val, sizeof(dialcontext));
10988          ast_debug(1, "found dialout context: %s\n", dialcontext);
10989       } else {
10990          dialcontext[0] = '\0';  
10991       }
10992       
10993       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
10994          ast_copy_string(callcontext, val, sizeof(callcontext));
10995          ast_debug(1, "found callback context: %s\n", callcontext);
10996       } else {
10997          callcontext[0] = '\0';
10998       }
10999 
11000       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
11001          ast_copy_string(exitcontext, val, sizeof(exitcontext));
11002          ast_debug(1, "found operator context: %s\n", exitcontext);
11003       } else {
11004          exitcontext[0] = '\0';
11005       }
11006       
11007       /* load password sounds configuration */
11008       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
11009          ast_copy_string(vm_password, val, sizeof(vm_password));
11010       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
11011          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
11012       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
11013          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
11014       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
11015          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
11016       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
11017          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
11018       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
11019          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
11020       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
11021          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
11022       }
11023       /* load configurable audio prompts */
11024       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
11025          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
11026       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
11027          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
11028       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
11029          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
11030       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
11031          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
11032       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
11033          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
11034 
11035       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
11036          val = "no";
11037       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
11038 
11039       poll_freq = DEFAULT_POLL_FREQ;
11040       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
11041          if (sscanf(val, "%30u", &poll_freq) != 1) {
11042             poll_freq = DEFAULT_POLL_FREQ;
11043             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
11044          }
11045       }
11046 
11047       poll_mailboxes = 0;
11048       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
11049          poll_mailboxes = ast_true(val);
11050 
11051       if (ucfg) { 
11052          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
11053             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
11054                continue;
11055             if ((current = find_or_create(userscontext, cat))) {
11056                populate_defaults(current);
11057                apply_options_full(current, ast_variable_browse(ucfg, cat));
11058                ast_copy_string(current->context, userscontext, sizeof(current->context));
11059             }
11060          }
11061          ast_config_destroy(ucfg);
11062       }
11063       cat = ast_category_browse(cfg, NULL);
11064       while (cat) {
11065          if (strcasecmp(cat, "general")) {
11066             var = ast_variable_browse(cfg, cat);
11067             if (strcasecmp(cat, "zonemessages")) {
11068                /* Process mailboxes in this context */
11069                while (var) {
11070                   append_mailbox(cat, var->name, var->value);
11071                   var = var->next;
11072                }
11073             } else {
11074                /* Timezones in this context */
11075                while (var) {
11076                   struct vm_zone *z;
11077                   if ((z = ast_malloc(sizeof(*z)))) {
11078                      char *msg_format, *tzone;
11079                      msg_format = ast_strdupa(var->value);
11080                      tzone = strsep(&msg_format, "|");
11081                      if (msg_format) {
11082                         ast_copy_string(z->name, var->name, sizeof(z->name));
11083                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
11084                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
11085                         AST_LIST_LOCK(&zones);
11086                         AST_LIST_INSERT_HEAD(&zones, z, list);
11087                         AST_LIST_UNLOCK(&zones);
11088                      } else {
11089                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
11090                         ast_free(z);
11091                      }
11092                   } else {
11093                      AST_LIST_UNLOCK(&users);
11094                      ast_config_destroy(cfg);
11095                      return -1;
11096                   }
11097                   var = var->next;
11098                }
11099             }
11100          }
11101          cat = ast_category_browse(cfg, cat);
11102       }
11103       memset(fromstring, 0, sizeof(fromstring));
11104       memset(pagerfromstring, 0, sizeof(pagerfromstring));
11105       strcpy(charset, "ISO-8859-1");
11106       if (emailbody) {
11107          ast_free(emailbody);
11108          emailbody = NULL;
11109       }
11110       if (emailsubject) {
11111          ast_free(emailsubject);
11112          emailsubject = NULL;
11113       }
11114       if (pagerbody) {
11115          ast_free(pagerbody);
11116          pagerbody = NULL;
11117       }
11118       if (pagersubject) {
11119          ast_free(pagersubject);
11120          pagersubject = NULL;
11121       }
11122       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
11123          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
11124       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
11125          ast_copy_string(fromstring, val, sizeof(fromstring));
11126       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
11127          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
11128       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
11129          ast_copy_string(charset, val, sizeof(charset));
11130       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
11131          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
11132          for (x = 0; x < 4; x++) {
11133             memcpy(&adsifdn[x], &tmpadsi[x], 1);
11134          }
11135       }
11136       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
11137          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
11138          for (x = 0; x < 4; x++) {
11139             memcpy(&adsisec[x], &tmpadsi[x], 1);
11140          }
11141       }
11142       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
11143          if (atoi(val)) {
11144             adsiver = atoi(val);
11145          }
11146       }
11147       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
11148          ast_copy_string(zonetag, val, sizeof(zonetag));
11149       }
11150       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
11151          emailsubject = ast_strdup(val);
11152       }
11153       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
11154          emailbody = substitute_escapes(val);
11155       }
11156       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
11157          pagersubject = ast_strdup(val);
11158       }
11159       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
11160          pagerbody = substitute_escapes(val);
11161       }
11162       AST_LIST_UNLOCK(&users);
11163       ast_config_destroy(cfg);
11164 
11165       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
11166          start_poll_thread();
11167       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
11168          stop_poll_thread();;
11169 
11170       return 0;
11171    } else {
11172       AST_LIST_UNLOCK(&users);
11173       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
11174       if (ucfg)
11175          ast_config_destroy(ucfg);
11176       return 0;
11177    }
11178 }

static int load_module ( void   )  [static]

Definition at line 11225 of file app_voicemail.c.

References ao2_container_alloc, ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_install_vm_functions(), ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application, ast_taskprocessor_get(), cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), inprocess_cmp_fn(), inprocess_container, inprocess_hash_fn(), load_config(), mailbox_exists_acf, manager_list_voicemail_users(), messagecount(), mwi_subscription_tps, RQ_CHAR, RQ_UINTEGER3, sayname(), SENTINEL, vm_box_exists(), vm_exec(), vm_execmain(), and vmauthenticate().

11226 {
11227    int res;
11228    my_umask = umask(0);
11229    umask(my_umask);
11230 
11231    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
11232       return AST_MODULE_LOAD_DECLINE;
11233    }
11234 
11235    /* compute the location of the voicemail spool directory */
11236    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
11237    
11238    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
11239       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
11240    }
11241 
11242    if ((res = load_config(0)))
11243       return res;
11244 
11245    res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
11246    res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
11247    res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
11248    res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
11249    res |= ast_custom_function_register(&mailbox_exists_acf);
11250    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
11251    if (res)
11252       return res;
11253 
11254    ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
11255 
11256    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
11257    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
11258    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
11259 
11260    return res;
11261 }

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.
The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1339 of file app_voicemail.c.

01340 {
01341    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01342 }

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

References add_email_attachment(), ast_channel_alloc, ast_channel_free(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_localtime(), ast_log(), ast_random(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), chan, charset, check_mime(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, ast_vm_user::email, emailbody, emaildateformat, emailsubject, encode_mime_str(), ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, ast_channel::name, ast_channel::next, pbx_substitute_variables_helper(), prep_email_sub_vars(), ast_channel::priority, quote(), strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

04074 {
04075    char date[256];
04076    char host[MAXHOSTNAMELEN] = "";
04077    char who[256];
04078    char bound[256];
04079    char dur[256];
04080    struct ast_tm tm;
04081    char enc_cidnum[256] = "", enc_cidname[256] = "";
04082    char *passdata = NULL, *passdata2;
04083    size_t len_passdata = 0, len_passdata2, tmplen;
04084    char *greeting_attachment; 
04085    char filename[256];
04086 
04087 
04088    /* One alloca for multiple fields */
04089    len_passdata2 = strlen(vmu->fullname);
04090    if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
04091       len_passdata2 = tmplen;
04092    }
04093    if ((tmplen = strlen(fromstring)) > len_passdata2) {
04094       len_passdata2 = tmplen;
04095    }
04096    len_passdata2 = len_passdata2 * 3 + 200;
04097    passdata2 = alloca(len_passdata2);
04098 
04099    if (cidnum) {
04100       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04101    }
04102    if (cidname) {
04103       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04104    }
04105    gethostname(host, sizeof(host) - 1);
04106 
04107    if (strchr(srcemail, '@'))
04108       ast_copy_string(who, srcemail, sizeof(who));
04109    else 
04110       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04111    
04112    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04113    if (greeting_attachment)
04114       *greeting_attachment++ = '\0';
04115 
04116    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04117    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04118    fprintf(p, "Date: %s" ENDL, date);
04119 
04120    /* Set date format for voicemail mail */
04121    ast_strftime(date, sizeof(date), emaildateformat, &tm);
04122 
04123    if (!ast_strlen_zero(fromstring)) {
04124       struct ast_channel *ast;
04125       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04126          char *ptr;
04127          memset(passdata2, 0, len_passdata2);
04128          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category, flag);
04129          pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
04130          len_passdata = strlen(passdata2) * 3 + 300;
04131          passdata = alloca(len_passdata);
04132          if (check_mime(passdata2)) {
04133             int first_line = 1;
04134             encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
04135             while ((ptr = strchr(passdata, ' '))) {
04136                *ptr = '\0';
04137                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
04138                first_line = 0;
04139                passdata = ptr + 1;
04140             }
04141             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
04142          } else {
04143             fprintf(p, "From: %s <%s>" ENDL, quote(passdata2, passdata, len_passdata), who);
04144          }
04145          ast_channel_free(ast);
04146       } else {
04147          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04148       }
04149    } else {
04150       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04151    }
04152 
04153    if (check_mime(vmu->fullname)) {
04154       int first_line = 1;
04155       char *ptr;
04156       encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
04157       while ((ptr = strchr(passdata2, ' '))) {
04158          *ptr = '\0';
04159          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
04160          first_line = 0;
04161          passdata2 = ptr + 1;
04162       }
04163       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
04164    } else {
04165       fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
04166    }
04167    if (!ast_strlen_zero(emailsubject)) {
04168       struct ast_channel *ast;
04169       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04170          int vmlen = strlen(emailsubject) * 3 + 200;
04171          /* Only allocate more space if the previous was not large enough */
04172          if (vmlen > len_passdata) {
04173             passdata = alloca(vmlen);
04174             len_passdata = vmlen;
04175          }
04176 
04177          memset(passdata, 0, len_passdata);
04178          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, len_passdata, category, flag);
04179          pbx_substitute_variables_helper(ast, emailsubject, passdata, len_passdata);
04180          if (check_mime(passdata)) {
04181             int first_line = 1;
04182             char *ptr;
04183             encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
04184             while ((ptr = strchr(passdata2, ' '))) {
04185                *ptr = '\0';
04186                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
04187                first_line = 0;
04188                passdata2 = ptr + 1;
04189             }
04190             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
04191          } else {
04192             fprintf(p, "Subject: %s" ENDL, passdata);
04193          }
04194          ast_channel_free(ast);
04195       } else {
04196          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04197       }
04198    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04199       if (ast_strlen_zero(flag)) {
04200          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04201       } else {
04202          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04203       }
04204    } else {
04205       if (ast_strlen_zero(flag)) {
04206          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04207       } else {
04208          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04209       }
04210    }
04211 
04212    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1, (unsigned int)ast_random(), mailbox, (int)getpid(), host);
04213    if (imap) {
04214       /* additional information needed for IMAP searching */
04215       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04216       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04217       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04218       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04219 #ifdef IMAP_STORAGE
04220       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04221 #else
04222       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04223 #endif
04224       /* flag added for Urgent */
04225       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04226       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04227       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04228       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04229       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04230       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04231       if (!ast_strlen_zero(category)) {
04232          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04233       } else {
04234          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04235       }
04236       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04237       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04238       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long)time(NULL));
04239    }
04240    if (!ast_strlen_zero(cidnum)) {
04241       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04242    }
04243    if (!ast_strlen_zero(cidname)) {
04244       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04245    }
04246    fprintf(p, "MIME-Version: 1.0" ENDL);
04247    if (attach_user_voicemail) {
04248       /* Something unique. */
04249       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox, (int)getpid(), (unsigned int)ast_random());
04250 
04251       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04252       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04253       fprintf(p, "--%s" ENDL, bound);
04254    }
04255    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04256    if (emailbody) {
04257       struct ast_channel *ast;
04258       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04259          char *passdata;
04260          int vmlen = strlen(emailbody)*3 + 200;
04261          passdata = alloca(vmlen);
04262          memset(passdata, 0, vmlen);
04263          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04264          pbx_substitute_variables_helper(ast, emailbody, passdata, vmlen);
04265 #ifdef IMAP_STORAGE
04266          {
04267             /* Convert body to native line terminators for IMAP backend */
04268             char *line = passdata, *next;
04269             do {
04270                /* Terminate line before outputting it to the file */
04271                if ((next = strchr(line, '\n'))) {
04272                   *next++ = '\0';
04273                }
04274                fprintf(p, "%s" ENDL, line);
04275                line = next;
04276             } while (!ast_strlen_zero(line));
04277          }
04278 #else
04279          fprintf(p, "%s" ENDL, passdata);
04280 #endif
04281          ast_channel_free(ast);
04282       } else
04283          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04284    } else if (msgnum > -1) {
04285       if (strcmp(vmu->mailbox, mailbox)) {
04286          /* Forwarded type */
04287          struct ast_config *msg_cfg;
04288          const char *v;
04289          int inttime;
04290          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04291          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04292          /* Retrieve info from VM attribute file */
04293          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04294          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04295          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04296             strcat(fromfile, ".txt");
04297          }
04298          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04299             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04300                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04301             }
04302 
04303             /* You might be tempted to do origdate, except that a) it's in the wrong
04304              * format, and b) it's missing for IMAP recordings. */
04305             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04306                struct timeval tv = { inttime, };
04307                struct ast_tm tm;
04308                ast_localtime(&tv, &tm, NULL);
04309                ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
04310             }
04311             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04312                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04313                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04314                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04315                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04316                date, origcallerid, origdate);
04317             ast_config_destroy(msg_cfg);
04318          } else {
04319             goto plain_message;
04320          }
04321       } else {
04322 plain_message:
04323          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04324             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04325             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04326             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04327             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04328       }
04329    } else {
04330       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04331             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04332    }
04333 
04334    if (imap || attach_user_voicemail) {
04335       if (!ast_strlen_zero(attach2)) {
04336          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04337          ast_debug(5, "creating second attachment filename %s\n", filename);
04338          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04339          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04340          ast_debug(5, "creating attachment filename %s\n", filename);
04341          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04342       } else {
04343          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04344          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04345          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04346       }
04347    }
04348 }

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.
The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1354 of file app_voicemail.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(), save_to_folder(), vm_execmain(), and vm_forwardoptions().

01355 {
01356    return snprintf(dest, len, "%s/msg%04d", dir, num);
01357 }

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

Manager list voicemail users command.

Definition at line 10369 of file app_voicemail.c.

References AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_ack(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::context, count_messages(), ast_vm_user::dialout, ast_vm_user::email, ast_vm_user::exit, ast_vm_user::fullname, inboxcount(), ast_vm_user::language, ast_vm_user::list, ast_vm_user::mailbox, ast_vm_user::mailcmd, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, s, 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().

10370 {
10371    struct ast_vm_user *vmu = NULL;
10372    const char *id = astman_get_header(m, "ActionID");
10373    char actionid[128] = "";
10374 
10375    if (!ast_strlen_zero(id))
10376       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
10377 
10378    AST_LIST_LOCK(&users);
10379 
10380    if (AST_LIST_EMPTY(&users)) {
10381       astman_send_ack(s, m, "There are no voicemail users currently defined.");
10382       AST_LIST_UNLOCK(&users);
10383       return RESULT_SUCCESS;
10384    }
10385    
10386    astman_send_ack(s, m, "Voicemail user list will follow");
10387    
10388    AST_LIST_TRAVERSE(&users, vmu, list) {
10389       char dirname[256];
10390 
10391 #ifdef IMAP_STORAGE
10392       int new, old;
10393       inboxcount(vmu->mailbox, &new, &old);
10394 #endif
10395       
10396       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
10397       astman_append(s,
10398          "%s"
10399          "Event: VoicemailUserEntry\r\n"
10400          "VMContext: %s\r\n"
10401          "VoiceMailbox: %s\r\n"
10402          "Fullname: %s\r\n"
10403          "Email: %s\r\n"
10404          "Pager: %s\r\n"
10405          "ServerEmail: %s\r\n"
10406          "MailCommand: %s\r\n"
10407          "Language: %s\r\n"
10408          "TimeZone: %s\r\n"
10409          "Callback: %s\r\n"
10410          "Dialout: %s\r\n"
10411          "UniqueID: %s\r\n"
10412          "ExitContext: %s\r\n"
10413          "SayDurationMinimum: %d\r\n"
10414          "SayEnvelope: %s\r\n"
10415          "SayCID: %s\r\n"
10416          "AttachMessage: %s\r\n"
10417          "AttachmentFormat: %s\r\n"
10418          "DeleteMessage: %s\r\n"
10419          "VolumeGain: %.2f\r\n"
10420          "CanReview: %s\r\n"
10421          "CallOperator: %s\r\n"
10422          "MaxMessageCount: %d\r\n"
10423          "MaxMessageLength: %d\r\n"
10424          "NewMessageCount: %d\r\n"
10425 #ifdef IMAP_STORAGE
10426          "OldMessageCount: %d\r\n"
10427          "IMAPUser: %s\r\n"
10428 #endif
10429          "\r\n",
10430          actionid,
10431          vmu->context,
10432          vmu->mailbox,
10433          vmu->fullname,
10434          vmu->email,
10435          vmu->pager,
10436          vmu->serveremail,
10437          vmu->mailcmd,
10438          vmu->language,
10439          vmu->zonetag,
10440          vmu->callback,
10441          vmu->dialout,
10442          vmu->uniqueid,
10443          vmu->exit,
10444          vmu->saydurationm,
10445          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
10446          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
10447          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
10448          vmu->attachfmt,
10449          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
10450          vmu->volgain,
10451          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
10452          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
10453          vmu->maxmsg,
10454          vmu->maxsecs,
10455 #ifdef IMAP_STORAGE
10456          new, old, vmu->imapuser
10457 #else
10458          count_messages(vmu, dirname)
10459 #endif
10460          );
10461    }     
10462    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
10463 
10464    AST_LIST_UNLOCK(&users);
10465 
10466    return RESULT_SUCCESS;
10467 }

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

Definition at line 10203 of file app_voicemail.c.

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

Referenced by start_poll_thread().

10204 {
10205    while (poll_thread_run) {
10206       struct timespec ts = { 0, };
10207       struct timeval wait;
10208 
10209       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
10210       ts.tv_sec = wait.tv_sec;
10211       ts.tv_nsec = wait.tv_usec * 1000;
10212 
10213       ast_mutex_lock(&poll_lock);
10214       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
10215       ast_mutex_unlock(&poll_lock);
10216 
10217       if (!poll_thread_run)
10218          break;
10219 
10220       poll_subscribed_mailboxes();
10221    }
10222 
10223    return NULL;
10224 }

static const char* mbox ( int  id  )  [static]

Definition at line 1396 of file app_voicemail.c.

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

01397 {
01398    static const char *msgs[] = {
01399 #ifdef IMAP_STORAGE
01400       imapfolder,
01401 #else
01402       "INBOX",
01403 #endif
01404       "Old",
01405       "Work",
01406       "Family",
01407       "Friends",
01408       "Cust1",
01409       "Cust2",
01410       "Cust3",
01411       "Cust4",
01412       "Cust5",
01413       "Deleted",
01414       "Urgent"
01415    };
01416    return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "Unknown";
01417 }

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

Definition at line 4855 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04856 {
04857    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
04858 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 10226 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

10227 {
10228    ast_free(mwi_sub);
10229 }

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

Definition at line 10304 of file app_voicemail.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_SUB, ast_free, ast_log(), ast_strdup, ast_taskprocessor_push(), handle_subscribe(), LOG_ERROR, and mwi_subscription_tps.

Referenced by start_poll_thread().

10305 {
10306    struct mwi_sub_task *mwist;
10307    
10308    if (ast_event_get_type(event) != AST_EVENT_SUB)
10309       return;
10310 
10311    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10312       return;
10313 
10314    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
10315       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
10316       return;
10317    }
10318    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
10319    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
10320    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10321    
10322    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
10323       ast_free(mwist);
10324    }
10325 }

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

Definition at line 10288 of file app_voicemail.c.

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

Referenced by start_poll_thread().

10289 {
10290    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
10291    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
10292       return;
10293 
10294    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10295       return;
10296 
10297    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10298    *uniqueid = u;
10299    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
10300       ast_free(uniqueid);
10301    }
10302 }

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.
Returns:
zero on success, -1 on error.

Definition at line 6400 of file app_voicemail.c.

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

06401 {
06402    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06403    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06404    const char *category;
06405    char *myserveremail = serveremail;
06406 
06407    ast_channel_lock(chan);
06408    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06409       category = ast_strdupa(category);
06410    }
06411    ast_channel_unlock(chan);
06412 
06413    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06414    make_file(fn, sizeof(fn), todir, msgnum);
06415    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06416 
06417    if (!ast_strlen_zero(vmu->attachfmt)) {
06418       if (strstr(fmt, vmu->attachfmt))
06419          fmt = vmu->attachfmt;
06420       else
06421          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);
06422    }
06423 
06424    /* Attach only the first format */
06425    fmt = ast_strdupa(fmt);
06426    stringp = fmt;
06427    strsep(&stringp, "|");
06428 
06429    if (!ast_strlen_zero(vmu->serveremail))
06430       myserveremail = vmu->serveremail;
06431 
06432    if (!ast_strlen_zero(vmu->email)) {
06433       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06434 
06435       if (attach_user_voicemail)
06436          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06437 
06438       /* XXX possible imap issue, should category be NULL XXX */
06439       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06440 
06441       if (attach_user_voicemail)
06442          DISPOSE(todir, msgnum);
06443    }
06444 
06445    if (!ast_strlen_zero(vmu->pager)) {
06446       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
06447    }
06448 
06449    if (ast_test_flag(vmu, VM_DELETE))
06450       DELETE(todir, msgnum, fn, vmu);
06451 
06452    /* Leave voicemail for someone */
06453    if (ast_app_has_voicemail(ext_context, NULL)) 
06454       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06455 
06456    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06457 
06458    manager_event(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);
06459    run_externnotify(vmu->context, vmu->mailbox, flag);
06460 
06461 #ifdef IMAP_STORAGE
06462    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06463    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06464       vm_imap_delete(NULL, vms->curmsg, vmu);
06465       vms->newmessages--;  /* Fix new message count */
06466    }
06467 #endif
06468 
06469    return 0;
06470 }

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

utility used by base_encode()

Definition at line 3799 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

03800 {
03801    if (bio->linelength >= BASELINELEN) {
03802       if (fputs(ENDL, so) == EOF) {
03803          return -1;
03804       }
03805 
03806       bio->linelength= 0;
03807    }
03808 
03809    if (putc(((unsigned char) c), so) == EOF) {
03810       return -1;
03811    }
03812 
03813    bio->linelength++;
03814 
03815    return 1;
03816 }

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

Definition at line 7176 of file app_voicemail.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, last_message_index(), vm_state::lastmsg, mbox(), vm_state::username, vm_lock_path(), and vm_state::vmbox.

Referenced by vm_execmain().

07177 {
07178    int count_msg, last_msg;
07179 
07180    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
07181    
07182    /* Rename the member vmbox HERE so that we don't try to return before
07183     * we know what's going on.
07184     */
07185    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07186    
07187    /* Faster to make the directory than to check if it exists. */
07188    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07189 
07190    count_msg = count_messages(vmu, vms->curdir);
07191    if (count_msg < 0)
07192       return count_msg;
07193    else
07194       vms->lastmsg = count_msg - 1;
07195 
07196    /*
07197    The following test is needed in case sequencing gets messed up.
07198    There appears to be more than one way to mess up sequence, so
07199    we will not try to find all of the root causes--just fix it when
07200    detected.
07201    */
07202 
07203    if (vm_lock_path(vms->curdir)) {
07204       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07205       return -1;
07206    }
07207 
07208    last_msg = last_message_index(vmu, vms->curdir);
07209    ast_unlock_path(vms->curdir);
07210 
07211    if (last_msg < 0) 
07212       return last_msg;
07213 
07214    return 0;
07215 }

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

Definition at line 6974 of file app_voicemail.c.

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

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

06975 {
06976    int res = 0;
06977    char filename[256], *cid;
06978    const char *origtime, *context, *category, *duration, *flag;
06979    struct ast_config *msg_cfg;
06980    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06981 
06982    vms->starting = 0;
06983    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06984    adsi_message(chan, vms);
06985    if (!vms->curmsg)
06986       res = wait_file2(chan, vms, "vm-first");  /* "First" */
06987    else if (vms->curmsg == vms->lastmsg)
06988       res = wait_file2(chan, vms, "vm-last");      /* "last" */
06989 
06990    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
06991    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
06992    msg_cfg = ast_config_load(filename, config_flags);
06993    if (!msg_cfg) {
06994       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06995       return 0;
06996    }
06997    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
06998 
06999    /* Play the word urgent if we are listening to urgent messages */
07000    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07001       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07002    }
07003 
07004    if (!res) {
07005       /* POLISH syntax */
07006       if (!strncasecmp(chan->language, "pl", 2)) {
07007          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07008             int ten, one;
07009             char nextmsg[256];
07010             ten = (vms->curmsg + 1) / 10;
07011             one = (vms->curmsg + 1) % 10;
07012 
07013             if (vms->curmsg < 20) {
07014                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07015                res = wait_file2(chan, vms, nextmsg);
07016             } else {
07017                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07018                res = wait_file2(chan, vms, nextmsg);
07019                if (one > 0) {
07020                   if (!res) {
07021                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07022                      res = wait_file2(chan, vms, nextmsg);
07023                   }
07024                }
07025             }
07026          }
07027          if (!res)
07028             res = wait_file2(chan, vms, "vm-message");
07029       /* HEBREW syntax */
07030       } else if (!strncasecmp(chan->language, "he", 2)) {
07031          if (!vms->curmsg) {
07032             res = wait_file2(chan, vms, "vm-message");
07033             res = wait_file2(chan, vms, "vm-first");
07034          } else if (vms->curmsg == vms->lastmsg) {
07035             res = wait_file2(chan, vms, "vm-message");
07036             res = wait_file2(chan, vms, "vm-last");
07037          } else {
07038             res = wait_file2(chan, vms, "vm-message");
07039             res = wait_file2(chan, vms, "vm-number");
07040             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07041          }
07042       } else {
07043          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07044             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07045          } else { /* DEFAULT syntax */
07046             res = wait_file2(chan, vms, "vm-message");
07047          }
07048          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07049             if (!res) {
07050                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07051             }
07052          }
07053       }
07054    }
07055 
07056    if (!msg_cfg) {
07057       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07058       return 0;
07059    }
07060 
07061    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07062       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07063       DISPOSE(vms->curdir, vms->curmsg);
07064       ast_config_destroy(msg_cfg);
07065       return 0;
07066    }
07067 
07068    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07069    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07070    category = ast_variable_retrieve(msg_cfg, "message", "category");
07071 
07072    context = ast_variable_retrieve(msg_cfg, "message", "context");
07073    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
07074       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
07075    if (!res) {
07076       res = play_message_category(chan, category);
07077    }
07078    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07079       res = play_message_datetime(chan, vmu, origtime, filename);
07080    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07081       res = play_message_callerid(chan, vms, cid, context, 0);
07082    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07083       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07084    /* Allow pressing '1' to skip envelope / callerid */
07085    if (res == '1')
07086       res = 0;
07087    ast_config_destroy(msg_cfg);
07088 
07089    if (!res) {
07090       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07091       vms->heard[vms->curmsg] = 1;
07092 #ifdef IMAP_STORAGE
07093       /*IMAP storage stores any prepended message from a forward
07094        * as a separate file from the rest of the message
07095        */
07096       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07097          wait_file(chan, vms, vms->introfn);
07098       }
07099 #endif
07100       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07101          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07102          res = 0;
07103       }
07104    }
07105    DISPOSE(vms->curdir, vms->curmsg);
07106    return res;
07107 }

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

Definition at line 6860 of file app_voicemail.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, chan, cidinternalcontexts, ast_channel::language, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

06861 {
06862    int res = 0;
06863    int i;
06864    char *callerid, *name;
06865    char prefile[PATH_MAX] = "";
06866    
06867 
06868    /* If voicemail cid is not enabled, or we didn't get cid or context from
06869     * the attribute file, leave now.
06870     *
06871     * TODO Still need to change this so that if this function is called by the
06872     * message envelope (and someone is explicitly requesting to hear the CID),
06873     * it does not check to see if CID is enabled in the config file.
06874     */
06875    if ((cid == NULL)||(context == NULL))
06876       return res;
06877 
06878    /* Strip off caller ID number from name */
06879    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
06880    ast_callerid_parse(cid, &name, &callerid);
06881    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
06882       /* Check for internal contexts and only */
06883       /* say extension when the call didn't come from an internal context in the list */
06884       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
06885          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
06886          if ((strcmp(cidinternalcontexts[i], context) == 0))
06887             break;
06888       }
06889       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
06890          if (!res) {
06891             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
06892             if (!ast_strlen_zero(prefile)) {
06893             /* See if we can find a recorded name for this person instead of their extension number */
06894                if (ast_fileexists(prefile, NULL, NULL) > 0) {
06895                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
06896                   if (!callback)
06897                      res = wait_file2(chan, vms, "vm-from");
06898                   res = ast_stream_and_wait(chan, prefile, "");
06899                } else {
06900                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
06901                   /* Say "from extension" as one saying to sound smoother */
06902                   if (!callback)
06903                      res = wait_file2(chan, vms, "vm-from-extension");
06904                   res = ast_say_digit_str(chan, callerid, "", chan->language);
06905                }
06906             }
06907          }
06908       } else if (!res) {
06909          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
06910          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
06911          if (!callback)
06912             res = wait_file2(chan, vms, "vm-from-phonenumber");
06913          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
06914       }
06915    } else {
06916       /* Number unknown */
06917       ast_debug(1, "VM-CID: From an unknown number\n");
06918       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
06919       res = wait_file2(chan, vms, "vm-unknown-caller");
06920    }
06921    return res;
06922 }

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

Definition at line 6773 of file app_voicemail.c.

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

Referenced by play_message().

06774 {
06775    int res = 0;
06776 
06777    if (!ast_strlen_zero(category))
06778       res = ast_play_and_wait(chan, category);
06779 
06780    if (res) {
06781       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
06782       res = 0;
06783    }
06784 
06785    return res;
06786 }

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

Definition at line 6788 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_get_time_t(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_log(), ast_say_date_with_format, ast_strlen_zero(), ast_tvnow(), chan, ast_channel::language, vm_zone::list, vm_zone::msg_format, vm_zone::name, pbx_builtin_setvar_helper(), vm_zone::timezone, and ast_vm_user::zonetag.

Referenced by advanced_options(), and play_message().

06789 {
06790    int res = 0;
06791    struct vm_zone *the_zone = NULL;
06792    time_t t;
06793 
06794    if (ast_get_time_t(origtime, &t, 0, NULL)) {
06795       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
06796       return 0;
06797    }
06798 
06799    /* Does this user have a timezone specified? */
06800    if (!ast_strlen_zero(vmu->zonetag)) {
06801       /* Find the zone in the list */
06802       struct vm_zone *z;
06803       AST_LIST_LOCK(&zones);
06804       AST_LIST_TRAVERSE(&zones, z, list) {
06805          if (!strcmp(z->name, vmu->zonetag)) {
06806             the_zone = z;
06807             break;
06808          }
06809       }
06810       AST_LIST_UNLOCK(&zones);
06811    }
06812 
06813 /* No internal variable parsing for now, so we'll comment it out for the time being */
06814 #if 0
06815    /* Set the DIFF_* variables */
06816    ast_localtime(&t, &time_now, NULL);
06817    tv_now = ast_tvnow();
06818    ast_localtime(&tv_now, &time_then, NULL);
06819 
06820    /* Day difference */
06821    if (time_now.tm_year == time_then.tm_year)
06822       snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
06823    else
06824       snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
06825    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
06826 
06827    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
06828 #endif
06829    if (the_zone) {
06830       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
06831    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
06832       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06833    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
06834       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
06835    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
06836       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);
06837    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
06838       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
06839    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
06840       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06841    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
06842       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
06843    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
06844       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);
06845    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
06846       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
06847    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
06848       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
06849    } else {
06850       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
06851    }
06852 #if 0
06853    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
06854 #endif
06855    return res;
06856 }

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

Definition at line 6924 of file app_voicemail.c.

References ast_debug, AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), chan, ast_channel::language, num, say_and_wait(), and wait_file2().

Referenced by play_message().

06925 {
06926    int res = 0;
06927    int durationm;
06928    int durations;
06929    /* Verify that we have a duration for the message */
06930    if (duration == NULL)
06931       return res;
06932 
06933    /* Convert from seconds to minutes */
06934    durations=atoi(duration);
06935    durationm=(durations / 60);
06936 
06937    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
06938 
06939    if ((!res) && (durationm >= minduration)) {
06940       res = wait_file2(chan, vms, "vm-duration");
06941 
06942       /* POLISH syntax */
06943       if (!strncasecmp(chan->language, "pl", 2)) {
06944          div_t num = div(durationm, 10);
06945 
06946          if (durationm == 1) {
06947             res = ast_play_and_wait(chan, "digits/1z");
06948             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
06949          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
06950             if (num.rem == 2) {
06951                if (!num.quot) {
06952                   res = ast_play_and_wait(chan, "digits/2-ie");
06953                } else {
06954                   res = say_and_wait(chan, durationm - 2 , chan->language);
06955                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
06956                }
06957             } else {
06958                res = say_and_wait(chan, durationm, chan->language);
06959             }
06960             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
06961          } else {
06962             res = say_and_wait(chan, durationm, chan->language);
06963             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
06964          }
06965       /* DEFAULT syntax */
06966       } else {
06967          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
06968          res = wait_file2(chan, vms, "vm-minutes");
06969       }
06970    }
06971    return res;
06972 }

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,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 11523 of file app_voicemail.c.

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

11526 {
11527    /* Record message & let caller review or re-record it, or set options if applicable */
11528    int res = 0;
11529    int cmd = 0;
11530    int max_attempts = 3;
11531    int attempts = 0;
11532    int recorded = 0;
11533    int msg_exists = 0;
11534    signed char zero_gain = 0;
11535    char tempfile[PATH_MAX];
11536    char *acceptdtmf = "#";
11537    char *canceldtmf = "";
11538 
11539    /* Note that urgent and private are for flagging messages as such in the future */
11540 
11541    /* barf if no pointer passed to store duration in */
11542    if (duration == NULL) {
11543       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
11544       return -1;
11545    }
11546 
11547    if (!outsidecaller)
11548       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
11549    else
11550       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
11551 
11552    cmd = '3';  /* Want to start by recording */
11553 
11554    while ((cmd >= 0) && (cmd != 't')) {
11555       switch (cmd) {
11556       case '1':
11557          if (!msg_exists) {
11558             /* In this case, 1 is to record a message */
11559             cmd = '3';
11560             break;
11561          } else {
11562             /* Otherwise 1 is to save the existing message */
11563             ast_verb(3, "Saving message as is\n");
11564             if (!outsidecaller) 
11565                ast_filerename(tempfile, recordfile, NULL);
11566             ast_stream_and_wait(chan, "vm-msgsaved", "");
11567             if (!outsidecaller) {
11568                /* Saves to IMAP server only if imapgreeting=yes */
11569                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
11570                DISPOSE(recordfile, -1);
11571             }
11572             cmd = 't';
11573             return res;
11574          }
11575       case '2':
11576          /* Review */
11577          ast_verb(3, "Reviewing the message\n");
11578          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
11579          break;
11580       case '3':
11581          msg_exists = 0;
11582          /* Record */
11583          if (recorded == 1) 
11584             ast_verb(3, "Re-recording the message\n");
11585          else  
11586             ast_verb(3, "Recording the message\n");
11587          
11588          if (recorded && outsidecaller) {
11589             cmd = ast_play_and_wait(chan, INTRO);
11590             cmd = ast_play_and_wait(chan, "beep");
11591          }
11592          recorded = 1;
11593          /* 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 */
11594          if (record_gain)
11595             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
11596          if (ast_test_flag(vmu, VM_OPERATOR))
11597             canceldtmf = "0";
11598          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
11599          if (record_gain)
11600             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
11601          if (cmd == -1) {
11602             /* User has hung up, no options to give */
11603             if (!outsidecaller) {
11604                /* user was recording a greeting and they hung up, so let's delete the recording. */
11605                ast_filedelete(tempfile, NULL);
11606             }     
11607             return cmd;
11608          }
11609          if (cmd == '0') {
11610             break;
11611          } else if (cmd == '*') {
11612             break;
11613 #if 0
11614          } else if (vmu->review && (*duration < 5)) {
11615             /* Message is too short */
11616             ast_verb(3, "Message too short\n");
11617             cmd = ast_play_and_wait(chan, "vm-tooshort");
11618             cmd = ast_filedelete(tempfile, NULL);
11619             break;
11620          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
11621             /* Message is all silence */
11622             ast_verb(3, "Nothing recorded\n");
11623             cmd = ast_filedelete(tempfile, NULL);
11624             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
11625             if (!cmd)
11626                cmd = ast_play_and_wait(chan, "vm-speakup");
11627             break;
11628 #endif
11629          } else {
11630             /* If all is well, a message exists */
11631             msg_exists = 1;
11632             cmd = 0;
11633          }
11634          break;
11635       case '4':
11636          if (outsidecaller) {  /* only mark vm messages */
11637             /* Mark Urgent */
11638             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11639                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
11640                ast_debug(1000, "This message is too urgent!\n");
11641                res = ast_play_and_wait(chan, "vm-marked-urgent");
11642                strcpy(flag, "Urgent");
11643             } else if (flag) {
11644                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
11645                res = ast_play_and_wait(chan, "vm-urgent-removed");
11646                strcpy(flag, "");
11647             } else {
11648                ast_play_and_wait(chan, "vm-sorry");
11649             }
11650             cmd = 0;
11651          } else {
11652             cmd = ast_play_and_wait(chan, "vm-sorry");
11653          }
11654          break;
11655       case '5':
11656       case '6':
11657       case '7':
11658       case '8':
11659       case '9':
11660       case '*':
11661       case '#':
11662          cmd = ast_play_and_wait(chan, "vm-sorry");
11663          break;
11664 #if 0 
11665 /*  XXX Commented out for the moment because of the dangers of deleting
11666     a message while recording (can put the message numbers out of sync) */
11667       case '*':
11668          /* Cancel recording, delete message, offer to take another message*/
11669          cmd = ast_play_and_wait(chan, "vm-deleted");
11670          cmd = ast_filedelete(tempfile, NULL);
11671          if (outsidecaller) {
11672             res = vm_exec(chan, NULL);
11673             return res;
11674          }
11675          else
11676             return 1;
11677 #endif
11678       case '0':
11679          if (!ast_test_flag(vmu, VM_OPERATOR) || !outsidecaller) {
11680             cmd = ast_play_and_wait(chan, "vm-sorry");
11681             break;
11682          }
11683          if (msg_exists || recorded) {
11684             cmd = ast_play_and_wait(chan, "vm-saveoper");
11685             if (!cmd)
11686                cmd = ast_waitfordigit(chan, 3000);
11687             if (cmd == '1') {
11688                ast_play_and_wait(chan, "vm-msgsaved");
11689                cmd = '0';
11690             } else if (cmd == '4') {
11691                if (flag) {
11692                   ast_play_and_wait(chan, "vm-marked-urgent");
11693                   strcpy(flag, "Urgent");
11694                }
11695                ast_play_and_wait(chan, "vm-msgsaved");
11696                cmd = '0';
11697             } else {
11698                ast_play_and_wait(chan, "vm-deleted");
11699                DELETE(recordfile, -1, recordfile, vmu);
11700                cmd = '0';
11701             }
11702          }
11703          return cmd;
11704       default:
11705          /* If the caller is an ouside caller, and the review option is enabled,
11706             allow them to review the message, but let the owner of the box review
11707             their OGM's */
11708          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
11709             return cmd;
11710          if (msg_exists) {
11711             cmd = ast_play_and_wait(chan, "vm-review");
11712             if (!cmd && outsidecaller) {
11713                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11714                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
11715                } else if (flag) {
11716                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
11717                }
11718             }
11719          } else {
11720             cmd = ast_play_and_wait(chan, "vm-torerecord");
11721             if (!cmd)
11722                cmd = ast_waitfordigit(chan, 600);
11723          }
11724          
11725          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
11726             cmd = ast_play_and_wait(chan, "vm-reachoper");
11727             if (!cmd)
11728                cmd = ast_waitfordigit(chan, 600);
11729          }
11730 #if 0
11731          if (!cmd)
11732             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
11733 #endif
11734          if (!cmd)
11735             cmd = ast_waitfordigit(chan, 6000);
11736          if (!cmd) {
11737             attempts++;
11738          }
11739          if (attempts > max_attempts) {
11740             cmd = 't';
11741          }
11742       }
11743    }
11744    if (cmd == 't')
11745       cmd = 0;
11746    else if (outsidecaller) /* won't play if time out occurs */
11747       ast_play_and_wait(chan, "vm-goodbye");
11748    return cmd;
11749 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 10176 of file app_voicemail.c.

References inboxcount2(), mwi_sub::mailbox, mwi_sub::old_new, mwi_sub::old_old, mwi_sub::old_urgent, and queue_mwi_event().

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

10177 {
10178    int new = 0, old = 0, urgent = 0;
10179 
10180    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
10181 
10182    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
10183       mwi_sub->old_urgent = urgent;
10184       mwi_sub->old_new = new;
10185       mwi_sub->old_old = old;
10186       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
10187    }
10188 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 10190 of file app_voicemail.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), mwi_sub::entry, mwi_sub::mailbox, and poll_subscribed_mailbox().

Referenced by mb_poll_thread().

10191 {
10192    struct mwi_sub *mwi_sub;
10193 
10194    AST_RWLIST_RDLOCK(&mwi_subs);
10195    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
10196       if (!ast_strlen_zero(mwi_sub->mailbox)) {
10197          poll_subscribed_mailbox(mwi_sub);
10198       }
10199    }
10200    AST_RWLIST_UNLOCK(&mwi_subs);
10201 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

Definition at line 815 of file app_voicemail.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_vm_user::callback, callcontext, dialcontext, ast_vm_user::dialout, ast_vm_user::exit, exitcontext, globalflags, ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::saydurationm, saydurationminfo, ast_vm_user::volgain, and ast_vm_user::zonetag.

00816 {
00817    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00818    if (saydurationminfo)
00819       vmu->saydurationm = saydurationminfo;
00820    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00821    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00822    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00823    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00824    if (vmmaxsecs)
00825       vmu->maxsecs = vmmaxsecs;
00826    if (maxmsg)
00827       vmu->maxmsg = maxmsg;
00828    if (maxdeletedmsg)
00829       vmu->maxdeletedmsg = maxdeletedmsg;
00830    vmu->volgain = volgain;
00831 }

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,
char *  passdata,
size_t  passdatasize,
const char *  category,
const char *  flag 
) [static]

Definition at line 3887 of file app_voicemail.c.

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

03888 {
03889    char callerid[256];
03890    char fromdir[256], fromfile[256];
03891    struct ast_config *msg_cfg;
03892    const char *origcallerid, *origtime;
03893    char origcidname[80], origcidnum[80], origdate[80];
03894    int inttime;
03895    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03896 
03897    /* Prepare variables for substitution in email body and subject */
03898    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
03899    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
03900    snprintf(passdata, passdatasize, "%d", msgnum);
03901    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
03902    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
03903    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
03904    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
03905       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
03906    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
03907    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
03908    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
03909    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
03910    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
03911 
03912    /* Retrieve info from VM attribute file */
03913    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
03914    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
03915    if (strlen(fromfile) < sizeof(fromfile) - 5) {
03916       strcat(fromfile, ".txt");
03917    }
03918    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
03919       if (option_debug > 0) {
03920          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
03921       }
03922       return;
03923    }
03924 
03925    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
03926       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
03927       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
03928       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
03929       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
03930    }
03931 
03932    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
03933       struct timeval tv = { inttime, };
03934       struct ast_tm tm;
03935       ast_localtime(&tv, &tm, NULL);
03936       ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
03937       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
03938    }
03939    ast_config_destroy(msg_cfg);
03940 }

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

Definition at line 6364 of file app_voicemail.c.

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

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

06365 {
06366    struct ast_event *event;
06367    char *mailbox, *context;
06368 
06369    /* Strip off @default */
06370    context = mailbox = ast_strdupa(box);
06371    strsep(&context, "@");
06372    if (ast_strlen_zero(context))
06373       context = "default";
06374 
06375    if (!(event = ast_event_new(AST_EVENT_MWI,
06376          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06377          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06378          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06379          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06380          AST_EVENT_IE_END))) {
06381       return;
06382    }
06383 
06384    ast_event_queue_and_cache(event);
06385 }

static char* quote ( const char *  from,
char *  to,
size_t  len 
) [static]

Wraps a character sequence in double quotes, escaping occurences of quotes within the string.

Parameters:
from The string to work with.
to The string to write the modified quoted string. This buffer should be sufficiently larger than the from string, so as to allow it to be expanded by the surrounding quotes and escaping of internal quotes.
Returns:
The destination string with quotes wrapped on it (the to field).

Definition at line 3949 of file app_voicemail.c.

03950 {
03951    char *ptr = to;
03952    *ptr++ = '"';
03953    for (; ptr < to + len - 1; from++) {
03954       if (*from == '"')
03955          *ptr++ = '\\';
03956       else if (*from == '\0')
03957          break;
03958       *ptr++ = *from;
03959    }
03960    if (ptr < to + len - 1)
03961       *ptr++ = '"';
03962    *ptr = '\0';
03963    return to;
03964 }

static int reload ( void   )  [static]

Definition at line 11194 of file app_voicemail.c.

References load_config().

11195 {
11196    return load_config(1);
11197 }

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

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

03565 {
03566    char stxt[PATH_MAX];
03567    char dtxt[PATH_MAX];
03568    ast_filerename(sfn,dfn,NULL);
03569    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03570    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03571    if (ast_check_realtime("voicemail_data")) {
03572       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03573    }
03574    rename(stxt, dtxt);
03575 }

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

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

Referenced by vm_change_password(), and vm_change_password_shell().

01223 {
01224    /* This function could be made to generate one from a database, too */
01225    struct ast_vm_user *cur;
01226    int res = -1;
01227    AST_LIST_LOCK(&users);
01228    AST_LIST_TRAVERSE(&users, cur, list) {
01229       if ((!context || !strcasecmp(context, cur->context)) &&
01230          (!strcasecmp(mailbox, cur->mailbox)))
01231             break;
01232    }
01233    if (cur) {
01234       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01235       res = 0;
01236    }
01237    AST_LIST_UNLOCK(&users);
01238    return res;
01239 }

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

Definition at line 4998 of file app_voicemail.c.

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

04999 {
05000    char arguments[255];
05001    char ext_context[256] = "";
05002    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05003    struct ast_smdi_mwi_message *mwi_msg;
05004 
05005    if (!ast_strlen_zero(context))
05006       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05007    else
05008       ast_copy_string(ext_context, extension, sizeof(ext_context));
05009 
05010    if (smdi_iface) {
05011       if (ast_app_has_voicemail(ext_context, NULL)) 
05012          ast_smdi_mwi_set(smdi_iface, extension);
05013       else
05014          ast_smdi_mwi_unset(smdi_iface, extension);
05015 
05016       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05017          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05018          if (!strncmp(mwi_msg->cause, "INV", 3))
05019             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05020          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05021             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05022          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05023          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05024       } else {
05025          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05026       }
05027    }
05028 
05029    if (!ast_strlen_zero(externnotify)) {
05030       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05031          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05032       } else {
05033          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05034          ast_debug(1, "Executing %s\n", arguments);
05035          ast_safe_system(arguments);
05036       }
05037    }
05038 }

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

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

05578 {
05579 #ifdef IMAP_STORAGE
05580    /* we must use mbox(x) folder names, and copy the message there */
05581    /* simple. huh? */
05582    char sequence[10];
05583    char mailbox[256];
05584    int res;
05585 
05586    /* get the real IMAP message number for this message */
05587    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
05588    
05589    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
05590    ast_mutex_lock(&vms->lock);
05591    /* if save to Old folder, put in INBOX as read */
05592    if (box == OLD_FOLDER) {
05593       mail_setflag(vms->mailstream, sequence, "\\Seen");
05594       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
05595    } else if (box == NEW_FOLDER) {
05596       mail_setflag(vms->mailstream, sequence, "\\Unseen");
05597       mail_clearflag(vms->mailstream, sequence, "\\Seen");
05598    }
05599    if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
05600       ast_mutex_unlock(&vms->lock);
05601       return 0;
05602    }
05603    /* Create the folder if it don't exist */
05604    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
05605    ast_debug(5, "Checking if folder exists: %s\n",mailbox);
05606    if (mail_create(vms->mailstream, mailbox) == NIL) 
05607       ast_debug(5, "Folder exists.\n");
05608    else
05609       ast_log(AST_LOG_NOTICE, "Folder %s created!\n",mbox(box));
05610    res = !mail_copy(vms->mailstream, sequence, (char *)mbox(box));
05611    ast_mutex_unlock(&vms->lock);
05612    return res;
05613 #else
05614    char *dir = vms->curdir;
05615    char *username = vms->username;
05616    char *context = vmu->context;
05617    char sfn[PATH_MAX];
05618    char dfn[PATH_MAX];
05619    char ddir[PATH_MAX];
05620    const char *dbox = mbox(box);
05621    int x, i;
05622    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
05623 
05624    if (vm_lock_path(ddir))
05625       return ERROR_LOCK_PATH;
05626 
05627    x = last_message_index(vmu, ddir) + 1;
05628 
05629    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
05630       x--;
05631       for (i = 1; i <= x; i++) {
05632          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
05633          make_file(sfn, sizeof(sfn), ddir, i);
05634          make_file(dfn, sizeof(dfn), ddir, i - 1);
05635          if (EXISTS(ddir, i, sfn, NULL)) {
05636             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
05637          } else
05638             break;
05639       }
05640    } else {
05641       if (x >= vmu->maxmsg) {
05642          ast_unlock_path(ddir);
05643          return -1;
05644       }
05645    }
05646    make_file(sfn, sizeof(sfn), dir, msg);
05647    make_file(dfn, sizeof(dfn), ddir, x);
05648    if (strcmp(sfn, dfn)) {
05649       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
05650    }
05651    ast_unlock_path(ddir);
05652 #endif
05653    return 0;
05654 }

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

Definition at line 5570 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_say_number(), and chan.

Referenced by play_message_duration(), vm_execmain(), vm_intro_cs(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_it(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_se(), and vm_intro_zh().

05571 {
05572    int d;
05573    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
05574    return d;
05575 }

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

Definition at line 11180 of file app_voicemail.c.

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

Referenced by load_module().

11181 {
11182    int res = -1;
11183    char dir[PATH_MAX];
11184    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
11185    ast_debug(2, "About to try retrieving name file %s\n", dir);
11186    RETRIEVE(dir, -1, mailbox, context);
11187    if (ast_fileexists(dir, NULL, NULL)) {
11188       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
11189    }
11190    DISPOSE(dir, -1);
11191    return res;
11192 }

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

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

04404 {
04405    FILE *p=NULL;
04406    char tmp[80] = "/tmp/astmail-XXXXXX";
04407    char tmp2[256];
04408 
04409    if (vmu && ast_strlen_zero(vmu->email)) {
04410       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04411       return(0);
04412    }
04413    if (!strcmp(format, "wav49"))
04414       format = "WAV";
04415    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04416    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04417       command hangs */
04418    if ((p = vm_mkftemp(tmp)) == NULL) {
04419       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04420       return -1;
04421    } else {
04422       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04423       fclose(p);
04424       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04425       ast_safe_system(tmp2);
04426       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04427    }
04428    return 0;
04429 }

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

References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, ast_log(), ast_safe_system(), AST_STATE_DOWN, ast_strftime(), ast_strlen_zero(), fromstring, MAXHOSTNAMELEN, pagerbody, pagerfromstring, pagersubject, pbx_substitute_variables_helper(), prep_email_sub_vars(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

04432 {
04433    char date[256];
04434    char host[MAXHOSTNAMELEN] = "";
04435    char who[256];
04436    char dur[PATH_MAX];
04437    char tmp[80] = "/tmp/astmail-XXXXXX";
04438    char tmp2[PATH_MAX];
04439    struct ast_tm tm;
04440    FILE *p;
04441 
04442    if ((p = vm_mkftemp(tmp)) == NULL) {
04443       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04444       return -1;
04445    }
04446    gethostname(host, sizeof(host)-1);
04447    if (strchr(srcemail, '@'))
04448       ast_copy_string(who, srcemail, sizeof(who));
04449    else 
04450       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04451    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04452    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04453    fprintf(p, "Date: %s\n", date);
04454 
04455    if (*pagerfromstring) {
04456       struct ast_channel *ast;
04457       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04458          char *passdata;
04459          int vmlen = strlen(fromstring)*3 + 200;
04460          passdata = alloca(vmlen);
04461          memset(passdata, 0, vmlen);
04462          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04463          pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
04464          fprintf(p, "From: %s <%s>\n", passdata, who);
04465          ast_channel_free(ast);
04466       } else 
04467          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04468    } else
04469       fprintf(p, "From: Asterisk PBX <%s>\n", who);
04470    fprintf(p, "To: %s\n", pager);
04471    if (pagersubject) {
04472       struct ast_channel *ast;
04473       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04474          char *passdata;
04475          int vmlen = strlen(pagersubject) * 3 + 200;
04476          passdata = alloca(vmlen);
04477          memset(passdata, 0, vmlen);
04478          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04479          pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
04480          fprintf(p, "Subject: %s\n\n", passdata);
04481          ast_channel_free(ast);
04482       } else
04483          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04484    } else {
04485       if (ast_strlen_zero(flag)) {
04486          fprintf(p, "Subject: New VM\n\n");
04487       } else {
04488          fprintf(p, "Subject: New %s VM\n\n", flag);
04489       }
04490    }
04491 
04492    ast_strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
04493    if (pagerbody) {
04494       struct ast_channel *ast;
04495       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04496          char *passdata;
04497          int vmlen = strlen(pagerbody) * 3 + 200;
04498          passdata = alloca(vmlen);
04499          memset(passdata, 0, vmlen);
04500          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04501          pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
04502          fprintf(p, "%s\n", passdata);
04503          ast_channel_free(ast);
04504       } else
04505          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04506    } else {
04507       fprintf(p, "New %s long %s msg in box %s\n"
04508             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04509    }
04510    fclose(p);
04511    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04512    ast_safe_system(tmp2);
04513    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04514    return 0;
04515 }

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

Definition at line 9974 of file app_voicemail.c.

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, SENTINEL, and var.

Referenced by handle_voicemail_show_users().

09975 {
09976    struct ast_config *cfg;
09977    const char *cat = NULL;
09978 
09979    if (!(cfg = ast_load_realtime_multientry("voicemail", 
09980       "context", context, SENTINEL))) {
09981       return CLI_FAILURE;
09982    }
09983 
09984    ast_cli(fd,
09985       "\n"
09986       "=============================================================\n"
09987       "=== Configured Voicemail Users ==============================\n"
09988       "=============================================================\n"
09989       "===\n");
09990 
09991    while ((cat = ast_category_browse(cfg, cat))) {
09992       struct ast_variable *var = NULL;
09993       ast_cli(fd,
09994          "=== Mailbox ...\n"
09995          "===\n");
09996       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
09997          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
09998       ast_cli(fd,
09999          "===\n"
10000          "=== ---------------------------------------------------------\n"
10001          "===\n");
10002    }
10003 
10004    ast_cli(fd,
10005       "=============================================================\n"
10006       "\n");
10007 
10008    ast_config_destroy(cfg);
10009 
10010    return CLI_SUCCESS;
10011 }

static void start_poll_thread ( void   )  [static]

Definition at line 10327 of file app_voicemail.c.

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

Referenced by load_config().

static void stop_poll_thread ( void   )  [static]

Definition at line 10345 of file app_voicemail.c.

References ast_cond_signal(), ast_event_unsubscribe(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, mwi_sub_sub, mwi_unsub_sub, and poll_lock.

Referenced by load_config(), and unload_module().

10346 {
10347    poll_thread_run = 0;
10348 
10349    if (mwi_sub_sub) {
10350       ast_event_unsubscribe(mwi_sub_sub);
10351       mwi_sub_sub = NULL;
10352    }
10353 
10354    if (mwi_unsub_sub) {
10355       ast_event_unsubscribe(mwi_unsub_sub);
10356       mwi_unsub_sub = NULL;
10357    }
10358 
10359    ast_mutex_lock(&poll_lock);
10360    ast_cond_signal(&poll_cond);
10361    ast_mutex_unlock(&poll_lock);
10362 
10363    pthread_join(poll_thread, NULL);
10364 
10365    poll_thread = AST_PTHREADT_NULL;
10366 }

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

Referenced by make_email_file().

00787 {
00788    char *bufptr = buf;
00789    for (; *input; input++) {
00790       if (*input < 32) {
00791          continue;
00792       }
00793       *bufptr++ = *input;
00794       if (bufptr == buf + buflen - 1) {
00795          break;
00796       }
00797    }
00798    *bufptr = '\0';
00799    return buf;
00800 }

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

Definition at line 10491 of file app_voicemail.c.

References ast_log(), AST_LOG_NOTICE, ast_str_append(), ast_str_create(), and str.

Referenced by load_config().

10492 {
10493    char *current, *result;
10494 
10495    /* Add 16 for fudge factor */
10496    struct ast_str *str = ast_str_create(strlen(value) + 16);
10497 
10498    /* Substitute strings \r, \n, and \t into the appropriate characters */
10499    for (current = (char *) value; *current; current++) {
10500       if (*current == '\\') {
10501          current++;
10502          if (!*current) {
10503             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
10504             break;
10505          }
10506          switch (*current) {
10507          case 'r':
10508             ast_str_append(&str, 0, "\r");
10509             break;
10510          case 'n':
10511 #ifdef IMAP_STORAGE
10512             if (!str->used || str->str[str->used - 1] != '\r') {
10513                ast_str_append(&str, 0, "\r");
10514             }
10515 #endif
10516             ast_str_append(&str, 0, "\n");
10517             break;
10518          case 't':
10519             ast_str_append(&str, 0, "\t");
10520             break;
10521          default:
10522             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
10523             break;
10524          }
10525       } else {
10526          ast_str_append(&str, 0, "%c", *current);
10527       }
10528    }
10529 
10530    result = ast_strdup(str->str);
10531    ast_free(str);
10532 
10533    return result;
10534 }

static int unload_module ( void   )  [static]

Definition at line 11199 of file app_voicemail.c.

References ao2_ref, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), ast_uninstall_vm_functions(), ast_unload_realtime(), ast_unregister_application(), cli_voicemail, free_vm_users(), free_vm_zones(), inprocess_container, mailbox_exists_acf, mwi_subscription_tps, and stop_poll_thread().

11200 {
11201    int res;
11202 
11203    res = ast_unregister_application(app);
11204    res |= ast_unregister_application(app2);
11205    res |= ast_unregister_application(app3);
11206    res |= ast_unregister_application(app4);
11207    res |= ast_custom_function_unregister(&mailbox_exists_acf);
11208    res |= ast_manager_unregister("VoicemailUsersList");
11209    ast_cli_unregister_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
11210    ast_uninstall_vm_functions();
11211    ao2_ref(inprocess_container, -1);
11212 
11213    if (poll_thread != AST_PTHREADT_NULL)
11214       stop_poll_thread();
11215 
11216    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
11217    ast_unload_realtime("voicemail");
11218    ast_unload_realtime("voicemail_data");
11219 
11220    free_vm_users();
11221    free_vm_zones();
11222    return res;
11223 }

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

References adsi_begin(), adsi_login(), adsi_password(), ast_copy_string(), ast_debug, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitstream(), chan, find_user(), ast_vm_user::password, and vm_password.

Referenced by vm_execmain(), and vmauthenticate().

08926 {
08927    int useadsi=0, valid=0, logretries=0;
08928    char password[AST_MAX_EXTENSION]="", *passptr;
08929    struct ast_vm_user vmus, *vmu = NULL;
08930 
08931    /* If ADSI is supported, setup login screen */
08932    adsi_begin(chan, &useadsi);
08933    if (!skipuser && useadsi)
08934       adsi_login(chan);
08935    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
08936       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
08937       return -1;
08938    }
08939    
08940    /* Authenticate them and get their mailbox/password */
08941    
08942    while (!valid && (logretries < max_logins)) {
08943       /* Prompt for, and read in the username */
08944       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
08945          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
08946          return -1;
08947       }
08948       if (ast_strlen_zero(mailbox)) {
08949          if (chan->cid.cid_num) {
08950             ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
08951          } else {
08952             ast_verb(3,"Username not entered\n");  
08953             return -1;
08954          }
08955       }
08956       if (useadsi)
08957          adsi_password(chan);
08958 
08959       if (!ast_strlen_zero(prefix)) {
08960          char fullusername[80] = "";
08961          ast_copy_string(fullusername, prefix, sizeof(fullusername));
08962          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
08963          ast_copy_string(mailbox, fullusername, mailbox_size);
08964       }
08965 
08966       ast_debug(1, "Before find user for mailbox %s\n",mailbox);
08967       vmu = find_user(&vmus, context, mailbox);
08968       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
08969          /* saved password is blank, so don't bother asking */
08970          password[0] = '\0';
08971       } else {
08972          if (ast_streamfile(chan, vm_password, chan->language)) {
08973             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
08974             return -1;
08975          }
08976          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
08977             ast_log(AST_LOG_WARNING, "Unable to read password\n");
08978             return -1;
08979          }
08980       }
08981 
08982       if (vmu) {
08983          passptr = vmu->password;
08984          if (passptr[0] == '-') passptr++;
08985       }
08986       if (vmu && !strcmp(passptr, password))
08987          valid++;
08988       else {
08989          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
08990          if (!ast_strlen_zero(prefix))
08991             mailbox[0] = '\0';
08992       }
08993       logretries++;
08994       if (!valid) {
08995          if (skipuser || logretries >= max_logins) {
08996             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
08997                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
08998                return -1;
08999             }
09000          } else {
09001             if (useadsi)
09002                adsi_login(chan);
09003             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09004                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09005                return -1;
09006             }
09007          }
09008          if (ast_waitstream(chan, "")) /* Channel is hung up */
09009             return -1;
09010       }
09011    }
09012    if (!valid && (logretries >= max_logins)) {
09013       ast_stopstream(chan);
09014       ast_play_and_wait(chan, "vm-goodbye");
09015       return -1;
09016    }
09017    if (vmu && !skipuser) {
09018       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09019    }
09020    return 0;
09021 }

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

Definition at line 9869 of file app_voicemail.c.

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

Referenced by load_module().

09870 {
09871    struct ast_vm_user svm;
09872    char *context, *box;
09873    AST_DECLARE_APP_ARGS(args,
09874       AST_APP_ARG(mbox);
09875       AST_APP_ARG(options);
09876    );
09877    static int dep_warning = 0;
09878 
09879    if (ast_strlen_zero(data)) {
09880       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
09881       return -1;
09882    }
09883 
09884    if (!dep_warning) {
09885       dep_warning = 1;
09886       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
09887    }
09888 
09889    box = ast_strdupa(data);
09890 
09891    AST_STANDARD_APP_ARGS(args, box);
09892 
09893    if (args.options) {
09894    }
09895 
09896    if ((context = strchr(args.mbox, '@'))) {
09897       *context = '\0';
09898       context++;
09899    }
09900 
09901    if (find_user(&svm, context, args.mbox)) {
09902       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
09903    } else
09904       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
09905 
09906    return 0;
09907 }

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

References chan, ast_channel::language, vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_pt(), and vm_browse_messages_zh().

Referenced by vm_execmain().

08905 {
08906    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
08907       return vm_browse_messages_es(chan, vms, vmu);
08908    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
08909       return vm_browse_messages_gr(chan, vms, vmu);
08910    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
08911       return vm_browse_messages_he(chan, vms, vmu);
08912    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
08913       return vm_browse_messages_it(chan, vms, vmu);
08914    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
08915       return vm_browse_messages_pt(chan, vms, vmu);
08916    } else if (!strncasecmp(chan->language, "zh", 2)) {
08917       return vm_browse_messages_zh(chan, vms, vmu);   /* CHINESE (Taiwan) */
08918    } else {                                             /* Default to English syntax */
08919       return vm_browse_messages_en(chan, vms, vmu);
08920    }
08921 }

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

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

Referenced by vm_browse_messages().

08768 {
08769    int cmd=0;
08770 
08771    if (vms->lastmsg > -1) {
08772       cmd = play_message(chan, vmu, vms);
08773    } else {
08774       cmd = ast_play_and_wait(chan, "vm-youhave");
08775       if (!cmd) 
08776          cmd = ast_play_and_wait(chan, "vm-no");
08777       if (!cmd) {
08778          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08779          cmd = ast_play_and_wait(chan, vms->fn);
08780       }
08781       if (!cmd)
08782          cmd = ast_play_and_wait(chan, "vm-messages");
08783    }
08784    return cmd;
08785 }

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

Spanish syntax for 'You have N messages' greeting.

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

Definition at line 8821 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08822 {
08823    int cmd=0;
08824 
08825    if (vms->lastmsg > -1) {
08826       cmd = play_message(chan, vmu, vms);
08827    } else {
08828       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08829       if (!cmd)
08830          cmd = ast_play_and_wait(chan, "vm-messages");
08831       if (!cmd) {
08832          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08833          cmd = ast_play_and_wait(chan, vms->fn);
08834       }
08835    }
08836    return cmd;
08837 }

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

Greek syntax for 'You have N messages' greeting.

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

Definition at line 8715 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08716 {
08717    int cmd=0;
08718 
08719    if (vms->lastmsg > -1) {
08720       cmd = play_message(chan, vmu, vms);
08721    } else {
08722       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08723       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
08724          if (!cmd) {
08725             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
08726             cmd = ast_play_and_wait(chan, vms->fn);
08727          }
08728          if (!cmd)
08729             cmd = ast_play_and_wait(chan, "vm-messages");
08730       } else {
08731          if (!cmd)
08732             cmd = ast_play_and_wait(chan, "vm-messages");
08733          if (!cmd) {
08734             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08735             cmd = ast_play_and_wait(chan, vms->fn);
08736          }
08737       }
08738    } 
08739    return cmd;
08740 }

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

Definition at line 8743 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08744 {
08745    int cmd = 0;
08746 
08747    if (vms->lastmsg > -1) {
08748       cmd = play_message(chan, vmu, vms);
08749    } else {
08750       if (!strcasecmp(vms->fn, "INBOX")) {
08751          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
08752       } else {
08753          cmd = ast_play_and_wait(chan, "vm-nomessages");
08754       }
08755    }
08756    return cmd;
08757 }

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

Italian syntax for 'You have N messages' greeting.

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

Definition at line 8795 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08796 {
08797    int cmd=0;
08798 
08799    if (vms->lastmsg > -1) {
08800       cmd = play_message(chan, vmu, vms);
08801    } else {
08802       cmd = ast_play_and_wait(chan, "vm-no");
08803       if (!cmd)
08804          cmd = ast_play_and_wait(chan, "vm-message");
08805       if (!cmd) {
08806          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08807          cmd = ast_play_and_wait(chan, vms->fn);
08808       }
08809    }
08810    return cmd;
08811 }

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

Portuguese syntax for 'You have N messages' greeting.

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

Definition at line 8847 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08848 {
08849    int cmd=0;
08850 
08851    if (vms->lastmsg > -1) {
08852       cmd = play_message(chan, vmu, vms);
08853    } else {
08854       cmd = ast_play_and_wait(chan, "vm-no");
08855       if (!cmd) {
08856          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08857          cmd = ast_play_and_wait(chan, vms->fn);
08858       }
08859       if (!cmd)
08860          cmd = ast_play_and_wait(chan, "vm-messages");
08861    }
08862    return cmd;
08863 }

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

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

Referenced by vm_browse_messages().

08874 {
08875    int cmd=0;
08876 
08877    if (vms->lastmsg > -1) {
08878       cmd = play_message(chan, vmu, vms);
08879    } else {
08880       cmd = ast_play_and_wait(chan, "vm-you");
08881       if (!cmd) 
08882          cmd = ast_play_and_wait(chan, "vm-haveno");
08883       if (!cmd)
08884          cmd = ast_play_and_wait(chan, "vm-messages");
08885       if (!cmd) {
08886          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08887          cmd = ast_play_and_wait(chan, vms->fn);
08888       }
08889    }
08890    return cmd;
08891 }

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

References ast_category_browse(), ast_category_get(), ast_config_load, ast_copy_string(), ast_debug, ast_log(), AST_LOG_WARNING, ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, config_flags, config_text_file_save(), ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, reset_user_pw(), var, and VOICEMAIL_CONFIG.

Referenced by vm_newuser(), and vm_options().

01249 {
01250    struct ast_config   *cfg=NULL;
01251    struct ast_variable *var=NULL;
01252    struct ast_category *cat=NULL;
01253    char *category=NULL, *value=NULL, *new=NULL;
01254    const char *tmp=NULL;
01255    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01256    if (!change_password_realtime(vmu, newpassword))
01257       return;
01258 
01259    /* check voicemail.conf */
01260    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags))) {
01261       while ((category = ast_category_browse(cfg, category))) {
01262          if (!strcasecmp(category, vmu->context)) {
01263             if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01264                ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01265                break;
01266             }
01267             value = strstr(tmp,",");
01268             if (!value) {
01269                ast_log(AST_LOG_WARNING, "variable has bad format.\n");
01270                break;
01271             }
01272             new = alloca((strlen(value)+strlen(newpassword)+1));
01273             sprintf(new,"%s%s", newpassword, value);
01274             if (!(cat = ast_category_get(cfg, category))) {
01275                ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01276                break;
01277             }
01278             ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01279          }
01280       }
01281       /* save the results */
01282       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01283       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01284       config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01285    }
01286    category = NULL;
01287    var = NULL;
01288    /* check users.conf and update the password stored for the mailbox*/
01289    /* if no vmsecret entry exists create one. */
01290    if ((cfg = ast_config_load("users.conf", config_flags))) {
01291       ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01292       while ((category = ast_category_browse(cfg, category))) {
01293          ast_debug(4, "users.conf: %s\n", category);
01294          if (!strcasecmp(category, vmu->mailbox)) {
01295             if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01296                ast_debug(3, "looks like we need to make vmsecret!\n");
01297                var = ast_variable_new("vmsecret", newpassword, "");
01298             } 
01299             new = alloca(strlen(newpassword)+1);
01300             sprintf(new, "%s", newpassword);
01301             if (!(cat = ast_category_get(cfg, category))) {
01302                ast_debug(4, "failed to get category!\n");
01303                break;
01304             }
01305             if (!var)      
01306                ast_variable_update(cat, "vmsecret", new, NULL, 0);
01307             else
01308                ast_variable_append(cat, var);
01309          }
01310       }
01311       /* save the results and clean things up */
01312       reset_user_pw(vmu->context, vmu->mailbox, newpassword);  
01313       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01314       config_text_file_save("users.conf", cfg, "AppVoicemail");
01315    }
01316 }

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

Definition at line 1318 of file app_voicemail.c.

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

Referenced by vm_newuser(), and vm_options().

01319 {
01320    char buf[255];
01321    snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
01322    if (!ast_safe_system(buf)) {
01323       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01324       /* Reset the password in memory, too */
01325       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01326    }
01327 }

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

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

00943 {
00944    int fds[2], pid = 0;
00945 
00946    memset(buf, 0, len);
00947 
00948    if (pipe(fds)) {
00949       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
00950    } else {
00951       /* good to go*/
00952       pid = ast_safe_fork(0);
00953 
00954       if (pid < 0) {
00955          /* ok maybe not */
00956          close(fds[0]);
00957          close(fds[1]);
00958          snprintf(buf, len, "FAILURE: Fork failed");
00959       } else if (pid) {
00960          /* parent */
00961          close(fds[1]);
00962          if (read(fds[0], buf, len) < 0) {
00963             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
00964          }
00965          close(fds[0]);
00966       } else {
00967          /*  child */
00968          AST_DECLARE_APP_ARGS(arg,
00969             AST_APP_ARG(v)[20];
00970          );
00971          char *mycmd = ast_strdupa(command);
00972 
00973          close(fds[0]);
00974          dup2(fds[1], STDOUT_FILENO);
00975          close(fds[1]);
00976          ast_close_fds_above_n(STDOUT_FILENO);
00977 
00978          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
00979 
00980          execv(arg.v[0], arg.v); 
00981          printf("FAILURE: %s", strerror(errno));
00982          _exit(0);
00983       }
00984    }
00985    return buf;
00986 }

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

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

03742 {
03743    char *txt;
03744    int txtsize = 0;
03745 
03746    txtsize = (strlen(file) + 5)*sizeof(char);
03747    txt = alloca(txtsize);
03748    /* Sprintf here would safe because we alloca'd exactly the right length,
03749     * but trying to eliminate all sprintf's anyhow
03750     */
03751    if (ast_check_realtime("voicemail_data")) {
03752       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
03753    }
03754    snprintf(txt, txtsize, "%s.txt", file);
03755    unlink(txt);
03756    return ast_filedelete(file, NULL);
03757 }

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

Definition at line 9734 of file app_voicemail.c.

References ast_channel::_state, 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_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, chan, ERROR_LOCK_PATH, ast_flags::flags, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and vm_app_options.

Referenced by load_module(), and play_record_review().

09735 {
09736    int res = 0;
09737    char *tmp;
09738    struct leave_vm_options leave_options;
09739    struct ast_flags flags = { 0 };
09740    char *opts[OPT_ARG_ARRAY_SIZE];
09741    AST_DECLARE_APP_ARGS(args,
09742       AST_APP_ARG(argv0);
09743       AST_APP_ARG(argv1);
09744    );
09745    
09746    memset(&leave_options, 0, sizeof(leave_options));
09747 
09748    if (chan->_state != AST_STATE_UP)
09749       ast_answer(chan);
09750 
09751    if (!ast_strlen_zero(data)) {
09752       tmp = ast_strdupa(data);
09753       AST_STANDARD_APP_ARGS(args, tmp);
09754       if (args.argc == 2) {
09755          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09756             return -1;
09757          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
09758          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09759             int gain;
09760 
09761             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09762                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09763                return -1;
09764             } else {
09765                leave_options.record_gain = (signed char) gain;
09766             }
09767          }
09768          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
09769             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
09770                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
09771          }
09772       }
09773    } else {
09774       char temp[256];
09775       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
09776       if (res < 0)
09777          return res;
09778       if (ast_strlen_zero(temp))
09779          return 0;
09780       args.argv0 = ast_strdupa(temp);
09781    }
09782 
09783    res = leave_voicemail(chan, args.argv0, &leave_options);
09784    if (res == OPERATOR_EXIT) {
09785       res = 0;
09786    }
09787 
09788    if (res == ERROR_LOCK_PATH) {
09789       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
09790       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
09791       res = 0;
09792    }
09793 
09794    return res;
09795 }

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

Definition at line 9023 of file app_voicemail.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), ast_adsi_unload_session, ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_log(), AST_LOG_ERROR, 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_verb, ast_waitfordigit(), ast_vm_user::callback, chan, close_mailbox(), ast_vm_user::context, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), ast_flags::flags, forward_message(), free_user(), get_folder2(), globalflags, has_voicemail(), language, ast_vm_user::language, ast_vm_user::mailbox, make_file(), manager_event, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), run_externnotify(), save_to_folder(), say_and_wait(), vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, and VM_SVMAIL.

Referenced by load_module().

09024 {
09025    /* XXX This is, admittedly, some pretty horrendous code.  For some
09026       reason it just seemed a lot easier to do with GOTO's.  I feel
09027       like I'm back in my GWBASIC days. XXX */
09028    int res=-1;
09029    int cmd=0;
09030    int valid = 0;
09031    char prefixstr[80] ="";
09032    char ext_context[256]="";
09033    int box;
09034    int useadsi = 0;
09035    int skipuser = 0;
09036    struct vm_state vms;
09037    struct ast_vm_user *vmu = NULL, vmus;
09038    char *context=NULL;
09039    int silentexit = 0;
09040    struct ast_flags flags = { 0 };
09041    signed char record_gain = 0;
09042    int play_auto = 0;
09043    int play_folder = 0;
09044    int in_urgent = 0;
09045 #ifdef IMAP_STORAGE
09046    int deleted = 0;
09047 #endif
09048 
09049    /* Add the vm_state to the active list and keep it active */
09050    memset(&vms, 0, sizeof(vms));
09051 
09052    vms.lastmsg = -1;
09053 
09054    memset(&vmus, 0, sizeof(vmus));
09055 
09056    if (chan->_state != AST_STATE_UP) {
09057       ast_debug(1, "Before ast_answer\n");
09058       ast_answer(chan);
09059    }
09060 
09061    if (!ast_strlen_zero(data)) {
09062       char *opts[OPT_ARG_ARRAY_SIZE];
09063       char *parse;
09064       AST_DECLARE_APP_ARGS(args,
09065          AST_APP_ARG(argv0);
09066          AST_APP_ARG(argv1);
09067       );
09068 
09069       parse = ast_strdupa(data);
09070 
09071       AST_STANDARD_APP_ARGS(args, parse);
09072 
09073       if (args.argc == 2) {
09074          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09075             return -1;
09076          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09077             int gain;
09078             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
09079                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09080                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09081                   return -1;
09082                } else {
09083                   record_gain = (signed char) gain;
09084                }
09085             } else {
09086                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
09087             }
09088          }
09089          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
09090             play_auto = 1;
09091             if (opts[OPT_ARG_PLAYFOLDER]) {
09092                if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
09093                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for folder autoplay option\n", opts[OPT_ARG_PLAYFOLDER]);
09094                }
09095             } else {
09096                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
09097             }  
09098             if ( play_folder > 9 || play_folder < 0) {
09099                ast_log(AST_LOG_WARNING, "Invalid value '%d' provided for folder autoplay option\n", play_folder);
09100                play_folder = 0;
09101             }
09102          }
09103       } else {
09104          /* old style options parsing */
09105          while (*(args.argv0)) {
09106             if (*(args.argv0) == 's')
09107                ast_set_flag(&flags, OPT_SILENT);
09108             else if (*(args.argv0) == 'p')
09109                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
09110             else 
09111                break;
09112             (args.argv0)++;
09113          }
09114 
09115       }
09116 
09117       valid = ast_test_flag(&flags, OPT_SILENT);
09118 
09119       if ((context = strchr(args.argv0, '@')))
09120          *context++ = '\0';
09121 
09122       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
09123          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
09124       else
09125          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
09126 
09127       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
09128          skipuser++;
09129       else
09130          valid = 0;
09131    }
09132 
09133    if (!valid)
09134       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
09135 
09136    ast_debug(1, "After vm_authenticate\n");
09137    if (!res) {
09138       valid = 1;
09139       if (!skipuser)
09140          vmu = &vmus;
09141    } else {
09142       res = 0;
09143    }
09144 
09145    /* If ADSI is supported, setup login screen */
09146    adsi_begin(chan, &useadsi);
09147 
09148    if (!valid) {
09149       goto out;
09150    }
09151 
09152 #ifdef IMAP_STORAGE
09153    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
09154    pthread_setspecific(ts_vmstate.key, &vms);
09155 
09156    vms.interactive = 1;
09157    vms.updated = 1;
09158    if (vmu)
09159       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
09160    vmstate_insert(&vms);
09161    init_vm_state(&vms);
09162 #endif
09163    if (!(vms.deleted = ast_calloc(vmu->maxmsg, sizeof(int)))) {
09164       ast_log(AST_LOG_ERROR, "Could not allocate memory for deleted message storage!\n");
09165       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09166       return -1;
09167    }
09168    if (!(vms.heard = ast_calloc(vmu->maxmsg, sizeof(int)))) {
09169       ast_log(AST_LOG_ERROR, "Could not allocate memory for heard message storage!\n");
09170       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09171       return -1;
09172    }
09173    
09174    /* Set language from config to override channel language */
09175    if (!ast_strlen_zero(vmu->language))
09176       ast_string_field_set(chan, language, vmu->language);
09177 
09178    /* Retrieve urgent, old and new message counts */
09179    ast_debug(1, "Before open_mailbox\n");
09180    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09181    if (res == ERROR_LOCK_PATH)
09182       goto out;
09183    vms.oldmessages = vms.lastmsg + 1;
09184    ast_debug(1, "Number of old messages: %d\n",vms.oldmessages);
09185    /* check INBOX */
09186    res = open_mailbox(&vms, vmu, NEW_FOLDER);
09187    if (res == ERROR_LOCK_PATH)
09188       goto out;
09189    vms.newmessages = vms.lastmsg + 1;
09190    ast_debug(1, "Number of new messages: %d\n",vms.newmessages);
09191    /* Start in Urgent */
09192    in_urgent = 1;
09193    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
09194    if (res == ERROR_LOCK_PATH)
09195       goto out;
09196    vms.urgentmessages = vms.lastmsg + 1;
09197    ast_debug(1, "Number of urgent messages: %d\n",vms.urgentmessages);
09198 
09199    /* Select proper mailbox FIRST!! */
09200    if (play_auto) {
09201       if (vms.urgentmessages) {
09202          in_urgent = 1;
09203          res = open_mailbox(&vms, vmu, 11);
09204       } else {
09205          in_urgent = 0;
09206          res = open_mailbox(&vms, vmu, play_folder);
09207       }
09208       if (res == ERROR_LOCK_PATH)
09209          goto out;
09210 
09211       /* If there are no new messages, inform the user and hangup */
09212       if (vms.lastmsg == -1) {
09213          in_urgent = 0;
09214          cmd = vm_browse_messages(chan, &vms, vmu);
09215          res = 0;
09216          goto out;
09217       }
09218    } else {
09219       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
09220          /* If we only have old messages start here */
09221          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09222          in_urgent = 0;
09223          play_folder = 1;
09224          if (res == ERROR_LOCK_PATH)
09225             goto out;
09226       } else if (!vms.urgentmessages && vms.newmessages) {
09227          /* If we have new messages but none are urgent */
09228          in_urgent = 0;
09229          res = open_mailbox(&vms, vmu, NEW_FOLDER);
09230          if (res == ERROR_LOCK_PATH)
09231             goto out;
09232       }
09233    }
09234 
09235    if (useadsi)
09236       adsi_status(chan, &vms);
09237    res = 0;
09238 
09239    /* Check to see if this is a new user */
09240    if (!strcasecmp(vmu->mailbox, vmu->password) && 
09241       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
09242       if (ast_play_and_wait(chan, "vm-newuser") == -1)
09243          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
09244       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
09245       if ((cmd == 't') || (cmd == '#')) {
09246          /* Timeout */
09247          res = 0;
09248          goto out;
09249       } else if (cmd < 0) {
09250          /* Hangup */
09251          res = -1;
09252          goto out;
09253       }
09254    }
09255 #ifdef IMAP_STORAGE
09256       ast_debug(3, "Checking quotas: comparing %u to %u\n",vms.quota_usage,vms.quota_limit);
09257       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
09258          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
09259          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09260       }
09261       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n",(vms.newmessages + vms.oldmessages),vmu->maxmsg);
09262       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
09263          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09264          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09265       }
09266 #endif
09267    if (play_auto) {
09268       cmd = '1';
09269    } else {
09270       cmd = vm_intro(chan, vmu, &vms);
09271    }
09272 
09273    vms.repeats = 0;
09274    vms.starting = 1;
09275    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09276       /* Run main menu */
09277       switch (cmd) {
09278       case '1': /* First message */
09279          vms.curmsg = 0;
09280          /* Fall through */
09281       case '5': /* Play current message */
09282          cmd = vm_browse_messages(chan, &vms, vmu);
09283          break;
09284       case '2': /* Change folders */
09285          if (useadsi)
09286             adsi_folders(chan, 0, "Change to folder...");
09287          cmd = get_folder2(chan, "vm-changeto", 0);
09288          if (cmd == '#') {
09289             cmd = 0;
09290          } else if (cmd > 0) {
09291             cmd = cmd - '0';
09292             res = close_mailbox(&vms, vmu);
09293             if (res == ERROR_LOCK_PATH)
09294                goto out;
09295             /* If folder is not urgent, set in_urgent to zero! */
09296             if (cmd != 11) in_urgent = 0;
09297             res = open_mailbox(&vms, vmu, cmd);
09298             if (res == ERROR_LOCK_PATH)
09299                goto out;
09300             play_folder = cmd;
09301             cmd = 0;
09302          }
09303          if (useadsi)
09304             adsi_status2(chan, &vms);
09305             
09306          if (!cmd)
09307             cmd = vm_play_folder_name(chan, vms.vmbox);
09308 
09309          vms.starting = 1;
09310          break;
09311       case '3': /* Advanced options */
09312          cmd = 0;
09313          vms.repeats = 0;
09314          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09315             switch (cmd) {
09316             case '1': /* Reply */
09317                if (vms.lastmsg > -1 && !vms.starting) {
09318                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
09319                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09320                      res = cmd;
09321                      goto out;
09322                   }
09323                } else
09324                   cmd = ast_play_and_wait(chan, "vm-sorry");
09325                cmd = 't';
09326                break;
09327             case '2': /* Callback */
09328                if (!vms.starting)
09329                   ast_verb(3, "Callback Requested\n");
09330                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
09331                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
09332                   if (cmd == 9) {
09333                      silentexit = 1;
09334                      goto out;
09335                   } else if (cmd == ERROR_LOCK_PATH) {
09336                      res = cmd;
09337                      goto out;
09338                   }
09339                } else 
09340                   cmd = ast_play_and_wait(chan, "vm-sorry");
09341                cmd = 't';
09342                break;
09343             case '3': /* Envelope */
09344                if (vms.lastmsg > -1 && !vms.starting) {
09345                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
09346                   if (cmd == ERROR_LOCK_PATH) {
09347                      res = cmd;
09348                      goto out;
09349                   }
09350                } else
09351                   cmd = ast_play_and_wait(chan, "vm-sorry");
09352                cmd = 't';
09353                break;
09354             case '4': /* Dialout */
09355                if (!ast_strlen_zero(vmu->dialout)) {
09356                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
09357                   if (cmd == 9) {
09358                      silentexit = 1;
09359                      goto out;
09360                   }
09361                } else 
09362                   cmd = ast_play_and_wait(chan, "vm-sorry");
09363                cmd = 't';
09364                break;
09365 
09366             case '5': /* Leave VoiceMail */
09367                if (ast_test_flag(vmu, VM_SVMAIL)) {
09368                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
09369                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09370                      res = cmd;
09371                      goto out;
09372                   }
09373                } else
09374                   cmd = ast_play_and_wait(chan,"vm-sorry");
09375                cmd='t';
09376                break;
09377                
09378             case '*': /* Return to main menu */
09379                cmd = 't';
09380                break;
09381 
09382             default:
09383                cmd = 0;
09384                if (!vms.starting) {
09385                   cmd = ast_play_and_wait(chan, "vm-toreply");
09386                }
09387                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
09388                   cmd = ast_play_and_wait(chan, "vm-tocallback");
09389                }
09390                if (!cmd && !vms.starting) {
09391                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
09392                }
09393                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
09394                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
09395                }
09396                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
09397                   cmd=ast_play_and_wait(chan, "vm-leavemsg");
09398                if (!cmd)
09399                   cmd = ast_play_and_wait(chan, "vm-starmain");
09400                if (!cmd)
09401                   cmd = ast_waitfordigit(chan,6000);
09402                if (!cmd)
09403                   vms.repeats++;
09404                if (vms.repeats > 3)
09405                   cmd = 't';
09406             }
09407          }
09408          if (cmd == 't') {
09409             cmd = 0;
09410             vms.repeats = 0;
09411          }
09412          break;
09413       case '4': /* Go to the previous message */
09414          if (vms.curmsg > 0) {
09415             vms.curmsg--;
09416             cmd = play_message(chan, vmu, &vms);
09417          } else {
09418             /* Check if we were listening to new
09419                messages.  If so, go to Urgent messages
09420                instead of saying "no more messages"
09421             */
09422             if (in_urgent == 0 && vms.urgentmessages > 0) {
09423                /* Check for Urgent messages */
09424                in_urgent = 1;
09425                res = close_mailbox(&vms, vmu);
09426                if (res == ERROR_LOCK_PATH)
09427                   goto out;
09428                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
09429                if (res == ERROR_LOCK_PATH)
09430                   goto out;
09431                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n",vms.lastmsg + 1);
09432                vms.curmsg = vms.lastmsg;
09433                if (vms.lastmsg < 0)
09434                   cmd = ast_play_and_wait(chan, "vm-nomore");
09435             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09436                vms.curmsg = vms.lastmsg;
09437                cmd = play_message(chan, vmu, &vms);
09438             } else {
09439                cmd = ast_play_and_wait(chan, "vm-nomore");
09440             }
09441          }
09442          break;
09443       case '6': /* Go to the next message */
09444          if (vms.curmsg < vms.lastmsg) {
09445             vms.curmsg++;
09446             cmd = play_message(chan, vmu, &vms);
09447          } else {
09448             if (in_urgent && vms.newmessages > 0) {
09449                /* Check if we were listening to urgent
09450                 * messages.  If so, go to regular new messages
09451                 * instead of saying "no more messages"
09452                 */
09453                in_urgent = 0;
09454                res = close_mailbox(&vms, vmu);
09455                if (res == ERROR_LOCK_PATH)
09456                   goto out;
09457                res = open_mailbox(&vms, vmu, NEW_FOLDER);
09458                if (res == ERROR_LOCK_PATH)
09459                   goto out;
09460                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09461                vms.curmsg = -1;
09462                if (vms.lastmsg < 0) {
09463                   cmd = ast_play_and_wait(chan, "vm-nomore");
09464                }
09465             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09466                vms.curmsg = 0;
09467                cmd = play_message(chan, vmu, &vms);
09468             } else {
09469                cmd = ast_play_and_wait(chan, "vm-nomore");
09470             }
09471          }
09472          break;
09473       case '7': /* Delete the current message */
09474          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
09475             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
09476             if (useadsi)
09477                adsi_delete(chan, &vms);
09478             if (vms.deleted[vms.curmsg]) {
09479                if (play_folder == 0) {
09480                   if (in_urgent) {
09481                      vms.urgentmessages--;
09482                   } else {
09483                      vms.newmessages--;
09484                   }
09485                }
09486                else if (play_folder == 1)
09487                   vms.oldmessages--;
09488                cmd = ast_play_and_wait(chan, "vm-deleted");
09489             } else {
09490                if (play_folder == 0) {
09491                   if (in_urgent) {
09492                      vms.urgentmessages++;
09493                   } else {
09494                      vms.newmessages++;
09495                   }
09496                }
09497                else if (play_folder == 1)
09498                   vms.oldmessages++;
09499                cmd = ast_play_and_wait(chan, "vm-undeleted");
09500             }
09501             if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
09502                if (vms.curmsg < vms.lastmsg) {
09503                   vms.curmsg++;
09504                   cmd = play_message(chan, vmu, &vms);
09505                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09506                   vms.curmsg = 0;
09507                   cmd = play_message(chan, vmu, &vms);
09508                } else {
09509                   /* Check if we were listening to urgent
09510                      messages.  If so, go to regular new messages
09511                      instead of saying "no more messages"
09512                   */
09513                   if (in_urgent == 1) {
09514                      /* Check for new messages */
09515                      in_urgent = 0;
09516                      res = close_mailbox(&vms, vmu);
09517                      if (res == ERROR_LOCK_PATH)
09518                         goto out;
09519                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
09520                      if (res == ERROR_LOCK_PATH)
09521                         goto out;
09522                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09523                      vms.curmsg = -1;
09524                      if (vms.lastmsg < 0)
09525                         cmd = ast_play_and_wait(chan, "vm-nomore");
09526                   } else {
09527                      cmd = ast_play_and_wait(chan, "vm-nomore");
09528                   }
09529                }
09530             }
09531          } else /* Delete not valid if we haven't selected a message */
09532             cmd = 0;
09533 #ifdef IMAP_STORAGE
09534          deleted = 1;
09535 #endif
09536          break;
09537    
09538       case '8': /* Forward the current messgae */
09539          if (vms.lastmsg > -1) {
09540             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
09541             if (cmd == ERROR_LOCK_PATH) {
09542                res = cmd;
09543                goto out;
09544             }
09545          } else {
09546             /* Check if we were listening to urgent
09547                messages.  If so, go to regular new messages
09548                instead of saying "no more messages"
09549             */
09550             if (in_urgent == 1 && vms.newmessages > 0) {
09551                /* Check for new messages */
09552                in_urgent = 0;
09553                res = close_mailbox(&vms, vmu);
09554                if (res == ERROR_LOCK_PATH)
09555                   goto out;
09556                res = open_mailbox(&vms, vmu, NEW_FOLDER);
09557                if (res == ERROR_LOCK_PATH)
09558                   goto out;
09559                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09560                vms.curmsg = -1;
09561                if (vms.lastmsg < 0)
09562                   cmd = ast_play_and_wait(chan, "vm-nomore");
09563             } else {
09564                cmd = ast_play_and_wait(chan, "vm-nomore");
09565             }
09566          }
09567          break;
09568       case '9': /* Save message to folder */
09569          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
09570             /* No message selected */
09571             cmd = 0;
09572             break;
09573          }
09574          if (useadsi)
09575             adsi_folders(chan, 1, "Save to folder...");
09576          cmd = get_folder2(chan, "vm-savefolder", 1);
09577          box = 0; /* Shut up compiler */
09578          if (cmd == '#') {
09579             cmd = 0;
09580             break;
09581          } else if (cmd > 0) {
09582             box = cmd = cmd - '0';
09583             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
09584             if (cmd == ERROR_LOCK_PATH) {
09585                res = cmd;
09586                goto out;
09587 #ifndef IMAP_STORAGE
09588             } else if (!cmd) {
09589                vms.deleted[vms.curmsg] = 1;
09590 #endif
09591             } else {
09592                vms.deleted[vms.curmsg] = 0;
09593                vms.heard[vms.curmsg] = 0;
09594             }
09595          }
09596          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
09597          if (useadsi)
09598             adsi_message(chan, &vms);
09599          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box));
09600          if (!cmd) {
09601             cmd = ast_play_and_wait(chan, "vm-message");
09602             if (!cmd) 
09603                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
09604             if (!cmd)
09605                cmd = ast_play_and_wait(chan, "vm-savedto");
09606             if (!cmd)
09607                cmd = vm_play_folder_name(chan, vms.fn);
09608          } else {
09609             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09610          }
09611          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
09612             if (vms.curmsg < vms.lastmsg) {
09613                vms.curmsg++;
09614                cmd = play_message(chan, vmu, &vms);
09615             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
09616                vms.curmsg = 0;
09617                cmd = play_message(chan, vmu, &vms);
09618             } else {
09619                /* Check if we were listening to urgent
09620                   messages.  If so, go to regular new messages
09621                   instead of saying "no more messages"
09622                */
09623                if (in_urgent == 1 && vms.newmessages > 0) {
09624                   /* Check for new messages */
09625                   in_urgent = 0;
09626                   res = close_mailbox(&vms, vmu);
09627                   if (res == ERROR_LOCK_PATH)
09628                      goto out;
09629                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
09630                   if (res == ERROR_LOCK_PATH)
09631                      goto out;
09632                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
09633                   vms.curmsg = -1;
09634                   if (vms.lastmsg < 0)
09635                      cmd = ast_play_and_wait(chan, "vm-nomore");
09636                } else {
09637                   cmd = ast_play_and_wait(chan, "vm-nomore");
09638                }
09639             }
09640          }
09641          break;
09642       case '*': /* Help */
09643          if (!vms.starting) {
09644             cmd = ast_play_and_wait(chan, "vm-onefor");
09645             if (!strncasecmp(chan->language, "he", 2)) {
09646                cmd = ast_play_and_wait(chan, "vm-for");
09647             }
09648             if (!cmd)
09649                cmd = vm_play_folder_name(chan, vms.vmbox);
09650             if (!cmd)
09651                cmd = ast_play_and_wait(chan, "vm-opts");
09652             if (!cmd)
09653                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
09654          } else
09655             cmd = 0;
09656          break;
09657       case '0': /* Mailbox options */
09658          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
09659          if (useadsi)
09660             adsi_status(chan, &vms);
09661          break;
09662       default: /* Nothing */
09663          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
09664          break;
09665       }
09666    }
09667    if ((cmd == 't') || (cmd == '#')) {
09668       /* Timeout */
09669       res = 0;
09670    } else {
09671       /* Hangup */
09672       res = -1;
09673    }
09674 
09675 out:
09676    if (res > -1) {
09677       ast_stopstream(chan);
09678       adsi_goodbye(chan);
09679       if (valid && res != OPERATOR_EXIT) {
09680          if (silentexit)
09681             res = ast_play_and_wait(chan, "vm-dialout");
09682          else 
09683             res = ast_play_and_wait(chan, "vm-goodbye");
09684       }
09685       if ((valid && res > 0) || res == OPERATOR_EXIT) {
09686          res = 0;
09687       }
09688       if (useadsi)
09689          ast_adsi_unload_session(chan);
09690    }
09691    if (vmu)
09692       close_mailbox(&vms, vmu);
09693    if (valid) {
09694       int new = 0, old = 0, urgent = 0;
09695       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
09696       manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
09697       /* Urgent flag not passwd to externnotify here */
09698       run_externnotify(vmu->context, vmu->mailbox, NULL);
09699       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
09700       queue_mwi_event(ext_context, urgent, new, old);
09701    }
09702 #ifdef IMAP_STORAGE
09703    /* expunge message - use UID Expunge if supported on IMAP server*/
09704    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n",deleted,expungeonhangup);
09705    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
09706       ast_mutex_lock(&vms.lock);
09707 #ifdef HAVE_IMAP_TK2006
09708       if (LEVELUIDPLUS (vms.mailstream)) {
09709          mail_expunge_full(vms.mailstream,NIL,EX_UID);
09710       } else 
09711 #endif
09712          mail_expunge(vms.mailstream);
09713       ast_mutex_unlock(&vms.lock);
09714    }
09715    /*  before we delete the state, we should copy pertinent info
09716     *  back to the persistent model */
09717    if (vmu) {
09718       vmstate_delete(&vms);
09719    }
09720 #endif
09721    if (vmu)
09722       free_user(vmu);
09723    if (vms.deleted)
09724       ast_free(vms.deleted);
09725    if (vms.heard)
09726       ast_free(vms.heard);
09727 
09728 #ifdef IMAP_STORAGE
09729    pthread_setspecific(ts_vmstate.key, NULL);
09730 #endif
09731    return res;
09732 }

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 
vmfmts 
context 
record_gain 
duration 
vms 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 6225 of file app_voicemail.c.

References ast_category_get(), ast_channel_setoption(), ast_config_destroy(), ast_config_load, ast_filecopy(), ast_filerename(), AST_OPTION_RXGAIN, ast_play_and_prepend(), ast_play_and_wait(), ast_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), chan, CONFIG_FLAG_NOCACHE, config_flags, config_text_file_save(), copy(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

Referenced by forward_message().

06227 {
06228 #ifdef IMAP_STORAGE
06229    int res;
06230 #endif
06231    int cmd = 0;
06232    int retries = 0, prepend_duration = 0, already_recorded = 0;
06233    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06234    char textfile[PATH_MAX];
06235    struct ast_config *msg_cfg;
06236    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06237 #ifndef IMAP_STORAGE
06238    signed char zero_gain = 0;
06239 #endif
06240    const char *duration_str;
06241 
06242    /* Must always populate duration correctly */
06243    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06244    strcpy(textfile, msgfile);
06245    strcpy(backup, msgfile);
06246    strcpy(backup_textfile, msgfile);
06247    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06248    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06249    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06250 
06251    if ((msg_cfg = ast_config_load(textfile, config_flags)) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06252       *duration = atoi(duration_str);
06253    } else {
06254       *duration = 0;
06255    }
06256 
06257    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06258       if (cmd)
06259          retries = 0;
06260       switch (cmd) {
06261       case '1': 
06262 
06263 #ifdef IMAP_STORAGE
06264          /* Record new intro file */
06265          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06266          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06267          res = ast_play_and_wait(chan, INTRO);
06268          res = ast_play_and_wait(chan, "beep");
06269          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *)duration, NULL, record_gain, vms, flag);
06270          cmd = 't';
06271 #else
06272 
06273          /* prepend a message to the current message, update the metadata and return */
06274 
06275          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06276          strcpy(textfile, msgfile);
06277          strncat(textfile, ".txt", sizeof(textfile) - 1);
06278          *duration = 0;
06279 
06280          /* if we can't read the message metadata, stop now */
06281          if (!msg_cfg) {
06282             cmd = 0;
06283             break;
06284          }
06285          
06286          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06287          if (already_recorded) {
06288             ast_filecopy(backup, msgfile, NULL);
06289             copy(backup_textfile, textfile);
06290          }
06291          else {
06292             ast_filecopy(msgfile, backup, NULL);
06293             copy(textfile,backup_textfile);
06294          }
06295          already_recorded = 1;
06296 
06297          if (record_gain)
06298             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06299 
06300          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06301          if (record_gain)
06302             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06303 
06304          
06305          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06306             *duration = atoi(duration_str);
06307 
06308          if (prepend_duration) {
06309             struct ast_category *msg_cat;
06310             /* need enough space for a maximum-length message duration */
06311             char duration_buf[12];
06312 
06313             *duration += prepend_duration;
06314             msg_cat = ast_category_get(msg_cfg, "message");
06315             snprintf(duration_buf, 11, "%ld", *duration);
06316             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06317                config_text_file_save(textfile, msg_cfg, "app_voicemail");
06318             }
06319          }
06320 
06321 #endif
06322          break;
06323       case '2': 
06324          /* NULL out introfile so we know there is no intro! */
06325 #ifdef IMAP_STORAGE
06326          *vms->introfn = '\0';
06327 #endif
06328          cmd = 't';
06329          break;
06330       case '*':
06331          cmd = '*';
06332          break;
06333       default: 
06334          cmd = ast_play_and_wait(chan,"vm-forwardoptions");
06335             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06336          if (!cmd)
06337             cmd = ast_play_and_wait(chan,"vm-starmain");
06338             /* "press star to return to the main menu" */
06339          if (!cmd)
06340             cmd = ast_waitfordigit(chan,6000);
06341          if (!cmd)
06342             retries++;
06343          if (retries > 3)
06344             cmd = 't';
06345       }
06346    }
06347 
06348    if (msg_cfg)
06349       ast_config_destroy(msg_cfg);
06350    if (prepend_duration)
06351       *duration = prepend_duration;
06352 
06353    if (already_recorded && cmd == -1) {
06354       /* restore original message if prepention cancelled */
06355       ast_filerename(backup, msgfile, NULL);
06356       rename(backup_textfile, textfile);
06357    }
06358 
06359    if (cmd == 't' || cmd == 'S')
06360       cmd = 0;
06361    return cmd;
06362 }

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

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

Referenced by vm_execmain().

08408 {
08409    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08410       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08411    } else {             /* Default to ENGLISH */
08412       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08413    }
08414 }

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

References ast_play_and_wait(), ast_test_flag, ast_waitfordigit(), chan, 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().

08307 {
08308    int res = 0;
08309    /* Play instructions and wait for new command */
08310    while (!res) {
08311       if (vms->starting) {
08312          if (vms->lastmsg > -1) {
08313             if (skipadvanced)
08314                res = ast_play_and_wait(chan, "vm-onefor-full");
08315             else
08316                res = ast_play_and_wait(chan, "vm-onefor");
08317             if (!res)
08318                res = vm_play_folder_name(chan, vms->vmbox);
08319          }
08320          if (!res) {
08321             if (skipadvanced)
08322                res = ast_play_and_wait(chan, "vm-opts-full");
08323             else
08324                res = ast_play_and_wait(chan, "vm-opts");
08325          }
08326       } else {
08327          /* Added for additional help */
08328          if (skipadvanced) {
08329             res = ast_play_and_wait(chan, "vm-onefor-full");
08330             if (!res)
08331                res = vm_play_folder_name(chan, vms->vmbox);
08332             res = ast_play_and_wait(chan, "vm-opts-full");
08333          }
08334          /* Logic:
08335           * If the current message is not the first OR
08336           * if we're listening to the first new message and there are
08337           * also urgent messages, then prompt for navigation to the
08338           * previous message
08339           */
08340          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08341             res = ast_play_and_wait(chan, "vm-prev");
08342          }
08343          if (!res && !skipadvanced)
08344             res = ast_play_and_wait(chan, "vm-advopts");
08345          if (!res)
08346             res = ast_play_and_wait(chan, "vm-repeat");
08347          /* Logic:
08348           * If we're not listening to the last message OR
08349           * we're listening to the last urgent message and there are
08350           * also new non-urgent messages, then prompt for navigation
08351           * to the next message
08352           */
08353          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08354             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08355             res = ast_play_and_wait(chan, "vm-next");
08356          }
08357          if (!res) {
08358             if (!vms->deleted[vms->curmsg])
08359                res = ast_play_and_wait(chan, "vm-delete");
08360             else
08361                res = ast_play_and_wait(chan, "vm-undelete");
08362             if (!res)
08363                res = ast_play_and_wait(chan, "vm-toforward");
08364             if (!res)
08365                res = ast_play_and_wait(chan, "vm-savemessage");
08366          }
08367       }
08368       if (!res) {
08369          res = ast_play_and_wait(chan, "vm-helpexit");
08370       }
08371       if (!res)
08372          res = ast_waitfordigit(chan, 6000);
08373       if (!res) {
08374          vms->repeats++;
08375          if (vms->repeats > 2) {
08376             res = 't';
08377          }
08378       }
08379    }
08380    return res;
08381 }

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

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

Referenced by vm_instructions().

08384 {
08385    int res = 0;
08386    /* Play instructions and wait for new command */
08387    while (!res) {
08388       if (vms->lastmsg > -1) {
08389          res = ast_play_and_wait(chan, "vm-listen");
08390          if (!res)
08391             res = vm_play_folder_name(chan, vms->vmbox);
08392          if (!res)
08393             res = ast_play_and_wait(chan, "press");
08394          if (!res)
08395             res = ast_play_and_wait(chan, "digits/1");
08396       }
08397       if (!res)
08398          res = ast_play_and_wait(chan, "vm-opts");
08399       if (!res) {
08400          vms->starting = 0;
08401          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08402       }
08403    }
08404    return res;
08405 }

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

Definition at line 8246 of file app_voicemail.c.

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

Referenced by vm_execmain().

08247 {
08248    char prefile[256];
08249    
08250    /* Notify the user that the temp greeting is set and give them the option to remove it */
08251    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08252    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08253       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08254       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08255          ast_play_and_wait(chan, "vm-tempgreetactive");
08256       }
08257       DISPOSE(prefile, -1);
08258    }
08259 
08260    /* Play voicemail intro - syntax is different for different languages */
08261    if (0) {
08262       return 0;
08263    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08264       return vm_intro_cs(chan, vms);
08265    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08266       static int deprecation_warning = 0;
08267       if (deprecation_warning++ % 10 == 0) {
08268          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08269       }
08270       return vm_intro_cs(chan, vms);
08271    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08272       return vm_intro_de(chan, vms);
08273    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08274       return vm_intro_es(chan, vms);
08275    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08276       return vm_intro_fr(chan, vms);
08277    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08278       return vm_intro_gr(chan, vms);
08279    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08280       return vm_intro_he(chan, vms);
08281    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08282       return vm_intro_it(chan, vms);
08283    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08284       return vm_intro_nl(chan, vms);
08285    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08286       return vm_intro_no(chan, vms);
08287    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08288       return vm_intro_pl(chan, vms);
08289    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08290       return vm_intro_pt_BR(chan, vms);
08291    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08292       return vm_intro_pt(chan, vms);
08293    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08294       return vm_intro_multilang(chan, vms, "n");
08295    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08296       return vm_intro_se(chan, vms);
08297    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08298       return vm_intro_multilang(chan, vms, "n");
08299    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08300       return vm_intro_zh(chan, vms);
08301    } else {                                             /* Default to ENGLISH */
08302       return vm_intro_en(chan, vms);
08303    }
08304 }

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

Definition at line 8147 of file app_voicemail.c.

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

Referenced by vm_intro().

08148 {
08149    int res;
08150    res = ast_play_and_wait(chan, "vm-youhave");
08151    if (!res) {
08152       if (vms->newmessages) {
08153          if (vms->newmessages == 1) {
08154             res = ast_play_and_wait(chan, "digits/jednu");
08155          } else {
08156             res = say_and_wait(chan, vms->newmessages, chan->language);
08157          }
08158          if (!res) {
08159             if ((vms->newmessages == 1))
08160                res = ast_play_and_wait(chan, "vm-novou");
08161             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08162                res = ast_play_and_wait(chan, "vm-nove");
08163             if (vms->newmessages > 4)
08164                res = ast_play_and_wait(chan, "vm-novych");
08165          }
08166          if (vms->oldmessages && !res)
08167             res = ast_play_and_wait(chan, "vm-and");
08168          else if (!res) {
08169             if ((vms->newmessages == 1))
08170                res = ast_play_and_wait(chan, "vm-zpravu");
08171             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08172                res = ast_play_and_wait(chan, "vm-zpravy");
08173             if (vms->newmessages > 4)
08174                res = ast_play_and_wait(chan, "vm-zprav");
08175          }
08176       }
08177       if (!res && vms->oldmessages) {
08178          res = say_and_wait(chan, vms->oldmessages, chan->language);
08179          if (!res) {
08180             if ((vms->oldmessages == 1))
08181                res = ast_play_and_wait(chan, "vm-starou");
08182             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08183                res = ast_play_and_wait(chan, "vm-stare");
08184             if (vms->oldmessages > 4)
08185                res = ast_play_and_wait(chan, "vm-starych");
08186          }
08187          if (!res) {
08188             if ((vms->oldmessages == 1))
08189                res = ast_play_and_wait(chan, "vm-zpravu");
08190             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08191                res = ast_play_and_wait(chan, "vm-zpravy");
08192             if (vms->oldmessages > 4)
08193                res = ast_play_and_wait(chan, "vm-zprav");
08194          }
08195       }
08196       if (!res) {
08197          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08198             res = ast_play_and_wait(chan, "vm-no");
08199             if (!res)
08200                res = ast_play_and_wait(chan, "vm-zpravy");
08201          }
08202       }
08203    }
08204    return res;
08205 }

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

Definition at line 7843 of file app_voicemail.c.

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

Referenced by vm_intro().

07844 {
07845    /* Introduce messages they have */
07846    int res;
07847    res = ast_play_and_wait(chan, "vm-youhave");
07848    if (!res) {
07849       if (vms->newmessages) {
07850          if ((vms->newmessages == 1))
07851             res = ast_play_and_wait(chan, "digits/1F");
07852          else
07853             res = say_and_wait(chan, vms->newmessages, chan->language);
07854          if (!res)
07855             res = ast_play_and_wait(chan, "vm-INBOX");
07856          if (vms->oldmessages && !res)
07857             res = ast_play_and_wait(chan, "vm-and");
07858          else if (!res) {
07859             if ((vms->newmessages == 1))
07860                res = ast_play_and_wait(chan, "vm-message");
07861             else
07862                res = ast_play_and_wait(chan, "vm-messages");
07863          }
07864             
07865       }
07866       if (!res && vms->oldmessages) {
07867          if (vms->oldmessages == 1)
07868             res = ast_play_and_wait(chan, "digits/1F");
07869          else
07870             res = say_and_wait(chan, vms->oldmessages, chan->language);
07871          if (!res)
07872             res = ast_play_and_wait(chan, "vm-Old");
07873          if (!res) {
07874             if (vms->oldmessages == 1)
07875                res = ast_play_and_wait(chan, "vm-message");
07876             else
07877                res = ast_play_and_wait(chan, "vm-messages");
07878          }
07879       }
07880       if (!res) {
07881          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07882             res = ast_play_and_wait(chan, "vm-no");
07883             if (!res)
07884                res = ast_play_and_wait(chan, "vm-messages");
07885          }
07886       }
07887    }
07888    return res;
07889 }

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

Definition at line 7592 of file app_voicemail.c.

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

Referenced by vm_intro().

07593 {
07594    int res;
07595 
07596    /* Introduce messages they have */
07597    res = ast_play_and_wait(chan, "vm-youhave");
07598    if (!res) {
07599       if (vms->urgentmessages) {
07600          res = say_and_wait(chan, vms->urgentmessages, chan->language);
07601          if (!res)
07602             res = ast_play_and_wait(chan, "vm-Urgent");
07603          if ((vms->oldmessages || vms->newmessages) && !res) {
07604             res = ast_play_and_wait(chan, "vm-and");
07605          } else if (!res) {
07606             if ((vms->urgentmessages == 1))
07607                res = ast_play_and_wait(chan, "vm-message");
07608             else
07609                res = ast_play_and_wait(chan, "vm-messages");
07610          }
07611       }
07612       if (vms->newmessages) {
07613          res = say_and_wait(chan, vms->newmessages, chan->language);
07614          if (!res)
07615             res = ast_play_and_wait(chan, "vm-INBOX");
07616          if (vms->oldmessages && !res)
07617             res = ast_play_and_wait(chan, "vm-and");
07618          else if (!res) {
07619             if ((vms->newmessages == 1))
07620                res = ast_play_and_wait(chan, "vm-message");
07621             else
07622                res = ast_play_and_wait(chan, "vm-messages");
07623          }
07624             
07625       }
07626       if (!res && vms->oldmessages) {
07627          res = say_and_wait(chan, vms->oldmessages, chan->language);
07628          if (!res)
07629             res = ast_play_and_wait(chan, "vm-Old");
07630          if (!res) {
07631             if (vms->oldmessages == 1)
07632                res = ast_play_and_wait(chan, "vm-message");
07633             else
07634                res = ast_play_and_wait(chan, "vm-messages");
07635          }
07636       }
07637       if (!res) {
07638          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
07639             res = ast_play_and_wait(chan, "vm-no");
07640             if (!res)
07641                res = ast_play_and_wait(chan, "vm-messages");
07642          }
07643       }
07644    }
07645    return res;
07646 }

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

Definition at line 7892 of file app_voicemail.c.

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

Referenced by vm_intro().

07893 {
07894    /* Introduce messages they have */
07895    int res;
07896    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07897       res = ast_play_and_wait(chan, "vm-youhaveno");
07898       if (!res)
07899          res = ast_play_and_wait(chan, "vm-messages");
07900    } else {
07901       res = ast_play_and_wait(chan, "vm-youhave");
07902    }
07903    if (!res) {
07904       if (vms->newmessages) {
07905          if (!res) {
07906             if ((vms->newmessages == 1)) {
07907                res = ast_play_and_wait(chan, "digits/1M");
07908                if (!res)
07909                   res = ast_play_and_wait(chan, "vm-message");
07910                if (!res)
07911                   res = ast_play_and_wait(chan, "vm-INBOXs");
07912             } else {
07913                res = say_and_wait(chan, vms->newmessages, chan->language);
07914                if (!res)
07915                   res = ast_play_and_wait(chan, "vm-messages");
07916                if (!res)
07917                   res = ast_play_and_wait(chan, "vm-INBOX");
07918             }
07919          }
07920          if (vms->oldmessages && !res)
07921             res = ast_play_and_wait(chan, "vm-and");
07922       }
07923       if (vms->oldmessages) {
07924          if (!res) {
07925             if (vms->oldmessages == 1) {
07926                res = ast_play_and_wait(chan, "digits/1M");
07927                if (!res)
07928                   res = ast_play_and_wait(chan, "vm-message");
07929                if (!res)
07930                   res = ast_play_and_wait(chan, "vm-Olds");
07931             } else {
07932                res = say_and_wait(chan, vms->oldmessages, chan->language);
07933                if (!res)
07934                   res = ast_play_and_wait(chan, "vm-messages");
07935                if (!res)
07936                   res = ast_play_and_wait(chan, "vm-Old");
07937             }
07938          }
07939       }
07940    }
07941 return res;
07942 }

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

Definition at line 7990 of file app_voicemail.c.

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

Referenced by vm_intro().

07991 {
07992    /* Introduce messages they have */
07993    int res;
07994    res = ast_play_and_wait(chan, "vm-youhave");
07995    if (!res) {
07996       if (vms->newmessages) {
07997          res = say_and_wait(chan, vms->newmessages, chan->language);
07998          if (!res)
07999             res = ast_play_and_wait(chan, "vm-INBOX");
08000          if (vms->oldmessages && !res)
08001             res = ast_play_and_wait(chan, "vm-and");
08002          else if (!res) {
08003             if ((vms->newmessages == 1))
08004                res = ast_play_and_wait(chan, "vm-message");
08005             else
08006                res = ast_play_and_wait(chan, "vm-messages");
08007          }
08008             
08009       }
08010       if (!res && vms->oldmessages) {
08011          res = say_and_wait(chan, vms->oldmessages, chan->language);
08012          if (!res)
08013             res = ast_play_and_wait(chan, "vm-Old");
08014          if (!res) {
08015             if (vms->oldmessages == 1)
08016                res = ast_play_and_wait(chan, "vm-message");
08017             else
08018                res = ast_play_and_wait(chan, "vm-messages");
08019          }
08020       }
08021       if (!res) {
08022          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08023             res = ast_play_and_wait(chan, "vm-no");
08024             if (!res)
08025                res = ast_play_and_wait(chan, "vm-messages");
08026          }
08027       }
08028    }
08029    return res;
08030 }

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

Definition at line 7391 of file app_voicemail.c.

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

Referenced by vm_intro().

07392 {
07393    int res = 0;
07394 
07395    if (vms->newmessages) {
07396       res = ast_play_and_wait(chan, "vm-youhave");
07397       if (!res) 
07398          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07399       if (!res) {
07400          if ((vms->newmessages == 1)) {
07401             res = ast_play_and_wait(chan, "vm-INBOX");
07402             if (!res)
07403                res = ast_play_and_wait(chan, "vm-message");
07404          } else {
07405             res = ast_play_and_wait(chan, "vm-INBOXs");
07406             if (!res)
07407                res = ast_play_and_wait(chan, "vm-messages");
07408          }
07409       }
07410    } else if (vms->oldmessages){
07411       res = ast_play_and_wait(chan, "vm-youhave");
07412       if (!res)
07413          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07414       if ((vms->oldmessages == 1)){
07415          res = ast_play_and_wait(chan, "vm-Old");
07416          if (!res)
07417             res = ast_play_and_wait(chan, "vm-message");
07418       } else {
07419          res = ast_play_and_wait(chan, "vm-Olds");
07420          if (!res)
07421             res = ast_play_and_wait(chan, "vm-messages");
07422       }
07423    } else if (!vms->oldmessages && !vms->newmessages) 
07424       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07425    return res;
07426 }

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

Definition at line 7525 of file app_voicemail.c.

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

Referenced by vm_intro().

07526 {
07527    int res = 0;
07528 
07529    /* Introduce messages they have */
07530    if (!res) {
07531       if ((vms->newmessages) || (vms->oldmessages)) {
07532          res = ast_play_and_wait(chan, "vm-youhave");
07533       }
07534       /*
07535        * The word "shtei" refers to the number 2 in hebrew when performing a count
07536        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
07537        * an element, this is one of them.
07538        */
07539       if (vms->newmessages) {
07540          if (!res) {
07541             if (vms->newmessages == 1) {
07542                res = ast_play_and_wait(chan, "vm-INBOX1");
07543             } else {
07544                if (vms->newmessages == 2) {
07545                   res = ast_play_and_wait(chan, "vm-shtei");
07546                } else {
07547                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07548                }
07549                res = ast_play_and_wait(chan, "vm-INBOX");
07550             }
07551          }
07552          if (vms->oldmessages && !res) {
07553             res = ast_play_and_wait(chan, "vm-and");
07554             if (vms->oldmessages == 1) {
07555                res = ast_play_and_wait(chan, "vm-Old1");
07556             } else {
07557                if (vms->oldmessages == 2) {
07558                   res = ast_play_and_wait(chan, "vm-shtei");
07559                } else {
07560                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07561                }
07562                res = ast_play_and_wait(chan, "vm-Old");
07563             }
07564          }
07565       }
07566       if (!res && vms->oldmessages && !vms->newmessages) {
07567          if (!res) {
07568             if (vms->oldmessages == 1) {
07569                res = ast_play_and_wait(chan, "vm-Old1");
07570             } else {
07571                if (vms->oldmessages == 2) {
07572                   res = ast_play_and_wait(chan, "vm-shtei");
07573                } else {
07574                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
07575                }
07576                res = ast_play_and_wait(chan, "vm-Old");
07577             }
07578          }
07579       }
07580       if (!res) {
07581          if (!vms->oldmessages && !vms->newmessages) {
07582             if (!res) {
07583                res = ast_play_and_wait(chan, "vm-nomessages");
07584             }
07585          }
07586       }
07587    }
07588    return res;
07589 }

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

Definition at line 7649 of file app_voicemail.c.

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

Referenced by vm_intro().

07650 {
07651    /* Introduce messages they have */
07652    int res;
07653    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
07654       res = ast_play_and_wait(chan, "vm-no") ||
07655          ast_play_and_wait(chan, "vm-message");
07656    else
07657       res = ast_play_and_wait(chan, "vm-youhave");
07658    if (!res && vms->newmessages) {
07659       res = (vms->newmessages == 1) ?
07660          ast_play_and_wait(chan, "digits/un") ||
07661          ast_play_and_wait(chan, "vm-nuovo") ||
07662          ast_play_and_wait(chan, "vm-message") :
07663          /* 2 or more new messages */
07664          say_and_wait(chan, vms->newmessages, chan->language) ||
07665          ast_play_and_wait(chan, "vm-nuovi") ||
07666          ast_play_and_wait(chan, "vm-messages");
07667       if (!res && vms->oldmessages)
07668          res = ast_play_and_wait(chan, "vm-and");
07669    }
07670    if (!res && vms->oldmessages) {
07671       res = (vms->oldmessages == 1) ?
07672          ast_play_and_wait(chan, "digits/un") ||
07673          ast_play_and_wait(chan, "vm-vecchio") ||
07674          ast_play_and_wait(chan, "vm-message") :
07675          /* 2 or more old messages */
07676          say_and_wait(chan, vms->oldmessages, chan->language) ||
07677          ast_play_and_wait(chan, "vm-vecchi") ||
07678          ast_play_and_wait(chan, "vm-messages");
07679    }
07680    return res;
07681 }

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

Definition at line 7485 of file app_voicemail.c.

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

Referenced by vm_intro().

07486 {
07487    int res;
07488    int lastnum = 0;
07489 
07490    res = ast_play_and_wait(chan, "vm-youhave");
07491 
07492    if (!res && vms->newmessages) {
07493       lastnum = vms->newmessages;
07494 
07495       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07496          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
07497       }
07498 
07499       if (!res && vms->oldmessages) {
07500          res = ast_play_and_wait(chan, "vm-and");
07501       }
07502    }
07503 
07504    if (!res && vms->oldmessages) {
07505       lastnum = vms->oldmessages;
07506 
07507       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07508          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
07509       }
07510    }
07511 
07512    if (!res) {
07513       if (lastnum == 0) {
07514          res = ast_play_and_wait(chan, "vm-no");
07515       }
07516       if (!res) {
07517          res = ast_say_counted_noun(chan, lastnum, "vm-message");
07518       }
07519    }
07520 
07521    return res;
07522 }

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

Definition at line 8033 of file app_voicemail.c.

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

Referenced by vm_intro().

08034 {
08035    /* Introduce messages they have */
08036    int res;
08037    res = ast_play_and_wait(chan, "vm-youhave");
08038    if (!res) {
08039       if (vms->newmessages) {
08040          res = say_and_wait(chan, vms->newmessages, chan->language);
08041          if (!res) {
08042             if (vms->newmessages == 1)
08043                res = ast_play_and_wait(chan, "vm-INBOXs");
08044             else
08045                res = ast_play_and_wait(chan, "vm-INBOX");
08046          }
08047          if (vms->oldmessages && !res)
08048             res = ast_play_and_wait(chan, "vm-and");
08049          else if (!res) {
08050             if ((vms->newmessages == 1))
08051                res = ast_play_and_wait(chan, "vm-message");
08052             else
08053                res = ast_play_and_wait(chan, "vm-messages");
08054          }
08055             
08056       }
08057       if (!res && vms->oldmessages) {
08058          res = say_and_wait(chan, vms->oldmessages, chan->language);
08059          if (!res) {
08060             if (vms->oldmessages == 1)
08061                res = ast_play_and_wait(chan, "vm-Olds");
08062             else
08063                res = ast_play_and_wait(chan, "vm-Old");
08064          }
08065          if (!res) {
08066             if (vms->oldmessages == 1)
08067                res = ast_play_and_wait(chan, "vm-message");
08068             else
08069                res = ast_play_and_wait(chan, "vm-messages");
08070          }
08071       }
08072       if (!res) {
08073          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08074             res = ast_play_and_wait(chan, "vm-no");
08075             if (!res)
08076                res = ast_play_and_wait(chan, "vm-messages");
08077          }
08078       }
08079    }
08080    return res;
08081 }

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

Definition at line 7799 of file app_voicemail.c.

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

Referenced by vm_intro().

07800 {
07801    /* Introduce messages they have */
07802    int res;
07803 
07804    res = ast_play_and_wait(chan, "vm-youhave");
07805    if (res)
07806       return res;
07807 
07808    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07809       res = ast_play_and_wait(chan, "vm-no");
07810       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07811       return res;
07812    }
07813 
07814    if (vms->newmessages) {
07815       if ((vms->newmessages == 1)) {
07816          res = ast_play_and_wait(chan, "digits/1");
07817          res = res ? res : ast_play_and_wait(chan, "vm-ny");
07818          res = res ? res : ast_play_and_wait(chan, "vm-message");
07819       } else {
07820          res = say_and_wait(chan, vms->newmessages, chan->language);
07821          res = res ? res : ast_play_and_wait(chan, "vm-nye");
07822          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07823       }
07824       if (!res && vms->oldmessages)
07825          res = ast_play_and_wait(chan, "vm-and");
07826    }
07827    if (!res && vms->oldmessages) {
07828       if (vms->oldmessages == 1) {
07829          res = ast_play_and_wait(chan, "digits/1");
07830          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
07831          res = res ? res : ast_play_and_wait(chan, "vm-message");
07832       } else {
07833          res = say_and_wait(chan, vms->oldmessages, chan->language);
07834          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
07835          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07836       }
07837    }
07838 
07839    return res;
07840 }

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

Definition at line 7684 of file app_voicemail.c.

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

Referenced by vm_intro().

07685 {
07686    /* Introduce messages they have */
07687    int res;
07688    div_t num;
07689 
07690    if (!vms->oldmessages && !vms->newmessages) {
07691       res = ast_play_and_wait(chan, "vm-no");
07692       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07693       return res;
07694    } else {
07695       res = ast_play_and_wait(chan, "vm-youhave");
07696    }
07697 
07698    if (vms->newmessages) {
07699       num = div(vms->newmessages, 10);
07700       if (vms->newmessages == 1) {
07701          res = ast_play_and_wait(chan, "digits/1-a");
07702          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
07703          res = res ? res : ast_play_and_wait(chan, "vm-message");
07704       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07705          if (num.rem == 2) {
07706             if (!num.quot) {
07707                res = ast_play_and_wait(chan, "digits/2-ie");
07708             } else {
07709                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
07710                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07711             }
07712          } else {
07713             res = say_and_wait(chan, vms->newmessages, chan->language);
07714          }
07715          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
07716          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07717       } else {
07718          res = say_and_wait(chan, vms->newmessages, chan->language);
07719          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
07720          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07721       }
07722       if (!res && vms->oldmessages)
07723          res = ast_play_and_wait(chan, "vm-and");
07724    }
07725    if (!res && vms->oldmessages) {
07726       num = div(vms->oldmessages, 10);
07727       if (vms->oldmessages == 1) {
07728          res = ast_play_and_wait(chan, "digits/1-a");
07729          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
07730          res = res ? res : ast_play_and_wait(chan, "vm-message");
07731       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07732          if (num.rem == 2) {
07733             if (!num.quot) {
07734                res = ast_play_and_wait(chan, "digits/2-ie");
07735             } else {
07736                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
07737                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07738             }
07739          } else {
07740             res = say_and_wait(chan, vms->oldmessages, chan->language);
07741          }
07742          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
07743          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07744       } else {
07745          res = say_and_wait(chan, vms->oldmessages, chan->language);
07746          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
07747          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07748       }
07749    }
07750 
07751    return res;
07752 }

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

Definition at line 8084 of file app_voicemail.c.

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

Referenced by vm_intro().

08085 {
08086    /* Introduce messages they have */
08087    int res;
08088    res = ast_play_and_wait(chan, "vm-youhave");
08089    if (!res) {
08090       if (vms->newmessages) {
08091          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08092          if (!res) {
08093             if ((vms->newmessages == 1)) {
08094                res = ast_play_and_wait(chan, "vm-message");
08095                if (!res)
08096                   res = ast_play_and_wait(chan, "vm-INBOXs");
08097             } else {
08098                res = ast_play_and_wait(chan, "vm-messages");
08099                if (!res)
08100                   res = ast_play_and_wait(chan, "vm-INBOX");
08101             }
08102          }
08103          if (vms->oldmessages && !res)
08104             res = ast_play_and_wait(chan, "vm-and");
08105       }
08106       if (!res && vms->oldmessages) {
08107          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08108          if (!res) {
08109             if (vms->oldmessages == 1) {
08110                res = ast_play_and_wait(chan, "vm-message");
08111                if (!res)
08112                   res = ast_play_and_wait(chan, "vm-Olds");
08113             } else {
08114                res = ast_play_and_wait(chan, "vm-messages");
08115                if (!res)
08116                   res = ast_play_and_wait(chan, "vm-Old");
08117             }
08118          }
08119       }
08120       if (!res) {
08121          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08122             res = ast_play_and_wait(chan, "vm-no");
08123             if (!res)
08124                res = ast_play_and_wait(chan, "vm-messages");
08125          }
08126       }
08127    }
08128    return res;
08129 }

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

Definition at line 7945 of file app_voicemail.c.

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

Referenced by vm_intro().

07945                                                                          {
07946    /* Introduce messages they have */
07947    int res;
07948    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07949       res = ast_play_and_wait(chan, "vm-nomessages");
07950       return res;
07951    } else {
07952       res = ast_play_and_wait(chan, "vm-youhave");
07953    }
07954    if (vms->newmessages) {
07955       if (!res)
07956          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07957       if ((vms->newmessages == 1)) {
07958          if (!res)
07959             res = ast_play_and_wait(chan, "vm-message");
07960          if (!res)
07961             res = ast_play_and_wait(chan, "vm-INBOXs");
07962       } else {
07963          if (!res)
07964             res = ast_play_and_wait(chan, "vm-messages");
07965          if (!res)
07966             res = ast_play_and_wait(chan, "vm-INBOX");
07967       }
07968       if (vms->oldmessages && !res)
07969          res = ast_play_and_wait(chan, "vm-and");
07970    }
07971    if (vms->oldmessages) {
07972       if (!res)
07973          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07974       if (vms->oldmessages == 1) {
07975          if (!res)
07976             res = ast_play_and_wait(chan, "vm-message");
07977          if (!res)
07978             res = ast_play_and_wait(chan, "vm-Olds");
07979       } else {
07980          if (!res)
07981             res = ast_play_and_wait(chan, "vm-messages");
07982          if (!res)
07983             res = ast_play_and_wait(chan, "vm-Old");
07984       }
07985    }
07986    return res;
07987 }

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

Definition at line 7755 of file app_voicemail.c.

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

Referenced by vm_intro().

07756 {
07757    /* Introduce messages they have */
07758    int res;
07759 
07760    res = ast_play_and_wait(chan, "vm-youhave");
07761    if (res)
07762       return res;
07763 
07764    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07765       res = ast_play_and_wait(chan, "vm-no");
07766       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07767       return res;
07768    }
07769 
07770    if (vms->newmessages) {
07771       if ((vms->newmessages == 1)) {
07772          res = ast_play_and_wait(chan, "digits/ett");
07773          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
07774          res = res ? res : ast_play_and_wait(chan, "vm-message");
07775       } else {
07776          res = say_and_wait(chan, vms->newmessages, chan->language);
07777          res = res ? res : ast_play_and_wait(chan, "vm-nya");
07778          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07779       }
07780       if (!res && vms->oldmessages)
07781          res = ast_play_and_wait(chan, "vm-and");
07782    }
07783    if (!res && vms->oldmessages) {
07784       if (vms->oldmessages == 1) {
07785          res = ast_play_and_wait(chan, "digits/ett");
07786          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
07787          res = res ? res : ast_play_and_wait(chan, "vm-message");
07788       } else {
07789          res = say_and_wait(chan, vms->oldmessages, chan->language);
07790          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
07791          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07792       }
07793    }
07794 
07795    return res;
07796 }

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

Definition at line 8208 of file app_voicemail.c.

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

Referenced by vm_intro().

08209 {
08210    int res;
08211    /* Introduce messages they have */
08212    res = ast_play_and_wait(chan, "vm-you");
08213 
08214    if (!res && vms->newmessages) {
08215       res = ast_play_and_wait(chan, "vm-have");
08216       if (!res)
08217          res = say_and_wait(chan, vms->newmessages, chan->language);
08218       if (!res)
08219          res = ast_play_and_wait(chan, "vm-tong");
08220       if (!res)
08221          res = ast_play_and_wait(chan, "vm-INBOX");
08222       if (vms->oldmessages && !res)
08223          res = ast_play_and_wait(chan, "vm-and");
08224       else if (!res) 
08225          res = ast_play_and_wait(chan, "vm-messages");
08226    }
08227    if (!res && vms->oldmessages) {
08228       res = ast_play_and_wait(chan, "vm-have");
08229       if (!res)
08230          res = say_and_wait(chan, vms->oldmessages, chan->language);
08231       if (!res)
08232          res = ast_play_and_wait(chan, "vm-tong");
08233       if (!res)
08234          res = ast_play_and_wait(chan, "vm-Old");
08235       if (!res)
08236          res = ast_play_and_wait(chan, "vm-messages");
08237    }
08238    if (!res && !vms->oldmessages && !vms->newmessages) {
08239       res = ast_play_and_wait(chan, "vm-haveno");
08240       if (!res)
08241          res = ast_play_and_wait(chan, "vm-messages");
08242    }
08243    return res;
08244 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

02874 {
02875    switch (ast_lock_path(path)) {
02876    case AST_LOCK_TIMEOUT:
02877       return -1;
02878    default:
02879       return 0;
02880    }
02881 }

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

Definition at line 1360 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01361 {
01362    FILE *p = NULL;
01363    int pfd = mkstemp(template);
01364    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01365    if (pfd > -1) {
01366       p = fdopen(pfd, "w+");
01367       if (!p) {
01368          close(pfd);
01369          pfd = -1;
01370       }
01371    }
01372    return p;
01373 }

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 8417 of file app_voicemail.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, chan, check_password(), play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, VM_FORCENAME, vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, and vm_reenterpassword.

Referenced by vm_execmain().

08418 {
08419    int cmd = 0;
08420    int duration = 0;
08421    int tries = 0;
08422    char newpassword[80] = "";
08423    char newpassword2[80] = "";
08424    char prefile[PATH_MAX] = "";
08425    unsigned char buf[256];
08426    int bytes=0;
08427 
08428    if (ast_adsi_available(chan)) {
08429       bytes += adsi_logo(buf + bytes);
08430       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08431       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08432       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08433       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08434       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08435    }
08436 
08437    /* First, have the user change their password 
08438       so they won't get here again */
08439    for (;;) {
08440       newpassword[1] = '\0';
08441       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08442       if (cmd == '#')
08443          newpassword[0] = '\0';
08444       if (cmd < 0 || cmd == 't' || cmd == '#')
08445          return cmd;
08446       cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
08447       if (cmd < 0 || cmd == 't' || cmd == '#')
08448          return cmd;
08449       cmd = check_password(vmu, newpassword); /* perform password validation */
08450       if (cmd != 0) {
08451          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08452          cmd = ast_play_and_wait(chan, vm_invalid_password);
08453       } else {
08454          newpassword2[1] = '\0';
08455          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08456          if (cmd == '#')
08457             newpassword2[0] = '\0';
08458          if (cmd < 0 || cmd == 't' || cmd == '#')
08459             return cmd;
08460          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
08461          if (cmd < 0 || cmd == 't' || cmd == '#')
08462             return cmd;
08463          if (!strcmp(newpassword, newpassword2))
08464             break;
08465          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08466          cmd = ast_play_and_wait(chan, vm_mismatch);
08467       }
08468       if (++tries == 3)
08469          return -1;
08470       if (cmd != 0) {
08471          cmd = ast_play_and_wait(chan, vm_pls_try_again);
08472       }
08473    }
08474    if (pwdchange & PWDCHANGE_INTERNAL)
08475       vm_change_password(vmu, newpassword);
08476    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08477       vm_change_password_shell(vmu, newpassword);
08478 
08479    ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08480    cmd = ast_play_and_wait(chan, vm_passchanged);
08481 
08482    /* If forcename is set, have the user record their name */  
08483    if (ast_test_flag(vmu, VM_FORCENAME)) {
08484       snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08485       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08486          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08487          if (cmd < 0 || cmd == 't' || cmd == '#')
08488             return cmd;
08489       }
08490    }
08491 
08492    /* If forcegreetings is set, have the user record their greetings */
08493    if (ast_test_flag(vmu, VM_FORCEGREET)) {
08494       snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08495       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08496          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08497          if (cmd < 0 || cmd == 't' || cmd == '#')
08498             return cmd;
08499       }
08500 
08501       snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08502       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08503          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08504          if (cmd < 0 || cmd == 't' || cmd == '#')
08505             return cmd;
08506       }
08507    }
08508 
08509    return cmd;
08510 }

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 8512 of file app_voicemail.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_waitfordigit(), chan, check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::password, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, vm_reenterpassword, and vm_tempgreeting().

Referenced by vm_execmain().

08513 {
08514    int cmd = 0;
08515    int retries = 0;
08516    int duration = 0;
08517    char newpassword[80] = "";
08518    char newpassword2[80] = "";
08519    char prefile[PATH_MAX] = "";
08520    unsigned char buf[256];
08521    int bytes=0;
08522 
08523    if (ast_adsi_available(chan)) {
08524       bytes += adsi_logo(buf + bytes);
08525       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
08526       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08527       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08528       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08529       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08530    }
08531    while ((cmd >= 0) && (cmd != 't')) {
08532       if (cmd)
08533          retries = 0;
08534       switch (cmd) {
08535       case '1': /* Record your unavailable message */
08536          snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08537          cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08538          break;
08539       case '2':  /* Record your busy message */
08540          snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08541          cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08542          break;
08543       case '3': /* Record greeting */
08544          snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08545          cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08546          break;
08547       case '4':  /* manage the temporary greeting */
08548          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
08549          break;
08550       case '5': /* change password */
08551          if (vmu->password[0] == '-') {
08552             cmd = ast_play_and_wait(chan, "vm-no");
08553             break;
08554          }
08555          newpassword[1] = '\0';
08556          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08557          if (cmd == '#')
08558             newpassword[0] = '\0';
08559          else {
08560             if (cmd < 0)
08561                break;
08562             if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
08563                break;
08564             }
08565          }
08566          cmd = check_password(vmu, newpassword); /* perform password validation */
08567          if (cmd != 0) {
08568             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08569             cmd = ast_play_and_wait(chan, vm_invalid_password);
08570             if (!cmd) {
08571                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08572             }
08573             break;
08574          }
08575          newpassword2[1] = '\0';
08576          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08577          if (cmd == '#')
08578             newpassword2[0] = '\0';
08579          else {
08580             if (cmd < 0)
08581                break;
08582 
08583             if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#")) < 0) {
08584                break;
08585             }
08586          }
08587          if (strcmp(newpassword, newpassword2)) {
08588             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08589             cmd = ast_play_and_wait(chan, vm_mismatch);
08590             if (!cmd) {
08591                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08592             }
08593             break;
08594          }
08595          if (pwdchange & PWDCHANGE_INTERNAL)
08596             vm_change_password(vmu, newpassword);
08597          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08598             vm_change_password_shell(vmu, newpassword);
08599 
08600          ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08601          cmd = ast_play_and_wait(chan, vm_passchanged);
08602          break;
08603       case '*': 
08604          cmd = 't';
08605          break;
08606       default: 
08607          cmd = 0;
08608          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08609          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08610          if (ast_fileexists(prefile, NULL, NULL)) {
08611             cmd = ast_play_and_wait(chan, "vm-tmpexists");
08612          }
08613          DISPOSE(prefile, -1);
08614          if (!cmd) {
08615             cmd = ast_play_and_wait(chan, "vm-options");
08616          }
08617          if (!cmd) {
08618             cmd = ast_waitfordigit(chan,6000);
08619          }
08620          if (!cmd) {
08621             retries++;
08622          }
08623          if (retries > 3) {
08624             cmd = 't';
08625          }
08626       }
08627    }
08628    if (cmd == 't')
08629       cmd = 0;
08630    return cmd;
08631 }

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

Definition at line 7356 of file app_voicemail.c.

References ast_play_and_wait(), chan, ast_channel::language, 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().

07357 {
07358    int cmd;
07359 
07360    if (  !strncasecmp(chan->language, "it", 2) ||
07361         !strncasecmp(chan->language, "es", 2) ||
07362         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07363       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07364       return cmd ? cmd : ast_play_and_wait(chan, box);
07365    } else if (!strncasecmp(chan->language, "gr", 2)) {
07366       return vm_play_folder_name_gr(chan, box);
07367    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07368       return ast_play_and_wait(chan, box);
07369    } else if (!strncasecmp(chan->language, "pl", 2)) {
07370       return vm_play_folder_name_pl(chan, box);
07371    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07372       return vm_play_folder_name_ua(chan, box);
07373    } else {  /* Default English */
07374       cmd = ast_play_and_wait(chan, box);
07375       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07376    }
07377 }

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

Definition at line 7309 of file app_voicemail.c.

References ast_play_and_wait(), and chan.

Referenced by vm_play_folder_name().

07310 {
07311    int cmd;
07312    char *buf;
07313 
07314    buf = alloca(strlen(box)+2); 
07315    strcpy(buf, box);
07316    strcat(buf,"s");
07317 
07318    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07319       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07320       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07321    } else {
07322       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07323       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07324    }
07325 }

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

Definition at line 7327 of file app_voicemail.c.

References ast_play_and_wait(), and chan.

Referenced by vm_play_folder_name().

07328 {
07329    int cmd;
07330 
07331    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07332       if (!strcasecmp(box, "vm-INBOX"))
07333          cmd = ast_play_and_wait(chan, "vm-new-e");
07334       else
07335          cmd = ast_play_and_wait(chan, "vm-old-e");
07336       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07337    } else {
07338       cmd = ast_play_and_wait(chan, "vm-messages");
07339       return cmd ? cmd : ast_play_and_wait(chan, box);
07340    }
07341 }

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

Definition at line 7343 of file app_voicemail.c.

References ast_play_and_wait(), and chan.

Referenced by vm_play_folder_name().

07344 {
07345    int cmd;
07346 
07347    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07348       cmd = ast_play_and_wait(chan, "vm-messages");
07349       return cmd ? cmd : ast_play_and_wait(chan, box);
07350    } else {
07351       cmd = ast_play_and_wait(chan, box);
07352       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07353    }
07354 }

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 8649 of file app_voicemail.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_waitfordigit(), chan, ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

08650 {
08651    int cmd = 0;
08652    int retries = 0;
08653    int duration = 0;
08654    char prefile[PATH_MAX] = "";
08655    unsigned char buf[256];
08656    int bytes = 0;
08657 
08658    if (ast_adsi_available(chan)) {
08659       bytes += adsi_logo(buf + bytes);
08660       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
08661       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08662       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08663       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08664       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08665    }
08666 
08667    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08668    while ((cmd >= 0) && (cmd != 't')) {
08669       if (cmd)
08670          retries = 0;
08671       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08672       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
08673          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08674          cmd = 't';  
08675       } else {
08676          switch (cmd) {
08677          case '1':
08678             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08679             break;
08680          case '2':
08681             DELETE(prefile, -1, prefile, vmu);
08682             ast_play_and_wait(chan, "vm-tempremoved");
08683             cmd = 't';  
08684             break;
08685          case '*': 
08686             cmd = 't';
08687             break;
08688          default:
08689             cmd = ast_play_and_wait(chan,
08690                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
08691                   "vm-tempgreeting2" : "vm-tempgreeting");
08692             if (!cmd)
08693                cmd = ast_waitfordigit(chan,6000);
08694             if (!cmd)
08695                retries++;
08696             if (retries > 3)
08697                cmd = 't';
08698          }
08699       }
08700       DISPOSE(prefile, -1);
08701    }
08702    if (cmd == 't')
08703       cmd = 0;
08704    return cmd;
08705 }

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

Definition at line 9938 of file app_voicemail.c.

References ast_copy_string(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), chan, ast_vm_user::context, pbx_builtin_setvar_helper(), s, strsep(), and vm_authenticate().

Referenced by load_module().

09939 {
09940    char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
09941    struct ast_vm_user vmus;
09942    char *options = NULL;
09943    int silent = 0, skipuser = 0;
09944    int res = -1;
09945    
09946    if (s) {
09947       s = ast_strdupa(s);
09948       user = strsep(&s, ",");
09949       options = strsep(&s, ",");
09950       if (user) {
09951          s = user;
09952          user = strsep(&s, "@");
09953          context = strsep(&s, "");
09954          if (!ast_strlen_zero(user))
09955             skipuser++;
09956          ast_copy_string(mailbox, user, sizeof(mailbox));
09957       }
09958    }
09959 
09960    if (options) {
09961       silent = (strchr(options, 's')) != NULL;
09962    }
09963 
09964    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
09965       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
09966       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
09967       ast_play_and_wait(chan, "auth-thankyou");
09968       res = 0;
09969    }
09970 
09971    return res;
09972 }

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

fill in *tm for current time according to the proper timezone, if any. Return tm so it can be used as a function argument.

Definition at line 3970 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

03971 {
03972    const struct vm_zone *z = NULL;
03973    struct timeval t = ast_tvnow();
03974 
03975    /* Does this user have a timezone specified? */
03976    if (!ast_strlen_zero(vmu->zonetag)) {
03977       /* Find the zone in the list */
03978       AST_LIST_LOCK(&zones);
03979       AST_LIST_TRAVERSE(&zones, z, list) {
03980          if (!strcmp(z->name, vmu->zonetag))
03981             break;
03982       }
03983       AST_LIST_UNLOCK(&zones);
03984    }
03985    ast_localtime(&t, tm, z ? z->timezone : NULL);
03986    return tm;
03987 }

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

Definition at line 6768 of file app_voicemail.c.

References ast_control_streamfile(), chan, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, and listen_control_stop_key.

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

Definition at line 6760 of file app_voicemail.c.

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

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

06761 {
06762    int res;
06763    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
06764       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
06765    return res;
06766 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 11759 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 513 of file app_voicemail.c.

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

Definition at line 706 of file app_voicemail.c.

Referenced by adsi_begin(), adsi_load_vmail(), and load_config().

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

Definition at line 707 of file app_voicemail.c.

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 708 of file app_voicemail.c.

Referenced by adsi_begin(), adsi_load_vmail(), and load_config().

char* app = "VoiceMail" [static]

Definition at line 598 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 601 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 603 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 604 of file app_voicemail.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 11759 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 692 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

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

Definition at line 704 of file app_voicemail.c.

Referenced by encode_mime_str(), load_config(), make_email_file(), and tds_load_module().

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 695 of file app_voicemail.c.

Referenced by load_config(), and play_message_callerid().

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

 {
   { .handler =  handle_voicemail_show_users , .summary =  "List defined voicemail boxes" ,__VA_ARGS__ },
   { .handler =  handle_voicemail_show_zones , .summary =  "List zone message formats" ,__VA_ARGS__ },
   { .handler =  handle_voicemail_reload , .summary =  "Reload voicemail configuration" ,__VA_ARGS__ },
}

Definition at line 10170 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* descrip_vm [static]

Definition at line 517 of file app_voicemail.c.

char* descrip_vm_box_exists [static]

Definition at line 575 of file app_voicemail.c.

char* descrip_vmain [static]

Definition at line 546 of file app_voicemail.c.

char* descrip_vmauthenticate [static]

Definition at line 587 of file app_voicemail.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 691 of file app_voicemail.c.

Referenced by dial_exec_full(), directory_exec(), load_config(), populate_defaults(), ring_entry(), and wait_for_answer().

char* emailbody = NULL [static]

Definition at line 698 of file app_voicemail.c.

Referenced by load_config(), make_email_file(), and message_template_parse_emailbody().

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

Definition at line 709 of file app_voicemail.c.

Referenced by load_config(), make_email_file(), and prep_email_sub_vars().

char* emailsubject = NULL [static]

Definition at line 699 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 693 of file app_voicemail.c.

Referenced by common_exec(), conf_run(), load_config(), and populate_defaults().

char ext_pass_check_cmd[128] [static]

Definition at line 493 of file app_voicemail.c.

char ext_pass_cmd[128] [static]

Definition at line 492 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 615 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 702 of file app_voicemail.c.

Referenced by load_config(), make_email_file(), and sendpage().

struct ast_flags globalflags = {0} [static]

Definition at line 687 of file app_voicemail.c.

struct ao2_container* inprocess_container

Definition at line 726 of file app_voicemail.c.

Referenced by inprocess_count(), load_module(), and unload_module().

char listen_control_forward_key[12] [static]

Definition at line 672 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 674 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 675 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 673 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 676 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

struct ast_custom_function mailbox_exists_acf [static]

Definition at line 9928 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char mailcmd[160] [static]

Definition at line 614 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 611 of file app_voicemail.c.

int maxgreet [static]

Definition at line 621 of file app_voicemail.c.

int maxlogins [static]

Definition at line 623 of file app_voicemail.c.

int maxmsg [static]

Definition at line 610 of file app_voicemail.c.

int maxsilence [static]

Definition at line 609 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 624 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 641 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

struct ast_taskprocessor* mwi_subscription_tps [static]

Definition at line 667 of file app_voicemail.c.

Referenced by load_module(), mwi_sub_event_cb(), mwi_unsub_event_cb(), and unload_module().

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 643 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

int my_umask [static]

Definition at line 495 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 700 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 703 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 701 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 636 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 631 of file app_voicemail.c.

ast_mutex_t poll_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 635 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

unsigned int poll_mailboxes [static]

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

Definition at line 628 of file app_voicemail.c.

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 637 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 638 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 499 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 689 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char serveremail[80] [static]

Definition at line 613 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 612 of file app_voicemail.c.

int skipms [static]

Definition at line 622 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 616 of file app_voicemail.c.

Referenced by load_config(), and run_externnotify().

char* synopsis_vm = "Leave a Voicemail message" [static]

Definition at line 515 of file app_voicemail.c.

char* synopsis_vm_box_exists [static]

Initial value:

"Check to see if Voicemail mailbox exists"

Definition at line 572 of file app_voicemail.c.

char* synopsis_vmain = "Check Voicemail messages" [static]

Definition at line 544 of file app_voicemail.c.

char* synopsis_vmauthenticate = "Authenticate with Voicemail passwords" [static]

Definition at line 585 of file app_voicemail.c.

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

Definition at line 511 of file app_voicemail.c.

Referenced by pbx_load_users().

struct ast_app_option vm_app_options[128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }} [static]

Definition at line 288 of file app_voicemail.c.

Referenced by vm_exec(), and vm_execmain().

enum { ... } vm_box

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

Definition at line 684 of file app_voicemail.c.

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

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

Definition at line 683 of file app_voicemail.c.

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

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

Definition at line 680 of file app_voicemail.c.

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

enum { ... } vm_option_args

enum { ... } vm_option_flags

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

Definition at line 681 of file app_voicemail.c.

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

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

Definition at line 679 of file app_voicemail.c.

Referenced by load_config(), and vm_authenticate().

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

Definition at line 685 of file app_voicemail.c.

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

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

Definition at line 682 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 490 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 617 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 620 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 619 of file app_voicemail.c.

double volgain [static]

Definition at line 618 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 608 of file app_voicemail.c.

Referenced by build_peer().


Generated on Wed Aug 18 22:34:04 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7