Thu Apr 8 01:21:39 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"
Include dependency graph for app_voicemail.c:

Go to the source code of this file.

Data Structures

struct  ast_vm_user
struct  baseio
struct  inprocess
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  mwi_sub
 An MWI subscription. More...
struct  mwi_sub_task
struct  mwi_subs
struct  users
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 eol   "\r\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 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 = "DAHDI Telephony w/PRI & SS7" , .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}
struct ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static 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 480 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 628 of file app_voicemail.c.

Referenced by load_config().

#define DELETE ( a,
b,
c,
 )     (vm_delete(c))
#define DISPOSE ( a,
 ) 
#define ENDL   "\n"
#define eol   "\r\n"

Definition at line 217 of file app_voicemail.c.

Referenced by base_encode(), and ochar().

#define ERROR_LOCK_PATH   -100

Definition at line 241 of file app_voicemail.c.

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

Definition at line 478 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"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#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 219 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 220 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 PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 493 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

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

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

#define RETRIEVE ( a,
b,
c,
 ) 
#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,
 ) 
#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 502 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 235 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 233 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 234 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 232 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 226 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 230 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 229 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 240 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 239 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 238 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 223 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 231 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 222 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 224 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 227 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 236 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 228 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 225 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 237 of file app_voicemail.c.

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

#define VMSTATE_MAX_MSG_ARRAY   256

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

00244      {
00245    NEW_FOLDER,
00246    OLD_FOLDER,
00247    WORK_FOLDER,
00248    FAMILY_FOLDER,
00249    FRIENDS_FOLDER,
00250    GREETINGS_FOLDER
00251 } 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 253 of file app_voicemail.c.

00253      {
00254    OPT_SILENT =           (1 << 0),
00255    OPT_BUSY_GREETING =    (1 << 1),
00256    OPT_UNAVAIL_GREETING = (1 << 2),
00257    OPT_RECORDGAIN =       (1 << 3),
00258    OPT_PREPEND_MAILBOX =  (1 << 4),
00259    OPT_AUTOPLAY =         (1 << 6),
00260    OPT_DTMFEXIT =         (1 << 7),
00261    OPT_MESSAGE_Urgent =   (1 << 8),
00262    OPT_MESSAGE_PRIORITY = (1 << 9)
00263 } vm_option_flags;

anonymous enum
Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 265 of file app_voicemail.c.

00265      {
00266    OPT_ARG_RECORDGAIN = 0,
00267    OPT_ARG_PLAYFOLDER = 1,
00268    OPT_ARG_DTMFEXIT   = 2,
00269    /* This *must* be the last value in this enum! */
00270    OPT_ARG_ARRAY_SIZE = 3,
00271 } vm_option_args;


Function Documentation

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

Definition at line 4815 of file app_voicemail.c.

References ast_strlen_zero().

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

04816 {
04817    DIR *dir;
04818    struct dirent *de;
04819    char fn[256];
04820    int ret = 0;
04821 
04822    /* If no mailbox, return immediately */
04823    if (ast_strlen_zero(mailbox))
04824       return 0;
04825 
04826    if (ast_strlen_zero(folder))
04827       folder = "INBOX";
04828    if (ast_strlen_zero(context))
04829       context = "default";
04830 
04831    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
04832 
04833    if (!(dir = opendir(fn)))
04834       return 0;
04835 
04836    while ((de = readdir(dir))) {
04837       if (!strncasecmp(de->d_name, "msg", 3)) {
04838          if (shortcircuit) {
04839             ret = 1;
04840             break;
04841          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
04842             ret++;
04843          }
04844       }
04845    }
04846 
04847    closedir(dir);
04848 
04849    return ret;
04850 }

static void __reg_module ( void   )  [static]

Definition at line 11712 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

09863 {
09864    struct ast_vm_user svm;
09865    AST_DECLARE_APP_ARGS(arg,
09866       AST_APP_ARG(mbox);
09867       AST_APP_ARG(context);
09868    );
09869 
09870    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
09871 
09872    if (ast_strlen_zero(arg.mbox)) {
09873       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
09874       return -1;
09875    }
09876 
09877    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
09878    return 0;
09879 }

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

04308 {
04309    char tmpdir[256], newtmp[256];
04310    char fname[256];
04311    char tmpcmd[256];
04312    int tmpfd = -1;
04313 
04314    /* Eww. We want formats to tell us their own MIME type */
04315    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04316 
04317    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04318       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04319       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04320       tmpfd = mkstemp(newtmp);
04321       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04322       ast_debug(3, "newtmp: %s\n", newtmp);
04323       if (tmpfd > -1) {
04324          int soxstatus;
04325          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04326          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04327             attach = newtmp;
04328             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04329          } else {
04330             ast_log(LOG_WARNING, "Sox failed to reencode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04331                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04332             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04333          }
04334       }
04335    }
04336    fprintf(p, "--%s" ENDL, bound);
04337    if (msgnum > -1)
04338       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04339    else
04340       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04341    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04342    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04343    if (msgnum > -1)
04344       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04345    else
04346       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04347    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04348    base_encode(fname, p);
04349    if (last)
04350       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04351    if (tmpfd > -1) {
04352       unlink(fname);
04353       close(tmpfd);
04354       unlink(newtmp);
04355    }
04356    return 0;
04357 }

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

Definition at line 5761 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

05762 {
05763    int x;
05764    if (!ast_adsi_available(chan))
05765       return;
05766    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05767    if (x < 0)
05768       return;
05769    if (!x) {
05770       if (adsi_load_vmail(chan, useadsi)) {
05771          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
05772          return;
05773       }
05774    } else
05775       *useadsi = 1;
05776 }

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

Definition at line 5950 of file app_voicemail.c.

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

Referenced by vm_execmain().

05951 {
05952    int bytes=0;
05953    unsigned char buf[256];
05954    unsigned char keys[8];
05955 
05956    int x;
05957 
05958    if (!ast_adsi_available(chan))
05959       return;
05960 
05961    /* New meaning for keys */
05962    for (x=0;x<5;x++)
05963       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05964 
05965    keys[6] = 0x0;
05966    keys[7] = 0x0;
05967 
05968    if (!vms->curmsg) {
05969       /* No prev key, provide "Folder" instead */
05970       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05971    }
05972    if (vms->curmsg >= vms->lastmsg) {
05973       /* If last message ... */
05974       if (vms->curmsg) {
05975          /* but not only message, provide "Folder" instead */
05976          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05977       } else {
05978          /* Otherwise if only message, leave blank */
05979          keys[3] = 1;
05980       }
05981    }
05982 
05983    /* If deleted, show "undeleted" */
05984    if (vms->deleted[vms->curmsg]) 
05985       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05986 
05987    /* Except "Exit" */
05988    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05989    bytes += ast_adsi_set_keys(buf + bytes, keys);
05990    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05991 
05992    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05993 }

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

Definition at line 5826 of file app_voicemail.c.

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

Referenced by vm_execmain().

05827 {
05828    unsigned char buf[256];
05829    int bytes=0;
05830    unsigned char keys[8];
05831    int x,y;
05832 
05833    if (!ast_adsi_available(chan))
05834       return;
05835 
05836    for (x=0;x<5;x++) {
05837       y = ADSI_KEY_APPS + 12 + start + x;
05838       if (y > ADSI_KEY_APPS + 12 + 4)
05839          y = 0;
05840       keys[x] = ADSI_KEY_SKT | y;
05841    }
05842    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05843    keys[6] = 0;
05844    keys[7] = 0;
05845 
05846    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05847    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05848    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05849    bytes += ast_adsi_set_keys(buf + bytes, keys);
05850    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05851 
05852    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05853 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 6098 of file app_voicemail.c.

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

Referenced by vm_execmain().

06099 {
06100    unsigned char buf[256];
06101    int bytes=0;
06102 
06103    if (!ast_adsi_available(chan))
06104       return;
06105    bytes += adsi_logo(buf + bytes);
06106    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06107    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06108    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06109    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06110 
06111    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06112 }

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

Definition at line 5632 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, mbox(), and num.

Referenced by adsi_begin().

05633 {
05634    unsigned char buf[256];
05635    int bytes=0;
05636    int x;
05637    char num[5];
05638 
05639    *useadsi = 0;
05640    bytes += ast_adsi_data_mode(buf + bytes);
05641    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05642 
05643    bytes = 0;
05644    bytes += adsi_logo(buf);
05645    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05646 #ifdef DISPLAY
05647    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
05648 #endif
05649    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05650    bytes += ast_adsi_data_mode(buf + bytes);
05651    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05652 
05653    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
05654       bytes = 0;
05655       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
05656       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05657       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05658       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05659       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05660       return 0;
05661    }
05662 
05663 #ifdef DISPLAY
05664    /* Add a dot */
05665    bytes = 0;
05666    bytes += ast_adsi_logo(buf);
05667    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05668    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
05669    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05670    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05671 #endif
05672    bytes = 0;
05673    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
05674    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
05675    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
05676    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
05677    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
05678    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
05679    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05680 
05681 #ifdef DISPLAY
05682    /* Add another dot */
05683    bytes = 0;
05684    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
05685    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05686 
05687    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05688    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05689 #endif
05690 
05691    bytes = 0;
05692    /* These buttons we load but don't use yet */
05693    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
05694    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
05695    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
05696    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
05697    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
05698    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
05699    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05700 
05701 #ifdef DISPLAY
05702    /* Add another dot */
05703    bytes = 0;
05704    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
05705    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05706    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05707 #endif
05708 
05709    bytes = 0;
05710    for (x=0;x<5;x++) {
05711       snprintf(num, sizeof(num), "%d", x);
05712       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
05713    }
05714    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
05715    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05716 
05717 #ifdef DISPLAY
05718    /* Add another dot */
05719    bytes = 0;
05720    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
05721    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05722    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05723 #endif
05724 
05725    if (ast_adsi_end_download(chan)) {
05726       bytes = 0;
05727       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
05728       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05729       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05730       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05731       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05732       return 0;
05733    }
05734    bytes = 0;
05735    bytes += ast_adsi_download_disconnect(buf + bytes);
05736    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05737    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05738 
05739    ast_debug(1, "Done downloading scripts...\n");
05740 
05741 #ifdef DISPLAY
05742    /* Add last dot */
05743    bytes = 0;
05744    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
05745    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05746 #endif
05747    ast_debug(1, "Restarting session...\n");
05748 
05749    bytes = 0;
05750    /* Load the session now */
05751    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
05752       *useadsi = 1;
05753       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
05754    } else
05755       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
05756 
05757    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05758    return 0;
05759 }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 5778 of file app_voicemail.c.

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

Referenced by vm_authenticate().

05779 {
05780    unsigned char buf[256];
05781    int bytes=0;
05782    unsigned char keys[8];
05783    int x;
05784    if (!ast_adsi_available(chan))
05785       return;
05786 
05787    for (x=0;x<8;x++)
05788       keys[x] = 0;
05789    /* Set one key for next */
05790    keys[3] = ADSI_KEY_APPS + 3;
05791 
05792    bytes += adsi_logo(buf + bytes);
05793    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05794    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
05795    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05796    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
05797    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05798    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05799    bytes += ast_adsi_set_keys(buf + bytes, keys);
05800    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05801    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05802 }

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

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

05625 {
05626    int bytes = 0;
05627    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
05628    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
05629    return bytes;
05630 }

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

Definition at line 5855 of file app_voicemail.c.

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

Referenced by play_message(), and vm_execmain().

05856 {
05857    int bytes=0;
05858    unsigned char buf[256]; 
05859    char buf1[256], buf2[256];
05860    char fn2[PATH_MAX];
05861 
05862    char cid[256]="";
05863    char *val;
05864    char *name, *num;
05865    char datetime[21]="";
05866    FILE *f;
05867 
05868    unsigned char keys[8];
05869 
05870    int x;
05871 
05872    if (!ast_adsi_available(chan))
05873       return;
05874 
05875    /* Retrieve important info */
05876    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
05877    f = fopen(fn2, "r");
05878    if (f) {
05879       while (!feof(f)) {   
05880          if (!fgets((char *)buf, sizeof(buf), f)) {
05881             continue;
05882          }
05883          if (!feof(f)) {
05884             char *stringp=NULL;
05885             stringp = (char *)buf;
05886             strsep(&stringp, "=");
05887             val = strsep(&stringp, "=");
05888             if (!ast_strlen_zero(val)) {
05889                if (!strcmp((char *)buf, "callerid"))
05890                   ast_copy_string(cid, val, sizeof(cid));
05891                if (!strcmp((char *)buf, "origdate"))
05892                   ast_copy_string(datetime, val, sizeof(datetime));
05893             }
05894          }
05895       }
05896       fclose(f);
05897    }
05898    /* New meaning for keys */
05899    for (x=0;x<5;x++)
05900       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05901    keys[6] = 0x0;
05902    keys[7] = 0x0;
05903 
05904    if (!vms->curmsg) {
05905       /* No prev key, provide "Folder" instead */
05906       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05907    }
05908    if (vms->curmsg >= vms->lastmsg) {
05909       /* If last message ... */
05910       if (vms->curmsg) {
05911          /* but not only message, provide "Folder" instead */
05912          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05913          bytes += ast_adsi_voice_mode(buf + bytes, 0);
05914 
05915       } else {
05916          /* Otherwise if only message, leave blank */
05917          keys[3] = 1;
05918       }
05919    }
05920 
05921    if (!ast_strlen_zero(cid)) {
05922       ast_callerid_parse(cid, &name, &num);
05923       if (!name)
05924          name = num;
05925    } else
05926       name = "Unknown Caller";
05927 
05928    /* If deleted, show "undeleted" */
05929 
05930    if (vms->deleted[vms->curmsg])
05931       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05932 
05933    /* Except "Exit" */
05934    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05935    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
05936       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
05937    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
05938 
05939    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05940    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05941    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
05942    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
05943    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05944    bytes += ast_adsi_set_keys(buf + bytes, keys);
05945    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05946 
05947    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05948 }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 5804 of file app_voicemail.c.

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

Referenced by vm_authenticate().

05805 {
05806    unsigned char buf[256];
05807    int bytes=0;
05808    unsigned char keys[8];
05809    int x;
05810    if (!ast_adsi_available(chan))
05811       return;
05812 
05813    for (x=0;x<8;x++)
05814       keys[x] = 0;
05815    /* Set one key for next */
05816    keys[3] = ADSI_KEY_APPS + 3;
05817 
05818    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05819    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05820    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05821    bytes += ast_adsi_set_keys(buf + bytes, keys);
05822    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05823    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05824 }

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

Definition at line 5995 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, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_execmain().

05996 {
05997    unsigned char buf[256] = "";
05998    char buf1[256] = "", buf2[256] = "";
05999    int bytes=0;
06000    unsigned char keys[8];
06001    int x;
06002 
06003    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06004    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06005    if (!ast_adsi_available(chan))
06006       return;
06007    if (vms->newmessages) {
06008       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06009       if (vms->oldmessages) {
06010          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06011          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06012       } else {
06013          snprintf(buf2, sizeof(buf2), "%s.", newm);
06014       }
06015    } else if (vms->oldmessages) {
06016       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06017       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06018    } else {
06019       strcpy(buf1, "You have no messages.");
06020       buf2[0] = ' ';
06021       buf2[1] = '\0';
06022    }
06023    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06024    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06025    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06026 
06027    for (x=0;x<6;x++)
06028       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06029    keys[6] = 0;
06030    keys[7] = 0;
06031 
06032    /* Don't let them listen if there are none */
06033    if (vms->lastmsg < 0)
06034       keys[0] = 1;
06035    bytes += ast_adsi_set_keys(buf + bytes, keys);
06036 
06037    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06038 
06039    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06040 }

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

Definition at line 6042 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, vm_state::curbox, and vm_state::lastmsg.

Referenced by vm_execmain().

06043 {
06044    unsigned char buf[256] = "";
06045    char buf1[256] = "", buf2[256] = "";
06046    int bytes=0;
06047    unsigned char keys[8];
06048    int x;
06049 
06050    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06051 
06052    if (!ast_adsi_available(chan))
06053       return;
06054 
06055    /* Original command keys */
06056    for (x=0;x<6;x++)
06057       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06058 
06059    keys[6] = 0;
06060    keys[7] = 0;
06061 
06062    if ((vms->lastmsg + 1) < 1)
06063       keys[0] = 0;
06064 
06065    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06066       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06067 
06068    if (vms->lastmsg + 1)
06069       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06070    else
06071       strcpy(buf2, "no messages.");
06072    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06073    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06074    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06075    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06076    bytes += ast_adsi_set_keys(buf + bytes, keys);
06077 
06078    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06079 
06080    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06081    
06082 }

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

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

Referenced by vm_execmain().

11289 {
11290    int res = 0;
11291    char filename[PATH_MAX];
11292    struct ast_config *msg_cfg = NULL;
11293    const char *origtime, *context;
11294    char *name, *num;
11295    int retries = 0;
11296    char *cid;
11297    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
11298 
11299    vms->starting = 0; 
11300 
11301    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11302 
11303    /* Retrieve info from VM attribute file */
11304    snprintf(filename,sizeof(filename), "%s.txt", vms->fn);
11305    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
11306    msg_cfg = ast_config_load(filename, config_flags);
11307    DISPOSE(vms->curdir, vms->curmsg);
11308    if (!msg_cfg) {
11309       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
11310       return 0;
11311    }
11312 
11313    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
11314       ast_config_destroy(msg_cfg);
11315       return 0;
11316    }
11317 
11318    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
11319 
11320    context = ast_variable_retrieve(msg_cfg, "message", "context");
11321    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
11322       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
11323    switch (option) {
11324    case 3: /* Play message envelope */
11325       if (!res)
11326          res = play_message_datetime(chan, vmu, origtime, filename);
11327       if (!res)
11328          res = play_message_callerid(chan, vms, cid, context, 0);
11329 
11330       res = 't';
11331       break;
11332 
11333    case 2:  /* Call back */
11334 
11335       if (ast_strlen_zero(cid))
11336          break;
11337 
11338       ast_callerid_parse(cid, &name, &num);
11339       while ((res > -1) && (res != 't')) {
11340          switch (res) {
11341          case '1':
11342             if (num) {
11343                /* Dial the CID number */
11344                res = dialout(chan, vmu, num, vmu->callback);
11345                if (res) {
11346                   ast_config_destroy(msg_cfg);
11347                   return 9;
11348                }
11349             } else {
11350                res = '2';
11351             }
11352             break;
11353 
11354          case '2':
11355             /* Want to enter a different number, can only do this if there's a dialout context for this user */
11356             if (!ast_strlen_zero(vmu->dialout)) {
11357                res = dialout(chan, vmu, NULL, vmu->dialout);
11358                if (res) {
11359                   ast_config_destroy(msg_cfg);
11360                   return 9;
11361                }
11362             } else {
11363                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
11364                res = ast_play_and_wait(chan, "vm-sorry");
11365             }
11366             ast_config_destroy(msg_cfg);
11367             return res;
11368          case '*':
11369             res = 't';
11370             break;
11371          case '3':
11372          case '4':
11373          case '5':
11374          case '6':
11375          case '7':
11376          case '8':
11377          case '9':
11378          case '0':
11379 
11380             res = ast_play_and_wait(chan, "vm-sorry");
11381             retries++;
11382             break;
11383          default:
11384             if (num) {
11385                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
11386                res = ast_play_and_wait(chan, "vm-num-i-have");
11387                if (!res)
11388                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
11389                if (!res)
11390                   res = ast_play_and_wait(chan, "vm-tocallnum");
11391                /* Only prompt for a caller-specified number if there is a dialout context specified */
11392                if (!ast_strlen_zero(vmu->dialout)) {
11393                   if (!res)
11394                      res = ast_play_and_wait(chan, "vm-calldiffnum");
11395                }
11396             } else {
11397                res = ast_play_and_wait(chan, "vm-nonumber");
11398                if (!ast_strlen_zero(vmu->dialout)) {
11399                   if (!res)
11400                      res = ast_play_and_wait(chan, "vm-toenternumber");
11401                }
11402             }
11403             if (!res)
11404                res = ast_play_and_wait(chan, "vm-star-cancel");
11405             if (!res)
11406                res = ast_waitfordigit(chan, 6000);
11407             if (!res) {
11408                retries++;
11409                if (retries > 3)
11410                   res = 't';
11411             }
11412             break; 
11413             
11414          }
11415          if (res == 't')
11416             res = 0;
11417          else if (res == '*')
11418             res = -1;
11419       }
11420       break;
11421       
11422    case 1:  /* Reply */
11423       /* Send reply directly to sender */
11424       if (ast_strlen_zero(cid))
11425          break;
11426 
11427       ast_callerid_parse(cid, &name, &num);
11428       if (!num) {
11429          ast_verb(3, "No CID number available, no reply sent\n");
11430          if (!res)
11431             res = ast_play_and_wait(chan, "vm-nonumber");
11432          ast_config_destroy(msg_cfg);
11433          return res;
11434       } else {
11435          struct ast_vm_user vmu2;
11436          if (find_user(&vmu2, vmu->context, num)) {
11437             struct leave_vm_options leave_options;
11438             char mailbox[AST_MAX_EXTENSION * 2 + 2];
11439             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
11440 
11441             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
11442             
11443             memset(&leave_options, 0, sizeof(leave_options));
11444             leave_options.record_gain = record_gain;
11445             res = leave_voicemail(chan, mailbox, &leave_options);
11446             if (!res)
11447                res = 't';
11448             ast_config_destroy(msg_cfg);
11449             return res;
11450          } else {
11451             /* Sender has no mailbox, can't reply */
11452             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
11453             ast_play_and_wait(chan, "vm-nobox");
11454             res = 't';
11455             ast_config_destroy(msg_cfg);
11456             return res;
11457          }
11458       } 
11459       res = 0;
11460 
11461       break;
11462    }
11463 
11464 #ifndef IMAP_STORAGE
11465    ast_config_destroy(msg_cfg);
11466 
11467    if (!res) {
11468       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11469       vms->heard[msg] = 1;
11470       res = wait_file(chan, vms, vms->fn);
11471    }
11472 #endif
11473    return res;
11474 }

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

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

09783 {
09784    /* Assumes lock is already held */
09785    char *tmp;
09786    char *stringp;
09787    char *s;
09788    struct ast_vm_user *vmu;
09789    char *mailbox_full;
09790    int new = 0, old = 0, urgent = 0;
09791 
09792    tmp = ast_strdupa(data);
09793 
09794    if (!(vmu = find_or_create(context, box)))
09795       return -1;
09796    
09797    populate_defaults(vmu);
09798 
09799    stringp = tmp;
09800    if ((s = strsep(&stringp, ","))) 
09801       ast_copy_string(vmu->password, s, sizeof(vmu->password));
09802    if (stringp && (s = strsep(&stringp, ","))) 
09803       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
09804    if (stringp && (s = strsep(&stringp, ","))) 
09805       ast_copy_string(vmu->email, s, sizeof(vmu->email));
09806    if (stringp && (s = strsep(&stringp, ","))) 
09807       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
09808    if (stringp && (s = strsep(&stringp, ","))) 
09809       apply_options(vmu, s);
09810 
09811    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
09812    strcpy(mailbox_full, box);
09813    strcat(mailbox_full, "@");
09814    strcat(mailbox_full, context);
09815 
09816    inboxcount2(mailbox_full, &urgent, &new, &old);
09817    queue_mwi_event(mailbox_full, urgent, new, old);
09818 
09819    return 0;
09820 }

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

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

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

Destructively Parse options and apply.

Definition at line 1049 of file app_voicemail.c.

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

Referenced by append_mailbox(), and apply_option().

01050 {  
01051    char *stringp;
01052    char *s;
01053    char *var, *value;
01054    stringp = ast_strdupa(options);
01055    while ((s = strsep(&stringp, "|"))) {
01056       value = s;
01057       if ((var = strsep(&value, "=")) && value) {
01058          apply_option(vmu, var, value);
01059       }
01060    }  
01061 }

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 1068 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, and ast_variable::value.

Referenced by find_user_realtime(), and load_config().

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

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

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

Referenced by add_email_attachment().

03796 {
03797    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
03798       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
03799       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
03800       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
03801    int i,hiteof= 0;
03802    FILE *fi;
03803    struct baseio bio;
03804 
03805    memset(&bio, 0, sizeof(bio));
03806    bio.iocp = BASEMAXINLINE;
03807 
03808    if (!(fi = fopen(filename, "rb"))) {
03809       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
03810       return -1;
03811    }
03812 
03813    while (!hiteof){
03814       unsigned char igroup[3], ogroup[4];
03815       int c,n;
03816 
03817       igroup[0]= igroup[1]= igroup[2]= 0;
03818 
03819       for (n= 0;n<3;n++) {
03820          if ((c = inchar(&bio, fi)) == EOF) {
03821             hiteof= 1;
03822             break;
03823          }
03824 
03825          igroup[n]= (unsigned char)c;
03826       }
03827 
03828       if (n> 0) {
03829          ogroup[0]= dtable[igroup[0]>>2];
03830          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
03831          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
03832          ogroup[3]= dtable[igroup[2]&0x3F];
03833 
03834          if (n<3) {
03835             ogroup[3]= '=';
03836 
03837             if (n<2)
03838                ogroup[2]= '=';
03839          }
03840 
03841          for (i= 0;i<4;i++)
03842             ochar(&bio, ogroup[i], so);
03843       }
03844    }
03845 
03846    fclose(fi);
03847    
03848    if (fputs(eol,so)==EOF)
03849       return 0;
03850 
03851    return 1;
03852 }

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

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

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

Referenced by make_email_file().

03961 {
03962    for (; *str; str++) {
03963       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
03964          return 1;
03965       }
03966    }
03967    return 0;
03968 }

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 990 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 vm_newuser(), and vm_options().

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

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

Definition at line 7176 of file app_voicemail.c.

References ast_check_realtime(), ast_debug, ast_log(), AST_LOG_WARNING, ast_test_flag, ast_unlock_path(), ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, DELETE, 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::maxdeletedmsg, ast_vm_user::maxmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by vm_execmain().

07177 {
07178    int x = 0;
07179 #ifndef IMAP_STORAGE
07180    int res = 0, nummsg;
07181    char fn2[PATH_MAX];
07182 #endif
07183 
07184    if (vms->lastmsg <= -1)
07185       goto done;
07186 
07187    vms->curmsg = -1; 
07188 #ifndef IMAP_STORAGE
07189    /* Get the deleted messages fixed */ 
07190    if (vm_lock_path(vms->curdir))
07191       return ERROR_LOCK_PATH;
07192 
07193    for (x = 0; x < vmu->maxmsg; x++) { 
07194       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) { 
07195          /* Save this message.  It's not in INBOX or hasn't been heard */ 
07196          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
07197          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
07198             break;
07199          vms->curmsg++; 
07200          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg); 
07201          if (strcmp(vms->fn, fn2)) { 
07202             RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07203          } 
07204       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { 
07205          /* Move to old folder before deleting */ 
07206          res = save_to_folder(vmu, vms, x, 1);
07207          if (res == ERROR_LOCK_PATH) {
07208             /* If save failed do not delete the message */
07209             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07210             vms->deleted[x] = 0;
07211             vms->heard[x] = 0;
07212             --x;
07213          }
07214       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07215          /* Move to deleted folder */ 
07216          res = save_to_folder(vmu, vms, x, 10);
07217          if (res == ERROR_LOCK_PATH) {
07218             /* If save failed do not delete the message */
07219             vms->deleted[x] = 0;
07220             vms->heard[x] = 0;
07221             --x;
07222          }
07223       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07224          /* If realtime storage enabled - we should explicitly delete this message,
07225          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07226          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07227          if (EXISTS(vms->curdir, x, vms->fn, NULL))
07228             DELETE(vms->curdir, x, vms->fn, vmu);
07229       }
07230    } 
07231 
07232    /* Delete ALL remaining messages */
07233    nummsg = x - 1;
07234    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07235       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07236       if (EXISTS(vms->curdir, x, vms->fn, NULL))
07237          DELETE(vms->curdir, x, vms->fn, vmu);
07238    }
07239    ast_unlock_path(vms->curdir);
07240 #else
07241    if (vms->deleted) {
07242       for (x=0;x < vmu->maxmsg;x++) { 
07243          if (vms->deleted[x]) { 
07244             ast_debug(3,"IMAP delete of %d\n",x);
07245             DELETE(vms->curdir, x, vms->fn, vmu);
07246          }
07247       }
07248    }
07249 #endif
07250 
07251 done:
07252    if (vms->deleted)
07253       memset(vms->deleted, 0, vmu->maxmsg * sizeof(int)); 
07254    if (vms->heard)
07255       memset(vms->heard, 0, vmu->maxmsg * sizeof(int)); 
07256 
07257    return 0;
07258 }

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

Definition at line 9966 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

09967 {
09968    int which = 0;
09969    int wordlen;
09970    struct ast_vm_user *vmu;
09971    const char *context = "";
09972 
09973    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
09974    if (pos > 4)
09975       return NULL;
09976    if (pos == 3)
09977       return (state == 0) ? ast_strdup("for") : NULL;
09978    wordlen = strlen(word);
09979    AST_LIST_TRAVERSE(&users, vmu, list) {
09980       if (!strncasecmp(word, vmu->context, wordlen)) {
09981          if (context && strcmp(context, vmu->context) && ++which > state)
09982             return ast_strdup(vmu->context);
09983          /* ignore repeated contexts ? */
09984          context = vmu->context;
09985       }
09986    }
09987    return NULL;
09988 }

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

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

Referenced by copy_plain_file(), and vm_forwardoptions().

03602 {
03603    int ifd;
03604    int ofd;
03605    int res;
03606    int len;
03607    char buf[4096];
03608 
03609 #ifdef HARDLINK_WHEN_POSSIBLE
03610    /* Hard link if possible; saves disk space & is faster */
03611    if (link(infile, outfile)) {
03612 #endif
03613       if ((ifd = open(infile, O_RDONLY)) < 0) {
03614          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03615          return -1;
03616       }
03617       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03618          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03619          close(ifd);
03620          return -1;
03621       }
03622       do {
03623          len = read(ifd, buf, sizeof(buf));
03624          if (len < 0) {
03625             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03626             close(ifd);
03627             close(ofd);
03628             unlink(outfile);
03629          }
03630          if (len) {
03631             res = write(ofd, buf, len);
03632             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03633                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03634                close(ifd);
03635                close(ofd);
03636                unlink(outfile);
03637             }
03638          }
03639       } while (len);
03640       close(ifd);
03641       close(ofd);
03642       return 0;
03643 #ifdef HARDLINK_WHEN_POSSIBLE
03644    } else {
03645       /* Hard link succeeded */
03646       return 0;
03647    }
03648 #endif
03649 }

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

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), 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(), 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().

04760 {
04761    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
04762    const char *frombox = mbox(imbox);
04763    int recipmsgnum;
04764 
04765    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
04766 
04767    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
04768       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
04769    } else {
04770       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04771    }
04772    
04773    if (!dir)
04774       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
04775    else
04776       ast_copy_string(fromdir, dir, sizeof(fromdir));
04777 
04778    make_file(frompath, sizeof(frompath), fromdir, msgnum);
04779    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04780 
04781    if (vm_lock_path(todir))
04782       return ERROR_LOCK_PATH;
04783 
04784    recipmsgnum = last_message_index(recip, todir) + 1;
04785    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
04786       make_file(topath, sizeof(topath), todir, recipmsgnum);
04787       if (EXISTS(fromdir, msgnum, frompath, chan->language)) {
04788          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
04789       } else {
04790          /* For ODBC storage, if the file we want to copy isn't yet in the database, then the SQL
04791           * copy will fail. Instead, we need to create a local copy, store it, and delete the local
04792           * copy. We don't have to #ifdef this because if file storage reaches this point, there's a
04793           * much worse problem happening and IMAP storage doesn't call this function
04794           */
04795          copy_plain_file(frompath, topath);
04796          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
04797          vm_delete(topath);
04798       }
04799    } else {
04800       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
04801    }
04802    ast_unlock_path(todir);
04803    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
04804    
04805    return 0;
04806 }

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

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

Referenced by copy_message().

03661 {
03662    char frompath2[PATH_MAX], topath2[PATH_MAX];
03663    struct ast_variable *tmp,*var = NULL;
03664    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
03665    ast_filecopy(frompath, topath, NULL);
03666    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
03667    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
03668    if (ast_check_realtime("voicemail_data")) {
03669       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
03670       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
03671       for (tmp = var; tmp; tmp = tmp->next) {
03672          if (!strcasecmp(tmp->name, "origmailbox")) {
03673             origmailbox = tmp->value;
03674          } else if (!strcasecmp(tmp->name, "context")) {
03675             context = tmp->value;
03676          } else if (!strcasecmp(tmp->name, "macrocontext")) {
03677             macrocontext = tmp->value;
03678          } else if (!strcasecmp(tmp->name, "exten")) {
03679             exten = tmp->value;
03680          } else if (!strcasecmp(tmp->name, "priority")) {
03681             priority = tmp->value;
03682          } else if (!strcasecmp(tmp->name, "callerchan")) {
03683             callerchan = tmp->value;
03684          } else if (!strcasecmp(tmp->name, "callerid")) {
03685             callerid = tmp->value;
03686          } else if (!strcasecmp(tmp->name, "origdate")) {
03687             origdate = tmp->value;
03688          } else if (!strcasecmp(tmp->name, "origtime")) {
03689             origtime = tmp->value;
03690          } else if (!strcasecmp(tmp->name, "category")) {
03691             category = tmp->value;
03692          } else if (!strcasecmp(tmp->name, "duration")) {
03693             duration = tmp->value;
03694          }
03695       }
03696       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);
03697    }
03698    copy(frompath2, topath2);
03699    ast_variables_destroy(var);
03700 }

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

03505 {
03506 
03507    int vmcount = 0;
03508    DIR *vmdir = NULL;
03509    struct dirent *vment = NULL;
03510 
03511    if (vm_lock_path(dir))
03512       return ERROR_LOCK_PATH;
03513 
03514    if ((vmdir = opendir(dir))) {
03515       while ((vment = readdir(vmdir))) {
03516          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03517             vmcount++;
03518          }
03519       }
03520       closedir(vmdir);
03521    }
03522    ast_unlock_path(dir);
03523    
03524    return vmcount;
03525 }

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

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

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

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

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

Definition at line 11216 of file app_voicemail.c.

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

Referenced by advanced_options(), and vm_execmain().

11217 {
11218    int cmd = 0;
11219    char destination[80] = "";
11220    int retries = 0;
11221 
11222    if (!num) {
11223       ast_verb(3, "Destination number will be entered manually\n");
11224       while (retries < 3 && cmd != 't') {
11225          destination[1] = '\0';
11226          destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
11227          if (!cmd)
11228             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
11229          if (!cmd)
11230             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
11231          if (!cmd) {
11232             cmd = ast_waitfordigit(chan, 6000);
11233             if (cmd)
11234                destination[0] = cmd;
11235          }
11236          if (!cmd) {
11237             retries++;
11238          } else {
11239 
11240             if (cmd < 0)
11241                return 0;
11242             if (cmd == '*') {
11243                ast_verb(3, "User hit '*' to cancel outgoing call\n");
11244                return 0;
11245             }
11246             if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0) 
11247                retries++;
11248             else
11249                cmd = 't';
11250          }
11251       }
11252       if (retries >= 3) {
11253          return 0;
11254       }
11255       
11256    } else {
11257       if (option_verbose > 2)
11258          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
11259       ast_copy_string(destination, num, sizeof(destination));
11260    }
11261 
11262    if (!ast_strlen_zero(destination)) {
11263       if (destination[strlen(destination) -1 ] == '*')
11264          return 0; 
11265       if (option_verbose > 2)
11266          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
11267       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
11268       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
11269       chan->priority = 0;
11270       return 9;
11271    }
11272    return 0;
11273 }

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

References charset.

Referenced by make_email_file().

03987 {
03988    char tmp[80];
03989    int first_section = 1;
03990    size_t endlen = 0, tmplen = 0;
03991    *end = '\0';
03992 
03993    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03994    for (; *start; start++) {
03995       int need_encoding = 0;
03996       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
03997          need_encoding = 1;
03998       }
03999       if ((first_section && need_encoding && preamble + tmplen > 70) ||
04000          (first_section && !need_encoding && preamble + tmplen > 72) ||
04001          (!first_section && need_encoding && tmplen > 70) ||
04002          (!first_section && !need_encoding && tmplen > 72)) {
04003          /* Start new line */
04004          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
04005          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
04006          first_section = 0;
04007       }
04008       if (need_encoding && *start == ' ') {
04009          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
04010       } else if (need_encoding) {
04011          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
04012       } else {
04013          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
04014       }
04015    }
04016    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
04017    return end;
04018 }

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

Definition at line 9750 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, LOG_WARNING, ast_vm_user::mailbox, and VM_SEARCH.

Referenced by append_mailbox(), and load_config().

09751 {
09752    struct ast_vm_user *vmu;
09753 
09754    AST_LIST_TRAVERSE(&users, vmu, list) {
09755       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
09756          if (strcasecmp(vmu->context, context)) {
09757             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
09758                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
09759                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
09760                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
09761          }
09762          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
09763          return NULL;
09764       }
09765       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
09766          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
09767          return NULL;
09768       }
09769    }
09770    
09771    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
09772       return NULL;
09773    
09774    ast_copy_string(vmu->context, context, sizeof(vmu->context));
09775    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
09776 
09777    AST_LIST_INSERT_TAIL(&users, vmu, list);
09778    
09779    return vmu;
09780 }

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

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

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

Definition at line 1174 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, VM_ALLOCED, and VM_SEARCH.

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

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

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

Finds a voicemail user from the realtime engine.

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

Definition at line 1137 of file app_voicemail.c.

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

Referenced by find_user().

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

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

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

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

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

Definition at line 6462 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_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), 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(), vm_state::fn, free_user(), globalflags, leave_voicemail(), LOG_NOTICE, ast_vm_user::mailbox, make_file(), pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, 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().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1414 of file app_voicemail.c.

References ast_free, ast_test_flag, and VM_ALLOCED.

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

01415 {
01416    if (ast_test_flag(vmu, VM_ALLOCED))
01417       ast_free(vmu);
01418 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 10423 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10424 {
10425    struct ast_vm_user *current;
10426    AST_LIST_LOCK(&users);
10427    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
10428       ast_set_flag(current, VM_ALLOCED);
10429       free_user(current);
10430    }
10431    AST_LIST_UNLOCK(&users);
10432 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 10435 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10436 {
10437    struct vm_zone *zcur;
10438    AST_LIST_LOCK(&zones);
10439    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
10440       free_zone(zcur);
10441    AST_LIST_UNLOCK(&zones);
10442 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4527 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

04528 {
04529    ast_free(z);
04530 }

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

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

Referenced by leave_voicemail().

04484 {
04485    struct ast_tm tm;
04486    struct timeval t = ast_tvnow();
04487    
04488    ast_localtime(&t, &tm, "UTC");
04489 
04490    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04491 }

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

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

Referenced by get_folder2().

06119 {
06120    int x;
06121    int d;
06122    char fn[PATH_MAX];
06123    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06124    if (d)
06125       return d;
06126    for (x = start; x< 5; x++) {  /* For all folders */
06127       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06128          return d;
06129       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06130       if (d)
06131          return d;
06132       snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
06133       d = vm_play_folder_name(chan, fn);
06134       if (d)
06135          return d;
06136       d = ast_waitfordigit(chan, 500);
06137       if (d)
06138          return d;
06139    }
06140    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06141    if (d)
06142       return d;
06143    d = ast_waitfordigit(chan, 4000);
06144    return d;
06145 }

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

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

06160 {
06161    int res = 0;
06162    res = ast_play_and_wait(chan, fn);  /* Folder name */
06163    while (((res < '0') || (res > '9')) &&
06164          (res != '#') && (res >= 0)) {
06165       res = get_folder(chan, 0);
06166    }
06167    return res;
06168 }

static int handle_subscribe ( void *  datap  )  [static]

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

10207 {
10208    unsigned int len;
10209    struct mwi_sub *mwi_sub;
10210    struct mwi_sub_task *p = datap;
10211 
10212    len = sizeof(*mwi_sub);
10213    if (!ast_strlen_zero(p->mailbox))
10214       len += strlen(p->mailbox);
10215 
10216    if (!ast_strlen_zero(p->context))
10217       len += strlen(p->context) + 1; /* Allow for seperator */
10218 
10219    if (!(mwi_sub = ast_calloc(1, len)))
10220       return -1;
10221 
10222    mwi_sub->uniqueid = p->uniqueid;
10223    if (!ast_strlen_zero(p->mailbox))
10224       strcpy(mwi_sub->mailbox, p->mailbox);
10225 
10226    if (!ast_strlen_zero(p->context)) {
10227       strcat(mwi_sub->mailbox, "@");
10228       strcat(mwi_sub->mailbox, p->context);
10229    }
10230 
10231    AST_RWLIST_WRLOCK(&mwi_subs);
10232    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
10233    AST_RWLIST_UNLOCK(&mwi_subs);
10234    ast_free((void *) p->mailbox);
10235    ast_free((void *) p->context);
10236    ast_free(p);
10237    poll_subscribed_mailbox(mwi_sub);
10238    return 0;
10239 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

10185 {
10186    struct mwi_sub *mwi_sub;
10187    uint32_t *uniqueid = datap;
10188    
10189    AST_RWLIST_WRLOCK(&mwi_subs);
10190    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
10191       if (mwi_sub->uniqueid == *uniqueid) {
10192          AST_LIST_REMOVE_CURRENT(entry);
10193          break;
10194       }
10195    }
10196    AST_RWLIST_TRAVERSE_SAFE_END
10197    AST_RWLIST_UNLOCK(&mwi_subs);
10198 
10199    if (mwi_sub)
10200       mwi_sub_destroy(mwi_sub);
10201 
10202    ast_free(uniqueid);  
10203    return 0;
10204 }

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

10102 {
10103    switch (cmd) {
10104    case CLI_INIT:
10105       e->command = "voicemail reload";
10106       e->usage =
10107          "Usage: voicemail reload\n"
10108          "       Reload voicemail configuration\n";
10109       return NULL;
10110    case CLI_GENERATE:
10111       return NULL;
10112    }
10113 
10114    if (a->argc != 2)
10115       return CLI_SHOWUSAGE;
10116 
10117    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
10118    load_config(1);
10119    
10120    return CLI_SUCCESS;
10121 }

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

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

09992 {
09993    struct ast_vm_user *vmu;
09994 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
09995    const char *context = NULL;
09996    int users_counter = 0;
09997 
09998    switch (cmd) {
09999    case CLI_INIT:
10000       e->command = "voicemail show users";
10001       e->usage =
10002          "Usage: voicemail show users [for <context>]\n"
10003          "       Lists all mailboxes currently set up\n";
10004       return NULL;
10005    case CLI_GENERATE:
10006       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10007    }  
10008 
10009    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10010       return CLI_SHOWUSAGE;
10011    if (a->argc == 5) {
10012       if (strcmp(a->argv[3],"for"))
10013          return CLI_SHOWUSAGE;
10014       context = a->argv[4];
10015    }
10016 
10017    if (ast_check_realtime("voicemail")) {
10018       if (!context) {
10019          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10020          return CLI_SHOWUSAGE;
10021       }
10022       return show_users_realtime(a->fd, context);
10023    }
10024 
10025    AST_LIST_LOCK(&users);
10026    if (AST_LIST_EMPTY(&users)) {
10027       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10028       AST_LIST_UNLOCK(&users);
10029       return CLI_FAILURE;
10030    }
10031    if (a->argc == 3)
10032       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10033    else {
10034       int count = 0;
10035       AST_LIST_TRAVERSE(&users, vmu, list) {
10036          if (!strcmp(context, vmu->context))
10037             count++;
10038       }
10039       if (count) {
10040          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10041       } else {
10042          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10043          AST_LIST_UNLOCK(&users);
10044          return CLI_FAILURE;
10045       }
10046    }
10047    AST_LIST_TRAVERSE(&users, vmu, list) {
10048       int newmsgs = 0, oldmsgs = 0;
10049       char count[12], tmp[256] = "";
10050 
10051       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10052          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10053          inboxcount(tmp, &newmsgs, &oldmsgs);
10054          snprintf(count, sizeof(count), "%d", newmsgs);
10055          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10056          users_counter++;
10057       }
10058    }
10059    AST_LIST_UNLOCK(&users);
10060    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10061    return CLI_SUCCESS;
10062 }

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

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

10066 {
10067    struct vm_zone *zone;
10068 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10069    char *res = CLI_SUCCESS;
10070 
10071    switch (cmd) {
10072    case CLI_INIT:
10073       e->command = "voicemail show zones";
10074       e->usage =
10075          "Usage: voicemail show zones\n"
10076          "       Lists zone message formats\n";
10077       return NULL;
10078    case CLI_GENERATE:
10079       return NULL;
10080    }
10081 
10082    if (a->argc != 3)
10083       return CLI_SHOWUSAGE;
10084 
10085    AST_LIST_LOCK(&zones);
10086    if (!AST_LIST_EMPTY(&zones)) {
10087       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10088       AST_LIST_TRAVERSE(&zones, zone, list) {
10089          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10090       }
10091    } else {
10092       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10093       res = CLI_FAILURE;
10094    }
10095    AST_LIST_UNLOCK(&zones);
10096 
10097    return res;
10098 }

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

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

Referenced by load_module(), and vm_execmain().

04862 {
04863    char tmp[256], *tmp2 = tmp, *box, *context;
04864    ast_copy_string(tmp, mailbox, sizeof(tmp));
04865    if (ast_strlen_zero(folder)) {
04866       folder = "INBOX";
04867    }
04868    while ((box = strsep(&tmp2, ",&"))) {
04869       if ((context = strchr(box, '@')))
04870          *context++ = '\0';
04871       else
04872          context = "default";
04873       if (__has_voicemail(context, box, folder, 1))
04874          return 1;
04875       /* If we are checking INBOX, we should check Urgent as well */
04876       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
04877          return 1;
04878       }
04879    }
04880    return 0;
04881 }

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

Definition at line 4943 of file app_voicemail.c.

References inboxcount2().

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

04944 {
04945    int urgentmsgs = 0;
04946    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
04947    if (newmsgs) {
04948       *newmsgs += urgentmsgs;
04949    }
04950    return res;
04951 }

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

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

04885 {
04886    char tmp[256];
04887    char *context;
04888 
04889    /* If no mailbox, return immediately */
04890    if (ast_strlen_zero(mailbox))
04891       return 0;
04892 
04893    if (newmsgs)
04894       *newmsgs = 0;
04895    if (oldmsgs)
04896       *oldmsgs = 0;
04897    if (urgentmsgs)
04898       *urgentmsgs = 0;
04899 
04900    if (strchr(mailbox, ',')) {
04901       int tmpnew, tmpold, tmpurgent;
04902       char *mb, *cur;
04903 
04904       ast_copy_string(tmp, mailbox, sizeof(tmp));
04905       mb = tmp;
04906       while ((cur = strsep(&mb, ", "))) {
04907          if (!ast_strlen_zero(cur)) {
04908             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
04909                return -1;
04910             else {
04911                if (newmsgs)
04912                   *newmsgs += tmpnew; 
04913                if (oldmsgs)
04914                   *oldmsgs += tmpold;
04915                if (urgentmsgs)
04916                   *urgentmsgs += tmpurgent;
04917             }
04918          }
04919       }
04920       return 0;
04921    }
04922 
04923    ast_copy_string(tmp, mailbox, sizeof(tmp));
04924    
04925    if ((context = strchr(tmp, '@')))
04926       *context++ = '\0';
04927    else
04928       context = "default";
04929 
04930    if (newmsgs)
04931       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
04932    if (oldmsgs)
04933       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
04934    if (urgentmsgs)
04935       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
04936 
04937    return 0;
04938 }

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

utility used by inchar(), for base_encode()

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

03733 {
03734    int l;
03735 
03736    if (bio->ateof)
03737       return 0;
03738 
03739    if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
03740       if (ferror(fi))
03741          return -1;
03742 
03743       bio->ateof = 1;
03744       return 0;
03745    }
03746 
03747    bio->iolen= l;
03748    bio->iocp= 0;
03749 
03750    return 1;
03751 }

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

utility used by base_encode()

Definition at line 3756 of file app_voicemail.c.

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

Referenced by base_encode().

03757 {
03758    if (bio->iocp>=bio->iolen) {
03759       if (!inbuf(bio, fi))
03760          return EOF;
03761    }
03762 
03763    return bio->iobuf[bio->iocp++];
03764 }

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

Definition at line 735 of file app_voicemail.c.

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

Referenced by load_module().

00736 {
00737    struct inprocess *i = obj, *j = arg;
00738    if (!strcmp(i->mailbox, j->mailbox)) {
00739       return 0;
00740    }
00741    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00742 }

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

Definition at line 744 of file app_voicemail.c.

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

Referenced by copy_message(), and leave_voicemail().

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

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

Definition at line 729 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

00730 {
00731    const struct inprocess *i = obj;
00732    return atoi(i->mailbox);
00733 }

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

Definition at line 4493 of file app_voicemail.c.

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

Referenced by leave_voicemail().

04494 {
04495    int res;
04496    char fn[PATH_MAX];
04497    char dest[PATH_MAX];
04498 
04499    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04500 
04501    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04502       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04503       return -1;
04504    }
04505 
04506    RETRIEVE(fn, -1, ext, context);
04507    if (ast_fileexists(fn, NULL, NULL) > 0) {
04508       res = ast_stream_and_wait(chan, fn, ecodes);
04509       if (res) {
04510          DISPOSE(fn, -1);
04511          return res;
04512       }
04513    } else {
04514       /* Dispose just in case */
04515       DISPOSE(fn, -1);
04516       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04517       if (res)
04518          return res;
04519       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04520       if (res)
04521          return res;
04522    }
04523    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04524    return res;
04525 }

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

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

Referenced by load_config().

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

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

03559 {
03560    int x;
03561    unsigned char map[MAXMSGLIMIT] = "";
03562    DIR *msgdir;
03563    struct dirent *msgdirent;
03564    int msgdirint;
03565 
03566    /* Reading the entire directory into a file map scales better than
03567     * doing a stat repeatedly on a predicted sequence.  I suspect this
03568     * is partially due to stat(2) internally doing a readdir(2) itself to
03569     * find each file. */
03570    if (!(msgdir = opendir(dir))) {
03571       return -1;
03572    }
03573 
03574    while ((msgdirent = readdir(msgdir))) {
03575       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03576          map[msgdirint] = 1;
03577    }
03578    closedir(msgdir);
03579 
03580    for (x = 0; x < vmu->maxmsg; x++) {
03581       if (map[x] == 0)
03582          break;
03583    }
03584 
03585    return x - 1;
03586 }

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 5016 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_LOG_WARNING, ast_mutex_lock(), ast_mutex_unlock(), ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer, ast_str_create(), ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verbose, ast_waitstream(), 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(), last_message_index(), ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, vm_state::newmessages, notify_new_message(), 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.

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

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

static int load_config ( int  reload  )  [static]

Definition at line 10489 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_LOG_WARNING, 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_STATUS_FILEUNCHANGED, ast_vm_user::context, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), ast_variable::lineno, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, LOG_ERROR, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, vm_zone::msg_format, vm_zone::name, ast_variable::name, ast_variable::next, pagerbody, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, saydurationminfo, SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, vm_zone::timezone, ast_variable::value, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, and VOICEMAIL_CONFIG.

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

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

static int load_module ( void   )  [static]

Definition at line 11178 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_LOG_WARNING, 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().

11179 {
11180    int res;
11181    my_umask = umask(0);
11182    umask(my_umask);
11183 
11184    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
11185       return AST_MODULE_LOAD_DECLINE;
11186    }
11187 
11188    /* compute the location of the voicemail spool directory */
11189    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
11190    
11191    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
11192       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
11193    }
11194 
11195    if ((res = load_config(0)))
11196       return res;
11197 
11198    res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
11199    res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
11200    res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
11201    res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
11202    res |= ast_custom_function_register(&mailbox_exists_acf);
11203    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
11204    if (res)
11205       return res;
11206 
11207    ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
11208 
11209    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
11210    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
11211    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
11212 
11213    return res;
11214 }

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

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

01335 {
01336    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01337 }

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 4040 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_LOG_WARNING, ast_random(), AST_STATE_DOWN, ast_strdupa, ast_strftime(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, 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, pbx_substitute_variables_helper(), prep_email_sub_vars(), ast_channel::priority, quote(), strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

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

01350 {
01351    return snprintf(dest, len, "%s/msg%04d", dir, num);
01352 }

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

Manager list voicemail users command.

Definition at line 10322 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::mailbox, ast_vm_user::mailcmd, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, ast_vm_user::saydurationm, ast_vm_user::serveremail, ast_vm_user::uniqueid, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_OPERATOR, VM_REVIEW, VM_SAYCID, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by load_module().

10323 {
10324    struct ast_vm_user *vmu = NULL;
10325    const char *id = astman_get_header(m, "ActionID");
10326    char actionid[128] = "";
10327 
10328    if (!ast_strlen_zero(id))
10329       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
10330 
10331    AST_LIST_LOCK(&users);
10332 
10333    if (AST_LIST_EMPTY(&users)) {
10334       astman_send_ack(s, m, "There are no voicemail users currently defined.");
10335       AST_LIST_UNLOCK(&users);
10336       return RESULT_SUCCESS;
10337    }
10338    
10339    astman_send_ack(s, m, "Voicemail user list will follow");
10340    
10341    AST_LIST_TRAVERSE(&users, vmu, list) {
10342       char dirname[256];
10343 
10344 #ifdef IMAP_STORAGE
10345       int new, old;
10346       inboxcount(vmu->mailbox, &new, &old);
10347 #endif
10348       
10349       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
10350       astman_append(s,
10351          "%s"
10352          "Event: VoicemailUserEntry\r\n"
10353          "VMContext: %s\r\n"
10354          "VoiceMailbox: %s\r\n"
10355          "Fullname: %s\r\n"
10356          "Email: %s\r\n"
10357          "Pager: %s\r\n"
10358          "ServerEmail: %s\r\n"
10359          "MailCommand: %s\r\n"
10360          "Language: %s\r\n"
10361          "TimeZone: %s\r\n"
10362          "Callback: %s\r\n"
10363          "Dialout: %s\r\n"
10364          "UniqueID: %s\r\n"
10365          "ExitContext: %s\r\n"
10366          "SayDurationMinimum: %d\r\n"
10367          "SayEnvelope: %s\r\n"
10368          "SayCID: %s\r\n"
10369          "AttachMessage: %s\r\n"
10370          "AttachmentFormat: %s\r\n"
10371          "DeleteMessage: %s\r\n"
10372          "VolumeGain: %.2f\r\n"
10373          "CanReview: %s\r\n"
10374          "CallOperator: %s\r\n"
10375          "MaxMessageCount: %d\r\n"
10376          "MaxMessageLength: %d\r\n"
10377          "NewMessageCount: %d\r\n"
10378 #ifdef IMAP_STORAGE
10379          "OldMessageCount: %d\r\n"
10380          "IMAPUser: %s\r\n"
10381 #endif
10382          "\r\n",
10383          actionid,
10384          vmu->context,
10385          vmu->mailbox,
10386          vmu->fullname,
10387          vmu->email,
10388          vmu->pager,
10389          vmu->serveremail,
10390          vmu->mailcmd,
10391          vmu->language,
10392          vmu->zonetag,
10393          vmu->callback,
10394          vmu->dialout,
10395          vmu->uniqueid,
10396          vmu->exit,
10397          vmu->saydurationm,
10398          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
10399          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
10400          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
10401          vmu->attachfmt,
10402          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
10403          vmu->volgain,
10404          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
10405          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
10406          vmu->maxmsg,
10407          vmu->maxsecs,
10408 #ifdef IMAP_STORAGE
10409          new, old, vmu->imapuser
10410 #else
10411          count_messages(vmu, dirname)
10412 #endif
10413          );
10414    }     
10415    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
10416 
10417    AST_LIST_UNLOCK(&users);
10418 
10419    return RESULT_SUCCESS;
10420 }

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

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

10157 {
10158    while (poll_thread_run) {
10159       struct timespec ts = { 0, };
10160       struct timeval wait;
10161 
10162       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
10163       ts.tv_sec = wait.tv_sec;
10164       ts.tv_nsec = wait.tv_usec * 1000;
10165 
10166       ast_mutex_lock(&poll_lock);
10167       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
10168       ast_mutex_unlock(&poll_lock);
10169 
10170       if (!poll_thread_run)
10171          break;
10172 
10173       poll_subscribed_mailboxes();
10174    }
10175 
10176    return NULL;
10177 }

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

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

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

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

Definition at line 4810 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04811 {
04812    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
04813 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 10179 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

10180 {
10181    ast_free(mwi_sub);
10182 }

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

Definition at line 10257 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(), mwi_sub_task::context, handle_subscribe(), LOG_ERROR, mwi_sub_task::mailbox, mwi_subscription_tps, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

10258 {
10259    struct mwi_sub_task *mwist;
10260    
10261    if (ast_event_get_type(event) != AST_EVENT_SUB)
10262       return;
10263 
10264    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10265       return;
10266 
10267    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
10268       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
10269       return;
10270    }
10271    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
10272    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
10273    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10274    
10275    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
10276       ast_free(mwist);
10277    }
10278 }

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

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

10242 {
10243    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
10244    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
10245       return;
10246 
10247    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10248       return;
10249 
10250    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10251    *uniqueid = u;
10252    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
10253       ast_free(uniqueid);
10254    }
10255 }

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

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_unlock, ast_log(), AST_LOG_WARNING, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_vm_user::attachfmt, ast_vm_user::context, vm_state::curmsg, DELETE, DISPOSE, ast_vm_user::email, EVENT_FLAG_CALL, globalflags, 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.

Referenced by copy_message(), and leave_voicemail().

06363 {
06364    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06365    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06366    const char *category;
06367    char *myserveremail = serveremail;
06368 
06369    ast_channel_lock(chan);
06370    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06371       category = ast_strdupa(category);
06372    }
06373    ast_channel_unlock(chan);
06374 
06375    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06376    make_file(fn, sizeof(fn), todir, msgnum);
06377    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06378 
06379    if (!ast_strlen_zero(vmu->attachfmt)) {
06380       if (strstr(fmt, vmu->attachfmt))
06381          fmt = vmu->attachfmt;
06382       else
06383          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);
06384    }
06385 
06386    /* Attach only the first format */
06387    fmt = ast_strdupa(fmt);
06388    stringp = fmt;
06389    strsep(&stringp, "|");
06390 
06391    if (!ast_strlen_zero(vmu->serveremail))
06392       myserveremail = vmu->serveremail;
06393 
06394    if (!ast_strlen_zero(vmu->email)) {
06395       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06396       if (!attach_user_voicemail)
06397          attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
06398 
06399       if (attach_user_voicemail)
06400          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06401 
06402       /* XXX possible imap issue, should category be NULL XXX */
06403       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06404 
06405       if (attach_user_voicemail)
06406          DISPOSE(todir, msgnum);
06407    }
06408 
06409    if (!ast_strlen_zero(vmu->pager)) {
06410       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
06411    }
06412 
06413    if (ast_test_flag(vmu, VM_DELETE))
06414       DELETE(todir, msgnum, fn, vmu);
06415 
06416    /* Leave voicemail for someone */
06417    if (ast_app_has_voicemail(ext_context, NULL)) 
06418       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06419 
06420    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06421 
06422    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);
06423    run_externnotify(vmu->context, vmu->mailbox, flag);
06424 
06425 #ifdef IMAP_STORAGE
06426    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06427    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06428       vm_imap_delete(NULL, vms->curmsg, vmu);
06429       vms->newmessages--;  /* Fix new message count */
06430    }
06431 #endif
06432 
06433    return 0;
06434 }

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

utility used by base_encode()

Definition at line 3769 of file app_voicemail.c.

References BASELINELEN, eol, and baseio::linelength.

Referenced by base_encode().

03770 {
03771    if (bio->linelength >= BASELINELEN) {
03772       if (fputs(eol,so) == EOF)
03773          return -1;
03774 
03775       bio->linelength= 0;
03776    }
03777 
03778    if (putc(((unsigned char)c),so) == EOF)
03779       return -1;
03780 
03781    bio->linelength++;
03782 
03783    return 1;
03784 }

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

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

07134 {
07135    int count_msg, last_msg;
07136 
07137    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
07138    
07139    /* Rename the member vmbox HERE so that we don't try to return before
07140     * we know what's going on.
07141     */
07142    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07143    
07144    /* Faster to make the directory than to check if it exists. */
07145    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07146 
07147    count_msg = count_messages(vmu, vms->curdir);
07148    if (count_msg < 0)
07149       return count_msg;
07150    else
07151       vms->lastmsg = count_msg - 1;
07152 
07153    /*
07154    The following test is needed in case sequencing gets messed up.
07155    There appears to be more than one way to mess up sequence, so
07156    we will not try to find all of the root causes--just fix it when
07157    detected.
07158    */
07159 
07160    if (vm_lock_path(vms->curdir)) {
07161       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07162       return -1;
07163    }
07164 
07165    last_msg = last_message_index(vmu, vms->curdir);
07166    ast_unlock_path(vms->curdir);
07167 
07168    if (last_msg < 0) 
07169       return last_msg;
07170 
07171    return 0;
07172 }

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

Definition at line 6931 of file app_voicemail.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), AST_LOG_WARNING, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, 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().

06932 {
06933    int res = 0;
06934    char filename[256], *cid;
06935    const char *origtime, *context, *category, *duration, *flag;
06936    struct ast_config *msg_cfg;
06937    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06938 
06939    vms->starting = 0;
06940    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06941    adsi_message(chan, vms);
06942    if (!vms->curmsg)
06943       res = wait_file2(chan, vms, "vm-first");  /* "First" */
06944    else if (vms->curmsg == vms->lastmsg)
06945       res = wait_file2(chan, vms, "vm-last");      /* "last" */
06946 
06947    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
06948    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
06949    msg_cfg = ast_config_load(filename, config_flags);
06950    if (!msg_cfg) {
06951       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06952       return 0;
06953    }
06954    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
06955 
06956    /* Play the word urgent if we are listening to urgent messages */
06957    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
06958       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
06959    }
06960 
06961    if (!res) {
06962       /* POLISH syntax */
06963       if (!strncasecmp(chan->language, "pl", 2)) {
06964          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06965             int ten, one;
06966             char nextmsg[256];
06967             ten = (vms->curmsg + 1) / 10;
06968             one = (vms->curmsg + 1) % 10;
06969 
06970             if (vms->curmsg < 20) {
06971                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
06972                res = wait_file2(chan, vms, nextmsg);
06973             } else {
06974                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
06975                res = wait_file2(chan, vms, nextmsg);
06976                if (one > 0) {
06977                   if (!res) {
06978                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
06979                      res = wait_file2(chan, vms, nextmsg);
06980                   }
06981                }
06982             }
06983          }
06984          if (!res)
06985             res = wait_file2(chan, vms, "vm-message");
06986       /* HEBREW syntax */
06987       } else if (!strncasecmp(chan->language, "he", 2)) {
06988          if (!vms->curmsg) {
06989             res = wait_file2(chan, vms, "vm-message");
06990             res = wait_file2(chan, vms, "vm-first");
06991          } else if (vms->curmsg == vms->lastmsg) {
06992             res = wait_file2(chan, vms, "vm-message");
06993             res = wait_file2(chan, vms, "vm-last");
06994          } else {
06995             res = wait_file2(chan, vms, "vm-message");
06996             res = wait_file2(chan, vms, "vm-number");
06997             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
06998          }
06999       } else {
07000          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07001             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07002          } else { /* DEFAULT syntax */
07003             res = wait_file2(chan, vms, "vm-message");
07004          }
07005          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07006             if (!res) {
07007                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07008             }
07009          }
07010       }
07011    }
07012 
07013    if (!msg_cfg) {
07014       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07015       return 0;
07016    }
07017 
07018    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07019       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07020       DISPOSE(vms->curdir, vms->curmsg);
07021       ast_config_destroy(msg_cfg);
07022       return 0;
07023    }
07024 
07025    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07026    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07027    category = ast_variable_retrieve(msg_cfg, "message", "category");
07028 
07029    context = ast_variable_retrieve(msg_cfg, "message", "context");
07030    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
07031       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
07032    if (!res) {
07033       res = play_message_category(chan, category);
07034    }
07035    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07036       res = play_message_datetime(chan, vmu, origtime, filename);
07037    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07038       res = play_message_callerid(chan, vms, cid, context, 0);
07039    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07040       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07041    /* Allow pressing '1' to skip envelope / callerid */
07042    if (res == '1')
07043       res = 0;
07044    ast_config_destroy(msg_cfg);
07045 
07046    if (!res) {
07047       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07048       vms->heard[vms->curmsg] = 1;
07049 #ifdef IMAP_STORAGE
07050       /*IMAP storage stores any prepended message from a forward
07051        * as a separate file from the rest of the message
07052        */
07053       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07054          wait_file(chan, vms, vms->introfn);
07055       }
07056 #endif
07057       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07058          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07059          res = 0;
07060       }
07061    }
07062    DISPOSE(vms->curdir, vms->curmsg);
07063    return res;
07064 }

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

Definition at line 6817 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, cidinternalcontexts, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

06818 {
06819    int res = 0;
06820    int i;
06821    char *callerid, *name;
06822    char prefile[PATH_MAX] = "";
06823    
06824 
06825    /* If voicemail cid is not enabled, or we didn't get cid or context from
06826     * the attribute file, leave now.
06827     *
06828     * TODO Still need to change this so that if this function is called by the
06829     * message envelope (and someone is explicitly requesting to hear the CID),
06830     * it does not check to see if CID is enabled in the config file.
06831     */
06832    if ((cid == NULL)||(context == NULL))
06833       return res;
06834 
06835    /* Strip off caller ID number from name */
06836    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
06837    ast_callerid_parse(cid, &name, &callerid);
06838    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
06839       /* Check for internal contexts and only */
06840       /* say extension when the call didn't come from an internal context in the list */
06841       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
06842          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
06843          if ((strcmp(cidinternalcontexts[i], context) == 0))
06844             break;
06845       }
06846       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
06847          if (!res) {
06848             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
06849             if (!ast_strlen_zero(prefile)) {
06850             /* See if we can find a recorded name for this person instead of their extension number */
06851                if (ast_fileexists(prefile, NULL, NULL) > 0) {
06852                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
06853                   if (!callback)
06854                      res = wait_file2(chan, vms, "vm-from");
06855                   res = ast_stream_and_wait(chan, prefile, "");
06856                } else {
06857                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
06858                   /* Say "from extension" as one saying to sound smoother */
06859                   if (!callback)
06860                      res = wait_file2(chan, vms, "vm-from-extension");
06861                   res = ast_say_digit_str(chan, callerid, "", chan->language);
06862                }
06863             }
06864          }
06865       } else if (!res) {
06866          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
06867          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
06868          if (!callback)
06869             res = wait_file2(chan, vms, "vm-from-phonenumber");
06870          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
06871       }
06872    } else {
06873       /* Number unknown */
06874       ast_debug(1, "VM-CID: From an unknown number\n");
06875       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
06876       res = wait_file2(chan, vms, "vm-unknown-caller");
06877    }
06878    return res;
06879 }

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

Definition at line 6730 of file app_voicemail.c.

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

Referenced by play_message().

06731 {
06732    int res = 0;
06733 
06734    if (!ast_strlen_zero(category))
06735       res = ast_play_and_wait(chan, category);
06736 
06737    if (res) {
06738       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
06739       res = 0;
06740    }
06741 
06742    return res;
06743 }

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

Definition at line 6745 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_LOG_WARNING, ast_say_date_with_format, ast_strlen_zero(), ast_tvnow(), 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().

06746 {
06747    int res = 0;
06748    struct vm_zone *the_zone = NULL;
06749    time_t t;
06750 
06751    if (ast_get_time_t(origtime, &t, 0, NULL)) {
06752       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
06753       return 0;
06754    }
06755 
06756    /* Does this user have a timezone specified? */
06757    if (!ast_strlen_zero(vmu->zonetag)) {
06758       /* Find the zone in the list */
06759       struct vm_zone *z;
06760       AST_LIST_LOCK(&zones);
06761       AST_LIST_TRAVERSE(&zones, z, list) {
06762          if (!strcmp(z->name, vmu->zonetag)) {
06763             the_zone = z;
06764             break;
06765          }
06766       }
06767       AST_LIST_UNLOCK(&zones);
06768    }
06769 
06770 /* No internal variable parsing for now, so we'll comment it out for the time being */
06771 #if 0
06772    /* Set the DIFF_* variables */
06773    ast_localtime(&t, &time_now, NULL);
06774    tv_now = ast_tvnow();
06775    ast_localtime(&tv_now, &time_then, NULL);
06776 
06777    /* Day difference */
06778    if (time_now.tm_year == time_then.tm_year)
06779       snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
06780    else
06781       snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
06782    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
06783 
06784    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
06785 #endif
06786    if (the_zone) {
06787       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
06788    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
06789       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06790    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
06791       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
06792    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
06793       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);
06794    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
06795       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
06796    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
06797       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06798    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
06799       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
06800    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
06801       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);
06802    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
06803       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
06804    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
06805       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
06806    } else {
06807       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
06808    }
06809 #if 0
06810    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
06811 #endif
06812    return res;
06813 }

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

Definition at line 6881 of file app_voicemail.c.

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

Referenced by play_message().

06882 {
06883    int res = 0;
06884    int durationm;
06885    int durations;
06886    /* Verify that we have a duration for the message */
06887    if (duration == NULL)
06888       return res;
06889 
06890    /* Convert from seconds to minutes */
06891    durations=atoi(duration);
06892    durationm=(durations / 60);
06893 
06894    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
06895 
06896    if ((!res) && (durationm >= minduration)) {
06897       res = wait_file2(chan, vms, "vm-duration");
06898 
06899       /* POLISH syntax */
06900       if (!strncasecmp(chan->language, "pl", 2)) {
06901          div_t num = div(durationm, 10);
06902 
06903          if (durationm == 1) {
06904             res = ast_play_and_wait(chan, "digits/1z");
06905             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
06906          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
06907             if (num.rem == 2) {
06908                if (!num.quot) {
06909                   res = ast_play_and_wait(chan, "digits/2-ie");
06910                } else {
06911                   res = say_and_wait(chan, durationm - 2 , chan->language);
06912                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
06913                }
06914             } else {
06915                res = say_and_wait(chan, durationm, chan->language);
06916             }
06917             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
06918          } else {
06919             res = say_and_wait(chan, durationm, chan->language);
06920             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
06921          }
06922       /* DEFAULT syntax */
06923       } else {
06924          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
06925          res = wait_file2(chan, vms, "vm-minutes");
06926       }
06927    }
06928    return res;
06929 }

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 11476 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_LOG_WARNING, AST_OPTION_RXGAIN, ast_play_and_record_full(), ast_play_and_wait(), ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, INTRO, ast_vm_user::mailbox, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

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

10130 {
10131    int new = 0, old = 0, urgent = 0;
10132 
10133    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
10134 
10135    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
10136       mwi_sub->old_urgent = urgent;
10137       mwi_sub->old_new = new;
10138       mwi_sub->old_old = old;
10139       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
10140    }
10141 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

10144 {
10145    struct mwi_sub *mwi_sub;
10146 
10147    AST_RWLIST_RDLOCK(&mwi_subs);
10148    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
10149       if (!ast_strlen_zero(mwi_sub->mailbox)) {
10150          poll_subscribed_mailbox(mwi_sub);
10151       }
10152    }
10153    AST_RWLIST_UNLOCK(&mwi_subs);
10154 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

  • all the globalflags
  • the saydurationminfo
  • the callcontext
  • the dialcontext
  • the exitcontext
  • vmmaxsecs, vmmaxmsg, maxdeletedmsg
  • volume gain.

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

Referenced by append_mailbox(), find_user_realtime(), and load_config().

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

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 3854 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, 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().

Referenced by make_email_file(), and sendpage().

03855 {
03856    char callerid[256];
03857    char fromdir[256], fromfile[256];
03858    struct ast_config *msg_cfg;
03859    const char *origcallerid, *origtime;
03860    char origcidname[80], origcidnum[80], origdate[80];
03861    int inttime;
03862    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03863 
03864    /* Prepare variables for substitution in email body and subject */
03865    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
03866    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
03867    snprintf(passdata, passdatasize, "%d", msgnum);
03868    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
03869    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
03870    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
03871    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
03872       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
03873    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
03874    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
03875    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
03876    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
03877    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
03878 
03879    /* Retrieve info from VM attribute file */
03880    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
03881    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
03882    if (strlen(fromfile) < sizeof(fromfile) - 5) {
03883       strcat(fromfile, ".txt");
03884    }
03885    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
03886       if (option_debug > 0) {
03887          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
03888       }
03889       return;
03890    }
03891 
03892    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
03893       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
03894       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
03895       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
03896       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
03897    }
03898 
03899    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
03900       struct timeval tv = { inttime, };
03901       struct ast_tm tm;
03902       ast_localtime(&tv, &tm, NULL);
03903       ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
03904       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
03905    }
03906    ast_config_destroy(msg_cfg);
03907 }

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

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

06327 {
06328    struct ast_event *event;
06329    char *mailbox, *context;
06330 
06331    /* Strip off @default */
06332    context = mailbox = ast_strdupa(box);
06333    strsep(&context, "@");
06334    if (ast_strlen_zero(context))
06335       context = "default";
06336 
06337    if (!(event = ast_event_new(AST_EVENT_MWI,
06338          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06339          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06340          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06341          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06342          AST_EVENT_IE_END))) {
06343       return;
06344    }
06345 
06346    ast_event_queue_and_cache(event);
06347 }

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

Referenced by make_email_file().

03917 {
03918    char *ptr = to;
03919    *ptr++ = '"';
03920    for (; ptr < to + len - 1; from++) {
03921       if (*from == '"')
03922          *ptr++ = '\\';
03923       else if (*from == '\0')
03924          break;
03925       *ptr++ = *from;
03926    }
03927    if (ptr < to + len - 1)
03928       *ptr++ = '"';
03929    *ptr = '\0';
03930    return to;
03931 }

static int reload ( void   )  [static]

Definition at line 11147 of file app_voicemail.c.

References load_config().

11148 {
11149    return load_config(1);
11150 }

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

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

03535 {
03536    char stxt[PATH_MAX];
03537    char dtxt[PATH_MAX];
03538    ast_filerename(sfn,dfn,NULL);
03539    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03540    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03541    if (ast_check_realtime("voicemail_data")) {
03542       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03543    }
03544    rename(stxt, dtxt);
03545 }

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 1217 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::mailbox, and ast_vm_user::password.

Referenced by vm_change_password(), and vm_change_password_shell().

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

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

Definition at line 4953 of file app_voicemail.c.

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

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

04954 {
04955    char arguments[255];
04956    char ext_context[256] = "";
04957    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
04958    struct ast_smdi_mwi_message *mwi_msg;
04959 
04960    if (!ast_strlen_zero(context))
04961       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
04962    else
04963       ast_copy_string(ext_context, extension, sizeof(ext_context));
04964 
04965    if (smdi_iface) {
04966       if (ast_app_has_voicemail(ext_context, NULL)) 
04967          ast_smdi_mwi_set(smdi_iface, extension);
04968       else
04969          ast_smdi_mwi_unset(smdi_iface, extension);
04970 
04971       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
04972          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
04973          if (!strncmp(mwi_msg->cause, "INV", 3))
04974             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
04975          else if (!strncmp(mwi_msg->cause, "BLK", 3))
04976             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
04977          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
04978          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
04979       } else {
04980          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
04981       }
04982    }
04983 
04984    if (!ast_strlen_zero(externnotify)) {
04985       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
04986          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
04987       } else {
04988          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
04989          ast_debug(1, "Executing %s\n", arguments);
04990          ast_safe_system(arguments);
04991       }
04992    }
04993 }

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

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

05546 {
05547 #ifdef IMAP_STORAGE
05548    /* we must use mbox(x) folder names, and copy the message there */
05549    /* simple. huh? */
05550    char sequence[10];
05551    char mailbox[256];
05552    int res;
05553 
05554    /* get the real IMAP message number for this message */
05555    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
05556    
05557    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
05558    ast_mutex_lock(&vms->lock);
05559    /* if save to Old folder, put in INBOX as read */
05560    if (box == OLD_FOLDER) {
05561       mail_setflag(vms->mailstream, sequence, "\\Seen");
05562       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
05563    } else if (box == NEW_FOLDER) {
05564       mail_setflag(vms->mailstream, sequence, "\\Unseen");
05565       mail_clearflag(vms->mailstream, sequence, "\\Seen");
05566    }
05567    if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
05568       ast_mutex_unlock(&vms->lock);
05569       return 0;
05570    }
05571    /* Create the folder if it don't exist */
05572    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
05573    ast_debug(5, "Checking if folder exists: %s\n",mailbox);
05574    if (mail_create(vms->mailstream, mailbox) == NIL) 
05575       ast_debug(5, "Folder exists.\n");
05576    else
05577       ast_log(AST_LOG_NOTICE, "Folder %s created!\n",mbox(box));
05578    res = !mail_copy(vms->mailstream, sequence, (char *)mbox(box));
05579    ast_mutex_unlock(&vms->lock);
05580    return res;
05581 #else
05582    char *dir = vms->curdir;
05583    char *username = vms->username;
05584    char *context = vmu->context;
05585    char sfn[PATH_MAX];
05586    char dfn[PATH_MAX];
05587    char ddir[PATH_MAX];
05588    const char *dbox = mbox(box);
05589    int x, i;
05590    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
05591 
05592    if (vm_lock_path(ddir))
05593       return ERROR_LOCK_PATH;
05594 
05595    x = last_message_index(vmu, ddir) + 1;
05596 
05597    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
05598       x--;
05599       for (i = 1; i <= x; i++) {
05600          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
05601          make_file(sfn, sizeof(sfn), ddir, i);
05602          make_file(dfn, sizeof(dfn), ddir, i - 1);
05603          if (EXISTS(ddir, i, sfn, NULL)) {
05604             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
05605          } else
05606             break;
05607       }
05608    } else {
05609       if (x >= vmu->maxmsg) {
05610          ast_unlock_path(ddir);
05611          return -1;
05612       }
05613    }
05614    make_file(sfn, sizeof(sfn), dir, msg);
05615    make_file(dfn, sizeof(dfn), ddir, x);
05616    if (strcmp(sfn, dfn)) {
05617       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
05618    }
05619    ast_unlock_path(ddir);
05620 #endif
05621    return 0;
05622 }

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

Definition at line 11133 of file app_voicemail.c.

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

Referenced by load_module().

11134 {
11135    int res = -1;
11136    char dir[PATH_MAX];
11137    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
11138    ast_debug(2, "About to try retrieving name file %s\n", dir);
11139    RETRIEVE(dir, -1, mailbox, context);
11140    if (ast_fileexists(dir, NULL, NULL)) {
11141       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
11142    }
11143    DISPOSE(dir, -1);
11144    return res;
11145 }

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

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

Referenced by forward_message(), and notify_new_message().

04361 {
04362    FILE *p=NULL;
04363    char tmp[80] = "/tmp/astmail-XXXXXX";
04364    char tmp2[256];
04365 
04366    if (vmu && ast_strlen_zero(vmu->email)) {
04367       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04368       return(0);
04369    }
04370    if (!strcmp(format, "wav49"))
04371       format = "WAV";
04372    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));
04373    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04374       command hangs */
04375    if ((p = vm_mkftemp(tmp)) == NULL) {
04376       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04377       return -1;
04378    } else {
04379       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04380       fclose(p);
04381       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04382       ast_safe_system(tmp2);
04383       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04384    }
04385    return 0;
04386 }

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

References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, ast_log(), AST_LOG_WARNING, 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().

04389 {
04390    char date[256];
04391    char host[MAXHOSTNAMELEN] = "";
04392    char who[256];
04393    char dur[PATH_MAX];
04394    char tmp[80] = "/tmp/astmail-XXXXXX";
04395    char tmp2[PATH_MAX];
04396    struct ast_tm tm;
04397    FILE *p;
04398 
04399    if ((p = vm_mkftemp(tmp)) == NULL) {
04400       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04401       return -1;
04402    }
04403    gethostname(host, sizeof(host)-1);
04404    if (strchr(srcemail, '@'))
04405       ast_copy_string(who, srcemail, sizeof(who));
04406    else 
04407       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04408    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04409    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04410    fprintf(p, "Date: %s\n", date);
04411 
04412    if (*pagerfromstring) {
04413       struct ast_channel *ast;
04414       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04415          char *passdata;
04416          int vmlen = strlen(fromstring)*3 + 200;
04417          passdata = alloca(vmlen);
04418          memset(passdata, 0, vmlen);
04419          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04420          pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
04421          fprintf(p, "From: %s <%s>\n", passdata, who);
04422          ast_channel_free(ast);
04423       } else 
04424          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04425    } else
04426       fprintf(p, "From: Asterisk PBX <%s>\n", who);
04427    fprintf(p, "To: %s\n", pager);
04428    if (pagersubject) {
04429       struct ast_channel *ast;
04430       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04431          char *passdata;
04432          int vmlen = strlen(pagersubject) * 3 + 200;
04433          passdata = alloca(vmlen);
04434          memset(passdata, 0, vmlen);
04435          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04436          pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
04437          fprintf(p, "Subject: %s\n\n", passdata);
04438          ast_channel_free(ast);
04439       } else
04440          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04441    } else {
04442       if (ast_strlen_zero(flag)) {
04443          fprintf(p, "Subject: New VM\n\n");
04444       } else {
04445          fprintf(p, "Subject: New %s VM\n\n", flag);
04446       }
04447    }
04448 
04449    ast_strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
04450    if (pagerbody) {
04451       struct ast_channel *ast;
04452       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04453          char *passdata;
04454          int vmlen = strlen(pagerbody) * 3 + 200;
04455          passdata = alloca(vmlen);
04456          memset(passdata, 0, vmlen);
04457          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04458          pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
04459          fprintf(p, "%s\n", passdata);
04460          ast_channel_free(ast);
04461       } else
04462          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04463    } else {
04464       fprintf(p, "New %s long %s msg in box %s\n"
04465             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04466    }
04467    fclose(p);
04468    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04469    ast_safe_system(tmp2);
04470    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04471    return 0;
04472 }

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

Definition at line 9927 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, ast_variable::name, ast_variable::next, SENTINEL, and ast_variable::value.

Referenced by handle_voicemail_show_users().

09928 {
09929    struct ast_config *cfg;
09930    const char *cat = NULL;
09931 
09932    if (!(cfg = ast_load_realtime_multientry("voicemail", 
09933       "context", context, SENTINEL))) {
09934       return CLI_FAILURE;
09935    }
09936 
09937    ast_cli(fd,
09938       "\n"
09939       "=============================================================\n"
09940       "=== Configured Voicemail Users ==============================\n"
09941       "=============================================================\n"
09942       "===\n");
09943 
09944    while ((cat = ast_category_browse(cfg, cat))) {
09945       struct ast_variable *var = NULL;
09946       ast_cli(fd,
09947          "=== Mailbox ...\n"
09948          "===\n");
09949       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
09950          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
09951       ast_cli(fd,
09952          "===\n"
09953          "=== ---------------------------------------------------------\n"
09954          "===\n");
09955    }
09956 
09957    ast_cli(fd,
09958       "=============================================================\n"
09959       "\n");
09960 
09961    ast_config_destroy(cfg);
09962 
09963    return CLI_SUCCESS;
09964 }

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

Definition at line 10298 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

10299 {
10300    poll_thread_run = 0;
10301 
10302    if (mwi_sub_sub) {
10303       ast_event_unsubscribe(mwi_sub_sub);
10304       mwi_sub_sub = NULL;
10305    }
10306 
10307    if (mwi_unsub_sub) {
10308       ast_event_unsubscribe(mwi_unsub_sub);
10309       mwi_unsub_sub = NULL;
10310    }
10311 
10312    ast_mutex_lock(&poll_lock);
10313    ast_cond_signal(&poll_cond);
10314    ast_mutex_unlock(&poll_lock);
10315 
10316    pthread_join(poll_thread, NULL);
10317 
10318    poll_thread = AST_PTHREADT_NULL;
10319 }

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

Referenced by make_email_file().

00782 {
00783    char *bufptr = buf;
00784    for (; *input; input++) {
00785       if (*input < 32) {
00786          continue;
00787       }
00788       *bufptr++ = *input;
00789       if (bufptr == buf + buflen - 1) {
00790          break;
00791       }
00792    }
00793    *bufptr = '\0';
00794    return buf;
00795 }

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

Definition at line 10444 of file app_voicemail.c.

References ast_free, ast_log(), AST_LOG_NOTICE, ast_str_append(), ast_str_create(), ast_strdup, ast_str::str, and ast_str::used.

Referenced by load_config().

10445 {
10446    char *current, *result;
10447 
10448    /* Add 16 for fudge factor */
10449    struct ast_str *str = ast_str_create(strlen(value) + 16);
10450 
10451    /* Substitute strings \r, \n, and \t into the appropriate characters */
10452    for (current = (char *) value; *current; current++) {
10453       if (*current == '\\') {
10454          current++;
10455          if (!*current) {
10456             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
10457             break;
10458          }
10459          switch (*current) {
10460          case 'r':
10461             ast_str_append(&str, 0, "\r");
10462             break;
10463          case 'n':
10464 #ifdef IMAP_STORAGE
10465             if (!str->used || str->str[str->used - 1] != '\r') {
10466                ast_str_append(&str, 0, "\r");
10467             }
10468 #endif
10469             ast_str_append(&str, 0, "\n");
10470             break;
10471          case 't':
10472             ast_str_append(&str, 0, "\t");
10473             break;
10474          default:
10475             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
10476             break;
10477          }
10478       } else {
10479          ast_str_append(&str, 0, "%c", *current);
10480       }
10481    }
10482 
10483    result = ast_strdup(str->str);
10484    ast_free(str);
10485 
10486    return result;
10487 }

static int unload_module ( void   )  [static]
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 8879 of file app_voicemail.c.

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

Referenced by vm_execmain(), and vmauthenticate().

08882 {
08883    int useadsi=0, valid=0, logretries=0;
08884    char password[AST_MAX_EXTENSION]="", *passptr;
08885    struct ast_vm_user vmus, *vmu = NULL;
08886 
08887    /* If ADSI is supported, setup login screen */
08888    adsi_begin(chan, &useadsi);
08889    if (!skipuser && useadsi)
08890       adsi_login(chan);
08891    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
08892       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
08893       return -1;
08894    }
08895    
08896    /* Authenticate them and get their mailbox/password */
08897    
08898    while (!valid && (logretries < max_logins)) {
08899       /* Prompt for, and read in the username */
08900       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
08901          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
08902          return -1;
08903       }
08904       if (ast_strlen_zero(mailbox)) {
08905          if (chan->cid.cid_num) {
08906             ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
08907          } else {
08908             ast_verb(3,"Username not entered\n");  
08909             return -1;
08910          }
08911       }
08912       if (useadsi)
08913          adsi_password(chan);
08914 
08915       if (!ast_strlen_zero(prefix)) {
08916          char fullusername[80] = "";
08917          ast_copy_string(fullusername, prefix, sizeof(fullusername));
08918          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
08919          ast_copy_string(mailbox, fullusername, mailbox_size);
08920       }
08921 
08922       ast_debug(1, "Before find user for mailbox %s\n",mailbox);
08923       vmu = find_user(&vmus, context, mailbox);
08924       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
08925          /* saved password is blank, so don't bother asking */
08926          password[0] = '\0';
08927       } else {
08928          if (ast_streamfile(chan, vm_password, chan->language)) {
08929             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
08930             return -1;
08931          }
08932          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
08933             ast_log(AST_LOG_WARNING, "Unable to read password\n");
08934             return -1;
08935          }
08936       }
08937 
08938       if (vmu) {
08939          passptr = vmu->password;
08940          if (passptr[0] == '-') passptr++;
08941       }
08942       if (vmu && !strcmp(passptr, password))
08943          valid++;
08944       else {
08945          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
08946          if (!ast_strlen_zero(prefix))
08947             mailbox[0] = '\0';
08948       }
08949       logretries++;
08950       if (!valid) {
08951          if (skipuser || logretries >= max_logins) {
08952             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
08953                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
08954                return -1;
08955             }
08956          } else {
08957             if (useadsi)
08958                adsi_login(chan);
08959             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
08960                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
08961                return -1;
08962             }
08963          }
08964          if (ast_waitstream(chan, "")) /* Channel is hung up */
08965             return -1;
08966       }
08967    }
08968    if (!valid && (logretries >= max_logins)) {
08969       ast_stopstream(chan);
08970       ast_play_and_wait(chan, "vm-goodbye");
08971       return -1;
08972    }
08973    if (vmu && !skipuser) {
08974       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
08975    }
08976    return 0;
08977 }

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

Definition at line 9822 of file app_voicemail.c.

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

Referenced by load_module().

09823 {
09824    struct ast_vm_user svm;
09825    char *context, *box;
09826    AST_DECLARE_APP_ARGS(args,
09827       AST_APP_ARG(mbox);
09828       AST_APP_ARG(options);
09829    );
09830    static int dep_warning = 0;
09831 
09832    if (ast_strlen_zero(data)) {
09833       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
09834       return -1;
09835    }
09836 
09837    if (!dep_warning) {
09838       dep_warning = 1;
09839       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
09840    }
09841 
09842    box = ast_strdupa(data);
09843 
09844    AST_STANDARD_APP_ARGS(args, box);
09845 
09846    if (args.options) {
09847    }
09848 
09849    if ((context = strchr(args.mbox, '@'))) {
09850       *context = '\0';
09851       context++;
09852    }
09853 
09854    if (find_user(&svm, context, args.mbox)) {
09855       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
09856    } else
09857       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
09858 
09859    return 0;
09860 }

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

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

Referenced by vm_execmain().

08861 {
08862    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
08863       return vm_browse_messages_es(chan, vms, vmu);
08864    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
08865       return vm_browse_messages_gr(chan, vms, vmu);
08866    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
08867       return vm_browse_messages_he(chan, vms, vmu);
08868    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
08869       return vm_browse_messages_it(chan, vms, vmu);
08870    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
08871       return vm_browse_messages_pt(chan, vms, vmu);
08872    } else if (!strncasecmp(chan->language, "zh", 2)) {
08873       return vm_browse_messages_zh(chan, vms, vmu);   /* CHINESE (Taiwan) */
08874    } else {                                             /* Default to English syntax */
08875       return vm_browse_messages_en(chan, vms, vmu);
08876    }
08877 }

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

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

Referenced by vm_browse_messages().

08724 {
08725    int cmd=0;
08726 
08727    if (vms->lastmsg > -1) {
08728       cmd = play_message(chan, vmu, vms);
08729    } else {
08730       cmd = ast_play_and_wait(chan, "vm-youhave");
08731       if (!cmd) 
08732          cmd = ast_play_and_wait(chan, "vm-no");
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       if (!cmd)
08738          cmd = ast_play_and_wait(chan, "vm-messages");
08739    }
08740    return cmd;
08741 }

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

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

Referenced by vm_browse_messages().

08778 {
08779    int cmd=0;
08780 
08781    if (vms->lastmsg > -1) {
08782       cmd = play_message(chan, vmu, vms);
08783    } else {
08784       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08785       if (!cmd)
08786          cmd = ast_play_and_wait(chan, "vm-messages");
08787       if (!cmd) {
08788          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08789          cmd = ast_play_and_wait(chan, vms->fn);
08790       }
08791    }
08792    return cmd;
08793 }

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

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

Referenced by vm_browse_messages().

08672 {
08673    int cmd=0;
08674 
08675    if (vms->lastmsg > -1) {
08676       cmd = play_message(chan, vmu, vms);
08677    } else {
08678       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08679       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
08680          if (!cmd) {
08681             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
08682             cmd = ast_play_and_wait(chan, vms->fn);
08683          }
08684          if (!cmd)
08685             cmd = ast_play_and_wait(chan, "vm-messages");
08686       } else {
08687          if (!cmd)
08688             cmd = ast_play_and_wait(chan, "vm-messages");
08689          if (!cmd) {
08690             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08691             cmd = ast_play_and_wait(chan, vms->fn);
08692          }
08693       }
08694    } 
08695    return cmd;
08696 }

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

Definition at line 8699 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08700 {
08701    int cmd = 0;
08702 
08703    if (vms->lastmsg > -1) {
08704       cmd = play_message(chan, vmu, vms);
08705    } else {
08706       if (!strcasecmp(vms->fn, "INBOX")) {
08707          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
08708       } else {
08709          cmd = ast_play_and_wait(chan, "vm-nomessages");
08710       }
08711    }
08712    return cmd;
08713 }

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

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

Referenced by vm_browse_messages().

08752 {
08753    int cmd=0;
08754 
08755    if (vms->lastmsg > -1) {
08756       cmd = play_message(chan, vmu, vms);
08757    } else {
08758       cmd = ast_play_and_wait(chan, "vm-no");
08759       if (!cmd)
08760          cmd = ast_play_and_wait(chan, "vm-message");
08761       if (!cmd) {
08762          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08763          cmd = ast_play_and_wait(chan, vms->fn);
08764       }
08765    }
08766    return cmd;
08767 }

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

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

Referenced by vm_browse_messages().

08804 {
08805    int cmd=0;
08806 
08807    if (vms->lastmsg > -1) {
08808       cmd = play_message(chan, vmu, vms);
08809    } else {
08810       cmd = ast_play_and_wait(chan, "vm-no");
08811       if (!cmd) {
08812          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08813          cmd = ast_play_and_wait(chan, vms->fn);
08814       }
08815       if (!cmd)
08816          cmd = ast_play_and_wait(chan, "vm-messages");
08817    }
08818    return cmd;
08819 }

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

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

Referenced by vm_browse_messages().

08830 {
08831    int cmd=0;
08832 
08833    if (vms->lastmsg > -1) {
08834       cmd = play_message(chan, vmu, vms);
08835    } else {
08836       cmd = ast_play_and_wait(chan, "vm-you");
08837       if (!cmd) 
08838          cmd = ast_play_and_wait(chan, "vm-haveno");
08839       if (!cmd)
08840          cmd = ast_play_and_wait(chan, "vm-messages");
08841       if (!cmd) {
08842          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08843          cmd = ast_play_and_wait(chan, vms->fn);
08844       }
08845    }
08846    return cmd;
08847 }

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

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

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

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

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

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

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

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

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

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

Referenced by copy_message(), and notify_new_message().

03712 {
03713    char *txt;
03714    int txtsize = 0;
03715 
03716    txtsize = (strlen(file) + 5)*sizeof(char);
03717    txt = alloca(txtsize);
03718    /* Sprintf here would safe because we alloca'd exactly the right length,
03719     * but trying to eliminate all sprintf's anyhow
03720     */
03721    if (ast_check_realtime("voicemail_data")) {
03722       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
03723    }
03724    snprintf(txt, txtsize, "%s.txt", file);
03725    unlink(txt);
03726    return ast_filedelete(file, NULL);
03727 }

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

Definition at line 9690 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_LOG_WARNING, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_vm_options::exitcontext, leave_voicemail(), 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(), leave_vm_options::record_gain, and vm_app_options.

Referenced by load_module(), and play_record_review().

09691 {
09692    int res = 0;
09693    char *tmp;
09694    struct leave_vm_options leave_options;
09695    struct ast_flags flags = { 0 };
09696    char *opts[OPT_ARG_ARRAY_SIZE];
09697    AST_DECLARE_APP_ARGS(args,
09698       AST_APP_ARG(argv0);
09699       AST_APP_ARG(argv1);
09700    );
09701    
09702    memset(&leave_options, 0, sizeof(leave_options));
09703 
09704    if (chan->_state != AST_STATE_UP)
09705       ast_answer(chan);
09706 
09707    if (!ast_strlen_zero(data)) {
09708       tmp = ast_strdupa(data);
09709       AST_STANDARD_APP_ARGS(args, tmp);
09710       if (args.argc == 2) {
09711          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09712             return -1;
09713          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
09714          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09715             int gain;
09716 
09717             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09718                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09719                return -1;
09720             } else {
09721                leave_options.record_gain = (signed char) gain;
09722             }
09723          }
09724          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
09725             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
09726                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
09727          }
09728       }
09729    } else {
09730       char temp[256];
09731       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
09732       if (res < 0)
09733          return res;
09734       if (ast_strlen_zero(temp))
09735          return 0;
09736       args.argv0 = ast_strdupa(temp);
09737    }
09738 
09739    res = leave_voicemail(chan, args.argv0, &leave_options);
09740 
09741    if (res == ERROR_LOCK_PATH) {
09742       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
09743       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
09744       res = 0;
09745    }
09746 
09747    return res;
09748 }

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

Definition at line 8979 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_LOG_WARNING, 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, close_mailbox(), ast_vm_user::context, vm_state::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), vm_state::fn, forward_message(), free_user(), get_folder2(), globalflags, has_voicemail(), vm_state::heard, language, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), manager_event, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, OLD_FOLDER, vm_state::oldmessages, open_mailbox(), OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), vm_state::repeats, run_externnotify(), save_to_folder(), say_and_wait(), vm_state::starting, vm_state::urgentmessages, vm_state::username, vm_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, VM_SVMAIL, and vm_state::vmbox.

Referenced by load_module().

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

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

Referenced by forward_message().

06189 {
06190 #ifdef IMAP_STORAGE
06191    int res;
06192 #endif
06193    int cmd = 0;
06194    int retries = 0, prepend_duration = 0, already_recorded = 0;
06195    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06196    char textfile[PATH_MAX];
06197    struct ast_config *msg_cfg;
06198    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06199 #ifndef IMAP_STORAGE
06200    signed char zero_gain = 0;
06201 #endif
06202    const char *duration_str;
06203 
06204    /* Must always populate duration correctly */
06205    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06206    strcpy(textfile, msgfile);
06207    strcpy(backup, msgfile);
06208    strcpy(backup_textfile, msgfile);
06209    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06210    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06211    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06212 
06213    if ((msg_cfg = ast_config_load(textfile, config_flags)) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06214       *duration = atoi(duration_str);
06215    } else {
06216       *duration = 0;
06217    }
06218 
06219    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06220       if (cmd)
06221          retries = 0;
06222       switch (cmd) {
06223       case '1': 
06224 
06225 #ifdef IMAP_STORAGE
06226          /* Record new intro file */
06227          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06228          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06229          res = ast_play_and_wait(chan, INTRO);
06230          res = ast_play_and_wait(chan, "beep");
06231          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *)duration, NULL, record_gain, vms, flag);
06232          cmd = 't';
06233 #else
06234 
06235          /* prepend a message to the current message, update the metadata and return */
06236 
06237          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06238          strcpy(textfile, msgfile);
06239          strncat(textfile, ".txt", sizeof(textfile) - 1);
06240          *duration = 0;
06241 
06242          /* if we can't read the message metadata, stop now */
06243          if (!msg_cfg) {
06244             cmd = 0;
06245             break;
06246          }
06247          
06248          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06249          if (already_recorded) {
06250             ast_filecopy(backup, msgfile, NULL);
06251             copy(backup_textfile, textfile);
06252          }
06253          else {
06254             ast_filecopy(msgfile, backup, NULL);
06255             copy(textfile,backup_textfile);
06256          }
06257          already_recorded = 1;
06258 
06259          if (record_gain)
06260             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06261 
06262          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06263          if (record_gain)
06264             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06265 
06266          
06267          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06268             *duration = atoi(duration_str);
06269 
06270          if (prepend_duration) {
06271             struct ast_category *msg_cat;
06272             /* need enough space for a maximum-length message duration */
06273             char duration_buf[12];
06274 
06275             *duration += prepend_duration;
06276             msg_cat = ast_category_get(msg_cfg, "message");
06277             snprintf(duration_buf, 11, "%ld", *duration);
06278             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06279                config_text_file_save(textfile, msg_cfg, "app_voicemail");
06280             }
06281          }
06282 
06283 #endif
06284          break;
06285       case '2': 
06286          /* NULL out introfile so we know there is no intro! */
06287 #ifdef IMAP_STORAGE
06288          *vms->introfn = '\0';
06289 #endif
06290          cmd = 't';
06291          break;
06292       case '*':
06293          cmd = '*';
06294          break;
06295       default: 
06296          cmd = ast_play_and_wait(chan,"vm-forwardoptions");
06297             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06298          if (!cmd)
06299             cmd = ast_play_and_wait(chan,"vm-starmain");
06300             /* "press star to return to the main menu" */
06301          if (!cmd)
06302             cmd = ast_waitfordigit(chan,6000);
06303          if (!cmd)
06304             retries++;
06305          if (retries > 3)
06306             cmd = 't';
06307       }
06308    }
06309 
06310    if (msg_cfg)
06311       ast_config_destroy(msg_cfg);
06312    if (prepend_duration)
06313       *duration = prepend_duration;
06314 
06315    if (already_recorded && cmd == -1) {
06316       /* restore original message if prepention cancelled */
06317       ast_filerename(backup, msgfile, NULL);
06318       rename(backup_textfile, textfile);
06319    }
06320 
06321    if (cmd == 't' || cmd == 'S')
06322       cmd = 0;
06323    return cmd;
06324 }

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

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

Referenced by vm_execmain().

08364 {
08365    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08366       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08367    } else {             /* Default to ENGLISH */
08368       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08369    }
08370 }

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

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

Referenced by vm_instructions(), and vm_instructions_zh().

08263 {
08264    int res = 0;
08265    /* Play instructions and wait for new command */
08266    while (!res) {
08267       if (vms->starting) {
08268          if (vms->lastmsg > -1) {
08269             if (skipadvanced)
08270                res = ast_play_and_wait(chan, "vm-onefor-full");
08271             else
08272                res = ast_play_and_wait(chan, "vm-onefor");
08273             if (!res)
08274                res = vm_play_folder_name(chan, vms->vmbox);
08275          }
08276          if (!res) {
08277             if (skipadvanced)
08278                res = ast_play_and_wait(chan, "vm-opts-full");
08279             else
08280                res = ast_play_and_wait(chan, "vm-opts");
08281          }
08282       } else {
08283          /* Added for additional help */
08284          if (skipadvanced) {
08285             res = ast_play_and_wait(chan, "vm-onefor-full");
08286             if (!res)
08287                res = vm_play_folder_name(chan, vms->vmbox);
08288             res = ast_play_and_wait(chan, "vm-opts-full");
08289          }
08290          /* Logic:
08291           * If the current message is not the first OR
08292           * if we're listening to the first new message and there are
08293           * also urgent messages, then prompt for navigation to the
08294           * previous message
08295           */
08296          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08297             res = ast_play_and_wait(chan, "vm-prev");
08298          }
08299          if (!res && !skipadvanced)
08300             res = ast_play_and_wait(chan, "vm-advopts");
08301          if (!res)
08302             res = ast_play_and_wait(chan, "vm-repeat");
08303          /* Logic:
08304           * If we're not listening to the last message OR
08305           * we're listening to the last urgent message and there are
08306           * also new non-urgent messages, then prompt for navigation
08307           * to the next message
08308           */
08309          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08310             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08311             res = ast_play_and_wait(chan, "vm-next");
08312          }
08313          if (!res) {
08314             if (!vms->deleted[vms->curmsg])
08315                res = ast_play_and_wait(chan, "vm-delete");
08316             else
08317                res = ast_play_and_wait(chan, "vm-undelete");
08318             if (!res)
08319                res = ast_play_and_wait(chan, "vm-toforward");
08320             if (!res)
08321                res = ast_play_and_wait(chan, "vm-savemessage");
08322          }
08323       }
08324       if (!res) {
08325          res = ast_play_and_wait(chan, "vm-helpexit");
08326       }
08327       if (!res)
08328          res = ast_waitfordigit(chan, 6000);
08329       if (!res) {
08330          vms->repeats++;
08331          if (vms->repeats > 2) {
08332             res = 't';
08333          }
08334       }
08335    }
08336    return res;
08337 }

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

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

Referenced by vm_instructions().

08340 {
08341    int res = 0;
08342    /* Play instructions and wait for new command */
08343    while (!res) {
08344       if (vms->lastmsg > -1) {
08345          res = ast_play_and_wait(chan, "vm-listen");
08346          if (!res)
08347             res = vm_play_folder_name(chan, vms->vmbox);
08348          if (!res)
08349             res = ast_play_and_wait(chan, "press");
08350          if (!res)
08351             res = ast_play_and_wait(chan, "digits/1");
08352       }
08353       if (!res)
08354          res = ast_play_and_wait(chan, "vm-opts");
08355       if (!res) {
08356          vms->starting = 0;
08357          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08358       }
08359    }
08360    return res;
08361 }

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

Definition at line 8203 of file app_voicemail.c.

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

Referenced by vm_execmain().

08204 {
08205    char prefile[256];
08206    
08207    /* Notify the user that the temp greeting is set and give them the option to remove it */
08208    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08209    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08210       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08211       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08212          ast_play_and_wait(chan, "vm-tempgreetactive");
08213       }
08214       DISPOSE(prefile, -1);
08215    }
08216 
08217    /* Play voicemail intro - syntax is different for different languages */
08218    if (0) {
08219    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08220       return vm_intro_cs(chan, vms);
08221    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08222       static int deprecation_warning = 0;
08223       if (deprecation_warning++ % 10 == 0) {
08224          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08225       }
08226       return vm_intro_cs(chan, vms);
08227    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08228       return vm_intro_de(chan, vms);
08229    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08230       return vm_intro_es(chan, vms);
08231    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08232       return vm_intro_fr(chan, vms);
08233    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08234       return vm_intro_gr(chan, vms);
08235    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08236       return vm_intro_he(chan, vms);
08237    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08238       return vm_intro_it(chan, vms);
08239    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08240       return vm_intro_nl(chan, vms);
08241    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08242       return vm_intro_no(chan, vms);
08243    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08244       return vm_intro_pl(chan, vms);
08245    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08246       return vm_intro_pt_BR(chan, vms);
08247    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08248       return vm_intro_pt(chan, vms);
08249    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08250       return vm_intro_multilang(chan, vms, "n");
08251    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08252       return vm_intro_se(chan, vms);
08253    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08254       return vm_intro_multilang(chan, vms, "n");
08255    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08256       return vm_intro_zh(chan, vms);
08257    } else {                                             /* Default to ENGLISH */
08258       return vm_intro_en(chan, vms);
08259    }
08260 }

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

Definition at line 8104 of file app_voicemail.c.

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

Referenced by vm_intro().

08105 {
08106    int res;
08107    res = ast_play_and_wait(chan, "vm-youhave");
08108    if (!res) {
08109       if (vms->newmessages) {
08110          if (vms->newmessages == 1) {
08111             res = ast_play_and_wait(chan, "digits/jednu");
08112          } else {
08113             res = say_and_wait(chan, vms->newmessages, chan->language);
08114          }
08115          if (!res) {
08116             if ((vms->newmessages == 1))
08117                res = ast_play_and_wait(chan, "vm-novou");
08118             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08119                res = ast_play_and_wait(chan, "vm-nove");
08120             if (vms->newmessages > 4)
08121                res = ast_play_and_wait(chan, "vm-novych");
08122          }
08123          if (vms->oldmessages && !res)
08124             res = ast_play_and_wait(chan, "vm-and");
08125          else if (!res) {
08126             if ((vms->newmessages == 1))
08127                res = ast_play_and_wait(chan, "vm-zpravu");
08128             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08129                res = ast_play_and_wait(chan, "vm-zpravy");
08130             if (vms->newmessages > 4)
08131                res = ast_play_and_wait(chan, "vm-zprav");
08132          }
08133       }
08134       if (!res && vms->oldmessages) {
08135          res = say_and_wait(chan, vms->oldmessages, chan->language);
08136          if (!res) {
08137             if ((vms->oldmessages == 1))
08138                res = ast_play_and_wait(chan, "vm-starou");
08139             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08140                res = ast_play_and_wait(chan, "vm-stare");
08141             if (vms->oldmessages > 4)
08142                res = ast_play_and_wait(chan, "vm-starych");
08143          }
08144          if (!res) {
08145             if ((vms->oldmessages == 1))
08146                res = ast_play_and_wait(chan, "vm-zpravu");
08147             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08148                res = ast_play_and_wait(chan, "vm-zpravy");
08149             if (vms->oldmessages > 4)
08150                res = ast_play_and_wait(chan, "vm-zprav");
08151          }
08152       }
08153       if (!res) {
08154          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08155             res = ast_play_and_wait(chan, "vm-no");
08156             if (!res)
08157                res = ast_play_and_wait(chan, "vm-zpravy");
08158          }
08159       }
08160    }
08161    return res;
08162 }

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

Definition at line 7800 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 7549 of file app_voicemail.c.

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

Referenced by vm_intro().

07550 {
07551    int res;
07552 
07553    /* Introduce messages they have */
07554    res = ast_play_and_wait(chan, "vm-youhave");
07555    if (!res) {
07556       if (vms->urgentmessages) {
07557          res = say_and_wait(chan, vms->urgentmessages, chan->language);
07558          if (!res)
07559             res = ast_play_and_wait(chan, "vm-Urgent");
07560          if ((vms->oldmessages || vms->newmessages) && !res) {
07561             res = ast_play_and_wait(chan, "vm-and");
07562          } else if (!res) {
07563             if ((vms->urgentmessages == 1))
07564                res = ast_play_and_wait(chan, "vm-message");
07565             else
07566                res = ast_play_and_wait(chan, "vm-messages");
07567          }
07568       }
07569       if (vms->newmessages) {
07570          res = say_and_wait(chan, vms->newmessages, chan->language);
07571          if (!res)
07572             res = ast_play_and_wait(chan, "vm-INBOX");
07573          if (vms->oldmessages && !res)
07574             res = ast_play_and_wait(chan, "vm-and");
07575          else if (!res) {
07576             if ((vms->newmessages == 1))
07577                res = ast_play_and_wait(chan, "vm-message");
07578             else
07579                res = ast_play_and_wait(chan, "vm-messages");
07580          }
07581             
07582       }
07583       if (!res && vms->oldmessages) {
07584          res = say_and_wait(chan, vms->oldmessages, chan->language);
07585          if (!res)
07586             res = ast_play_and_wait(chan, "vm-Old");
07587          if (!res) {
07588             if (vms->oldmessages == 1)
07589                res = ast_play_and_wait(chan, "vm-message");
07590             else
07591                res = ast_play_and_wait(chan, "vm-messages");
07592          }
07593       }
07594       if (!res) {
07595          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
07596             res = ast_play_and_wait(chan, "vm-no");
07597             if (!res)
07598                res = ast_play_and_wait(chan, "vm-messages");
07599          }
07600       }
07601    }
07602    return res;
07603 }

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

Definition at line 7849 of file app_voicemail.c.

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

Referenced by vm_intro().

07850 {
07851    /* Introduce messages they have */
07852    int res;
07853    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07854       res = ast_play_and_wait(chan, "vm-youhaveno");
07855       if (!res)
07856          res = ast_play_and_wait(chan, "vm-messages");
07857    } else {
07858       res = ast_play_and_wait(chan, "vm-youhave");
07859    }
07860    if (!res) {
07861       if (vms->newmessages) {
07862          if (!res) {
07863             if ((vms->newmessages == 1)) {
07864                res = ast_play_and_wait(chan, "digits/1M");
07865                if (!res)
07866                   res = ast_play_and_wait(chan, "vm-message");
07867                if (!res)
07868                   res = ast_play_and_wait(chan, "vm-INBOXs");
07869             } else {
07870                res = say_and_wait(chan, vms->newmessages, chan->language);
07871                if (!res)
07872                   res = ast_play_and_wait(chan, "vm-messages");
07873                if (!res)
07874                   res = ast_play_and_wait(chan, "vm-INBOX");
07875             }
07876          }
07877          if (vms->oldmessages && !res)
07878             res = ast_play_and_wait(chan, "vm-and");
07879       }
07880       if (vms->oldmessages) {
07881          if (!res) {
07882             if (vms->oldmessages == 1) {
07883                res = ast_play_and_wait(chan, "digits/1M");
07884                if (!res)
07885                   res = ast_play_and_wait(chan, "vm-message");
07886                if (!res)
07887                   res = ast_play_and_wait(chan, "vm-Olds");
07888             } else {
07889                res = say_and_wait(chan, vms->oldmessages, chan->language);
07890                if (!res)
07891                   res = ast_play_and_wait(chan, "vm-messages");
07892                if (!res)
07893                   res = ast_play_and_wait(chan, "vm-Old");
07894             }
07895          }
07896       }
07897    }
07898 return res;
07899 }

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

Definition at line 7947 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 7348 of file app_voicemail.c.

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

Referenced by vm_intro().

07349 {
07350    int res = 0;
07351 
07352    if (vms->newmessages) {
07353       res = ast_play_and_wait(chan, "vm-youhave");
07354       if (!res) 
07355          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07356       if (!res) {
07357          if ((vms->newmessages == 1)) {
07358             res = ast_play_and_wait(chan, "vm-INBOX");
07359             if (!res)
07360                res = ast_play_and_wait(chan, "vm-message");
07361          } else {
07362             res = ast_play_and_wait(chan, "vm-INBOXs");
07363             if (!res)
07364                res = ast_play_and_wait(chan, "vm-messages");
07365          }
07366       }
07367    } else if (vms->oldmessages){
07368       res = ast_play_and_wait(chan, "vm-youhave");
07369       if (!res)
07370          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07371       if ((vms->oldmessages == 1)){
07372          res = ast_play_and_wait(chan, "vm-Old");
07373          if (!res)
07374             res = ast_play_and_wait(chan, "vm-message");
07375       } else {
07376          res = ast_play_and_wait(chan, "vm-Olds");
07377          if (!res)
07378             res = ast_play_and_wait(chan, "vm-messages");
07379       }
07380    } else if (!vms->oldmessages && !vms->newmessages) 
07381       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07382    return res;
07383 }

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

Definition at line 7482 of file app_voicemail.c.

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

Referenced by vm_intro().

07483 {
07484    int res = 0;
07485 
07486    /* Introduce messages they have */
07487    if (!res) {
07488       if ((vms->newmessages) || (vms->oldmessages)) {
07489          res = ast_play_and_wait(chan, "vm-youhave");
07490       }
07491       /*
07492        * The word "shtei" refers to the number 2 in hebrew when performing a count
07493        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
07494        * an element, this is one of them.
07495        */
07496       if (vms->newmessages) {
07497          if (!res) {
07498             if (vms->newmessages == 1) {
07499                res = ast_play_and_wait(chan, "vm-INBOX1");
07500             } else {
07501                if (vms->newmessages == 2) {
07502                   res = ast_play_and_wait(chan, "vm-shtei");
07503                } else {
07504                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07505                }
07506                res = ast_play_and_wait(chan, "vm-INBOX");
07507             }
07508          }
07509          if (vms->oldmessages && !res) {
07510             res = ast_play_and_wait(chan, "vm-and");
07511             if (vms->oldmessages == 1) {
07512                res = ast_play_and_wait(chan, "vm-Old1");
07513             } else {
07514                if (vms->oldmessages == 2) {
07515                   res = ast_play_and_wait(chan, "vm-shtei");
07516                } else {
07517                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07518                }
07519                res = ast_play_and_wait(chan, "vm-Old");
07520             }
07521          }
07522       }
07523       if (!res && vms->oldmessages && !vms->newmessages) {
07524          if (!res) {
07525             if (vms->oldmessages == 1) {
07526                res = ast_play_and_wait(chan, "vm-Old1");
07527             } else {
07528                if (vms->oldmessages == 2) {
07529                   res = ast_play_and_wait(chan, "vm-shtei");
07530                } else {
07531                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
07532                }
07533                res = ast_play_and_wait(chan, "vm-Old");
07534             }
07535          }
07536       }
07537       if (!res) {
07538          if (!vms->oldmessages && !vms->newmessages) {
07539             if (!res) {
07540                res = ast_play_and_wait(chan, "vm-nomessages");
07541             }
07542          }
07543       }
07544    }
07545    return res;
07546 }

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

Definition at line 7606 of file app_voicemail.c.

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

Referenced by vm_intro().

07607 {
07608    /* Introduce messages they have */
07609    int res;
07610    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
07611       res = ast_play_and_wait(chan, "vm-no") ||
07612          ast_play_and_wait(chan, "vm-message");
07613    else
07614       res = ast_play_and_wait(chan, "vm-youhave");
07615    if (!res && vms->newmessages) {
07616       res = (vms->newmessages == 1) ?
07617          ast_play_and_wait(chan, "digits/un") ||
07618          ast_play_and_wait(chan, "vm-nuovo") ||
07619          ast_play_and_wait(chan, "vm-message") :
07620          /* 2 or more new messages */
07621          say_and_wait(chan, vms->newmessages, chan->language) ||
07622          ast_play_and_wait(chan, "vm-nuovi") ||
07623          ast_play_and_wait(chan, "vm-messages");
07624       if (!res && vms->oldmessages)
07625          res = ast_play_and_wait(chan, "vm-and");
07626    }
07627    if (!res && vms->oldmessages) {
07628       res = (vms->oldmessages == 1) ?
07629          ast_play_and_wait(chan, "digits/un") ||
07630          ast_play_and_wait(chan, "vm-vecchio") ||
07631          ast_play_and_wait(chan, "vm-message") :
07632          /* 2 or more old messages */
07633          say_and_wait(chan, vms->oldmessages, chan->language) ||
07634          ast_play_and_wait(chan, "vm-vecchi") ||
07635          ast_play_and_wait(chan, "vm-messages");
07636    }
07637    return res;
07638 }

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

Definition at line 7442 of file app_voicemail.c.

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

Referenced by vm_intro().

07443 {
07444    int res;
07445    int lastnum = 0;
07446 
07447    res = ast_play_and_wait(chan, "vm-youhave");
07448 
07449    if (!res && vms->newmessages) {
07450       lastnum = vms->newmessages;
07451 
07452       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07453          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
07454       }
07455 
07456       if (!res && vms->oldmessages) {
07457          res = ast_play_and_wait(chan, "vm-and");
07458       }
07459    }
07460 
07461    if (!res && vms->oldmessages) {
07462       lastnum = vms->oldmessages;
07463 
07464       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07465          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
07466       }
07467    }
07468 
07469    if (!res) {
07470       if (lastnum == 0) {
07471          res = ast_play_and_wait(chan, "vm-no");
07472       }
07473       if (!res) {
07474          res = ast_say_counted_noun(chan, lastnum, "vm-message");
07475       }
07476    }
07477 
07478    return res;
07479 }

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

Definition at line 7990 of file app_voicemail.c.

References ast_play_and_wait(), 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             if (vms->newmessages == 1)
08000                res = ast_play_and_wait(chan, "vm-INBOXs");
08001             else
08002                res = ast_play_and_wait(chan, "vm-INBOX");
08003          }
08004          if (vms->oldmessages && !res)
08005             res = ast_play_and_wait(chan, "vm-and");
08006          else if (!res) {
08007             if ((vms->newmessages == 1))
08008                res = ast_play_and_wait(chan, "vm-message");
08009             else
08010                res = ast_play_and_wait(chan, "vm-messages");
08011          }
08012             
08013       }
08014       if (!res && vms->oldmessages) {
08015          res = say_and_wait(chan, vms->oldmessages, chan->language);
08016          if (!res) {
08017             if (vms->oldmessages == 1)
08018                res = ast_play_and_wait(chan, "vm-Olds");
08019             else
08020                res = ast_play_and_wait(chan, "vm-Old");
08021          }
08022          if (!res) {
08023             if (vms->oldmessages == 1)
08024                res = ast_play_and_wait(chan, "vm-message");
08025             else
08026                res = ast_play_and_wait(chan, "vm-messages");
08027          }
08028       }
08029       if (!res) {
08030          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08031             res = ast_play_and_wait(chan, "vm-no");
08032             if (!res)
08033                res = ast_play_and_wait(chan, "vm-messages");
08034          }
08035       }
08036    }
08037    return res;
08038 }

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

Definition at line 7756 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 7641 of file app_voicemail.c.

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

Referenced by vm_intro().

07642 {
07643    /* Introduce messages they have */
07644    int res;
07645    div_t num;
07646 
07647    if (!vms->oldmessages && !vms->newmessages) {
07648       res = ast_play_and_wait(chan, "vm-no");
07649       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07650       return res;
07651    } else {
07652       res = ast_play_and_wait(chan, "vm-youhave");
07653    }
07654 
07655    if (vms->newmessages) {
07656       num = div(vms->newmessages, 10);
07657       if (vms->newmessages == 1) {
07658          res = ast_play_and_wait(chan, "digits/1-a");
07659          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
07660          res = res ? res : ast_play_and_wait(chan, "vm-message");
07661       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07662          if (num.rem == 2) {
07663             if (!num.quot) {
07664                res = ast_play_and_wait(chan, "digits/2-ie");
07665             } else {
07666                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
07667                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07668             }
07669          } else {
07670             res = say_and_wait(chan, vms->newmessages, chan->language);
07671          }
07672          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
07673          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07674       } else {
07675          res = say_and_wait(chan, vms->newmessages, chan->language);
07676          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
07677          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07678       }
07679       if (!res && vms->oldmessages)
07680          res = ast_play_and_wait(chan, "vm-and");
07681    }
07682    if (!res && vms->oldmessages) {
07683       num = div(vms->oldmessages, 10);
07684       if (vms->oldmessages == 1) {
07685          res = ast_play_and_wait(chan, "digits/1-a");
07686          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
07687          res = res ? res : ast_play_and_wait(chan, "vm-message");
07688       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07689          if (num.rem == 2) {
07690             if (!num.quot) {
07691                res = ast_play_and_wait(chan, "digits/2-ie");
07692             } else {
07693                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
07694                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07695             }
07696          } else {
07697             res = say_and_wait(chan, vms->oldmessages, chan->language);
07698          }
07699          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
07700          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07701       } else {
07702          res = say_and_wait(chan, vms->oldmessages, chan->language);
07703          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
07704          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07705       }
07706    }
07707 
07708    return res;
07709 }

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

Definition at line 8041 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 7902 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 7712 of file app_voicemail.c.

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

Referenced by vm_intro().

07713 {
07714    /* Introduce messages they have */
07715    int res;
07716 
07717    res = ast_play_and_wait(chan, "vm-youhave");
07718    if (res)
07719       return res;
07720 
07721    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07722       res = ast_play_and_wait(chan, "vm-no");
07723       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07724       return res;
07725    }
07726 
07727    if (vms->newmessages) {
07728       if ((vms->newmessages == 1)) {
07729          res = ast_play_and_wait(chan, "digits/ett");
07730          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
07731          res = res ? res : ast_play_and_wait(chan, "vm-message");
07732       } else {
07733          res = say_and_wait(chan, vms->newmessages, chan->language);
07734          res = res ? res : ast_play_and_wait(chan, "vm-nya");
07735          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07736       }
07737       if (!res && vms->oldmessages)
07738          res = ast_play_and_wait(chan, "vm-and");
07739    }
07740    if (!res && vms->oldmessages) {
07741       if (vms->oldmessages == 1) {
07742          res = ast_play_and_wait(chan, "digits/ett");
07743          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
07744          res = res ? res : ast_play_and_wait(chan, "vm-message");
07745       } else {
07746          res = say_and_wait(chan, vms->oldmessages, chan->language);
07747          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
07748          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07749       }
07750    }
07751 
07752    return res;
07753 }

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

Definition at line 8165 of file app_voicemail.c.

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

Referenced by vm_intro().

08166 {
08167    int res;
08168    /* Introduce messages they have */
08169    res = ast_play_and_wait(chan, "vm-you");
08170 
08171    if (!res && vms->newmessages) {
08172       res = ast_play_and_wait(chan, "vm-have");
08173       if (!res)
08174          res = say_and_wait(chan, vms->newmessages, chan->language);
08175       if (!res)
08176          res = ast_play_and_wait(chan, "vm-tong");
08177       if (!res)
08178          res = ast_play_and_wait(chan, "vm-INBOX");
08179       if (vms->oldmessages && !res)
08180          res = ast_play_and_wait(chan, "vm-and");
08181       else if (!res) 
08182          res = ast_play_and_wait(chan, "vm-messages");
08183    }
08184    if (!res && vms->oldmessages) {
08185       res = ast_play_and_wait(chan, "vm-have");
08186       if (!res)
08187          res = say_and_wait(chan, vms->oldmessages, chan->language);
08188       if (!res)
08189          res = ast_play_and_wait(chan, "vm-tong");
08190       if (!res)
08191          res = ast_play_and_wait(chan, "vm-Old");
08192       if (!res)
08193          res = ast_play_and_wait(chan, "vm-messages");
08194    }
08195    if (!res && !vms->oldmessages && !vms->newmessages) {
08196       res = ast_play_and_wait(chan, "vm-haveno");
08197       if (!res)
08198          res = ast_play_and_wait(chan, "vm-messages");
08199    }
08200    return res;
08201 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

02844 {
02845    switch (ast_lock_path(path)) {
02846    case AST_LOCK_TIMEOUT:
02847       return -1;
02848    default:
02849       return 0;
02850    }
02851 }

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

Definition at line 1355 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01356 {
01357    FILE *p = NULL;
01358    int pfd = mkstemp(template);
01359    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01360    if (pfd > -1) {
01361       p = fdopen(pfd, "w+");
01362       if (!p) {
01363          close(pfd);
01364          pfd = -1;
01365       }
01366    }
01367    return p;
01368 }

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 8373 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, check_password(), ast_vm_user::context, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, VM_FORCENAME, vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, and vm_reenterpassword.

Referenced by vm_execmain().

08374 {
08375    int cmd = 0;
08376    int duration = 0;
08377    int tries = 0;
08378    char newpassword[80] = "";
08379    char newpassword2[80] = "";
08380    char prefile[PATH_MAX] = "";
08381    unsigned char buf[256];
08382    int bytes=0;
08383 
08384    if (ast_adsi_available(chan)) {
08385       bytes += adsi_logo(buf + bytes);
08386       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08387       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08388       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08389       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08390       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08391    }
08392 
08393    /* First, have the user change their password 
08394       so they won't get here again */
08395    for (;;) {
08396       newpassword[1] = '\0';
08397       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08398       if (cmd == '#')
08399          newpassword[0] = '\0';
08400       if (cmd < 0 || cmd == 't' || cmd == '#')
08401          return cmd;
08402       cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
08403       if (cmd < 0 || cmd == 't' || cmd == '#')
08404          return cmd;
08405       cmd = check_password(vmu, newpassword); /* perform password validation */
08406       if (cmd != 0) {
08407          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08408          cmd = ast_play_and_wait(chan, vm_invalid_password);
08409       } else {
08410          newpassword2[1] = '\0';
08411          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08412          if (cmd == '#')
08413             newpassword2[0] = '\0';
08414          if (cmd < 0 || cmd == 't' || cmd == '#')
08415             return cmd;
08416          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
08417          if (cmd < 0 || cmd == 't' || cmd == '#')
08418             return cmd;
08419          if (!strcmp(newpassword, newpassword2))
08420             break;
08421          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08422          cmd = ast_play_and_wait(chan, vm_mismatch);
08423       }
08424       if (++tries == 3)
08425          return -1;
08426       if (cmd != 0) {
08427          cmd = ast_play_and_wait(chan, vm_pls_try_again);
08428       }
08429    }
08430    if (pwdchange & PWDCHANGE_INTERNAL)
08431       vm_change_password(vmu, newpassword);
08432    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08433       vm_change_password_shell(vmu, newpassword);
08434 
08435    ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08436    cmd = ast_play_and_wait(chan, vm_passchanged);
08437 
08438    /* If forcename is set, have the user record their name */  
08439    if (ast_test_flag(vmu, VM_FORCENAME)) {
08440       snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08441       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08442          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08443          if (cmd < 0 || cmd == 't' || cmd == '#')
08444             return cmd;
08445       }
08446    }
08447 
08448    /* If forcegreetings is set, have the user record their greetings */
08449    if (ast_test_flag(vmu, VM_FORCEGREET)) {
08450       snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08451       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08452          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08453          if (cmd < 0 || cmd == 't' || cmd == '#')
08454             return cmd;
08455       }
08456 
08457       snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08458       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08459          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08460          if (cmd < 0 || cmd == 't' || cmd == '#')
08461             return cmd;
08462       }
08463    }
08464 
08465    return cmd;
08466 }

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

Referenced by vm_execmain().

08469 {
08470    int cmd = 0;
08471    int retries = 0;
08472    int duration = 0;
08473    char newpassword[80] = "";
08474    char newpassword2[80] = "";
08475    char prefile[PATH_MAX] = "";
08476    unsigned char buf[256];
08477    int bytes=0;
08478 
08479    if (ast_adsi_available(chan)) {
08480       bytes += adsi_logo(buf + bytes);
08481       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
08482       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08483       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08484       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08485       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08486    }
08487    while ((cmd >= 0) && (cmd != 't')) {
08488       if (cmd)
08489          retries = 0;
08490       switch (cmd) {
08491       case '1': /* Record your unavailable message */
08492          snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08493          cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08494          break;
08495       case '2':  /* Record your busy message */
08496          snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08497          cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08498          break;
08499       case '3': /* Record greeting */
08500          snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08501          cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08502          break;
08503       case '4':  /* manage the temporary greeting */
08504          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
08505          break;
08506       case '5': /* change password */
08507          if (vmu->password[0] == '-') {
08508             cmd = ast_play_and_wait(chan, "vm-no");
08509             break;
08510          }
08511          newpassword[1] = '\0';
08512          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08513          if (cmd == '#')
08514             newpassword[0] = '\0';
08515          else {
08516             if (cmd < 0)
08517                break;
08518             if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
08519                break;
08520             }
08521          }
08522          cmd = check_password(vmu, newpassword); /* perform password validation */
08523          if (cmd != 0) {
08524             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08525             cmd = ast_play_and_wait(chan, vm_invalid_password);
08526             if (!cmd) {
08527                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08528             }
08529             break;
08530          }
08531          newpassword2[1] = '\0';
08532          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08533          if (cmd == '#')
08534             newpassword2[0] = '\0';
08535          else {
08536             if (cmd < 0)
08537                break;
08538 
08539             if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#")) < 0) {
08540                break;
08541             }
08542          }
08543          if (strcmp(newpassword, newpassword2)) {
08544             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08545             cmd = ast_play_and_wait(chan, vm_mismatch);
08546             if (!cmd) {
08547                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08548             }
08549             break;
08550          }
08551          if (pwdchange & PWDCHANGE_INTERNAL)
08552             vm_change_password(vmu, newpassword);
08553          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08554             vm_change_password_shell(vmu, newpassword);
08555 
08556          ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08557          cmd = ast_play_and_wait(chan, vm_passchanged);
08558          break;
08559       case '*': 
08560          cmd = 't';
08561          break;
08562       default: 
08563          cmd = 0;
08564          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08565          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08566          if (ast_fileexists(prefile, NULL, NULL)) {
08567             cmd = ast_play_and_wait(chan, "vm-tmpexists");
08568          }
08569          DISPOSE(prefile, -1);
08570          if (!cmd) {
08571             cmd = ast_play_and_wait(chan, "vm-options");
08572          }
08573          if (!cmd) {
08574             cmd = ast_waitfordigit(chan,6000);
08575          }
08576          if (!cmd) {
08577             retries++;
08578          }
08579          if (retries > 3) {
08580             cmd = 't';
08581          }
08582       }
08583    }
08584    if (cmd == 't')
08585       cmd = 0;
08586    return cmd;
08587 }

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

Definition at line 7313 of file app_voicemail.c.

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

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

07314 {
07315    int cmd;
07316 
07317    if (  !strncasecmp(chan->language, "it", 2) ||
07318         !strncasecmp(chan->language, "es", 2) ||
07319         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07320       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07321       return cmd ? cmd : ast_play_and_wait(chan, box);
07322    } else if (!strncasecmp(chan->language, "gr", 2)) {
07323       return vm_play_folder_name_gr(chan, box);
07324    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07325       return ast_play_and_wait(chan, box);
07326    } else if (!strncasecmp(chan->language, "pl", 2)) {
07327       return vm_play_folder_name_pl(chan, box);
07328    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07329       return vm_play_folder_name_ua(chan, box);
07330    } else {  /* Default English */
07331       cmd = ast_play_and_wait(chan, box);
07332       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07333    }
07334 }

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

Definition at line 7266 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07267 {
07268    int cmd;
07269    char *buf;
07270 
07271    buf = alloca(strlen(box)+2); 
07272    strcpy(buf, box);
07273    strcat(buf,"s");
07274 
07275    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07276       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07277       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07278    } else {
07279       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07280       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07281    }
07282 }

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

Definition at line 7284 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07285 {
07286    int cmd;
07287 
07288    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07289       if (!strcasecmp(box, "vm-INBOX"))
07290          cmd = ast_play_and_wait(chan, "vm-new-e");
07291       else
07292          cmd = ast_play_and_wait(chan, "vm-old-e");
07293       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07294    } else {
07295       cmd = ast_play_and_wait(chan, "vm-messages");
07296       return cmd ? cmd : ast_play_and_wait(chan, box);
07297    }
07298 }

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

Definition at line 7300 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07301 {
07302    int cmd;
07303 
07304    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07305       cmd = ast_play_and_wait(chan, "vm-messages");
07306       return cmd ? cmd : ast_play_and_wait(chan, box);
07307    } else {
07308       cmd = ast_play_and_wait(chan, box);
07309       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07310    }
07311 }

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 8605 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(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

08606 {
08607    int cmd = 0;
08608    int retries = 0;
08609    int duration = 0;
08610    char prefile[PATH_MAX] = "";
08611    unsigned char buf[256];
08612    int bytes = 0;
08613 
08614    if (ast_adsi_available(chan)) {
08615       bytes += adsi_logo(buf + bytes);
08616       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
08617       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08618       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08619       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08620       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08621    }
08622 
08623    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08624    while ((cmd >= 0) && (cmd != 't')) {
08625       if (cmd)
08626          retries = 0;
08627       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08628       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
08629          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08630          cmd = 't';  
08631       } else {
08632          switch (cmd) {
08633          case '1':
08634             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08635             break;
08636          case '2':
08637             DELETE(prefile, -1, prefile, vmu);
08638             ast_play_and_wait(chan, "vm-tempremoved");
08639             cmd = 't';  
08640             break;
08641          case '*': 
08642             cmd = 't';
08643             break;
08644          default:
08645             cmd = ast_play_and_wait(chan,
08646                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
08647                   "vm-tempgreeting2" : "vm-tempgreeting");
08648             if (!cmd)
08649                cmd = ast_waitfordigit(chan,6000);
08650             if (!cmd)
08651                retries++;
08652             if (retries > 3)
08653                cmd = 't';
08654          }
08655       }
08656       DISPOSE(prefile, -1);
08657    }
08658    if (cmd == 't')
08659       cmd = 0;
08660    return cmd;
08661 }

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

Definition at line 9891 of file app_voicemail.c.

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

Referenced by load_module().

09892 {
09893    char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
09894    struct ast_vm_user vmus;
09895    char *options = NULL;
09896    int silent = 0, skipuser = 0;
09897    int res = -1;
09898    
09899    if (s) {
09900       s = ast_strdupa(s);
09901       user = strsep(&s, ",");
09902       options = strsep(&s, ",");
09903       if (user) {
09904          s = user;
09905          user = strsep(&s, "@");
09906          context = strsep(&s, "");
09907          if (!ast_strlen_zero(user))
09908             skipuser++;
09909          ast_copy_string(mailbox, user, sizeof(mailbox));
09910       }
09911    }
09912 
09913    if (options) {
09914       silent = (strchr(options, 's')) != NULL;
09915    }
09916 
09917    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
09918       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
09919       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
09920       ast_play_and_wait(chan, "auth-thankyou");
09921       res = 0;
09922    }
09923 
09924    return res;
09925 }

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

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

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

03938 {
03939    const struct vm_zone *z = NULL;
03940    struct timeval t = ast_tvnow();
03941 
03942    /* Does this user have a timezone specified? */
03943    if (!ast_strlen_zero(vmu->zonetag)) {
03944       /* Find the zone in the list */
03945       AST_LIST_LOCK(&zones);
03946       AST_LIST_TRAVERSE(&zones, z, list) {
03947          if (!strcmp(z->name, vmu->zonetag))
03948             break;
03949       }
03950       AST_LIST_UNLOCK(&zones);
03951    }
03952    ast_localtime(&t, tm, z ? z->timezone : NULL);
03953    return tm;
03954 }

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

Definition at line 6717 of file app_voicemail.c.

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

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

06718 {
06719    int res;
06720    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
06721       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
06722    return res;
06723 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "DAHDI Telephony w/PRI & SS7" , .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 11712 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 508 of file app_voicemail.c.

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

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

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 703 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 593 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 596 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 598 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 599 of file app_voicemail.c.

Definition at line 11712 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 687 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

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

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

Referenced by load_config(), and play_message_callerid().

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

Definition at line 10123 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* descrip_vm [static]

Definition at line 512 of file app_voicemail.c.

char* descrip_vm_box_exists [static]

Definition at line 570 of file app_voicemail.c.

char* descrip_vmain [static]

Definition at line 541 of file app_voicemail.c.

char* descrip_vmauthenticate [static]

Definition at line 582 of file app_voicemail.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]
char* emailbody = NULL [static]

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

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

char* emailsubject = NULL [static]

Definition at line 694 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

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

char ext_pass_cmd[128] [static]

Definition at line 487 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 610 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 697 of file app_voicemail.c.

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

struct ast_flags globalflags = {0} [static]

Definition at line 721 of file app_voicemail.c.

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

char listen_control_forward_key[12] [static]

Definition at line 667 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 669 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 670 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 668 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 671 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

Definition at line 9881 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char mailcmd[160] [static]

Definition at line 609 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 606 of file app_voicemail.c.

int maxgreet [static]

Definition at line 616 of file app_voicemail.c.

int maxlogins [static]

Definition at line 618 of file app_voicemail.c.

int maxmsg [static]

Definition at line 605 of file app_voicemail.c.

int maxsilence [static]

Definition at line 604 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 619 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 636 of file app_voicemail.c.

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

int my_umask [static]

Definition at line 490 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 695 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 698 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 696 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 631 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 626 of file app_voicemail.c.

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

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 632 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 633 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 494 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 684 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char serveremail[80] [static]

Definition at line 608 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 607 of file app_voicemail.c.

int skipms [static]

Definition at line 617 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 611 of file app_voicemail.c.

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

Definition at line 510 of file app_voicemail.c.

char* synopsis_vm_box_exists [static]
Initial value:
"Check to see if Voicemail mailbox exists"

Definition at line 567 of file app_voicemail.c.

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

Definition at line 539 of file app_voicemail.c.

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

Definition at line 580 of file app_voicemail.c.

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

Definition at line 506 of file app_voicemail.c.

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

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

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

Definition at line 678 of file app_voicemail.c.

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

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

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

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

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

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

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

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

Definition at line 677 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 485 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 612 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 615 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 614 of file app_voicemail.c.

double volgain [static]

Definition at line 613 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 603 of file app_voicemail.c.

Referenced by build_peer().


Generated on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1