Tue Mar 2 17:32:30 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/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  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 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}
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 191 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 214 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 215 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 188 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 184 of file app_voicemail.c.

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

Definition at line 479 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 196 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 198 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 199 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 197 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 200 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

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

Referenced by base_encode(), and ochar().

#define ERROR_LOCK_PATH   -100

Definition at line 240 of file app_voicemail.c.

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

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

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

#define MAX_DATETIME_FORMAT   512

Definition at line 218 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 219 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 209 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

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

Referenced by load_config().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 492 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 491 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 478 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 205 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

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

#define VALID_DTMF   "1234567890*#"

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

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

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 418 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 190 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 186 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

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

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

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

anonymous enum
Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 264 of file app_voicemail.c.

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


Function Documentation

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

Definition at line 4754 of file app_voicemail.c.

References ast_strlen_zero().

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

04755 {
04756    DIR *dir;
04757    struct dirent *de;
04758    char fn[256];
04759    int ret = 0;
04760 
04761    /* If no mailbox, return immediately */
04762    if (ast_strlen_zero(mailbox))
04763       return 0;
04764 
04765    if (ast_strlen_zero(folder))
04766       folder = "INBOX";
04767    if (ast_strlen_zero(context))
04768       context = "default";
04769 
04770    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
04771 
04772    if (!(dir = opendir(fn)))
04773       return 0;
04774 
04775    while ((de = readdir(dir))) {
04776       if (!strncasecmp(de->d_name, "msg", 3)) {
04777          if (shortcircuit) {
04778             ret = 1;
04779             break;
04780          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
04781             if (shortcircuit) return 1;
04782             ret++;
04783          }
04784       }
04785    }
04786 
04787    closedir(dir);
04788 
04789    /* If we are checking INBOX, we should check Urgent as well */
04790    if (strcmp(folder, "INBOX") == 0) {
04791       return (ret + __has_voicemail(context, mailbox, "Urgent", shortcircuit));
04792    } else {
04793       return ret;
04794    }
04795 }

static void __reg_module ( void   )  [static]

Definition at line 11595 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

09751 {
09752    struct ast_vm_user svm;
09753    AST_DECLARE_APP_ARGS(arg,
09754       AST_APP_ARG(mbox);
09755       AST_APP_ARG(context);
09756    );
09757 
09758    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
09759 
09760    if (ast_strlen_zero(arg.mbox)) {
09761       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
09762       return -1;
09763    }
09764 
09765    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
09766    return 0;
09767 }

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

04246 {
04247    char tmpdir[256], newtmp[256];
04248    char fname[256];
04249    char tmpcmd[256];
04250    int tmpfd = -1;
04251 
04252    /* Eww. We want formats to tell us their own MIME type */
04253    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04254 
04255    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04256       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04257       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04258       tmpfd = mkstemp(newtmp);
04259       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04260       ast_debug(3, "newtmp: %s\n", newtmp);
04261       if (tmpfd > -1) {
04262          int soxstatus;
04263          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04264          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04265             attach = newtmp;
04266             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04267          } else {
04268             ast_log(LOG_WARNING, "Sox failed to reencode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04269                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04270             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04271          }
04272       }
04273    }
04274    fprintf(p, "--%s" ENDL, bound);
04275    if (msgnum > -1)
04276       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04277    else
04278       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04279    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04280    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04281    if (msgnum > -1)
04282       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04283    else
04284       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04285    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04286    base_encode(fname, p);
04287    if (last)
04288       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04289    if (tmpfd > -1) {
04290       unlink(fname);
04291       close(tmpfd);
04292       unlink(newtmp);
04293    }
04294    return 0;
04295 }

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

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

05676 {
05677    int x;
05678    if (!ast_adsi_available(chan))
05679       return;
05680    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05681    if (x < 0)
05682       return;
05683    if (!x) {
05684       if (adsi_load_vmail(chan, useadsi)) {
05685          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
05686          return;
05687       }
05688    } else
05689       *useadsi = 1;
05690 }

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

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

05865 {
05866    int bytes=0;
05867    unsigned char buf[256];
05868    unsigned char keys[8];
05869 
05870    int x;
05871 
05872    if (!ast_adsi_available(chan))
05873       return;
05874 
05875    /* New meaning for keys */
05876    for (x=0;x<5;x++)
05877       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05878 
05879    keys[6] = 0x0;
05880    keys[7] = 0x0;
05881 
05882    if (!vms->curmsg) {
05883       /* No prev key, provide "Folder" instead */
05884       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05885    }
05886    if (vms->curmsg >= vms->lastmsg) {
05887       /* If last message ... */
05888       if (vms->curmsg) {
05889          /* but not only message, provide "Folder" instead */
05890          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05891       } else {
05892          /* Otherwise if only message, leave blank */
05893          keys[3] = 1;
05894       }
05895    }
05896 
05897    /* If deleted, show "undeleted" */
05898    if (vms->deleted[vms->curmsg]) 
05899       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05900 
05901    /* Except "Exit" */
05902    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05903    bytes += ast_adsi_set_keys(buf + bytes, keys);
05904    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05905 
05906    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05907 }

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

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

05741 {
05742    unsigned char buf[256];
05743    int bytes=0;
05744    unsigned char keys[8];
05745    int x,y;
05746 
05747    if (!ast_adsi_available(chan))
05748       return;
05749 
05750    for (x=0;x<5;x++) {
05751       y = ADSI_KEY_APPS + 12 + start + x;
05752       if (y > ADSI_KEY_APPS + 12 + 4)
05753          y = 0;
05754       keys[x] = ADSI_KEY_SKT | y;
05755    }
05756    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05757    keys[6] = 0;
05758    keys[7] = 0;
05759 
05760    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05761    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05762    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05763    bytes += ast_adsi_set_keys(buf + bytes, keys);
05764    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05765 
05766    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05767 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06013 {
06014    unsigned char buf[256];
06015    int bytes=0;
06016 
06017    if (!ast_adsi_available(chan))
06018       return;
06019    bytes += adsi_logo(buf + bytes);
06020    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06021    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06022    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06023    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06024 
06025    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06026 }

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

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

05547 {
05548    unsigned char buf[256];
05549    int bytes=0;
05550    int x;
05551    char num[5];
05552 
05553    *useadsi = 0;
05554    bytes += ast_adsi_data_mode(buf + bytes);
05555    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05556 
05557    bytes = 0;
05558    bytes += adsi_logo(buf);
05559    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05560 #ifdef DISPLAY
05561    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
05562 #endif
05563    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05564    bytes += ast_adsi_data_mode(buf + bytes);
05565    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05566 
05567    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
05568       bytes = 0;
05569       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
05570       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05571       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05572       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05573       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05574       return 0;
05575    }
05576 
05577 #ifdef DISPLAY
05578    /* Add a dot */
05579    bytes = 0;
05580    bytes += ast_adsi_logo(buf);
05581    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05582    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
05583    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05584    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05585 #endif
05586    bytes = 0;
05587    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
05588    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
05589    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
05590    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
05591    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
05592    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
05593    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05594 
05595 #ifdef DISPLAY
05596    /* Add another dot */
05597    bytes = 0;
05598    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
05599    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05600 
05601    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05602    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05603 #endif
05604 
05605    bytes = 0;
05606    /* These buttons we load but don't use yet */
05607    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
05608    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
05609    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
05610    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
05611    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
05612    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
05613    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05614 
05615 #ifdef DISPLAY
05616    /* Add another dot */
05617    bytes = 0;
05618    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
05619    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05620    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05621 #endif
05622 
05623    bytes = 0;
05624    for (x=0;x<5;x++) {
05625       snprintf(num, sizeof(num), "%d", x);
05626       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
05627    }
05628    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
05629    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05630 
05631 #ifdef DISPLAY
05632    /* Add another dot */
05633    bytes = 0;
05634    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
05635    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05636    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05637 #endif
05638 
05639    if (ast_adsi_end_download(chan)) {
05640       bytes = 0;
05641       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
05642       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05643       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05644       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05645       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05646       return 0;
05647    }
05648    bytes = 0;
05649    bytes += ast_adsi_download_disconnect(buf + bytes);
05650    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05651    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05652 
05653    ast_debug(1, "Done downloading scripts...\n");
05654 
05655 #ifdef DISPLAY
05656    /* Add last dot */
05657    bytes = 0;
05658    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
05659    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05660 #endif
05661    ast_debug(1, "Restarting session...\n");
05662 
05663    bytes = 0;
05664    /* Load the session now */
05665    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
05666       *useadsi = 1;
05667       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
05668    } else
05669       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
05670 
05671    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05672    return 0;
05673 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

05693 {
05694    unsigned char buf[256];
05695    int bytes=0;
05696    unsigned char keys[8];
05697    int x;
05698    if (!ast_adsi_available(chan))
05699       return;
05700 
05701    for (x=0;x<8;x++)
05702       keys[x] = 0;
05703    /* Set one key for next */
05704    keys[3] = ADSI_KEY_APPS + 3;
05705 
05706    bytes += adsi_logo(buf + bytes);
05707    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05708    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
05709    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05710    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
05711    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05712    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05713    bytes += ast_adsi_set_keys(buf + bytes, keys);
05714    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05715    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05716 }

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

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

05539 {
05540    int bytes = 0;
05541    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
05542    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
05543    return bytes;
05544 }

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

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

05770 {
05771    int bytes=0;
05772    unsigned char buf[256]; 
05773    char buf1[256], buf2[256];
05774    char fn2[PATH_MAX];
05775 
05776    char cid[256]="";
05777    char *val;
05778    char *name, *num;
05779    char datetime[21]="";
05780    FILE *f;
05781 
05782    unsigned char keys[8];
05783 
05784    int x;
05785 
05786    if (!ast_adsi_available(chan))
05787       return;
05788 
05789    /* Retrieve important info */
05790    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
05791    f = fopen(fn2, "r");
05792    if (f) {
05793       while (!feof(f)) {   
05794          if (!fgets((char *)buf, sizeof(buf), f)) {
05795             continue;
05796          }
05797          if (!feof(f)) {
05798             char *stringp=NULL;
05799             stringp = (char *)buf;
05800             strsep(&stringp, "=");
05801             val = strsep(&stringp, "=");
05802             if (!ast_strlen_zero(val)) {
05803                if (!strcmp((char *)buf, "callerid"))
05804                   ast_copy_string(cid, val, sizeof(cid));
05805                if (!strcmp((char *)buf, "origdate"))
05806                   ast_copy_string(datetime, val, sizeof(datetime));
05807             }
05808          }
05809       }
05810       fclose(f);
05811    }
05812    /* New meaning for keys */
05813    for (x=0;x<5;x++)
05814       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
05815    keys[6] = 0x0;
05816    keys[7] = 0x0;
05817 
05818    if (!vms->curmsg) {
05819       /* No prev key, provide "Folder" instead */
05820       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05821    }
05822    if (vms->curmsg >= vms->lastmsg) {
05823       /* If last message ... */
05824       if (vms->curmsg) {
05825          /* but not only message, provide "Folder" instead */
05826          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
05827          bytes += ast_adsi_voice_mode(buf + bytes, 0);
05828 
05829       } else {
05830          /* Otherwise if only message, leave blank */
05831          keys[3] = 1;
05832       }
05833    }
05834 
05835    if (!ast_strlen_zero(cid)) {
05836       ast_callerid_parse(cid, &name, &num);
05837       if (!name)
05838          name = num;
05839    } else
05840       name = "Unknown Caller";
05841 
05842    /* If deleted, show "undeleted" */
05843 
05844    if (vms->deleted[vms->curmsg])
05845       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
05846 
05847    /* Except "Exit" */
05848    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
05849    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
05850       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
05851    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
05852 
05853    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05854    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05855    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
05856    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
05857    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05858    bytes += ast_adsi_set_keys(buf + bytes, keys);
05859    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05860 
05861    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05862 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

05719 {
05720    unsigned char buf[256];
05721    int bytes=0;
05722    unsigned char keys[8];
05723    int x;
05724    if (!ast_adsi_available(chan))
05725       return;
05726 
05727    for (x=0;x<8;x++)
05728       keys[x] = 0;
05729    /* Set one key for next */
05730    keys[3] = ADSI_KEY_APPS + 3;
05731 
05732    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05733    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05734    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05735    bytes += ast_adsi_set_keys(buf + bytes, keys);
05736    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05737    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05738 }

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

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

05910 {
05911    unsigned char buf[256] = "";
05912    char buf1[256] = "", buf2[256] = "";
05913    int bytes=0;
05914    unsigned char keys[8];
05915    int x;
05916 
05917    char *newm = (vms->newmessages == 1) ? "message" : "messages";
05918    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
05919    if (!ast_adsi_available(chan))
05920       return;
05921    if (vms->newmessages) {
05922       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
05923       if (vms->oldmessages) {
05924          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
05925          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
05926       } else {
05927          snprintf(buf2, sizeof(buf2), "%s.", newm);
05928       }
05929    } else if (vms->oldmessages) {
05930       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
05931       snprintf(buf2, sizeof(buf2), "%s.", oldm);
05932    } else {
05933       strcpy(buf1, "You have no messages.");
05934       buf2[0] = ' ';
05935       buf2[1] = '\0';
05936    }
05937    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05938    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05939    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05940 
05941    for (x=0;x<6;x++)
05942       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05943    keys[6] = 0;
05944    keys[7] = 0;
05945 
05946    /* Don't let them listen if there are none */
05947    if (vms->lastmsg < 0)
05948       keys[0] = 1;
05949    bytes += ast_adsi_set_keys(buf + bytes, keys);
05950 
05951    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05952 
05953    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05954 }

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

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

05957 {
05958    unsigned char buf[256] = "";
05959    char buf1[256] = "", buf2[256] = "";
05960    int bytes=0;
05961    unsigned char keys[8];
05962    int x;
05963 
05964    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
05965 
05966    if (!ast_adsi_available(chan))
05967       return;
05968 
05969    /* Original command keys */
05970    for (x=0;x<6;x++)
05971       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
05972 
05973    keys[6] = 0;
05974    keys[7] = 0;
05975 
05976    if ((vms->lastmsg + 1) < 1)
05977       keys[0] = 0;
05978 
05979    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
05980       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
05981 
05982    if (vms->lastmsg + 1)
05983       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
05984    else
05985       strcpy(buf2, "no messages.");
05986    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
05987    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
05988    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
05989    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05990    bytes += ast_adsi_set_keys(buf + bytes, keys);
05991 
05992    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05993 
05994    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05995    
05996 }

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

11172 {
11173    int res = 0;
11174    char filename[PATH_MAX];
11175    struct ast_config *msg_cfg = NULL;
11176    const char *origtime, *context;
11177    char *name, *num;
11178    int retries = 0;
11179    char *cid;
11180    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
11181 
11182    vms->starting = 0; 
11183 
11184    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11185 
11186    /* Retrieve info from VM attribute file */
11187    snprintf(filename,sizeof(filename), "%s.txt", vms->fn);
11188    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
11189    msg_cfg = ast_config_load(filename, config_flags);
11190    DISPOSE(vms->curdir, vms->curmsg);
11191    if (!msg_cfg) {
11192       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
11193       return 0;
11194    }
11195 
11196    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
11197       ast_config_destroy(msg_cfg);
11198       return 0;
11199    }
11200 
11201    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
11202 
11203    context = ast_variable_retrieve(msg_cfg, "message", "context");
11204    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
11205       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
11206    switch (option) {
11207    case 3: /* Play message envelope */
11208       if (!res)
11209          res = play_message_datetime(chan, vmu, origtime, filename);
11210       if (!res)
11211          res = play_message_callerid(chan, vms, cid, context, 0);
11212 
11213       res = 't';
11214       break;
11215 
11216    case 2:  /* Call back */
11217 
11218       if (ast_strlen_zero(cid))
11219          break;
11220 
11221       ast_callerid_parse(cid, &name, &num);
11222       while ((res > -1) && (res != 't')) {
11223          switch (res) {
11224          case '1':
11225             if (num) {
11226                /* Dial the CID number */
11227                res = dialout(chan, vmu, num, vmu->callback);
11228                if (res) {
11229                   ast_config_destroy(msg_cfg);
11230                   return 9;
11231                }
11232             } else {
11233                res = '2';
11234             }
11235             break;
11236 
11237          case '2':
11238             /* Want to enter a different number, can only do this if there's a dialout context for this user */
11239             if (!ast_strlen_zero(vmu->dialout)) {
11240                res = dialout(chan, vmu, NULL, vmu->dialout);
11241                if (res) {
11242                   ast_config_destroy(msg_cfg);
11243                   return 9;
11244                }
11245             } else {
11246                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
11247                res = ast_play_and_wait(chan, "vm-sorry");
11248             }
11249             ast_config_destroy(msg_cfg);
11250             return res;
11251          case '*':
11252             res = 't';
11253             break;
11254          case '3':
11255          case '4':
11256          case '5':
11257          case '6':
11258          case '7':
11259          case '8':
11260          case '9':
11261          case '0':
11262 
11263             res = ast_play_and_wait(chan, "vm-sorry");
11264             retries++;
11265             break;
11266          default:
11267             if (num) {
11268                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
11269                res = ast_play_and_wait(chan, "vm-num-i-have");
11270                if (!res)
11271                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
11272                if (!res)
11273                   res = ast_play_and_wait(chan, "vm-tocallnum");
11274                /* Only prompt for a caller-specified number if there is a dialout context specified */
11275                if (!ast_strlen_zero(vmu->dialout)) {
11276                   if (!res)
11277                      res = ast_play_and_wait(chan, "vm-calldiffnum");
11278                }
11279             } else {
11280                res = ast_play_and_wait(chan, "vm-nonumber");
11281                if (!ast_strlen_zero(vmu->dialout)) {
11282                   if (!res)
11283                      res = ast_play_and_wait(chan, "vm-toenternumber");
11284                }
11285             }
11286             if (!res)
11287                res = ast_play_and_wait(chan, "vm-star-cancel");
11288             if (!res)
11289                res = ast_waitfordigit(chan, 6000);
11290             if (!res) {
11291                retries++;
11292                if (retries > 3)
11293                   res = 't';
11294             }
11295             break; 
11296             
11297          }
11298          if (res == 't')
11299             res = 0;
11300          else if (res == '*')
11301             res = -1;
11302       }
11303       break;
11304       
11305    case 1:  /* Reply */
11306       /* Send reply directly to sender */
11307       if (ast_strlen_zero(cid))
11308          break;
11309 
11310       ast_callerid_parse(cid, &name, &num);
11311       if (!num) {
11312          ast_verb(3, "No CID number available, no reply sent\n");
11313          if (!res)
11314             res = ast_play_and_wait(chan, "vm-nonumber");
11315          ast_config_destroy(msg_cfg);
11316          return res;
11317       } else {
11318          struct ast_vm_user vmu2;
11319          if (find_user(&vmu2, vmu->context, num)) {
11320             struct leave_vm_options leave_options;
11321             char mailbox[AST_MAX_EXTENSION * 2 + 2];
11322             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
11323 
11324             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
11325             
11326             memset(&leave_options, 0, sizeof(leave_options));
11327             leave_options.record_gain = record_gain;
11328             res = leave_voicemail(chan, mailbox, &leave_options);
11329             if (!res)
11330                res = 't';
11331             ast_config_destroy(msg_cfg);
11332             return res;
11333          } else {
11334             /* Sender has no mailbox, can't reply */
11335             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
11336             ast_play_and_wait(chan, "vm-nobox");
11337             res = 't';
11338             ast_config_destroy(msg_cfg);
11339             return res;
11340          }
11341       } 
11342       res = 0;
11343 
11344       break;
11345    }
11346 
11347 #ifndef IMAP_STORAGE
11348    ast_config_destroy(msg_cfg);
11349 
11350    if (!res) {
11351       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11352       vms->heard[msg] = 1;
11353       res = wait_file(chan, vms, vms->fn);
11354    }
11355 #endif
11356    return res;
11357 }

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

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

09671 {
09672    /* Assumes lock is already held */
09673    char *tmp;
09674    char *stringp;
09675    char *s;
09676    struct ast_vm_user *vmu;
09677    char *mailbox_full;
09678    int new = 0, old = 0, urgent = 0;
09679 
09680    tmp = ast_strdupa(data);
09681 
09682    if (!(vmu = find_or_create(context, box)))
09683       return -1;
09684    
09685    populate_defaults(vmu);
09686 
09687    stringp = tmp;
09688    if ((s = strsep(&stringp, ","))) 
09689       ast_copy_string(vmu->password, s, sizeof(vmu->password));
09690    if (stringp && (s = strsep(&stringp, ","))) 
09691       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
09692    if (stringp && (s = strsep(&stringp, ","))) 
09693       ast_copy_string(vmu->email, s, sizeof(vmu->email));
09694    if (stringp && (s = strsep(&stringp, ","))) 
09695       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
09696    if (stringp && (s = strsep(&stringp, ","))) 
09697       apply_options(vmu, s);
09698 
09699    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
09700    strcpy(mailbox_full, box);
09701    strcat(mailbox_full, "@");
09702    strcat(mailbox_full, context);
09703 
09704    inboxcount2(mailbox_full, &urgent, &new, &old);
09705    queue_mwi_event(mailbox_full, urgent, new, old);
09706 
09707    return 0;
09708 }

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

00786 {
00787    int x;
00788    if (!strcasecmp(var, "attach")) {
00789       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00790    } else if (!strcasecmp(var, "attachfmt")) {
00791       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00792    } else if (!strcasecmp(var, "serveremail")) {
00793       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00794    } else if (!strcasecmp(var, "language")) {
00795       ast_copy_string(vmu->language, value, sizeof(vmu->language));
00796    } else if (!strcasecmp(var, "tz")) {
00797       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00798 #ifdef IMAP_STORAGE
00799    } else if (!strcasecmp(var, "imapuser")) {
00800       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00801       vmu->imapversion = imapversion;
00802    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
00803       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00804       vmu->imapversion = imapversion;
00805    } else if (!strcasecmp(var, "imapvmshareid")) {
00806       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
00807       vmu->imapversion = imapversion;
00808 #endif
00809    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00810       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
00811    } else if (!strcasecmp(var, "saycid")){
00812       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
00813    } else if (!strcasecmp(var,"sendvoicemail")){
00814       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
00815    } else if (!strcasecmp(var, "review")){
00816       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00817    } else if (!strcasecmp(var, "tempgreetwarn")){
00818       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
00819    } else if (!strcasecmp(var, "messagewrap")){
00820       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
00821    } else if (!strcasecmp(var, "operator")) {
00822       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
00823    } else if (!strcasecmp(var, "envelope")){
00824       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
00825    } else if (!strcasecmp(var, "moveheard")){
00826       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
00827    } else if (!strcasecmp(var, "sayduration")){
00828       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
00829    } else if (!strcasecmp(var, "saydurationm")){
00830       if (sscanf(value, "%30d", &x) == 1) {
00831          vmu->saydurationm = x;
00832       } else {
00833          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
00834       }
00835    } else if (!strcasecmp(var, "forcename")){
00836       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
00837    } else if (!strcasecmp(var, "forcegreetings")){
00838       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
00839    } else if (!strcasecmp(var, "callback")) {
00840       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00841    } else if (!strcasecmp(var, "dialout")) {
00842       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00843    } else if (!strcasecmp(var, "exitcontext")) {
00844       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00845    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
00846       vmu->maxsecs = atoi(value);
00847       if (vmu->maxsecs <= 0) {
00848          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
00849          vmu->maxsecs = vmmaxsecs;
00850       } else {
00851          vmu->maxsecs = atoi(value);
00852       }
00853       if (!strcasecmp(var, "maxmessage"))
00854          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
00855    } else if (!strcasecmp(var, "maxmsg")) {
00856       vmu->maxmsg = atoi(value);
00857       if (vmu->maxmsg <= 0) {
00858          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
00859          vmu->maxmsg = MAXMSG;
00860       } else if (vmu->maxmsg > MAXMSGLIMIT) {
00861          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00862          vmu->maxmsg = MAXMSGLIMIT;
00863       }
00864    } else if (!strcasecmp(var, "backupdeleted")) {
00865       if (sscanf(value, "%30d", &x) == 1)
00866          vmu->maxdeletedmsg = x;
00867       else if (ast_true(value))
00868          vmu->maxdeletedmsg = MAXMSG;
00869       else
00870          vmu->maxdeletedmsg = 0;
00871 
00872       if (vmu->maxdeletedmsg < 0) {
00873          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
00874          vmu->maxdeletedmsg = MAXMSG;
00875       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
00876          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
00877          vmu->maxdeletedmsg = MAXMSGLIMIT;
00878       }
00879    } else if (!strcasecmp(var, "volgain")) {
00880       sscanf(value, "%30lf", &vmu->volgain);
00881    } else if (!strcasecmp(var, "options")) {
00882       apply_options(vmu, value);
00883    }
00884 }

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

Destructively Parse options and apply.

Definition at line 998 of file app_voicemail.c.

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

Referenced by append_mailbox(), and apply_option().

00999 {  
01000    char *stringp;
01001    char *s;
01002    char *var, *value;
01003    stringp = ast_strdupa(options);
01004    while ((s = strsep(&stringp, "|"))) {
01005       value = s;
01006       if ((var = strsep(&value, "=")) && value) {
01007          apply_option(vmu, var, value);
01008       }
01009    }  
01010 }

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

01018 {
01019    struct ast_variable *tmp;
01020    tmp = var;
01021    while (tmp) {
01022       if (!strcasecmp(tmp->name, "vmsecret")) {
01023          ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
01024       } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) { /* don't overwrite vmsecret if it exists */
01025          if (ast_strlen_zero(retval->password))
01026             ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
01027       } else if (!strcasecmp(tmp->name, "uniqueid")) {
01028          ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
01029       } else if (!strcasecmp(tmp->name, "pager")) {
01030          ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
01031       } else if (!strcasecmp(tmp->name, "email")) {
01032          ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
01033       } else if (!strcasecmp(tmp->name, "fullname")) {
01034          ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
01035       } else if (!strcasecmp(tmp->name, "context")) {
01036          ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
01037 #ifdef IMAP_STORAGE
01038       } else if (!strcasecmp(tmp->name, "imapuser")) {
01039          ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
01040          retval->imapversion = imapversion;
01041       } else if (!strcasecmp(tmp->name, "imappassword") || !strcasecmp(tmp->name, "imapsecret")) {
01042          ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
01043          retval->imapversion = imapversion;
01044       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01045          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01046          retval->imapversion = imapversion;
01047 #endif
01048       } else
01049          apply_option(retval, tmp->name, tmp->value);
01050       tmp = tmp->next;
01051    } 
01052 }

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

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

Referenced by add_email_attachment().

03734 {
03735    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
03736       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
03737       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
03738       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
03739    int i,hiteof= 0;
03740    FILE *fi;
03741    struct baseio bio;
03742 
03743    memset(&bio, 0, sizeof(bio));
03744    bio.iocp = BASEMAXINLINE;
03745 
03746    if (!(fi = fopen(filename, "rb"))) {
03747       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
03748       return -1;
03749    }
03750 
03751    while (!hiteof){
03752       unsigned char igroup[3], ogroup[4];
03753       int c,n;
03754 
03755       igroup[0]= igroup[1]= igroup[2]= 0;
03756 
03757       for (n= 0;n<3;n++) {
03758          if ((c = inchar(&bio, fi)) == EOF) {
03759             hiteof= 1;
03760             break;
03761          }
03762 
03763          igroup[n]= (unsigned char)c;
03764       }
03765 
03766       if (n> 0) {
03767          ogroup[0]= dtable[igroup[0]>>2];
03768          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
03769          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
03770          ogroup[3]= dtable[igroup[2]&0x3F];
03771 
03772          if (n<3) {
03773             ogroup[3]= '=';
03774 
03775             if (n<2)
03776                ogroup[2]= '=';
03777          }
03778 
03779          for (i= 0;i<4;i++)
03780             ochar(&bio, ogroup[i], so);
03781       }
03782    }
03783 
03784    fclose(fi);
03785    
03786    if (fputs(eol,so)==EOF)
03787       return 0;
03788 
03789    return 1;
03790 }

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

00978 {
00979    int res = -1;
00980    if (!strcmp(vmu->password, password)) {
00981       /* No change (but an update would return 0 rows updated, so we opt out here) */
00982       res = 0;
00983    } else if (!ast_strlen_zero(vmu->uniqueid)) {
00984       if (strlen(password) > 10) {
00985          ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
00986       }
00987       if (ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, SENTINEL) > 0) {
00988          ast_copy_string(vmu->password, password, sizeof(vmu->password));
00989          res = 0;
00990       }
00991    }
00992    return res;
00993 }

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

Referenced by make_email_file().

03899 {
03900    for (; *str; str++) {
03901       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
03902          return 1;
03903       }
03904    }
03905    return 0;
03906 }

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

00940 {
00941    /* check minimum length */
00942    if (strlen(password) < minpassword)
00943       return 1;
00944    if (!ast_strlen_zero(ext_pass_check_cmd)) {
00945       char cmd[255], buf[255];
00946 
00947       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
00948 
00949       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
00950       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
00951          ast_debug(5, "Result: %s\n", buf);
00952          if (!strncasecmp(buf, "VALID", 5)) {
00953             ast_debug(3, "Passed password check: '%s'\n", buf);
00954             return 0;
00955          } else if (!strncasecmp(buf, "FAILURE", 7)) {
00956             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
00957             return 0;
00958          } else {
00959             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
00960             return 1;
00961          }
00962       }
00963    }
00964    return 0;
00965 }

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

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

07065 {
07066    int x = 0;
07067 #ifndef IMAP_STORAGE
07068    int res = 0, nummsg;
07069    char fn2[PATH_MAX];
07070 #endif
07071 
07072    if (vms->lastmsg <= -1)
07073       goto done;
07074 
07075    vms->curmsg = -1; 
07076 #ifndef IMAP_STORAGE
07077    /* Get the deleted messages fixed */ 
07078    if (vm_lock_path(vms->curdir))
07079       return ERROR_LOCK_PATH;
07080 
07081    for (x = 0; x < vmu->maxmsg; x++) { 
07082       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) { 
07083          /* Save this message.  It's not in INBOX or hasn't been heard */ 
07084          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
07085          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
07086             break;
07087          vms->curmsg++; 
07088          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg); 
07089          if (strcmp(vms->fn, fn2)) { 
07090             RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07091          } 
07092       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { 
07093          /* Move to old folder before deleting */ 
07094          res = save_to_folder(vmu, vms, x, 1);
07095          if (res == ERROR_LOCK_PATH) {
07096             /* If save failed do not delete the message */
07097             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07098             vms->deleted[x] = 0;
07099             vms->heard[x] = 0;
07100             --x;
07101          }
07102       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07103          /* Move to deleted folder */ 
07104          res = save_to_folder(vmu, vms, x, 10);
07105          if (res == ERROR_LOCK_PATH) {
07106             /* If save failed do not delete the message */
07107             vms->deleted[x] = 0;
07108             vms->heard[x] = 0;
07109             --x;
07110          }
07111       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07112          /* If realtime storage enabled - we should explicitly delete this message,
07113          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07114          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07115          if (EXISTS(vms->curdir, x, vms->fn, NULL))
07116             DELETE(vms->curdir, x, vms->fn, vmu);
07117       }
07118    } 
07119 
07120    /* Delete ALL remaining messages */
07121    nummsg = x - 1;
07122    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07123       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07124       if (EXISTS(vms->curdir, x, vms->fn, NULL))
07125          DELETE(vms->curdir, x, vms->fn, vmu);
07126    }
07127    ast_unlock_path(vms->curdir);
07128 #else
07129    if (vms->deleted) {
07130       for (x=0;x < vmu->maxmsg;x++) { 
07131          if (vms->deleted[x]) { 
07132             ast_debug(3,"IMAP delete of %d\n",x);
07133             DELETE(vms->curdir, x, vms->fn, vmu);
07134          }
07135       }
07136    }
07137 #endif
07138 
07139 done:
07140    if (vms->deleted)
07141       memset(vms->deleted, 0, vmu->maxmsg * sizeof(int)); 
07142    if (vms->heard)
07143       memset(vms->heard, 0, vmu->maxmsg * sizeof(int)); 
07144 
07145    return 0;
07146 }

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

Definition at line 9854 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

09855 {
09856    int which = 0;
09857    int wordlen;
09858    struct ast_vm_user *vmu;
09859    const char *context = "";
09860 
09861    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
09862    if (pos > 4)
09863       return NULL;
09864    if (pos == 3)
09865       return (state == 0) ? ast_strdup("for") : NULL;
09866    wordlen = strlen(word);
09867    AST_LIST_TRAVERSE(&users, vmu, list) {
09868       if (!strncasecmp(word, vmu->context, wordlen)) {
09869          if (context && strcmp(context, vmu->context) && ++which > state)
09870             return ast_strdup(vmu->context);
09871          /* ignore repeated contexts ? */
09872          context = vmu->context;
09873       }
09874    }
09875    return NULL;
09876 }

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

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

Referenced by copy_plain_file().

03540 {
03541    int ifd;
03542    int ofd;
03543    int res;
03544    int len;
03545    char buf[4096];
03546 
03547 #ifdef HARDLINK_WHEN_POSSIBLE
03548    /* Hard link if possible; saves disk space & is faster */
03549    if (link(infile, outfile)) {
03550 #endif
03551       if ((ifd = open(infile, O_RDONLY)) < 0) {
03552          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03553          return -1;
03554       }
03555       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03556          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03557          close(ifd);
03558          return -1;
03559       }
03560       do {
03561          len = read(ifd, buf, sizeof(buf));
03562          if (len < 0) {
03563             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03564             close(ifd);
03565             close(ofd);
03566             unlink(outfile);
03567          }
03568          if (len) {
03569             res = write(ofd, buf, len);
03570             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03571                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03572                close(ifd);
03573                close(ofd);
03574                unlink(outfile);
03575             }
03576          }
03577       } while (len);
03578       close(ifd);
03579       close(ofd);
03580       return 0;
03581 #ifdef HARDLINK_WHEN_POSSIBLE
03582    } else {
03583       /* Hard link succeeded */
03584       return 0;
03585    }
03586 #endif
03587 }

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

04699 {
04700    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
04701    const char *frombox = mbox(imbox);
04702    int recipmsgnum;
04703 
04704    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
04705 
04706    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
04707       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
04708    } else {
04709       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04710    }
04711    
04712    if (!dir)
04713       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
04714    else
04715       ast_copy_string(fromdir, dir, sizeof(fromdir));
04716 
04717    make_file(frompath, sizeof(frompath), fromdir, msgnum);
04718    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04719 
04720    if (vm_lock_path(todir))
04721       return ERROR_LOCK_PATH;
04722 
04723    recipmsgnum = last_message_index(recip, todir) + 1;
04724    if (recipmsgnum < recip->maxmsg) {
04725       make_file(topath, sizeof(topath), todir, recipmsgnum);
04726       if (EXISTS(fromdir, msgnum, frompath, chan->language)) {
04727          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
04728       } else {
04729          /* For ODBC storage, if the file we want to copy isn't yet in the database, then the SQL
04730           * copy will fail. Instead, we need to create a local copy, store it, and delete the local
04731           * copy. We don't have to #ifdef this because if file storage reaches this point, there's a
04732           * much worse problem happening and IMAP storage doesn't call this function
04733           */
04734          copy_plain_file(frompath, topath);
04735          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
04736          vm_delete(topath);
04737       }
04738    } else {
04739       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
04740    }
04741    ast_unlock_path(todir);
04742    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
04743    
04744    return 0;
04745 }

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

03599 {
03600    char frompath2[PATH_MAX], topath2[PATH_MAX];
03601    struct ast_variable *tmp,*var = NULL;
03602    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
03603    ast_filecopy(frompath, topath, NULL);
03604    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
03605    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
03606    if (ast_check_realtime("voicemail_data")) {
03607       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
03608       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
03609       for (tmp = var; tmp; tmp = tmp->next) {
03610          if (!strcasecmp(tmp->name, "origmailbox")) {
03611             origmailbox = tmp->value;
03612          } else if (!strcasecmp(tmp->name, "context")) {
03613             context = tmp->value;
03614          } else if (!strcasecmp(tmp->name, "macrocontext")) {
03615             macrocontext = tmp->value;
03616          } else if (!strcasecmp(tmp->name, "exten")) {
03617             exten = tmp->value;
03618          } else if (!strcasecmp(tmp->name, "priority")) {
03619             priority = tmp->value;
03620          } else if (!strcasecmp(tmp->name, "callerchan")) {
03621             callerchan = tmp->value;
03622          } else if (!strcasecmp(tmp->name, "callerid")) {
03623             callerid = tmp->value;
03624          } else if (!strcasecmp(tmp->name, "origdate")) {
03625             origdate = tmp->value;
03626          } else if (!strcasecmp(tmp->name, "origtime")) {
03627             origtime = tmp->value;
03628          } else if (!strcasecmp(tmp->name, "category")) {
03629             category = tmp->value;
03630          } else if (!strcasecmp(tmp->name, "duration")) {
03631             duration = tmp->value;
03632          }
03633       }
03634       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);
03635    }
03636    copy(frompath2, topath2);
03637    ast_variables_destroy(var);
03638 }

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

03443 {
03444 
03445    int vmcount = 0;
03446    DIR *vmdir = NULL;
03447    struct dirent *vment = NULL;
03448 
03449    if (vm_lock_path(dir))
03450       return ERROR_LOCK_PATH;
03451 
03452    if ((vmdir = opendir(dir))) {
03453       while ((vment = readdir(vmdir))) {
03454          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03455             vmcount++;
03456          }
03457       }
03458       closedir(vmdir);
03459    }
03460    ast_unlock_path(dir);
03461    
03462    return vmcount;
03463 }

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

01328 {
01329    mode_t   mode = VOICEMAIL_DIR_MODE;
01330    int res;
01331 
01332    make_dir(dest, len, context, ext, folder);
01333    if ((res = ast_mkdir(dest, mode))) {
01334       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01335       return -1;
01336    }
01337    return 0;
01338 }

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

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

11100 {
11101    int cmd = 0;
11102    char destination[80] = "";
11103    int retries = 0;
11104 
11105    if (!num) {
11106       ast_verb(3, "Destination number will be entered manually\n");
11107       while (retries < 3 && cmd != 't') {
11108          destination[1] = '\0';
11109          destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
11110          if (!cmd)
11111             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
11112          if (!cmd)
11113             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
11114          if (!cmd) {
11115             cmd = ast_waitfordigit(chan, 6000);
11116             if (cmd)
11117                destination[0] = cmd;
11118          }
11119          if (!cmd) {
11120             retries++;
11121          } else {
11122 
11123             if (cmd < 0)
11124                return 0;
11125             if (cmd == '*') {
11126                ast_verb(3, "User hit '*' to cancel outgoing call\n");
11127                return 0;
11128             }
11129             if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0) 
11130                retries++;
11131             else
11132                cmd = 't';
11133          }
11134       }
11135       if (retries >= 3) {
11136          return 0;
11137       }
11138       
11139    } else {
11140       if (option_verbose > 2)
11141          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
11142       ast_copy_string(destination, num, sizeof(destination));
11143    }
11144 
11145    if (!ast_strlen_zero(destination)) {
11146       if (destination[strlen(destination) -1 ] == '*')
11147          return 0; 
11148       if (option_verbose > 2)
11149          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
11150       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
11151       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
11152       chan->priority = 0;
11153       return 9;
11154    }
11155    return 0;
11156 }

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

References charset.

Referenced by make_email_file().

03925 {
03926    char tmp[80];
03927    int first_section = 1;
03928    size_t endlen = 0, tmplen = 0;
03929    *end = '\0';
03930 
03931    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03932    for (; *start; start++) {
03933       int need_encoding = 0;
03934       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
03935          need_encoding = 1;
03936       }
03937       if ((first_section && need_encoding && preamble + tmplen > 70) ||
03938          (first_section && !need_encoding && preamble + tmplen > 72) ||
03939          (!first_section && need_encoding && tmplen > 70) ||
03940          (!first_section && !need_encoding && tmplen > 72)) {
03941          /* Start new line */
03942          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
03943          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
03944          first_section = 0;
03945       }
03946       if (need_encoding && *start == ' ') {
03947          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
03948       } else if (need_encoding) {
03949          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
03950       } else {
03951          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
03952       }
03953    }
03954    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
03955    return end;
03956 }

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

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

09639 {
09640    struct ast_vm_user *vmu;
09641 
09642    AST_LIST_TRAVERSE(&users, vmu, list) {
09643       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
09644          if (strcasecmp(vmu->context, context)) {
09645             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
09646                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
09647                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
09648                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
09649          }
09650          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
09651          return NULL;
09652       }
09653       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
09654          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
09655          return NULL;
09656       }
09657    }
09658    
09659    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
09660       return NULL;
09661    
09662    ast_copy_string(vmu->context, context, sizeof(vmu->context));
09663    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
09664 
09665    AST_LIST_INSERT_TAIL(&users, vmu, list);
09666    
09667    return vmu;
09668 }

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

01124 {
01125    /* This function could be made to generate one from a database, too */
01126    struct ast_vm_user *vmu=NULL, *cur;
01127    AST_LIST_LOCK(&users);
01128 
01129    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01130       context = "default";
01131 
01132    AST_LIST_TRAVERSE(&users, cur, list) {
01133 #ifdef IMAP_STORAGE
01134       if (cur->imapversion != imapversion) {
01135          continue;
01136       }
01137 #endif
01138       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01139          break;
01140       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01141          break;
01142    }
01143    if (cur) {
01144       /* Make a copy, so that on a reload, we have no race */
01145       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01146          memcpy(vmu, cur, sizeof(*vmu));
01147          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01148          AST_LIST_NEXT(vmu, list) = NULL;
01149       }
01150    } else
01151       vmu = find_user_realtime(ivm, context, mailbox);
01152    AST_LIST_UNLOCK(&users);
01153    return vmu;
01154 }

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

01087 {
01088    struct ast_variable *var;
01089    struct ast_vm_user *retval;
01090 
01091    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01092       if (!ivm)
01093          ast_set_flag(retval, VM_ALLOCED);   
01094       else
01095          memset(retval, 0, sizeof(*retval));
01096       if (mailbox) 
01097          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01098       populate_defaults(retval);
01099       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01100          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01101       else
01102          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01103       if (var) {
01104          apply_options_full(retval, var);
01105          ast_variables_destroy(var);
01106       } else { 
01107          if (!ivm) 
01108             ast_free(retval);
01109          retval = NULL;
01110       }  
01111    } 
01112    return retval;
01113 }

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

References ast_clear_flag, ast_copy_string(), ast_fileexists(), 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, 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().

06367 {
06368 #ifdef IMAP_STORAGE
06369    int todircount=0;
06370    struct vm_state *dstvms;
06371 #endif
06372    char username[70]="";
06373    char fn[PATH_MAX]; /* for playback of name greeting */
06374    char ecodes[16] = "#";
06375    int res = 0, cmd = 0;
06376    struct ast_vm_user *receiver = NULL, *vmtmp;
06377    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06378    char *stringp;
06379    const char *s;
06380    int saved_messages = 0, found = 0;
06381    int valid_extensions = 0;
06382    char *dir;
06383    int curmsg;
06384    char urgent_str[7] = "";
06385    char tmptxtfile[PATH_MAX];
06386 
06387    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
06388       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
06389    }
06390 
06391    if (vms == NULL) return -1;
06392    dir = vms->curdir;
06393    curmsg = vms->curmsg;
06394 
06395    tmptxtfile[0] = '\0';
06396    while (!res && !valid_extensions) {
06397       int use_directory = 0;
06398       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
06399          int done = 0;
06400          int retries = 0;
06401          cmd=0;
06402          while ((cmd >= 0) && !done ){
06403             if (cmd)
06404                retries = 0;
06405             switch (cmd) {
06406             case '1': 
06407                use_directory = 0;
06408                done = 1;
06409                break;
06410             case '2': 
06411                use_directory = 1;
06412                done=1;
06413                break;
06414             case '*': 
06415                cmd = 't';
06416                done = 1;
06417                break;
06418             default: 
06419                /* Press 1 to enter an extension press 2 to use the directory */
06420                cmd = ast_play_and_wait(chan,"vm-forward");
06421                if (!cmd)
06422                   cmd = ast_waitfordigit(chan,3000);
06423                if (!cmd)
06424                   retries++;
06425                if (retries > 3) {
06426                   cmd = 't';
06427                   done = 1;
06428                }
06429                
06430             }
06431          }
06432          if (cmd < 0 || cmd == 't')
06433             break;
06434       }
06435       
06436       if (use_directory) {
06437          /* use app_directory */
06438          
06439          char old_context[sizeof(chan->context)];
06440          char old_exten[sizeof(chan->exten)];
06441          int old_priority;
06442          struct ast_app* directory_app;
06443 
06444          directory_app = pbx_findapp("Directory");
06445          if (directory_app) {
06446             char vmcontext[256];
06447             /* make backup copies */
06448             memcpy(old_context, chan->context, sizeof(chan->context));
06449             memcpy(old_exten, chan->exten, sizeof(chan->exten));
06450             old_priority = chan->priority;
06451             
06452             /* call the the Directory, changes the channel */
06453             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
06454             res = pbx_exec(chan, directory_app, vmcontext);
06455             
06456             ast_copy_string(username, chan->exten, sizeof(username));
06457             
06458             /* restore the old context, exten, and priority */
06459             memcpy(chan->context, old_context, sizeof(chan->context));
06460             memcpy(chan->exten, old_exten, sizeof(chan->exten));
06461             chan->priority = old_priority;
06462          } else {
06463             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
06464             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
06465          }
06466       } else {
06467          /* Ask for an extension */
06468          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
06469          if (res)
06470             break;
06471          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
06472             break;
06473       }
06474       
06475       /* start all over if no username */
06476       if (ast_strlen_zero(username))
06477          continue;
06478       stringp = username;
06479       s = strsep(&stringp, "*");
06480       /* start optimistic */
06481       valid_extensions = 1;
06482       while (s) {
06483          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
06484             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
06485             found++;
06486          } else {
06487             /* XXX Optimization for the future.  When we encounter a single bad extension,
06488              * bailing out on all of the extensions may not be the way to go.  We should
06489              * probably just bail on that single extension, then allow the user to enter
06490              * several more. XXX
06491              */
06492             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
06493                free_user(receiver);
06494             }
06495             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
06496             valid_extensions = 0;
06497             break;
06498          }
06499 
06500          /* play name if available, else play extension number */
06501          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
06502          RETRIEVE(fn, -1, s, receiver->context);
06503          if (ast_fileexists(fn, NULL, NULL) > 0) {
06504             res = ast_stream_and_wait(chan, fn, ecodes);
06505             if (res) {
06506                DISPOSE(fn, -1);
06507                return res;
06508             }
06509          } else {
06510             res = ast_say_digit_str(chan, s, ecodes, chan->language);
06511          }
06512          DISPOSE(fn, -1);
06513 
06514          s = strsep(&stringp, "*");
06515       }
06516       /* break from the loop of reading the extensions */
06517       if (valid_extensions)
06518          break;
06519       /* "I am sorry, that's not a valid extension.  Please try again." */
06520       res = ast_play_and_wait(chan, "pbx-invalid");
06521    }
06522    /* check if we're clear to proceed */
06523    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
06524       return res;
06525    if (is_new_message == 1) {
06526       struct leave_vm_options leave_options;
06527       char mailbox[AST_MAX_EXTENSION * 2 + 2];
06528       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
06529 
06530       /* Send VoiceMail */
06531       memset(&leave_options, 0, sizeof(leave_options));
06532       leave_options.record_gain = record_gain;
06533       cmd = leave_voicemail(chan, mailbox, &leave_options);
06534    } else {
06535       /* Forward VoiceMail */
06536       long duration = 0;
06537       struct vm_state vmstmp;
06538       memcpy(&vmstmp, vms, sizeof(vmstmp));
06539 
06540       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
06541 
06542       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
06543       if (!cmd) {
06544          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
06545 #ifdef IMAP_STORAGE
06546             int attach_user_voicemail;
06547             char *myserveremail = serveremail;
06548             
06549             /* get destination mailbox */
06550             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
06551             if (!dstvms) {
06552                dstvms = create_vm_state_from_user(vmtmp);
06553             }
06554             if (dstvms) {
06555                init_mailstream(dstvms, 0);
06556                if (!dstvms->mailstream) {
06557                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
06558                } else {
06559                   STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
06560                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
06561                }
06562             } else {
06563                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
06564             }
06565             if (!ast_strlen_zero(vmtmp->serveremail))
06566                myserveremail = vmtmp->serveremail;
06567             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
06568             /* NULL category for IMAP storage */
06569             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);
06570 #else
06571             copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
06572 #endif
06573             saved_messages++;
06574             AST_LIST_REMOVE_CURRENT(list);
06575             free_user(vmtmp);
06576             if (res)
06577                break;
06578          }
06579          AST_LIST_TRAVERSE_SAFE_END;
06580          if (saved_messages > 0) {
06581             /* give confirmation that the message was saved */
06582             /* commented out since we can't forward batches yet
06583             if (saved_messages == 1)
06584                res = ast_play_and_wait(chan, "vm-message");
06585             else
06586                res = ast_play_and_wait(chan, "vm-messages");
06587             if (!res)
06588                res = ast_play_and_wait(chan, "vm-saved"); */
06589 #ifdef IMAP_STORAGE
06590             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
06591             if (ast_strlen_zero(vmstmp.introfn))
06592 #endif
06593             res = ast_play_and_wait(chan, "vm-msgsaved");
06594          }  
06595       }
06596       DISPOSE(dir, curmsg);
06597    }
06598 
06599    /* If anything failed above, we still have this list to free */
06600    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
06601       free_user(vmtmp);
06602    return res ? res : cmd;
06603 }

static void free_user ( struct ast_vm_user vmu  )  [static]

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

01364 {
01365    if (ast_test_flag(vmu, VM_ALLOCED))
01366       ast_free(vmu);
01367 }

static void free_vm_users ( void   )  [static]

Free the users structure.

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

10312 {
10313    struct ast_vm_user *current;
10314    AST_LIST_LOCK(&users);
10315    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
10316       ast_set_flag(current, VM_ALLOCED);
10317       free_user(current);
10318    }
10319    AST_LIST_UNLOCK(&users);
10320 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

10324 {
10325    struct vm_zone *zcur;
10326    AST_LIST_LOCK(&zones);
10327    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
10328       free_zone(zcur);
10329    AST_LIST_UNLOCK(&zones);
10330 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4465 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

04466 {
04467    ast_free(z);
04468 }

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

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

Referenced by leave_voicemail().

04422 {
04423    struct ast_tm tm;
04424    struct timeval t = ast_tvnow();
04425    
04426    ast_localtime(&t, &tm, "UTC");
04427 
04428    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04429 }

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

06033 {
06034    int x;
06035    int d;
06036    char fn[PATH_MAX];
06037    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06038    if (d)
06039       return d;
06040    for (x = start; x< 5; x++) {  /* For all folders */
06041       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06042          return d;
06043       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06044       if (d)
06045          return d;
06046       snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
06047       d = vm_play_folder_name(chan, fn);
06048       if (d)
06049          return d;
06050       d = ast_waitfordigit(chan, 500);
06051       if (d)
06052          return d;
06053    }
06054    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06055    if (d)
06056       return d;
06057    d = ast_waitfordigit(chan, 4000);
06058    return d;
06059 }

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

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

06074 {
06075    int res = 0;
06076    res = ast_play_and_wait(chan, fn);  /* Folder name */
06077    while (((res < '0') || (res > '9')) &&
06078          (res != '#') && (res >= 0)) {
06079       res = get_folder(chan, 0);
06080    }
06081    return res;
06082 }

static int handle_subscribe ( void *  datap  )  [static]

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

10095 {
10096    unsigned int len;
10097    struct mwi_sub *mwi_sub;
10098    struct mwi_sub_task *p = datap;
10099 
10100    len = sizeof(*mwi_sub);
10101    if (!ast_strlen_zero(p->mailbox))
10102       len += strlen(p->mailbox);
10103 
10104    if (!ast_strlen_zero(p->context))
10105       len += strlen(p->context) + 1; /* Allow for seperator */
10106 
10107    if (!(mwi_sub = ast_calloc(1, len)))
10108       return -1;
10109 
10110    mwi_sub->uniqueid = p->uniqueid;
10111    if (!ast_strlen_zero(p->mailbox))
10112       strcpy(mwi_sub->mailbox, p->mailbox);
10113 
10114    if (!ast_strlen_zero(p->context)) {
10115       strcat(mwi_sub->mailbox, "@");
10116       strcat(mwi_sub->mailbox, p->context);
10117    }
10118 
10119    AST_RWLIST_WRLOCK(&mwi_subs);
10120    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
10121    AST_RWLIST_UNLOCK(&mwi_subs);
10122    ast_free((void *) p->mailbox);
10123    ast_free((void *) p->context);
10124    ast_free(p);
10125    poll_subscribed_mailbox(mwi_sub);
10126    return 0;
10127 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

10073 {
10074    struct mwi_sub *mwi_sub;
10075    uint32_t *uniqueid = datap;
10076    
10077    AST_RWLIST_WRLOCK(&mwi_subs);
10078    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
10079       if (mwi_sub->uniqueid == *uniqueid) {
10080          AST_LIST_REMOVE_CURRENT(entry);
10081          break;
10082       }
10083    }
10084    AST_RWLIST_TRAVERSE_SAFE_END
10085    AST_RWLIST_UNLOCK(&mwi_subs);
10086 
10087    if (mwi_sub)
10088       mwi_sub_destroy(mwi_sub);
10089 
10090    ast_free(uniqueid);  
10091    return 0;
10092 }

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

09990 {
09991    switch (cmd) {
09992    case CLI_INIT:
09993       e->command = "voicemail reload";
09994       e->usage =
09995          "Usage: voicemail reload\n"
09996          "       Reload voicemail configuration\n";
09997       return NULL;
09998    case CLI_GENERATE:
09999       return NULL;
10000    }
10001 
10002    if (a->argc != 2)
10003       return CLI_SHOWUSAGE;
10004 
10005    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
10006    load_config(1);
10007    
10008    return CLI_SUCCESS;
10009 }

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

09880 {
09881    struct ast_vm_user *vmu;
09882 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
09883    const char *context = NULL;
09884    int users_counter = 0;
09885 
09886    switch (cmd) {
09887    case CLI_INIT:
09888       e->command = "voicemail show users";
09889       e->usage =
09890          "Usage: voicemail show users [for <context>]\n"
09891          "       Lists all mailboxes currently set up\n";
09892       return NULL;
09893    case CLI_GENERATE:
09894       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
09895    }  
09896 
09897    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
09898       return CLI_SHOWUSAGE;
09899    if (a->argc == 5) {
09900       if (strcmp(a->argv[3],"for"))
09901          return CLI_SHOWUSAGE;
09902       context = a->argv[4];
09903    }
09904 
09905    if (ast_check_realtime("voicemail")) {
09906       if (!context) {
09907          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
09908          return CLI_SHOWUSAGE;
09909       }
09910       return show_users_realtime(a->fd, context);
09911    }
09912 
09913    AST_LIST_LOCK(&users);
09914    if (AST_LIST_EMPTY(&users)) {
09915       ast_cli(a->fd, "There are no voicemail users currently defined\n");
09916       AST_LIST_UNLOCK(&users);
09917       return CLI_FAILURE;
09918    }
09919    if (a->argc == 3)
09920       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
09921    else {
09922       int count = 0;
09923       AST_LIST_TRAVERSE(&users, vmu, list) {
09924          if (!strcmp(context, vmu->context))
09925             count++;
09926       }
09927       if (count) {
09928          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
09929       } else {
09930          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
09931          AST_LIST_UNLOCK(&users);
09932          return CLI_FAILURE;
09933       }
09934    }
09935    AST_LIST_TRAVERSE(&users, vmu, list) {
09936       int newmsgs = 0, oldmsgs = 0;
09937       char count[12], tmp[256] = "";
09938 
09939       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
09940          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
09941          inboxcount(tmp, &newmsgs, &oldmsgs);
09942          snprintf(count, sizeof(count), "%d", newmsgs);
09943          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
09944          users_counter++;
09945       }
09946    }
09947    AST_LIST_UNLOCK(&users);
09948    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
09949    return CLI_SUCCESS;
09950 }

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

09954 {
09955    struct vm_zone *zone;
09956 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
09957    char *res = CLI_SUCCESS;
09958 
09959    switch (cmd) {
09960    case CLI_INIT:
09961       e->command = "voicemail show zones";
09962       e->usage =
09963          "Usage: voicemail show zones\n"
09964          "       Lists zone message formats\n";
09965       return NULL;
09966    case CLI_GENERATE:
09967       return NULL;
09968    }
09969 
09970    if (a->argc != 3)
09971       return CLI_SHOWUSAGE;
09972 
09973    AST_LIST_LOCK(&zones);
09974    if (!AST_LIST_EMPTY(&zones)) {
09975       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
09976       AST_LIST_TRAVERSE(&zones, zone, list) {
09977          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
09978       }
09979    } else {
09980       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
09981       res = CLI_FAILURE;
09982    }
09983    AST_LIST_UNLOCK(&zones);
09984 
09985    return res;
09986 }

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 messagecount(). 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 4806 of file app_voicemail.c.

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

Referenced by load_module(), and vm_execmain().

04807 {
04808    char tmp[256], *tmp2 = tmp, *box, *context;
04809    ast_copy_string(tmp, mailbox, sizeof(tmp));
04810    while ((box = strsep(&tmp2, ","))) {
04811       if ((context = strchr(box, '@')))
04812          *context++ = '\0';
04813       else
04814          context = "default";
04815       if (__has_voicemail(context, box, folder, 1))
04816          return 1;
04817    }
04818    return 0;
04819 }

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

Definition at line 4878 of file app_voicemail.c.

References inboxcount2().

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

04879 {
04880    return inboxcount2(mailbox, NULL, newmsgs, oldmsgs);
04881 }

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

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

04823 {
04824    char tmp[256];
04825    char *context;
04826 
04827    /* If no mailbox, return immediately */
04828    if (ast_strlen_zero(mailbox))
04829       return 0;
04830 
04831    if (newmsgs)
04832       *newmsgs = 0;
04833    if (oldmsgs)
04834       *oldmsgs = 0;
04835    if (urgentmsgs)
04836       *urgentmsgs = 0;
04837 
04838    if (strchr(mailbox, ',')) {
04839       int tmpnew, tmpold, tmpurgent;
04840       char *mb, *cur;
04841 
04842       ast_copy_string(tmp, mailbox, sizeof(tmp));
04843       mb = tmp;
04844       while ((cur = strsep(&mb, ", "))) {
04845          if (!ast_strlen_zero(cur)) {
04846             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
04847                return -1;
04848             else {
04849                if (newmsgs)
04850                   *newmsgs += tmpnew; 
04851                if (oldmsgs)
04852                   *oldmsgs += tmpold;
04853                if (urgentmsgs)
04854                   *urgentmsgs += tmpurgent;
04855             }
04856          }
04857       }
04858       return 0;
04859    }
04860 
04861    ast_copy_string(tmp, mailbox, sizeof(tmp));
04862    
04863    if ((context = strchr(tmp, '@')))
04864       *context++ = '\0';
04865    else
04866       context = "default";
04867 
04868    if (newmsgs)
04869       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
04870    if (oldmsgs)
04871       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
04872    if (urgentmsgs)
04873       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
04874 
04875    return 0;
04876 }

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

utility used by inchar(), for base_encode()

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

03671 {
03672    int l;
03673 
03674    if (bio->ateof)
03675       return 0;
03676 
03677    if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
03678       if (ferror(fi))
03679          return -1;
03680 
03681       bio->ateof = 1;
03682       return 0;
03683    }
03684 
03685    bio->iolen= l;
03686    bio->iocp= 0;
03687 
03688    return 1;
03689 }

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

utility used by base_encode()

Definition at line 3694 of file app_voicemail.c.

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

Referenced by base_encode().

03695 {
03696    if (bio->iocp>=bio->iolen) {
03697       if (!inbuf(bio, fi))
03698          return EOF;
03699    }
03700 
03701    return bio->iobuf[bio->iocp++];
03702 }

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

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

04432 {
04433    int res;
04434    char fn[PATH_MAX];
04435    char dest[PATH_MAX];
04436 
04437    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04438 
04439    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04440       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04441       return -1;
04442    }
04443 
04444    RETRIEVE(fn, -1, ext, context);
04445    if (ast_fileexists(fn, NULL, NULL) > 0) {
04446       res = ast_stream_and_wait(chan, fn, ecodes);
04447       if (res) {
04448          DISPOSE(fn, -1);
04449          return res;
04450       }
04451    } else {
04452       /* Dispose just in case */
04453       DISPOSE(fn, -1);
04454       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04455       if (res)
04456          return res;
04457       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04458       if (res)
04459          return res;
04460    }
04461    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04462    return res;
04463 }

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

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

Referenced by load_config().

01062 {
01063    int i;
01064    char *local_key = ast_strdupa(key);
01065 
01066    for (i = 0; i < strlen(key); ++i) {
01067       if (!strchr(VALID_DTMF, *local_key)) {
01068          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01069          return 0;
01070       }
01071       local_key++;
01072    }
01073    return 1;
01074 }

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

03497 {
03498    int x;
03499    unsigned char map[MAXMSGLIMIT] = "";
03500    DIR *msgdir;
03501    struct dirent *msgdirent;
03502    int msgdirint;
03503 
03504    /* Reading the entire directory into a file map scales better than
03505     * doing a stat repeatedly on a predicted sequence.  I suspect this
03506     * is partially due to stat(2) internally doing a readdir(2) itself to
03507     * find each file. */
03508    if (!(msgdir = opendir(dir))) {
03509       return -1;
03510    }
03511 
03512    while ((msgdirent = readdir(msgdir))) {
03513       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03514          map[msgdirint] = 1;
03515    }
03516    closedir(msgdir);
03517 
03518    for (x = 0; x < vmu->maxmsg; x++) {
03519       if (map[x] == 0)
03520          break;
03521    }
03522 
03523    return x - 1;
03524 }

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

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

static int load_config ( int  reload  )  [static]

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

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

static int load_module ( void   )  [static]

Definition at line 11065 of file app_voicemail.c.

References 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_realtime_require_field(), ast_register_application, ast_taskprocessor_get(), cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), 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().

11066 {
11067    int res;
11068    my_umask = umask(0);
11069    umask(my_umask);
11070 
11071    /* compute the location of the voicemail spool directory */
11072    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
11073    
11074    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
11075       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
11076    }
11077 
11078    if ((res = load_config(0)))
11079       return res;
11080 
11081    res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
11082    res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
11083    res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
11084    res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
11085    res |= ast_custom_function_register(&mailbox_exists_acf);
11086    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
11087    if (res)
11088       return res;
11089 
11090    ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
11091 
11092    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
11093    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
11094    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
11095 
11096    return res;
11097 }

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

01284 {
01285    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01286 }

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

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

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

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

01299 {
01300    return snprintf(dest, len, "%s/msg%04d", dir, num);
01301 }

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

Manager list voicemail users command.

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

10211 {
10212    struct ast_vm_user *vmu = NULL;
10213    const char *id = astman_get_header(m, "ActionID");
10214    char actionid[128] = "";
10215 
10216    if (!ast_strlen_zero(id))
10217       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
10218 
10219    AST_LIST_LOCK(&users);
10220 
10221    if (AST_LIST_EMPTY(&users)) {
10222       astman_send_ack(s, m, "There are no voicemail users currently defined.");
10223       AST_LIST_UNLOCK(&users);
10224       return RESULT_SUCCESS;
10225    }
10226    
10227    astman_send_ack(s, m, "Voicemail user list will follow");
10228    
10229    AST_LIST_TRAVERSE(&users, vmu, list) {
10230       char dirname[256];
10231 
10232 #ifdef IMAP_STORAGE
10233       int new, old;
10234       inboxcount(vmu->mailbox, &new, &old);
10235 #endif
10236       
10237       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
10238       astman_append(s,
10239          "%s"
10240          "Event: VoicemailUserEntry\r\n"
10241          "VMContext: %s\r\n"
10242          "VoiceMailbox: %s\r\n"
10243          "Fullname: %s\r\n"
10244          "Email: %s\r\n"
10245          "Pager: %s\r\n"
10246          "ServerEmail: %s\r\n"
10247          "MailCommand: %s\r\n"
10248          "Language: %s\r\n"
10249          "TimeZone: %s\r\n"
10250          "Callback: %s\r\n"
10251          "Dialout: %s\r\n"
10252          "UniqueID: %s\r\n"
10253          "ExitContext: %s\r\n"
10254          "SayDurationMinimum: %d\r\n"
10255          "SayEnvelope: %s\r\n"
10256          "SayCID: %s\r\n"
10257          "AttachMessage: %s\r\n"
10258          "AttachmentFormat: %s\r\n"
10259          "DeleteMessage: %s\r\n"
10260          "VolumeGain: %.2f\r\n"
10261          "CanReview: %s\r\n"
10262          "CallOperator: %s\r\n"
10263          "MaxMessageCount: %d\r\n"
10264          "MaxMessageLength: %d\r\n"
10265          "NewMessageCount: %d\r\n"
10266 #ifdef IMAP_STORAGE
10267          "OldMessageCount: %d\r\n"
10268          "IMAPUser: %s\r\n"
10269 #endif
10270          "\r\n",
10271          actionid,
10272          vmu->context,
10273          vmu->mailbox,
10274          vmu->fullname,
10275          vmu->email,
10276          vmu->pager,
10277          vmu->serveremail,
10278          vmu->mailcmd,
10279          vmu->language,
10280          vmu->zonetag,
10281          vmu->callback,
10282          vmu->dialout,
10283          vmu->uniqueid,
10284          vmu->exit,
10285          vmu->saydurationm,
10286          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
10287          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
10288          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
10289          vmu->attachfmt,
10290          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
10291          vmu->volgain,
10292          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
10293          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
10294          vmu->maxmsg,
10295          vmu->maxsecs,
10296 #ifdef IMAP_STORAGE
10297          new, old, vmu->imapuser
10298 #else
10299          count_messages(vmu, dirname)
10300 #endif
10301          );
10302    }     
10303    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
10304 
10305    AST_LIST_UNLOCK(&users);
10306 
10307    return RESULT_SUCCESS;
10308 }

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

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

10045 {
10046    while (poll_thread_run) {
10047       struct timespec ts = { 0, };
10048       struct timeval wait;
10049 
10050       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
10051       ts.tv_sec = wait.tv_sec;
10052       ts.tv_nsec = wait.tv_usec * 1000;
10053 
10054       ast_mutex_lock(&poll_lock);
10055       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
10056       ast_mutex_unlock(&poll_lock);
10057 
10058       if (!poll_thread_run)
10059          break;
10060 
10061       poll_subscribed_mailboxes();
10062    }
10063 
10064    return NULL;
10065 }

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

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

01341 {
01342    static const char *msgs[] = {
01343 #ifdef IMAP_STORAGE
01344       imapfolder,
01345 #else
01346       "INBOX",
01347 #endif
01348       "Old",
01349       "Work",
01350       "Family",
01351       "Friends",
01352       "Cust1",
01353       "Cust2",
01354       "Cust3",
01355       "Cust4",
01356       "Cust5",
01357       "Deleted",
01358       "Urgent"
01359    };
01360    return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "Unknown";
01361 }

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

Definition at line 4749 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04750 {
04751    return __has_voicemail(context, mailbox, folder, 0);
04752 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 10067 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

10068 {
10069    ast_free(mwi_sub);
10070 }

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

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

10146 {
10147    struct mwi_sub_task *mwist;
10148    
10149    if (ast_event_get_type(event) != AST_EVENT_SUB)
10150       return;
10151 
10152    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10153       return;
10154 
10155    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
10156       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
10157       return;
10158    }
10159    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
10160    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
10161    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10162    
10163    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
10164       ast_free(mwist);
10165    }
10166 }

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

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

10130 {
10131    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
10132    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
10133       return;
10134 
10135    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10136       return;
10137 
10138    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10139    *uniqueid = u;
10140    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
10141       ast_free(uniqueid);
10142    }
10143 }

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

06267 {
06268    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06269    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06270    const char *category;
06271    char *myserveremail = serveremail;
06272 
06273    ast_channel_lock(chan);
06274    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06275       category = ast_strdupa(category);
06276    }
06277    ast_channel_unlock(chan);
06278 
06279    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
06280    make_file(fn, sizeof(fn), todir, msgnum);
06281    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06282 
06283    if (!ast_strlen_zero(vmu->attachfmt)) {
06284       if (strstr(fmt, vmu->attachfmt))
06285          fmt = vmu->attachfmt;
06286       else
06287          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);
06288    }
06289 
06290    /* Attach only the first format */
06291    fmt = ast_strdupa(fmt);
06292    stringp = fmt;
06293    strsep(&stringp, "|");
06294 
06295    if (!ast_strlen_zero(vmu->serveremail))
06296       myserveremail = vmu->serveremail;
06297 
06298    if (!ast_strlen_zero(vmu->email)) {
06299       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06300       if (!attach_user_voicemail)
06301          attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
06302 
06303       if (attach_user_voicemail)
06304          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06305 
06306       /* XXX possible imap issue, should category be NULL XXX */
06307       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06308 
06309       if (attach_user_voicemail)
06310          DISPOSE(todir, msgnum);
06311    }
06312 
06313    if (!ast_strlen_zero(vmu->pager)) {
06314       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
06315    }
06316 
06317    if (ast_test_flag(vmu, VM_DELETE))
06318       DELETE(todir, msgnum, fn, vmu);
06319 
06320    /* Leave voicemail for someone */
06321    if (ast_app_has_voicemail(ext_context, NULL)) 
06322       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06323 
06324    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06325 
06326    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);
06327    run_externnotify(vmu->context, vmu->mailbox, flag);
06328 
06329 #ifdef IMAP_STORAGE
06330    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06331    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06332       vm_imap_delete(NULL, vms->curmsg, vmu);
06333       vms->newmessages--;  /* Fix new message count */
06334    }
06335 #endif
06336 
06337    return 0;
06338 }

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

utility used by base_encode()

Definition at line 3707 of file app_voicemail.c.

References BASELINELEN, eol, and baseio::linelength.

Referenced by base_encode().

03708 {
03709    if (bio->linelength >= BASELINELEN) {
03710       if (fputs(eol,so) == EOF)
03711          return -1;
03712 
03713       bio->linelength= 0;
03714    }
03715 
03716    if (putc(((unsigned char)c),so) == EOF)
03717       return -1;
03718 
03719    bio->linelength++;
03720 
03721    return 1;
03722 }

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

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

07022 {
07023    int count_msg, last_msg;
07024 
07025    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
07026    
07027    /* Rename the member vmbox HERE so that we don't try to return before
07028     * we know what's going on.
07029     */
07030    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07031    
07032    /* Faster to make the directory than to check if it exists. */
07033    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07034 
07035    count_msg = count_messages(vmu, vms->curdir);
07036    if (count_msg < 0)
07037       return count_msg;
07038    else
07039       vms->lastmsg = count_msg - 1;
07040 
07041    /*
07042    The following test is needed in case sequencing gets messed up.
07043    There appears to be more than one way to mess up sequence, so
07044    we will not try to find all of the root causes--just fix it when
07045    detected.
07046    */
07047 
07048    if (vm_lock_path(vms->curdir)) {
07049       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07050       return -1;
07051    }
07052 
07053    last_msg = last_message_index(vmu, vms->curdir);
07054    ast_unlock_path(vms->curdir);
07055 
07056    if (last_msg < 0) 
07057       return last_msg;
07058 
07059    return 0;
07060 }

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

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

06820 {
06821    int res = 0;
06822    char filename[256], *cid;
06823    const char *origtime, *context, *category, *duration, *flag;
06824    struct ast_config *msg_cfg;
06825    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06826 
06827    vms->starting = 0;
06828    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06829    adsi_message(chan, vms);
06830    if (!vms->curmsg)
06831       res = wait_file2(chan, vms, "vm-first");  /* "First" */
06832    else if (vms->curmsg == vms->lastmsg)
06833       res = wait_file2(chan, vms, "vm-last");      /* "last" */
06834 
06835    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
06836    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
06837    msg_cfg = ast_config_load(filename, config_flags);
06838    if (!msg_cfg) {
06839       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06840       return 0;
06841    }
06842    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
06843 
06844    /* Play the word urgent if we are listening to urgent messages */
06845    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
06846       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
06847    }
06848 
06849    if (!res) {
06850       /* POLISH syntax */
06851       if (!strncasecmp(chan->language, "pl", 2)) {
06852          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06853             int ten, one;
06854             char nextmsg[256];
06855             ten = (vms->curmsg + 1) / 10;
06856             one = (vms->curmsg + 1) % 10;
06857 
06858             if (vms->curmsg < 20) {
06859                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
06860                res = wait_file2(chan, vms, nextmsg);
06861             } else {
06862                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
06863                res = wait_file2(chan, vms, nextmsg);
06864                if (one > 0) {
06865                   if (!res) {
06866                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
06867                      res = wait_file2(chan, vms, nextmsg);
06868                   }
06869                }
06870             }
06871          }
06872          if (!res)
06873             res = wait_file2(chan, vms, "vm-message");
06874       /* HEBREW syntax */
06875       } else if (!strncasecmp(chan->language, "he", 2)) {
06876          if (!vms->curmsg) {
06877             res = wait_file2(chan, vms, "vm-message");
06878             res = wait_file2(chan, vms, "vm-first");
06879          } else if (vms->curmsg == vms->lastmsg) {
06880             res = wait_file2(chan, vms, "vm-message");
06881             res = wait_file2(chan, vms, "vm-last");
06882          } else {
06883             res = wait_file2(chan, vms, "vm-message");
06884             res = wait_file2(chan, vms, "vm-number");
06885             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
06886          }
06887       } else {
06888          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
06889             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
06890          } else { /* DEFAULT syntax */
06891             res = wait_file2(chan, vms, "vm-message");
06892          }
06893          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
06894             if (!res) {
06895                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
06896             }
06897          }
06898       }
06899    }
06900 
06901    if (!msg_cfg) {
06902       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06903       return 0;
06904    }
06905 
06906    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
06907       ast_log(AST_LOG_WARNING, "No origtime?!\n");
06908       DISPOSE(vms->curdir, vms->curmsg);
06909       ast_config_destroy(msg_cfg);
06910       return 0;
06911    }
06912 
06913    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
06914    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
06915    category = ast_variable_retrieve(msg_cfg, "message", "category");
06916 
06917    context = ast_variable_retrieve(msg_cfg, "message", "context");
06918    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
06919       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
06920    if (!res) {
06921       res = play_message_category(chan, category);
06922    }
06923    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
06924       res = play_message_datetime(chan, vmu, origtime, filename);
06925    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
06926       res = play_message_callerid(chan, vms, cid, context, 0);
06927    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
06928       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
06929    /* Allow pressing '1' to skip envelope / callerid */
06930    if (res == '1')
06931       res = 0;
06932    ast_config_destroy(msg_cfg);
06933 
06934    if (!res) {
06935       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
06936       vms->heard[vms->curmsg] = 1;
06937 #ifdef IMAP_STORAGE
06938       /*IMAP storage stores any prepended message from a forward
06939        * as a separate file from the rest of the message
06940        */
06941       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
06942          wait_file(chan, vms, vms->introfn);
06943       }
06944 #endif
06945       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
06946          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
06947          res = 0;
06948       }
06949    }
06950    DISPOSE(vms->curdir, vms->curmsg);
06951    return res;
06952 }

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

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

06706 {
06707    int res = 0;
06708    int i;
06709    char *callerid, *name;
06710    char prefile[PATH_MAX] = "";
06711    
06712 
06713    /* If voicemail cid is not enabled, or we didn't get cid or context from
06714     * the attribute file, leave now.
06715     *
06716     * TODO Still need to change this so that if this function is called by the
06717     * message envelope (and someone is explicitly requesting to hear the CID),
06718     * it does not check to see if CID is enabled in the config file.
06719     */
06720    if ((cid == NULL)||(context == NULL))
06721       return res;
06722 
06723    /* Strip off caller ID number from name */
06724    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
06725    ast_callerid_parse(cid, &name, &callerid);
06726    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
06727       /* Check for internal contexts and only */
06728       /* say extension when the call didn't come from an internal context in the list */
06729       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
06730          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
06731          if ((strcmp(cidinternalcontexts[i], context) == 0))
06732             break;
06733       }
06734       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
06735          if (!res) {
06736             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
06737             if (!ast_strlen_zero(prefile)) {
06738             /* See if we can find a recorded name for this person instead of their extension number */
06739                if (ast_fileexists(prefile, NULL, NULL) > 0) {
06740                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
06741                   if (!callback)
06742                      res = wait_file2(chan, vms, "vm-from");
06743                   res = ast_stream_and_wait(chan, prefile, "");
06744                } else {
06745                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
06746                   /* Say "from extension" as one saying to sound smoother */
06747                   if (!callback)
06748                      res = wait_file2(chan, vms, "vm-from-extension");
06749                   res = ast_say_digit_str(chan, callerid, "", chan->language);
06750                }
06751             }
06752          }
06753       } else if (!res) {
06754          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
06755          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
06756          if (!callback)
06757             res = wait_file2(chan, vms, "vm-from-phonenumber");
06758          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
06759       }
06760    } else {
06761       /* Number unknown */
06762       ast_debug(1, "VM-CID: From an unknown number\n");
06763       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
06764       res = wait_file2(chan, vms, "vm-unknown-caller");
06765    }
06766    return res;
06767 }

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

Definition at line 6618 of file app_voicemail.c.

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

Referenced by play_message().

06619 {
06620    int res = 0;
06621 
06622    if (!ast_strlen_zero(category))
06623       res = ast_play_and_wait(chan, category);
06624 
06625    if (res) {
06626       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
06627       res = 0;
06628    }
06629 
06630    return res;
06631 }

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

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

06634 {
06635    int res = 0;
06636    struct vm_zone *the_zone = NULL;
06637    time_t t;
06638 
06639    if (ast_get_time_t(origtime, &t, 0, NULL)) {
06640       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
06641       return 0;
06642    }
06643 
06644    /* Does this user have a timezone specified? */
06645    if (!ast_strlen_zero(vmu->zonetag)) {
06646       /* Find the zone in the list */
06647       struct vm_zone *z;
06648       AST_LIST_LOCK(&zones);
06649       AST_LIST_TRAVERSE(&zones, z, list) {
06650          if (!strcmp(z->name, vmu->zonetag)) {
06651             the_zone = z;
06652             break;
06653          }
06654       }
06655       AST_LIST_UNLOCK(&zones);
06656    }
06657 
06658 /* No internal variable parsing for now, so we'll comment it out for the time being */
06659 #if 0
06660    /* Set the DIFF_* variables */
06661    ast_localtime(&t, &time_now, NULL);
06662    tv_now = ast_tvnow();
06663    ast_localtime(&tv_now, &time_then, NULL);
06664 
06665    /* Day difference */
06666    if (time_now.tm_year == time_then.tm_year)
06667       snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
06668    else
06669       snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
06670    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
06671 
06672    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
06673 #endif
06674    if (the_zone) {
06675       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
06676    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
06677       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06678    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
06679       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
06680    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
06681       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);
06682    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
06683       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
06684    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
06685       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06686    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
06687       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
06688    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
06689       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);
06690    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
06691       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
06692    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
06693       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
06694    } else {
06695       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
06696    }
06697 #if 0
06698    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
06699 #endif
06700    return res;
06701 }

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

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

06770 {
06771    int res = 0;
06772    int durationm;
06773    int durations;
06774    /* Verify that we have a duration for the message */
06775    if (duration == NULL)
06776       return res;
06777 
06778    /* Convert from seconds to minutes */
06779    durations=atoi(duration);
06780    durationm=(durations / 60);
06781 
06782    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
06783 
06784    if ((!res) && (durationm >= minduration)) {
06785       res = wait_file2(chan, vms, "vm-duration");
06786 
06787       /* POLISH syntax */
06788       if (!strncasecmp(chan->language, "pl", 2)) {
06789          div_t num = div(durationm, 10);
06790 
06791          if (durationm == 1) {
06792             res = ast_play_and_wait(chan, "digits/1z");
06793             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
06794          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
06795             if (num.rem == 2) {
06796                if (!num.quot) {
06797                   res = ast_play_and_wait(chan, "digits/2-ie");
06798                } else {
06799                   res = say_and_wait(chan, durationm - 2 , chan->language);
06800                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
06801                }
06802             } else {
06803                res = say_and_wait(chan, durationm, chan->language);
06804             }
06805             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
06806          } else {
06807             res = say_and_wait(chan, durationm, chan->language);
06808             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
06809          }
06810       /* DEFAULT syntax */
06811       } else {
06812          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
06813          res = wait_file2(chan, vms, "vm-minutes");
06814       }
06815    }
06816    return res;
06817 }

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

11362 {
11363    /* Record message & let caller review or re-record it, or set options if applicable */
11364    int res = 0;
11365    int cmd = 0;
11366    int max_attempts = 3;
11367    int attempts = 0;
11368    int recorded = 0;
11369    int msg_exists = 0;
11370    signed char zero_gain = 0;
11371    char tempfile[PATH_MAX];
11372    char *acceptdtmf = "#";
11373    char *canceldtmf = "";
11374 
11375    /* Note that urgent and private are for flagging messages as such in the future */
11376 
11377    /* barf if no pointer passed to store duration in */
11378    if (duration == NULL) {
11379       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
11380       return -1;
11381    }
11382 
11383    if (!outsidecaller)
11384       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
11385    else
11386       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
11387 
11388    cmd = '3';  /* Want to start by recording */
11389 
11390    while ((cmd >= 0) && (cmd != 't')) {
11391       switch (cmd) {
11392       case '1':
11393          if (!msg_exists) {
11394             /* In this case, 1 is to record a message */
11395             cmd = '3';
11396             break;
11397          } else {
11398             /* Otherwise 1 is to save the existing message */
11399             ast_verb(3, "Saving message as is\n");
11400             if (!outsidecaller) 
11401                ast_filerename(tempfile, recordfile, NULL);
11402             ast_stream_and_wait(chan, "vm-msgsaved", "");
11403             if (!outsidecaller) {
11404                /* Saves to IMAP server only if imapgreeting=yes */
11405                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
11406                DISPOSE(recordfile, -1);
11407             }
11408             cmd = 't';
11409             return res;
11410          }
11411       case '2':
11412          /* Review */
11413          ast_verb(3, "Reviewing the message\n");
11414          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
11415          break;
11416       case '3':
11417          msg_exists = 0;
11418          /* Record */
11419          if (recorded == 1) 
11420             ast_verb(3, "Re-recording the message\n");
11421          else  
11422             ast_verb(3, "Recording the message\n");
11423          
11424          if (recorded && outsidecaller) {
11425             cmd = ast_play_and_wait(chan, INTRO);
11426             cmd = ast_play_and_wait(chan, "beep");
11427          }
11428          recorded = 1;
11429          /* 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 */
11430          if (record_gain)
11431             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
11432          if (ast_test_flag(vmu, VM_OPERATOR))
11433             canceldtmf = "0";
11434          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
11435          if (record_gain)
11436             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
11437          if (cmd == -1) {
11438             /* User has hung up, no options to give */
11439             if (!outsidecaller) {
11440                /* user was recording a greeting and they hung up, so let's delete the recording. */
11441                ast_filedelete(tempfile, NULL);
11442             }     
11443             return cmd;
11444          }
11445          if (cmd == '0') {
11446             break;
11447          } else if (cmd == '*') {
11448             break;
11449 #if 0
11450          } else if (vmu->review && (*duration < 5)) {
11451             /* Message is too short */
11452             ast_verb(3, "Message too short\n");
11453             cmd = ast_play_and_wait(chan, "vm-tooshort");
11454             cmd = ast_filedelete(tempfile, NULL);
11455             break;
11456          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
11457             /* Message is all silence */
11458             ast_verb(3, "Nothing recorded\n");
11459             cmd = ast_filedelete(tempfile, NULL);
11460             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
11461             if (!cmd)
11462                cmd = ast_play_and_wait(chan, "vm-speakup");
11463             break;
11464 #endif
11465          } else {
11466             /* If all is well, a message exists */
11467             msg_exists = 1;
11468             cmd = 0;
11469          }
11470          break;
11471       case '4':
11472          if (outsidecaller) {  /* only mark vm messages */
11473             /* Mark Urgent */
11474             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11475                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
11476                ast_debug(1000, "This message is too urgent!\n");
11477                res = ast_play_and_wait(chan, "vm-marked-urgent");
11478                strcpy(flag, "Urgent");
11479             } else if (flag) {
11480                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
11481                res = ast_play_and_wait(chan, "vm-urgent-removed");
11482                strcpy(flag, "");
11483             } else {
11484                ast_play_and_wait(chan, "vm-sorry");
11485             }
11486             cmd = 0;
11487          } else {
11488             cmd = ast_play_and_wait(chan, "vm-sorry");
11489          }
11490          break;
11491       case '5':
11492       case '6':
11493       case '7':
11494       case '8':
11495       case '9':
11496       case '*':
11497       case '#':
11498          cmd = ast_play_and_wait(chan, "vm-sorry");
11499          break;
11500 #if 0 
11501 /*  XXX Commented out for the moment because of the dangers of deleting
11502     a message while recording (can put the message numbers out of sync) */
11503       case '*':
11504          /* Cancel recording, delete message, offer to take another message*/
11505          cmd = ast_play_and_wait(chan, "vm-deleted");
11506          cmd = ast_filedelete(tempfile, NULL);
11507          if (outsidecaller) {
11508             res = vm_exec(chan, NULL);
11509             return res;
11510          }
11511          else
11512             return 1;
11513 #endif
11514       case '0':
11515          if (!ast_test_flag(vmu, VM_OPERATOR)) {
11516             cmd = ast_play_and_wait(chan, "vm-sorry");
11517             break;
11518          }
11519          if (msg_exists || recorded) {
11520             cmd = ast_play_and_wait(chan, "vm-saveoper");
11521             if (!cmd)
11522                cmd = ast_waitfordigit(chan, 3000);
11523             if (cmd == '1') {
11524                ast_play_and_wait(chan, "vm-msgsaved");
11525                cmd = '0';
11526             } else if (cmd == '4') {
11527                if (flag) {
11528                   ast_play_and_wait(chan, "vm-marked-urgent");
11529                   strcpy(flag, "Urgent");
11530                }
11531                ast_play_and_wait(chan, "vm-msgsaved");
11532                cmd = '0';
11533             } else {
11534                ast_play_and_wait(chan, "vm-deleted");
11535                DELETE(recordfile, -1, recordfile, vmu);
11536                cmd = '0';
11537             }
11538          }
11539          return cmd;
11540       default:
11541          /* If the caller is an ouside caller, and the review option is enabled,
11542             allow them to review the message, but let the owner of the box review
11543             their OGM's */
11544          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
11545             return cmd;
11546          if (msg_exists) {
11547             cmd = ast_play_and_wait(chan, "vm-review");
11548             if (!cmd && outsidecaller) {
11549                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11550                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
11551                } else if (flag) {
11552                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
11553                }
11554             }
11555          } else {
11556             cmd = ast_play_and_wait(chan, "vm-torerecord");
11557             if (!cmd)
11558                cmd = ast_waitfordigit(chan, 600);
11559          }
11560          
11561          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
11562             cmd = ast_play_and_wait(chan, "vm-reachoper");
11563             if (!cmd)
11564                cmd = ast_waitfordigit(chan, 600);
11565          }
11566 #if 0
11567          if (!cmd)
11568             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
11569 #endif
11570          if (!cmd)
11571             cmd = ast_waitfordigit(chan, 6000);
11572          if (!cmd) {
11573             attempts++;
11574          }
11575          if (attempts > max_attempts) {
11576             cmd = 't';
11577          }
11578       }
11579    }
11580    if (outsidecaller)
11581       ast_play_and_wait(chan, "vm-goodbye");
11582    if (cmd == 't')
11583       cmd = 0;
11584    return cmd;
11585 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

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

10018 {
10019    int new = 0, old = 0, urgent = 0;
10020 
10021    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
10022 
10023    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
10024       mwi_sub->old_urgent = urgent;
10025       mwi_sub->old_new = new;
10026       mwi_sub->old_old = old;
10027       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
10028    }
10029 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

10032 {
10033    struct mwi_sub *mwi_sub;
10034 
10035    AST_RWLIST_RDLOCK(&mwi_subs);
10036    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
10037       if (!ast_strlen_zero(mwi_sub->mailbox)) {
10038          poll_subscribed_mailbox(mwi_sub);
10039       }
10040    }
10041    AST_RWLIST_UNLOCK(&mwi_subs);
10042 }

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

00760 {
00761    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00762    if (saydurationminfo)
00763       vmu->saydurationm = saydurationminfo;
00764    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00765    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00766    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00767    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00768    if (vmmaxsecs)
00769       vmu->maxsecs = vmmaxsecs;
00770    if (maxmsg)
00771       vmu->maxmsg = maxmsg;
00772    if (maxdeletedmsg)
00773       vmu->maxdeletedmsg = maxdeletedmsg;
00774    vmu->volgain = volgain;
00775 }

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

03793 {
03794    char callerid[256];
03795    char fromdir[256], fromfile[256];
03796    struct ast_config *msg_cfg;
03797    const char *origcallerid, *origtime;
03798    char origcidname[80], origcidnum[80], origdate[80];
03799    int inttime;
03800    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03801 
03802    /* Prepare variables for substitution in email body and subject */
03803    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
03804    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
03805    snprintf(passdata, passdatasize, "%d", msgnum);
03806    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
03807    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
03808    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
03809    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
03810       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
03811    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
03812    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
03813    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
03814    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
03815    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
03816 
03817    /* Retrieve info from VM attribute file */
03818    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
03819    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
03820    if (strlen(fromfile) < sizeof(fromfile) - 5) {
03821       strcat(fromfile, ".txt");
03822    }
03823    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
03824       if (option_debug > 0) {
03825          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
03826       }
03827       return;
03828    }
03829 
03830    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
03831       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
03832       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
03833       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
03834       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
03835    }
03836 
03837    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
03838       struct timeval tv = { inttime, };
03839       struct ast_tm tm;
03840       ast_localtime(&tv, &tm, NULL);
03841       ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
03842       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
03843    }
03844    ast_config_destroy(msg_cfg);
03845 }

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

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

06231 {
06232    struct ast_event *event;
06233    char *mailbox, *context;
06234 
06235    /* Strip off @default */
06236    context = mailbox = ast_strdupa(box);
06237    strsep(&context, "@");
06238    if (ast_strlen_zero(context))
06239       context = "default";
06240 
06241    if (!(event = ast_event_new(AST_EVENT_MWI,
06242          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06243          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06244          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06245          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06246          AST_EVENT_IE_END))) {
06247       return;
06248    }
06249 
06250    ast_event_queue_and_cache(event);
06251 }

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

Referenced by make_email_file().

03855 {
03856    char *ptr = to;
03857    *ptr++ = '"';
03858    for (; ptr < to + len - 1; from++) {
03859       if (*from == '"')
03860          *ptr++ = '\\';
03861       else if (*from == '\0')
03862          break;
03863       *ptr++ = *from;
03864    }
03865    if (ptr < to + len - 1)
03866       *ptr++ = '"';
03867    *ptr = '\0';
03868    return to;
03869 }

static int reload ( void   )  [static]

Definition at line 11035 of file app_voicemail.c.

References load_config().

11036 {
11037    return load_config(1);
11038 }

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

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

03473 {
03474    char stxt[PATH_MAX];
03475    char dtxt[PATH_MAX];
03476    ast_filerename(sfn,dfn,NULL);
03477    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03478    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03479    if (ast_check_realtime("voicemail_data")) {
03480       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03481    }
03482    rename(stxt, dtxt);
03483 }

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

01167 {
01168    /* This function could be made to generate one from a database, too */
01169    struct ast_vm_user *cur;
01170    int res = -1;
01171    AST_LIST_LOCK(&users);
01172    AST_LIST_TRAVERSE(&users, cur, list) {
01173       if ((!context || !strcasecmp(context, cur->context)) &&
01174          (!strcasecmp(mailbox, cur->mailbox)))
01175             break;
01176    }
01177    if (cur) {
01178       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01179       res = 0;
01180    }
01181    AST_LIST_UNLOCK(&users);
01182    return res;
01183 }

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

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

04886 {
04887    char arguments[255];
04888    char ext_context[256] = "";
04889    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
04890    struct ast_smdi_mwi_message *mwi_msg;
04891 
04892    if (!ast_strlen_zero(context))
04893       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
04894    else
04895       ast_copy_string(ext_context, extension, sizeof(ext_context));
04896 
04897    if (smdi_iface) {
04898       if (ast_app_has_voicemail(ext_context, NULL)) 
04899          ast_smdi_mwi_set(smdi_iface, extension);
04900       else
04901          ast_smdi_mwi_unset(smdi_iface, extension);
04902 
04903       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
04904          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
04905          if (!strncmp(mwi_msg->cause, "INV", 3))
04906             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
04907          else if (!strncmp(mwi_msg->cause, "BLK", 3))
04908             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
04909          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
04910          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
04911       } else {
04912          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
04913       }
04914    }
04915 
04916    if (!ast_strlen_zero(externnotify)) {
04917       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
04918          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
04919       } else {
04920          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
04921          ast_debug(1, "Executing %s\n", arguments);
04922          ast_safe_system(arguments);
04923       }
04924    }
04925 }

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

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

05460 {
05461 #ifdef IMAP_STORAGE
05462    /* we must use mbox(x) folder names, and copy the message there */
05463    /* simple. huh? */
05464    char sequence[10];
05465    char mailbox[256];
05466    int res;
05467 
05468    /* get the real IMAP message number for this message */
05469    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
05470    
05471    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
05472    ast_mutex_lock(&vms->lock);
05473    /* if save to Old folder, put in INBOX as read */
05474    if (box == OLD_FOLDER) {
05475       mail_setflag(vms->mailstream, sequence, "\\Seen");
05476       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
05477    } else if (box == NEW_FOLDER) {
05478       mail_setflag(vms->mailstream, sequence, "\\Unseen");
05479       mail_clearflag(vms->mailstream, sequence, "\\Seen");
05480    }
05481    if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
05482       ast_mutex_unlock(&vms->lock);
05483       return 0;
05484    }
05485    /* Create the folder if it don't exist */
05486    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
05487    ast_debug(5, "Checking if folder exists: %s\n",mailbox);
05488    if (mail_create(vms->mailstream, mailbox) == NIL) 
05489       ast_debug(5, "Folder exists.\n");
05490    else
05491       ast_log(AST_LOG_NOTICE, "Folder %s created!\n",mbox(box));
05492    res = !mail_copy(vms->mailstream, sequence, (char *)mbox(box));
05493    ast_mutex_unlock(&vms->lock);
05494    return res;
05495 #else
05496    char *dir = vms->curdir;
05497    char *username = vms->username;
05498    char *context = vmu->context;
05499    char sfn[PATH_MAX];
05500    char dfn[PATH_MAX];
05501    char ddir[PATH_MAX];
05502    const char *dbox = mbox(box);
05503    int x, i;
05504    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
05505 
05506    if (vm_lock_path(ddir))
05507       return ERROR_LOCK_PATH;
05508 
05509    x = last_message_index(vmu, ddir) + 1;
05510 
05511    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
05512       x--;
05513       for (i = 1; i <= x; i++) {
05514          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
05515          make_file(sfn, sizeof(sfn), ddir, i);
05516          make_file(dfn, sizeof(dfn), ddir, i - 1);
05517          if (EXISTS(ddir, i, sfn, NULL)) {
05518             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
05519          } else
05520             break;
05521       }
05522    } else {
05523       if (x >= vmu->maxmsg) {
05524          ast_unlock_path(ddir);
05525          return -1;
05526       }
05527    }
05528    make_file(sfn, sizeof(sfn), dir, msg);
05529    make_file(dfn, sizeof(dfn), ddir, x);
05530    if (strcmp(sfn, dfn)) {
05531       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
05532    }
05533    ast_unlock_path(ddir);
05534 #endif
05535    return 0;
05536 }

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

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

Referenced by load_module().

11022 {
11023    int res = -1;
11024    char dir[PATH_MAX];
11025    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
11026    ast_debug(2, "About to try retrieving name file %s\n", dir);
11027    RETRIEVE(dir, -1, mailbox, context);
11028    if (ast_fileexists(dir, NULL, NULL)) {
11029       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
11030    }
11031    DISPOSE(dir, -1);
11032    return res;
11033 }

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

04299 {
04300    FILE *p=NULL;
04301    char tmp[80] = "/tmp/astmail-XXXXXX";
04302    char tmp2[256];
04303 
04304    if (vmu && ast_strlen_zero(vmu->email)) {
04305       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04306       return(0);
04307    }
04308    if (!strcmp(format, "wav49"))
04309       format = "WAV";
04310    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));
04311    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04312       command hangs */
04313    if ((p = vm_mkftemp(tmp)) == NULL) {
04314       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04315       return -1;
04316    } else {
04317       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04318       fclose(p);
04319       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04320       ast_safe_system(tmp2);
04321       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04322    }
04323    return 0;
04324 }

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

04327 {
04328    char date[256];
04329    char host[MAXHOSTNAMELEN] = "";
04330    char who[256];
04331    char dur[PATH_MAX];
04332    char tmp[80] = "/tmp/astmail-XXXXXX";
04333    char tmp2[PATH_MAX];
04334    struct ast_tm tm;
04335    FILE *p;
04336 
04337    if ((p = vm_mkftemp(tmp)) == NULL) {
04338       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04339       return -1;
04340    }
04341    gethostname(host, sizeof(host)-1);
04342    if (strchr(srcemail, '@'))
04343       ast_copy_string(who, srcemail, sizeof(who));
04344    else 
04345       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04346    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04347    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04348    fprintf(p, "Date: %s\n", date);
04349 
04350    if (*pagerfromstring) {
04351       struct ast_channel *ast;
04352       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04353          char *passdata;
04354          int vmlen = strlen(fromstring)*3 + 200;
04355          passdata = alloca(vmlen);
04356          memset(passdata, 0, vmlen);
04357          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04358          pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
04359          fprintf(p, "From: %s <%s>\n", passdata, who);
04360          ast_channel_free(ast);
04361       } else 
04362          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04363    } else
04364       fprintf(p, "From: Asterisk PBX <%s>\n", who);
04365    fprintf(p, "To: %s\n", pager);
04366    if (pagersubject) {
04367       struct ast_channel *ast;
04368       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04369          char *passdata;
04370          int vmlen = strlen(pagersubject) * 3 + 200;
04371          passdata = alloca(vmlen);
04372          memset(passdata, 0, vmlen);
04373          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04374          pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
04375          fprintf(p, "Subject: %s\n\n", passdata);
04376          ast_channel_free(ast);
04377       } else
04378          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04379    } else {
04380       if (ast_strlen_zero(flag)) {
04381          fprintf(p, "Subject: New VM\n\n");
04382       } else {
04383          fprintf(p, "Subject: New %s VM\n\n", flag);
04384       }
04385    }
04386 
04387    ast_strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
04388    if (pagerbody) {
04389       struct ast_channel *ast;
04390       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04391          char *passdata;
04392          int vmlen = strlen(pagerbody) * 3 + 200;
04393          passdata = alloca(vmlen);
04394          memset(passdata, 0, vmlen);
04395          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04396          pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
04397          fprintf(p, "%s\n", passdata);
04398          ast_channel_free(ast);
04399       } else
04400          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04401    } else {
04402       fprintf(p, "New %s long %s msg in box %s\n"
04403             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04404    }
04405    fclose(p);
04406    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04407    ast_safe_system(tmp2);
04408    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04409    return 0;
04410 }

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

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

09816 {
09817    struct ast_config *cfg;
09818    const char *cat = NULL;
09819 
09820    if (!(cfg = ast_load_realtime_multientry("voicemail", 
09821       "context", context, SENTINEL))) {
09822       return CLI_FAILURE;
09823    }
09824 
09825    ast_cli(fd,
09826       "\n"
09827       "=============================================================\n"
09828       "=== Configured Voicemail Users ==============================\n"
09829       "=============================================================\n"
09830       "===\n");
09831 
09832    while ((cat = ast_category_browse(cfg, cat))) {
09833       struct ast_variable *var = NULL;
09834       ast_cli(fd,
09835          "=== Mailbox ...\n"
09836          "===\n");
09837       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
09838          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
09839       ast_cli(fd,
09840          "===\n"
09841          "=== ---------------------------------------------------------\n"
09842          "===\n");
09843    }
09844 
09845    ast_cli(fd,
09846       "=============================================================\n"
09847       "\n");
09848 
09849    ast_config_destroy(cfg);
09850 
09851    return CLI_SUCCESS;
09852 }

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

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

10187 {
10188    poll_thread_run = 0;
10189 
10190    if (mwi_sub_sub) {
10191       ast_event_unsubscribe(mwi_sub_sub);
10192       mwi_sub_sub = NULL;
10193    }
10194 
10195    if (mwi_unsub_sub) {
10196       ast_event_unsubscribe(mwi_unsub_sub);
10197       mwi_unsub_sub = NULL;
10198    }
10199 
10200    ast_mutex_lock(&poll_lock);
10201    ast_cond_signal(&poll_cond);
10202    ast_mutex_unlock(&poll_lock);
10203 
10204    pthread_join(poll_thread, NULL);
10205 
10206    poll_thread = AST_PTHREADT_NULL;
10207 }

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

Referenced by make_email_file().

00731 {
00732    char *bufptr = buf;
00733    for (; *input; input++) {
00734       if (*input < 32) {
00735          continue;
00736       }
00737       *bufptr++ = *input;
00738       if (bufptr == buf + buflen - 1) {
00739          break;
00740       }
00741    }
00742    *bufptr = '\0';
00743    return buf;
00744 }

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

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

10333 {
10334    char *current, *result;
10335 
10336    /* Add 16 for fudge factor */
10337    struct ast_str *str = ast_str_create(strlen(value) + 16);
10338 
10339    /* Substitute strings \r, \n, and \t into the appropriate characters */
10340    for (current = (char *) value; *current; current++) {
10341       if (*current == '\\') {
10342          current++;
10343          if (!*current) {
10344             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
10345             break;
10346          }
10347          switch (*current) {
10348          case 'r':
10349             ast_str_append(&str, 0, "\r");
10350             break;
10351          case 'n':
10352 #ifdef IMAP_STORAGE
10353             if (!str->used || str->str[str->used - 1] != '\r') {
10354                ast_str_append(&str, 0, "\r");
10355             }
10356 #endif
10357             ast_str_append(&str, 0, "\n");
10358             break;
10359          case 't':
10360             ast_str_append(&str, 0, "\t");
10361             break;
10362          default:
10363             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
10364             break;
10365          }
10366       } else {
10367          ast_str_append(&str, 0, "%c", *current);
10368       }
10369    }
10370 
10371    result = ast_strdup(str->str);
10372    ast_free(str);
10373 
10374    return result;
10375 }

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

08770 {
08771    int useadsi=0, valid=0, logretries=0;
08772    char password[AST_MAX_EXTENSION]="", *passptr;
08773    struct ast_vm_user vmus, *vmu = NULL;
08774 
08775    /* If ADSI is supported, setup login screen */
08776    adsi_begin(chan, &useadsi);
08777    if (!skipuser && useadsi)
08778       adsi_login(chan);
08779    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
08780       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
08781       return -1;
08782    }
08783    
08784    /* Authenticate them and get their mailbox/password */
08785    
08786    while (!valid && (logretries < max_logins)) {
08787       /* Prompt for, and read in the username */
08788       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
08789          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
08790          return -1;
08791       }
08792       if (ast_strlen_zero(mailbox)) {
08793          if (chan->cid.cid_num) {
08794             ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
08795          } else {
08796             ast_verb(3,"Username not entered\n");  
08797             return -1;
08798          }
08799       }
08800       if (useadsi)
08801          adsi_password(chan);
08802 
08803       if (!ast_strlen_zero(prefix)) {
08804          char fullusername[80] = "";
08805          ast_copy_string(fullusername, prefix, sizeof(fullusername));
08806          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
08807          ast_copy_string(mailbox, fullusername, mailbox_size);
08808       }
08809 
08810       ast_debug(1, "Before find user for mailbox %s\n",mailbox);
08811       vmu = find_user(&vmus, context, mailbox);
08812       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
08813          /* saved password is blank, so don't bother asking */
08814          password[0] = '\0';
08815       } else {
08816          if (ast_streamfile(chan, vm_password, chan->language)) {
08817             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
08818             return -1;
08819          }
08820          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
08821             ast_log(AST_LOG_WARNING, "Unable to read password\n");
08822             return -1;
08823          }
08824       }
08825 
08826       if (vmu) {
08827          passptr = vmu->password;
08828          if (passptr[0] == '-') passptr++;
08829       }
08830       if (vmu && !strcmp(passptr, password))
08831          valid++;
08832       else {
08833          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
08834          if (!ast_strlen_zero(prefix))
08835             mailbox[0] = '\0';
08836       }
08837       logretries++;
08838       if (!valid) {
08839          if (skipuser || logretries >= max_logins) {
08840             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
08841                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
08842                return -1;
08843             }
08844          } else {
08845             if (useadsi)
08846                adsi_login(chan);
08847             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
08848                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
08849                return -1;
08850             }
08851          }
08852          if (ast_waitstream(chan, "")) /* Channel is hung up */
08853             return -1;
08854       }
08855    }
08856    if (!valid && (logretries >= max_logins)) {
08857       ast_stopstream(chan);
08858       ast_play_and_wait(chan, "vm-goodbye");
08859       return -1;
08860    }
08861    if (vmu && !skipuser) {
08862       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
08863    }
08864    return 0;
08865 }

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

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

09711 {
09712    struct ast_vm_user svm;
09713    char *context, *box;
09714    AST_DECLARE_APP_ARGS(args,
09715       AST_APP_ARG(mbox);
09716       AST_APP_ARG(options);
09717    );
09718    static int dep_warning = 0;
09719 
09720    if (ast_strlen_zero(data)) {
09721       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
09722       return -1;
09723    }
09724 
09725    if (!dep_warning) {
09726       dep_warning = 1;
09727       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
09728    }
09729 
09730    box = ast_strdupa(data);
09731 
09732    AST_STANDARD_APP_ARGS(args, box);
09733 
09734    if (args.options) {
09735    }
09736 
09737    if ((context = strchr(args.mbox, '@'))) {
09738       *context = '\0';
09739       context++;
09740    }
09741 
09742    if (find_user(&svm, context, args.mbox)) {
09743       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
09744    } else
09745       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
09746 
09747    return 0;
09748 }

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

08749 {
08750    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
08751       return vm_browse_messages_es(chan, vms, vmu);
08752    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
08753       return vm_browse_messages_gr(chan, vms, vmu);
08754    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
08755       return vm_browse_messages_he(chan, vms, vmu);
08756    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
08757       return vm_browse_messages_it(chan, vms, vmu);
08758    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
08759       return vm_browse_messages_pt(chan, vms, vmu);
08760    } else if (!strncasecmp(chan->language, "zh", 2)) {
08761       return vm_browse_messages_zh(chan, vms, vmu);   /* CHINESE (Taiwan) */
08762    } else {                                             /* Default to English syntax */
08763       return vm_browse_messages_en(chan, vms, vmu);
08764    }
08765 }

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

08612 {
08613    int cmd=0;
08614 
08615    if (vms->lastmsg > -1) {
08616       cmd = play_message(chan, vmu, vms);
08617    } else {
08618       cmd = ast_play_and_wait(chan, "vm-youhave");
08619       if (!cmd) 
08620          cmd = ast_play_and_wait(chan, "vm-no");
08621       if (!cmd) {
08622          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08623          cmd = ast_play_and_wait(chan, vms->fn);
08624       }
08625       if (!cmd)
08626          cmd = ast_play_and_wait(chan, "vm-messages");
08627    }
08628    return cmd;
08629 }

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

08666 {
08667    int cmd=0;
08668 
08669    if (vms->lastmsg > -1) {
08670       cmd = play_message(chan, vmu, vms);
08671    } else {
08672       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08673       if (!cmd)
08674          cmd = ast_play_and_wait(chan, "vm-messages");
08675       if (!cmd) {
08676          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08677          cmd = ast_play_and_wait(chan, vms->fn);
08678       }
08679    }
08680    return cmd;
08681 }

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

08560 {
08561    int cmd=0;
08562 
08563    if (vms->lastmsg > -1) {
08564       cmd = play_message(chan, vmu, vms);
08565    } else {
08566       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08567       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
08568          if (!cmd) {
08569             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
08570             cmd = ast_play_and_wait(chan, vms->fn);
08571          }
08572          if (!cmd)
08573             cmd = ast_play_and_wait(chan, "vm-messages");
08574       } else {
08575          if (!cmd)
08576             cmd = ast_play_and_wait(chan, "vm-messages");
08577          if (!cmd) {
08578             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08579             cmd = ast_play_and_wait(chan, vms->fn);
08580          }
08581       }
08582    } 
08583    return cmd;
08584 }

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

Definition at line 8587 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08588 {
08589    int cmd = 0;
08590 
08591    if (vms->lastmsg > -1) {
08592       cmd = play_message(chan, vmu, vms);
08593    } else {
08594       if (!strcasecmp(vms->fn, "INBOX")) {
08595          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
08596       } else {
08597          cmd = ast_play_and_wait(chan, "vm-nomessages");
08598       }
08599    }
08600    return cmd;
08601 }

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

08640 {
08641    int cmd=0;
08642 
08643    if (vms->lastmsg > -1) {
08644       cmd = play_message(chan, vmu, vms);
08645    } else {
08646       cmd = ast_play_and_wait(chan, "vm-no");
08647       if (!cmd)
08648          cmd = ast_play_and_wait(chan, "vm-message");
08649       if (!cmd) {
08650          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08651          cmd = ast_play_and_wait(chan, vms->fn);
08652       }
08653    }
08654    return cmd;
08655 }

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

08692 {
08693    int cmd=0;
08694 
08695    if (vms->lastmsg > -1) {
08696       cmd = play_message(chan, vmu, vms);
08697    } else {
08698       cmd = ast_play_and_wait(chan, "vm-no");
08699       if (!cmd) {
08700          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08701          cmd = ast_play_and_wait(chan, vms->fn);
08702       }
08703       if (!cmd)
08704          cmd = ast_play_and_wait(chan, "vm-messages");
08705    }
08706    return cmd;
08707 }

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

08718 {
08719    int cmd=0;
08720 
08721    if (vms->lastmsg > -1) {
08722       cmd = play_message(chan, vmu, vms);
08723    } else {
08724       cmd = ast_play_and_wait(chan, "vm-you");
08725       if (!cmd) 
08726          cmd = ast_play_and_wait(chan, "vm-haveno");
08727       if (!cmd)
08728          cmd = ast_play_and_wait(chan, "vm-messages");
08729       if (!cmd) {
08730          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08731          cmd = ast_play_and_wait(chan, vms->fn);
08732       }
08733    }
08734    return cmd;
08735 }

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

01193 {
01194    struct ast_config   *cfg=NULL;
01195    struct ast_variable *var=NULL;
01196    struct ast_category *cat=NULL;
01197    char *category=NULL, *value=NULL, *new=NULL;
01198    const char *tmp=NULL;
01199    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01200    if (!change_password_realtime(vmu, newpassword))
01201       return;
01202 
01203    /* check voicemail.conf */
01204    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags))) {
01205       while ((category = ast_category_browse(cfg, category))) {
01206          if (!strcasecmp(category, vmu->context)) {
01207             if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01208                ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01209                break;
01210             }
01211             value = strstr(tmp,",");
01212             if (!value) {
01213                ast_log(AST_LOG_WARNING, "variable has bad format.\n");
01214                break;
01215             }
01216             new = alloca((strlen(value)+strlen(newpassword)+1));
01217             sprintf(new,"%s%s", newpassword, value);
01218             if (!(cat = ast_category_get(cfg, category))) {
01219                ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01220                break;
01221             }
01222             ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01223          }
01224       }
01225       /* save the results */
01226       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01227       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01228       config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01229    }
01230    category = NULL;
01231    var = NULL;
01232    /* check users.conf and update the password stored for the mailbox*/
01233    /* if no vmsecret entry exists create one. */
01234    if ((cfg = ast_config_load("users.conf", config_flags))) {
01235       ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01236       while ((category = ast_category_browse(cfg, category))) {
01237          ast_debug(4, "users.conf: %s\n", category);
01238          if (!strcasecmp(category, vmu->mailbox)) {
01239             if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01240                ast_debug(3, "looks like we need to make vmsecret!\n");
01241                var = ast_variable_new("vmsecret", newpassword, "");
01242             } 
01243             new = alloca(strlen(newpassword)+1);
01244             sprintf(new, "%s", newpassword);
01245             if (!(cat = ast_category_get(cfg, category))) {
01246                ast_debug(4, "failed to get category!\n");
01247                break;
01248             }
01249             if (!var)      
01250                ast_variable_update(cat, "vmsecret", new, NULL, 0);
01251             else
01252                ast_variable_append(cat, var);
01253          }
01254       }
01255       /* save the results and clean things up */
01256       reset_user_pw(vmu->context, vmu->mailbox, newpassword);  
01257       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01258       config_text_file_save("users.conf", cfg, "AppVoicemail");
01259    }
01260 }

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

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

01263 {
01264    char buf[255];
01265    snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
01266    if (!ast_safe_system(buf)) {
01267       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01268       /* Reset the password in memory, too */
01269       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01270    }
01271 }

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

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

00887 {
00888    int fds[2], pid = 0;
00889 
00890    memset(buf, 0, len);
00891 
00892    if (pipe(fds)) {
00893       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
00894    } else {
00895       /* good to go*/
00896       pid = ast_safe_fork(0);
00897 
00898       if (pid < 0) {
00899          /* ok maybe not */
00900          close(fds[0]);
00901          close(fds[1]);
00902          snprintf(buf, len, "FAILURE: Fork failed");
00903       } else if (pid) {
00904          /* parent */
00905          close(fds[1]);
00906          if (read(fds[0], buf, len) < 0) {
00907             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
00908          }
00909          close(fds[0]);
00910       } else {
00911          /*  child */
00912          AST_DECLARE_APP_ARGS(arg,
00913             AST_APP_ARG(v)[20];
00914          );
00915          char *mycmd = ast_strdupa(command);
00916 
00917          close(fds[0]);
00918          dup2(fds[1], STDOUT_FILENO);
00919          close(fds[1]);
00920          ast_close_fds_above_n(STDOUT_FILENO);
00921 
00922          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
00923 
00924          execv(arg.v[0], arg.v); 
00925          printf("FAILURE: %s", strerror(errno));
00926          _exit(0);
00927       }
00928    }
00929    return buf;
00930 }

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

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

Referenced by copy_message(), and notify_new_message().

03650 {
03651    char *txt;
03652    int txtsize = 0;
03653 
03654    txtsize = (strlen(file) + 5)*sizeof(char);
03655    txt = alloca(txtsize);
03656    /* Sprintf here would safe because we alloca'd exactly the right length,
03657     * but trying to eliminate all sprintf's anyhow
03658     */
03659    if (ast_check_realtime("voicemail_data")) {
03660       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
03661    }
03662    snprintf(txt, txtsize, "%s.txt", file);
03663    unlink(txt);
03664    return ast_filedelete(file, NULL);
03665 }

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

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

09579 {
09580    int res = 0;
09581    char *tmp;
09582    struct leave_vm_options leave_options;
09583    struct ast_flags flags = { 0 };
09584    char *opts[OPT_ARG_ARRAY_SIZE];
09585    AST_DECLARE_APP_ARGS(args,
09586       AST_APP_ARG(argv0);
09587       AST_APP_ARG(argv1);
09588    );
09589    
09590    memset(&leave_options, 0, sizeof(leave_options));
09591 
09592    if (chan->_state != AST_STATE_UP)
09593       ast_answer(chan);
09594 
09595    if (!ast_strlen_zero(data)) {
09596       tmp = ast_strdupa(data);
09597       AST_STANDARD_APP_ARGS(args, tmp);
09598       if (args.argc == 2) {
09599          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09600             return -1;
09601          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
09602          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09603             int gain;
09604 
09605             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09606                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09607                return -1;
09608             } else {
09609                leave_options.record_gain = (signed char) gain;
09610             }
09611          }
09612          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
09613             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
09614                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
09615          }
09616       }
09617    } else {
09618       char temp[256];
09619       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
09620       if (res < 0)
09621          return res;
09622       if (ast_strlen_zero(temp))
09623          return 0;
09624       args.argv0 = ast_strdupa(temp);
09625    }
09626 
09627    res = leave_voicemail(chan, args.argv0, &leave_options);
09628 
09629    if (res == ERROR_LOCK_PATH) {
09630       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
09631       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
09632       res = 0;
09633    }
09634 
09635    return res;
09636 }

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

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

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

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

References ast_category_get(), ast_channel_setoption(), ast_config_destroy(), ast_config_load, ast_filecopy(), ast_filedelete(), 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(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

Referenced by forward_message().

06103 {
06104 #ifdef IMAP_STORAGE
06105    int res;
06106 #endif
06107    int cmd = 0;
06108    int retries = 0, prepend_duration = 0, already_recorded = 0;
06109    char msgfile[PATH_MAX], backup[PATH_MAX];
06110    char textfile[PATH_MAX];
06111    struct ast_config *msg_cfg;
06112    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06113 #ifndef IMAP_STORAGE
06114    signed char zero_gain = 0;
06115 #endif
06116    const char *duration_str;
06117 
06118    /* Must always populate duration correctly */
06119    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06120    strcpy(textfile, msgfile);
06121    strcpy(backup, msgfile);
06122    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06123    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06124 
06125    if ((msg_cfg = ast_config_load(textfile, config_flags)) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06126       *duration = atoi(duration_str);
06127    } else {
06128       *duration = 0;
06129    }
06130 
06131    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06132       if (cmd)
06133          retries = 0;
06134       switch (cmd) {
06135       case '1': 
06136 
06137 #ifdef IMAP_STORAGE
06138          /* Record new intro file */
06139          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06140          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06141          res = ast_play_and_wait(chan, INTRO);
06142          res = ast_play_and_wait(chan, "beep");
06143          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *)duration, NULL, record_gain, vms, flag);
06144          cmd = 't';
06145 #else
06146 
06147          /* prepend a message to the current message, update the metadata and return */
06148 
06149          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06150          strcpy(textfile, msgfile);
06151          strncat(textfile, ".txt", sizeof(textfile) - 1);
06152          *duration = 0;
06153 
06154          /* if we can't read the message metadata, stop now */
06155          if (!msg_cfg) {
06156             cmd = 0;
06157             break;
06158          }
06159          
06160          /* Back up the original file, so we can retry the prepend */
06161          if (already_recorded)
06162             ast_filecopy(backup, msgfile, NULL);
06163          else
06164             ast_filecopy(msgfile, backup, NULL);
06165          already_recorded = 1;
06166 
06167          if (record_gain)
06168             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06169 
06170          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06171          if (record_gain)
06172             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06173 
06174          
06175          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06176             *duration = atoi(duration_str);
06177 
06178          if (prepend_duration) {
06179             struct ast_category *msg_cat;
06180             /* need enough space for a maximum-length message duration */
06181             char duration_buf[12];
06182 
06183             *duration += prepend_duration;
06184             msg_cat = ast_category_get(msg_cfg, "message");
06185             snprintf(duration_buf, 11, "%ld", *duration);
06186             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06187                config_text_file_save(textfile, msg_cfg, "app_voicemail");
06188             }
06189          }
06190 
06191 #endif
06192          break;
06193       case '2': 
06194          /* NULL out introfile so we know there is no intro! */
06195 #ifdef IMAP_STORAGE
06196          *vms->introfn = '\0';
06197 #endif
06198          cmd = 't';
06199          break;
06200       case '*':
06201          cmd = '*';
06202          break;
06203       default: 
06204          cmd = ast_play_and_wait(chan,"vm-forwardoptions");
06205             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06206          if (!cmd)
06207             cmd = ast_play_and_wait(chan,"vm-starmain");
06208             /* "press star to return to the main menu" */
06209          if (!cmd)
06210             cmd = ast_waitfordigit(chan,6000);
06211          if (!cmd)
06212             retries++;
06213          if (retries > 3)
06214             cmd = 't';
06215       }
06216    }
06217 
06218    if (msg_cfg)
06219       ast_config_destroy(msg_cfg);
06220    if (already_recorded)
06221       ast_filedelete(backup, NULL);
06222    if (prepend_duration)
06223       *duration = prepend_duration;
06224 
06225    if (cmd == 't' || cmd == 'S')
06226       cmd = 0;
06227    return cmd;
06228 }

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

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

Referenced by vm_execmain().

08252 {
08253    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08254       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08255    } else {             /* Default to ENGLISH */
08256       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08257    }
08258 }

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

08151 {
08152    int res = 0;
08153    /* Play instructions and wait for new command */
08154    while (!res) {
08155       if (vms->starting) {
08156          if (vms->lastmsg > -1) {
08157             if (skipadvanced)
08158                res = ast_play_and_wait(chan, "vm-onefor-full");
08159             else
08160                res = ast_play_and_wait(chan, "vm-onefor");
08161             if (!res)
08162                res = vm_play_folder_name(chan, vms->vmbox);
08163          }
08164          if (!res) {
08165             if (skipadvanced)
08166                res = ast_play_and_wait(chan, "vm-opts-full");
08167             else
08168                res = ast_play_and_wait(chan, "vm-opts");
08169          }
08170       } else {
08171          /* Added for additional help */
08172          if (skipadvanced) {
08173             res = ast_play_and_wait(chan, "vm-onefor-full");
08174             if (!res)
08175                res = vm_play_folder_name(chan, vms->vmbox);
08176             res = ast_play_and_wait(chan, "vm-opts-full");
08177          }
08178          /* Logic:
08179           * If the current message is not the first OR
08180           * if we're listening to the first new message and there are
08181           * also urgent messages, then prompt for navigation to the
08182           * previous message
08183           */
08184          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08185             res = ast_play_and_wait(chan, "vm-prev");
08186          }
08187          if (!res && !skipadvanced)
08188             res = ast_play_and_wait(chan, "vm-advopts");
08189          if (!res)
08190             res = ast_play_and_wait(chan, "vm-repeat");
08191          /* Logic:
08192           * If we're not listening to the last message OR
08193           * we're listening to the last urgent message and there are
08194           * also new non-urgent messages, then prompt for navigation
08195           * to the next message
08196           */
08197          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08198             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08199             res = ast_play_and_wait(chan, "vm-next");
08200          }
08201          if (!res) {
08202             if (!vms->deleted[vms->curmsg])
08203                res = ast_play_and_wait(chan, "vm-delete");
08204             else
08205                res = ast_play_and_wait(chan, "vm-undelete");
08206             if (!res)
08207                res = ast_play_and_wait(chan, "vm-toforward");
08208             if (!res)
08209                res = ast_play_and_wait(chan, "vm-savemessage");
08210          }
08211       }
08212       if (!res) {
08213          res = ast_play_and_wait(chan, "vm-helpexit");
08214       }
08215       if (!res)
08216          res = ast_waitfordigit(chan, 6000);
08217       if (!res) {
08218          vms->repeats++;
08219          if (vms->repeats > 2) {
08220             res = 't';
08221          }
08222       }
08223    }
08224    return res;
08225 }

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

08228 {
08229    int res = 0;
08230    /* Play instructions and wait for new command */
08231    while (!res) {
08232       if (vms->lastmsg > -1) {
08233          res = ast_play_and_wait(chan, "vm-listen");
08234          if (!res)
08235             res = vm_play_folder_name(chan, vms->vmbox);
08236          if (!res)
08237             res = ast_play_and_wait(chan, "press");
08238          if (!res)
08239             res = ast_play_and_wait(chan, "digits/1");
08240       }
08241       if (!res)
08242          res = ast_play_and_wait(chan, "vm-opts");
08243       if (!res) {
08244          vms->starting = 0;
08245          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08246       }
08247    }
08248    return res;
08249 }

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

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

08092 {
08093    char prefile[256];
08094    
08095    /* Notify the user that the temp greeting is set and give them the option to remove it */
08096    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08097    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08098       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08099       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08100          ast_play_and_wait(chan, "vm-tempgreetactive");
08101       }
08102       DISPOSE(prefile, -1);
08103    }
08104 
08105    /* Play voicemail intro - syntax is different for different languages */
08106    if (0) {
08107    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08108       return vm_intro_cs(chan, vms);
08109    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08110       static int deprecation_warning = 0;
08111       if (deprecation_warning++ % 10 == 0) {
08112          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08113       }
08114       return vm_intro_cs(chan, vms);
08115    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08116       return vm_intro_de(chan, vms);
08117    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08118       return vm_intro_es(chan, vms);
08119    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08120       return vm_intro_fr(chan, vms);
08121    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08122       return vm_intro_gr(chan, vms);
08123    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08124       return vm_intro_he(chan, vms);
08125    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08126       return vm_intro_it(chan, vms);
08127    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08128       return vm_intro_nl(chan, vms);
08129    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08130       return vm_intro_no(chan, vms);
08131    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08132       return vm_intro_pl(chan, vms);
08133    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08134       return vm_intro_pt_BR(chan, vms);
08135    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08136       return vm_intro_pt(chan, vms);
08137    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08138       return vm_intro_multilang(chan, vms, "n");
08139    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08140       return vm_intro_se(chan, vms);
08141    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08142       return vm_intro_multilang(chan, vms, "n");
08143    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08144       return vm_intro_zh(chan, vms);
08145    } else {                                             /* Default to ENGLISH */
08146       return vm_intro_en(chan, vms);
08147    }
08148 }

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

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

07993 {
07994    int res;
07995    res = ast_play_and_wait(chan, "vm-youhave");
07996    if (!res) {
07997       if (vms->newmessages) {
07998          if (vms->newmessages == 1) {
07999             res = ast_play_and_wait(chan, "digits/jednu");
08000          } else {
08001             res = say_and_wait(chan, vms->newmessages, chan->language);
08002          }
08003          if (!res) {
08004             if ((vms->newmessages == 1))
08005                res = ast_play_and_wait(chan, "vm-novou");
08006             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08007                res = ast_play_and_wait(chan, "vm-nove");
08008             if (vms->newmessages > 4)
08009                res = ast_play_and_wait(chan, "vm-novych");
08010          }
08011          if (vms->oldmessages && !res)
08012             res = ast_play_and_wait(chan, "vm-and");
08013          else if (!res) {
08014             if ((vms->newmessages == 1))
08015                res = ast_play_and_wait(chan, "vm-zpravu");
08016             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08017                res = ast_play_and_wait(chan, "vm-zpravy");
08018             if (vms->newmessages > 4)
08019                res = ast_play_and_wait(chan, "vm-zprav");
08020          }
08021       }
08022       if (!res && vms->oldmessages) {
08023          res = say_and_wait(chan, vms->oldmessages, chan->language);
08024          if (!res) {
08025             if ((vms->oldmessages == 1))
08026                res = ast_play_and_wait(chan, "vm-starou");
08027             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08028                res = ast_play_and_wait(chan, "vm-stare");
08029             if (vms->oldmessages > 4)
08030                res = ast_play_and_wait(chan, "vm-starych");
08031          }
08032          if (!res) {
08033             if ((vms->oldmessages == 1))
08034                res = ast_play_and_wait(chan, "vm-zpravu");
08035             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08036                res = ast_play_and_wait(chan, "vm-zpravy");
08037             if (vms->oldmessages > 4)
08038                res = ast_play_and_wait(chan, "vm-zprav");
08039          }
08040       }
08041       if (!res) {
08042          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08043             res = ast_play_and_wait(chan, "vm-no");
08044             if (!res)
08045                res = ast_play_and_wait(chan, "vm-zpravy");
08046          }
08047       }
08048    }
08049    return res;
08050 }

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

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

07689 {
07690    /* Introduce messages they have */
07691    int res;
07692    res = ast_play_and_wait(chan, "vm-youhave");
07693    if (!res) {
07694       if (vms->newmessages) {
07695          if ((vms->newmessages == 1))
07696             res = ast_play_and_wait(chan, "digits/1F");
07697          else
07698             res = say_and_wait(chan, vms->newmessages, chan->language);
07699          if (!res)
07700             res = ast_play_and_wait(chan, "vm-INBOX");
07701          if (vms->oldmessages && !res)
07702             res = ast_play_and_wait(chan, "vm-and");
07703          else if (!res) {
07704             if ((vms->newmessages == 1))
07705                res = ast_play_and_wait(chan, "vm-message");
07706             else
07707                res = ast_play_and_wait(chan, "vm-messages");
07708          }
07709             
07710       }
07711       if (!res && vms->oldmessages) {
07712          if (vms->oldmessages == 1)
07713             res = ast_play_and_wait(chan, "digits/1F");
07714          else
07715             res = say_and_wait(chan, vms->oldmessages, chan->language);
07716          if (!res)
07717             res = ast_play_and_wait(chan, "vm-Old");
07718          if (!res) {
07719             if (vms->oldmessages == 1)
07720                res = ast_play_and_wait(chan, "vm-message");
07721             else
07722                res = ast_play_and_wait(chan, "vm-messages");
07723          }
07724       }
07725       if (!res) {
07726          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07727             res = ast_play_and_wait(chan, "vm-no");
07728             if (!res)
07729                res = ast_play_and_wait(chan, "vm-messages");
07730          }
07731       }
07732    }
07733    return res;
07734 }

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

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

07438 {
07439    int res;
07440 
07441    /* Introduce messages they have */
07442    res = ast_play_and_wait(chan, "vm-youhave");
07443    if (!res) {
07444       if (vms->urgentmessages) {
07445          res = say_and_wait(chan, vms->urgentmessages, chan->language);
07446          if (!res)
07447             res = ast_play_and_wait(chan, "vm-Urgent");
07448          if ((vms->oldmessages || vms->newmessages) && !res) {
07449             res = ast_play_and_wait(chan, "vm-and");
07450          } else if (!res) {
07451             if ((vms->urgentmessages == 1))
07452                res = ast_play_and_wait(chan, "vm-message");
07453             else
07454                res = ast_play_and_wait(chan, "vm-messages");
07455          }
07456       }
07457       if (vms->newmessages) {
07458          res = say_and_wait(chan, vms->newmessages, chan->language);
07459          if (!res)
07460             res = ast_play_and_wait(chan, "vm-INBOX");
07461          if (vms->oldmessages && !res)
07462             res = ast_play_and_wait(chan, "vm-and");
07463          else if (!res) {
07464             if ((vms->newmessages == 1))
07465                res = ast_play_and_wait(chan, "vm-message");
07466             else
07467                res = ast_play_and_wait(chan, "vm-messages");
07468          }
07469             
07470       }
07471       if (!res && vms->oldmessages) {
07472          res = say_and_wait(chan, vms->oldmessages, chan->language);
07473          if (!res)
07474             res = ast_play_and_wait(chan, "vm-Old");
07475          if (!res) {
07476             if (vms->oldmessages == 1)
07477                res = ast_play_and_wait(chan, "vm-message");
07478             else
07479                res = ast_play_and_wait(chan, "vm-messages");
07480          }
07481       }
07482       if (!res) {
07483          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
07484             res = ast_play_and_wait(chan, "vm-no");
07485             if (!res)
07486                res = ast_play_and_wait(chan, "vm-messages");
07487          }
07488       }
07489    }
07490    return res;
07491 }

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

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

07738 {
07739    /* Introduce messages they have */
07740    int res;
07741    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07742       res = ast_play_and_wait(chan, "vm-youhaveno");
07743       if (!res)
07744          res = ast_play_and_wait(chan, "vm-messages");
07745    } else {
07746       res = ast_play_and_wait(chan, "vm-youhave");
07747    }
07748    if (!res) {
07749       if (vms->newmessages) {
07750          if (!res) {
07751             if ((vms->newmessages == 1)) {
07752                res = ast_play_and_wait(chan, "digits/1M");
07753                if (!res)
07754                   res = ast_play_and_wait(chan, "vm-message");
07755                if (!res)
07756                   res = ast_play_and_wait(chan, "vm-INBOXs");
07757             } else {
07758                res = say_and_wait(chan, vms->newmessages, chan->language);
07759                if (!res)
07760                   res = ast_play_and_wait(chan, "vm-messages");
07761                if (!res)
07762                   res = ast_play_and_wait(chan, "vm-INBOX");
07763             }
07764          }
07765          if (vms->oldmessages && !res)
07766             res = ast_play_and_wait(chan, "vm-and");
07767       }
07768       if (vms->oldmessages) {
07769          if (!res) {
07770             if (vms->oldmessages == 1) {
07771                res = ast_play_and_wait(chan, "digits/1M");
07772                if (!res)
07773                   res = ast_play_and_wait(chan, "vm-message");
07774                if (!res)
07775                   res = ast_play_and_wait(chan, "vm-Olds");
07776             } else {
07777                res = say_and_wait(chan, vms->oldmessages, chan->language);
07778                if (!res)
07779                   res = ast_play_and_wait(chan, "vm-messages");
07780                if (!res)
07781                   res = ast_play_and_wait(chan, "vm-Old");
07782             }
07783          }
07784       }
07785    }
07786 return res;
07787 }

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

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

07836 {
07837    /* Introduce messages they have */
07838    int res;
07839    res = ast_play_and_wait(chan, "vm-youhave");
07840    if (!res) {
07841       if (vms->newmessages) {
07842          res = say_and_wait(chan, vms->newmessages, chan->language);
07843          if (!res)
07844             res = ast_play_and_wait(chan, "vm-INBOX");
07845          if (vms->oldmessages && !res)
07846             res = ast_play_and_wait(chan, "vm-and");
07847          else if (!res) {
07848             if ((vms->newmessages == 1))
07849                res = ast_play_and_wait(chan, "vm-message");
07850             else
07851                res = ast_play_and_wait(chan, "vm-messages");
07852          }
07853             
07854       }
07855       if (!res && vms->oldmessages) {
07856          res = say_and_wait(chan, vms->oldmessages, chan->language);
07857          if (!res)
07858             res = ast_play_and_wait(chan, "vm-Old");
07859          if (!res) {
07860             if (vms->oldmessages == 1)
07861                res = ast_play_and_wait(chan, "vm-message");
07862             else
07863                res = ast_play_and_wait(chan, "vm-messages");
07864          }
07865       }
07866       if (!res) {
07867          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07868             res = ast_play_and_wait(chan, "vm-no");
07869             if (!res)
07870                res = ast_play_and_wait(chan, "vm-messages");
07871          }
07872       }
07873    }
07874    return res;
07875 }

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

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

07237 {
07238    int res = 0;
07239 
07240    if (vms->newmessages) {
07241       res = ast_play_and_wait(chan, "vm-youhave");
07242       if (!res) 
07243          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07244       if (!res) {
07245          if ((vms->newmessages == 1)) {
07246             res = ast_play_and_wait(chan, "vm-INBOX");
07247             if (!res)
07248                res = ast_play_and_wait(chan, "vm-message");
07249          } else {
07250             res = ast_play_and_wait(chan, "vm-INBOXs");
07251             if (!res)
07252                res = ast_play_and_wait(chan, "vm-messages");
07253          }
07254       }
07255    } else if (vms->oldmessages){
07256       res = ast_play_and_wait(chan, "vm-youhave");
07257       if (!res)
07258          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07259       if ((vms->oldmessages == 1)){
07260          res = ast_play_and_wait(chan, "vm-Old");
07261          if (!res)
07262             res = ast_play_and_wait(chan, "vm-message");
07263       } else {
07264          res = ast_play_and_wait(chan, "vm-Olds");
07265          if (!res)
07266             res = ast_play_and_wait(chan, "vm-messages");
07267       }
07268    } else if (!vms->oldmessages && !vms->newmessages) 
07269       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07270    return res;
07271 }

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

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

07371 {
07372    int res = 0;
07373 
07374    /* Introduce messages they have */
07375    if (!res) {
07376       if ((vms->newmessages) || (vms->oldmessages)) {
07377          res = ast_play_and_wait(chan, "vm-youhave");
07378       }
07379       /*
07380        * The word "shtei" refers to the number 2 in hebrew when performing a count
07381        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
07382        * an element, this is one of them.
07383        */
07384       if (vms->newmessages) {
07385          if (!res) {
07386             if (vms->newmessages == 1) {
07387                res = ast_play_and_wait(chan, "vm-INBOX1");
07388             } else {
07389                if (vms->newmessages == 2) {
07390                   res = ast_play_and_wait(chan, "vm-shtei");
07391                } else {
07392                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07393                }
07394                res = ast_play_and_wait(chan, "vm-INBOX");
07395             }
07396          }
07397          if (vms->oldmessages && !res) {
07398             res = ast_play_and_wait(chan, "vm-and");
07399             if (vms->oldmessages == 1) {
07400                res = ast_play_and_wait(chan, "vm-Old1");
07401             } else {
07402                if (vms->oldmessages == 2) {
07403                   res = ast_play_and_wait(chan, "vm-shtei");
07404                } else {
07405                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07406                }
07407                res = ast_play_and_wait(chan, "vm-Old");
07408             }
07409          }
07410       }
07411       if (!res && vms->oldmessages && !vms->newmessages) {
07412          if (!res) {
07413             if (vms->oldmessages == 1) {
07414                res = ast_play_and_wait(chan, "vm-Old1");
07415             } else {
07416                if (vms->oldmessages == 2) {
07417                   res = ast_play_and_wait(chan, "vm-shtei");
07418                } else {
07419                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
07420                }
07421                res = ast_play_and_wait(chan, "vm-Old");
07422             }
07423          }
07424       }
07425       if (!res) {
07426          if (!vms->oldmessages && !vms->newmessages) {
07427             if (!res) {
07428                res = ast_play_and_wait(chan, "vm-nomessages");
07429             }
07430          }
07431       }
07432    }
07433    return res;
07434 }

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

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

07495 {
07496    /* Introduce messages they have */
07497    int res;
07498    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
07499       res = ast_play_and_wait(chan, "vm-no") ||
07500          ast_play_and_wait(chan, "vm-message");
07501    else
07502       res = ast_play_and_wait(chan, "vm-youhave");
07503    if (!res && vms->newmessages) {
07504       res = (vms->newmessages == 1) ?
07505          ast_play_and_wait(chan, "digits/un") ||
07506          ast_play_and_wait(chan, "vm-nuovo") ||
07507          ast_play_and_wait(chan, "vm-message") :
07508          /* 2 or more new messages */
07509          say_and_wait(chan, vms->newmessages, chan->language) ||
07510          ast_play_and_wait(chan, "vm-nuovi") ||
07511          ast_play_and_wait(chan, "vm-messages");
07512       if (!res && vms->oldmessages)
07513          res = ast_play_and_wait(chan, "vm-and");
07514    }
07515    if (!res && vms->oldmessages) {
07516       res = (vms->oldmessages == 1) ?
07517          ast_play_and_wait(chan, "digits/un") ||
07518          ast_play_and_wait(chan, "vm-vecchio") ||
07519          ast_play_and_wait(chan, "vm-message") :
07520          /* 2 or more old messages */
07521          say_and_wait(chan, vms->oldmessages, chan->language) ||
07522          ast_play_and_wait(chan, "vm-vecchi") ||
07523          ast_play_and_wait(chan, "vm-messages");
07524    }
07525    return res;
07526 }

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

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

07331 {
07332    int res;
07333    int lastnum = 0;
07334 
07335    res = ast_play_and_wait(chan, "vm-youhave");
07336 
07337    if (!res && vms->newmessages) {
07338       lastnum = vms->newmessages;
07339 
07340       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07341          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
07342       }
07343 
07344       if (!res && vms->oldmessages) {
07345          res = ast_play_and_wait(chan, "vm-and");
07346       }
07347    }
07348 
07349    if (!res && vms->oldmessages) {
07350       lastnum = vms->oldmessages;
07351 
07352       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07353          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
07354       }
07355    }
07356 
07357    if (!res) {
07358       if (lastnum == 0) {
07359          res = ast_play_and_wait(chan, "vm-no");
07360       }
07361       if (!res) {
07362          res = ast_say_counted_noun(chan, lastnum, "vm-message");
07363       }
07364    }
07365 
07366    return res;
07367 }

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

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

07879 {
07880    /* Introduce messages they have */
07881    int res;
07882    res = ast_play_and_wait(chan, "vm-youhave");
07883    if (!res) {
07884       if (vms->newmessages) {
07885          res = say_and_wait(chan, vms->newmessages, chan->language);
07886          if (!res) {
07887             if (vms->newmessages == 1)
07888                res = ast_play_and_wait(chan, "vm-INBOXs");
07889             else
07890                res = ast_play_and_wait(chan, "vm-INBOX");
07891          }
07892          if (vms->oldmessages && !res)
07893             res = ast_play_and_wait(chan, "vm-and");
07894          else if (!res) {
07895             if ((vms->newmessages == 1))
07896                res = ast_play_and_wait(chan, "vm-message");
07897             else
07898                res = ast_play_and_wait(chan, "vm-messages");
07899          }
07900             
07901       }
07902       if (!res && vms->oldmessages) {
07903          res = say_and_wait(chan, vms->oldmessages, chan->language);
07904          if (!res) {
07905             if (vms->oldmessages == 1)
07906                res = ast_play_and_wait(chan, "vm-Olds");
07907             else
07908                res = ast_play_and_wait(chan, "vm-Old");
07909          }
07910          if (!res) {
07911             if (vms->oldmessages == 1)
07912                res = ast_play_and_wait(chan, "vm-message");
07913             else
07914                res = ast_play_and_wait(chan, "vm-messages");
07915          }
07916       }
07917       if (!res) {
07918          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07919             res = ast_play_and_wait(chan, "vm-no");
07920             if (!res)
07921                res = ast_play_and_wait(chan, "vm-messages");
07922          }
07923       }
07924    }
07925    return res;
07926 }

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

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

07645 {
07646    /* Introduce messages they have */
07647    int res;
07648 
07649    res = ast_play_and_wait(chan, "vm-youhave");
07650    if (res)
07651       return res;
07652 
07653    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07654       res = ast_play_and_wait(chan, "vm-no");
07655       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07656       return res;
07657    }
07658 
07659    if (vms->newmessages) {
07660       if ((vms->newmessages == 1)) {
07661          res = ast_play_and_wait(chan, "digits/1");
07662          res = res ? res : ast_play_and_wait(chan, "vm-ny");
07663          res = res ? res : ast_play_and_wait(chan, "vm-message");
07664       } else {
07665          res = say_and_wait(chan, vms->newmessages, chan->language);
07666          res = res ? res : ast_play_and_wait(chan, "vm-nye");
07667          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07668       }
07669       if (!res && vms->oldmessages)
07670          res = ast_play_and_wait(chan, "vm-and");
07671    }
07672    if (!res && vms->oldmessages) {
07673       if (vms->oldmessages == 1) {
07674          res = ast_play_and_wait(chan, "digits/1");
07675          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
07676          res = res ? res : ast_play_and_wait(chan, "vm-message");
07677       } else {
07678          res = say_and_wait(chan, vms->oldmessages, chan->language);
07679          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
07680          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07681       }
07682    }
07683 
07684    return res;
07685 }

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

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

07530 {
07531    /* Introduce messages they have */
07532    int res;
07533    div_t num;
07534 
07535    if (!vms->oldmessages && !vms->newmessages) {
07536       res = ast_play_and_wait(chan, "vm-no");
07537       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07538       return res;
07539    } else {
07540       res = ast_play_and_wait(chan, "vm-youhave");
07541    }
07542 
07543    if (vms->newmessages) {
07544       num = div(vms->newmessages, 10);
07545       if (vms->newmessages == 1) {
07546          res = ast_play_and_wait(chan, "digits/1-a");
07547          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
07548          res = res ? res : ast_play_and_wait(chan, "vm-message");
07549       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07550          if (num.rem == 2) {
07551             if (!num.quot) {
07552                res = ast_play_and_wait(chan, "digits/2-ie");
07553             } else {
07554                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
07555                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07556             }
07557          } else {
07558             res = say_and_wait(chan, vms->newmessages, chan->language);
07559          }
07560          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
07561          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07562       } else {
07563          res = say_and_wait(chan, vms->newmessages, chan->language);
07564          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
07565          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07566       }
07567       if (!res && vms->oldmessages)
07568          res = ast_play_and_wait(chan, "vm-and");
07569    }
07570    if (!res && vms->oldmessages) {
07571       num = div(vms->oldmessages, 10);
07572       if (vms->oldmessages == 1) {
07573          res = ast_play_and_wait(chan, "digits/1-a");
07574          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
07575          res = res ? res : ast_play_and_wait(chan, "vm-message");
07576       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07577          if (num.rem == 2) {
07578             if (!num.quot) {
07579                res = ast_play_and_wait(chan, "digits/2-ie");
07580             } else {
07581                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
07582                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07583             }
07584          } else {
07585             res = say_and_wait(chan, vms->oldmessages, chan->language);
07586          }
07587          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
07588          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07589       } else {
07590          res = say_and_wait(chan, vms->oldmessages, chan->language);
07591          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
07592          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07593       }
07594    }
07595 
07596    return res;
07597 }

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

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

07930 {
07931    /* Introduce messages they have */
07932    int res;
07933    res = ast_play_and_wait(chan, "vm-youhave");
07934    if (!res) {
07935       if (vms->newmessages) {
07936          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07937          if (!res) {
07938             if ((vms->newmessages == 1)) {
07939                res = ast_play_and_wait(chan, "vm-message");
07940                if (!res)
07941                   res = ast_play_and_wait(chan, "vm-INBOXs");
07942             } else {
07943                res = ast_play_and_wait(chan, "vm-messages");
07944                if (!res)
07945                   res = ast_play_and_wait(chan, "vm-INBOX");
07946             }
07947          }
07948          if (vms->oldmessages && !res)
07949             res = ast_play_and_wait(chan, "vm-and");
07950       }
07951       if (!res && vms->oldmessages) {
07952          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07953          if (!res) {
07954             if (vms->oldmessages == 1) {
07955                res = ast_play_and_wait(chan, "vm-message");
07956                if (!res)
07957                   res = ast_play_and_wait(chan, "vm-Olds");
07958             } else {
07959                res = ast_play_and_wait(chan, "vm-messages");
07960                if (!res)
07961                   res = ast_play_and_wait(chan, "vm-Old");
07962             }
07963          }
07964       }
07965       if (!res) {
07966          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07967             res = ast_play_and_wait(chan, "vm-no");
07968             if (!res)
07969                res = ast_play_and_wait(chan, "vm-messages");
07970          }
07971       }
07972    }
07973    return res;
07974 }

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

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

07790                                                                          {
07791    /* Introduce messages they have */
07792    int res;
07793    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07794       res = ast_play_and_wait(chan, "vm-nomessages");
07795       return res;
07796    } else {
07797       res = ast_play_and_wait(chan, "vm-youhave");
07798    }
07799    if (vms->newmessages) {
07800       if (!res)
07801          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07802       if ((vms->newmessages == 1)) {
07803          if (!res)
07804             res = ast_play_and_wait(chan, "vm-message");
07805          if (!res)
07806             res = ast_play_and_wait(chan, "vm-INBOXs");
07807       } else {
07808          if (!res)
07809             res = ast_play_and_wait(chan, "vm-messages");
07810          if (!res)
07811             res = ast_play_and_wait(chan, "vm-INBOX");
07812       }
07813       if (vms->oldmessages && !res)
07814          res = ast_play_and_wait(chan, "vm-and");
07815    }
07816    if (vms->oldmessages) {
07817       if (!res)
07818          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07819       if (vms->oldmessages == 1) {
07820          if (!res)
07821             res = ast_play_and_wait(chan, "vm-message");
07822          if (!res)
07823             res = ast_play_and_wait(chan, "vm-Olds");
07824       } else {
07825          if (!res)
07826             res = ast_play_and_wait(chan, "vm-messages");
07827          if (!res)
07828             res = ast_play_and_wait(chan, "vm-Old");
07829       }
07830    }
07831    return res;
07832 }

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

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

07601 {
07602    /* Introduce messages they have */
07603    int res;
07604 
07605    res = ast_play_and_wait(chan, "vm-youhave");
07606    if (res)
07607       return res;
07608 
07609    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07610       res = ast_play_and_wait(chan, "vm-no");
07611       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07612       return res;
07613    }
07614 
07615    if (vms->newmessages) {
07616       if ((vms->newmessages == 1)) {
07617          res = ast_play_and_wait(chan, "digits/ett");
07618          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
07619          res = res ? res : ast_play_and_wait(chan, "vm-message");
07620       } else {
07621          res = say_and_wait(chan, vms->newmessages, chan->language);
07622          res = res ? res : ast_play_and_wait(chan, "vm-nya");
07623          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07624       }
07625       if (!res && vms->oldmessages)
07626          res = ast_play_and_wait(chan, "vm-and");
07627    }
07628    if (!res && vms->oldmessages) {
07629       if (vms->oldmessages == 1) {
07630          res = ast_play_and_wait(chan, "digits/ett");
07631          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
07632          res = res ? res : ast_play_and_wait(chan, "vm-message");
07633       } else {
07634          res = say_and_wait(chan, vms->oldmessages, chan->language);
07635          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
07636          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07637       }
07638    }
07639 
07640    return res;
07641 }

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

Definition at line 8053 of file app_voicemail.c.

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

Referenced by vm_intro().

08054 {
08055    int res;
08056    /* Introduce messages they have */
08057    res = ast_play_and_wait(chan, "vm-you");
08058 
08059    if (!res && vms->newmessages) {
08060       res = ast_play_and_wait(chan, "vm-have");
08061       if (!res)
08062          res = say_and_wait(chan, vms->newmessages, chan->language);
08063       if (!res)
08064          res = ast_play_and_wait(chan, "vm-tong");
08065       if (!res)
08066          res = ast_play_and_wait(chan, "vm-INBOX");
08067       if (vms->oldmessages && !res)
08068          res = ast_play_and_wait(chan, "vm-and");
08069       else if (!res) 
08070          res = ast_play_and_wait(chan, "vm-messages");
08071    }
08072    if (!res && vms->oldmessages) {
08073       res = ast_play_and_wait(chan, "vm-have");
08074       if (!res)
08075          res = say_and_wait(chan, vms->oldmessages, chan->language);
08076       if (!res)
08077          res = ast_play_and_wait(chan, "vm-tong");
08078       if (!res)
08079          res = ast_play_and_wait(chan, "vm-Old");
08080       if (!res)
08081          res = ast_play_and_wait(chan, "vm-messages");
08082    }
08083    if (!res && !vms->oldmessages && !vms->newmessages) {
08084       res = ast_play_and_wait(chan, "vm-haveno");
08085       if (!res)
08086          res = ast_play_and_wait(chan, "vm-messages");
08087    }
08088    return res;
08089 }

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

02784 {
02785    switch (ast_lock_path(path)) {
02786    case AST_LOCK_TIMEOUT:
02787       return -1;
02788    default:
02789       return 0;
02790    }
02791 }

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

Definition at line 1304 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01305 {
01306    FILE *p = NULL;
01307    int pfd = mkstemp(template);
01308    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01309    if (pfd > -1) {
01310       p = fdopen(pfd, "w+");
01311       if (!p) {
01312          close(pfd);
01313          pfd = -1;
01314       }
01315    }
01316    return p;
01317 }

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

08262 {
08263    int cmd = 0;
08264    int duration = 0;
08265    int tries = 0;
08266    char newpassword[80] = "";
08267    char newpassword2[80] = "";
08268    char prefile[PATH_MAX] = "";
08269    unsigned char buf[256];
08270    int bytes=0;
08271 
08272    if (ast_adsi_available(chan)) {
08273       bytes += adsi_logo(buf + bytes);
08274       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08275       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08276       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08277       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08278       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08279    }
08280 
08281    /* First, have the user change their password 
08282       so they won't get here again */
08283    for (;;) {
08284       newpassword[1] = '\0';
08285       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08286       if (cmd == '#')
08287          newpassword[0] = '\0';
08288       if (cmd < 0 || cmd == 't' || cmd == '#')
08289          return cmd;
08290       cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
08291       if (cmd < 0 || cmd == 't' || cmd == '#')
08292          return cmd;
08293       cmd = check_password(vmu, newpassword); /* perform password validation */
08294       if (cmd != 0) {
08295          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08296          cmd = ast_play_and_wait(chan, vm_invalid_password);
08297       } else {
08298          newpassword2[1] = '\0';
08299          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08300          if (cmd == '#')
08301             newpassword2[0] = '\0';
08302          if (cmd < 0 || cmd == 't' || cmd == '#')
08303             return cmd;
08304          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
08305          if (cmd < 0 || cmd == 't' || cmd == '#')
08306             return cmd;
08307          if (!strcmp(newpassword, newpassword2))
08308             break;
08309          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08310          cmd = ast_play_and_wait(chan, vm_mismatch);
08311       }
08312       if (++tries == 3)
08313          return -1;
08314       if (cmd != 0) {
08315          cmd = ast_play_and_wait(chan, vm_pls_try_again);
08316       }
08317    }
08318    if (pwdchange & PWDCHANGE_INTERNAL)
08319       vm_change_password(vmu, newpassword);
08320    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08321       vm_change_password_shell(vmu, newpassword);
08322 
08323    ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08324    cmd = ast_play_and_wait(chan, vm_passchanged);
08325 
08326    /* If forcename is set, have the user record their name */  
08327    if (ast_test_flag(vmu, VM_FORCENAME)) {
08328       snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08329       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08330          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08331          if (cmd < 0 || cmd == 't' || cmd == '#')
08332             return cmd;
08333       }
08334    }
08335 
08336    /* If forcegreetings is set, have the user record their greetings */
08337    if (ast_test_flag(vmu, VM_FORCEGREET)) {
08338       snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08339       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08340          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08341          if (cmd < 0 || cmd == 't' || cmd == '#')
08342             return cmd;
08343       }
08344 
08345       snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08346       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08347          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08348          if (cmd < 0 || cmd == 't' || cmd == '#')
08349             return cmd;
08350       }
08351    }
08352 
08353    return cmd;
08354 }

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

08357 {
08358    int cmd = 0;
08359    int retries = 0;
08360    int duration = 0;
08361    char newpassword[80] = "";
08362    char newpassword2[80] = "";
08363    char prefile[PATH_MAX] = "";
08364    unsigned char buf[256];
08365    int bytes=0;
08366 
08367    if (ast_adsi_available(chan)) {
08368       bytes += adsi_logo(buf + bytes);
08369       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
08370       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08371       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08372       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08373       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08374    }
08375    while ((cmd >= 0) && (cmd != 't')) {
08376       if (cmd)
08377          retries = 0;
08378       switch (cmd) {
08379       case '1': /* Record your unavailable message */
08380          snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08381          cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08382          break;
08383       case '2':  /* Record your busy message */
08384          snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08385          cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08386          break;
08387       case '3': /* Record greeting */
08388          snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08389          cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08390          break;
08391       case '4':  /* manage the temporary greeting */
08392          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
08393          break;
08394       case '5': /* change password */
08395          if (vmu->password[0] == '-') {
08396             cmd = ast_play_and_wait(chan, "vm-no");
08397             break;
08398          }
08399          newpassword[1] = '\0';
08400          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08401          if (cmd == '#')
08402             newpassword[0] = '\0';
08403          else {
08404             if (cmd < 0)
08405                break;
08406             if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
08407                break;
08408             }
08409          }
08410          cmd = check_password(vmu, newpassword); /* perform password validation */
08411          if (cmd != 0) {
08412             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08413             cmd = ast_play_and_wait(chan, vm_invalid_password);
08414             if (!cmd) {
08415                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08416             }
08417             break;
08418          }
08419          newpassword2[1] = '\0';
08420          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08421          if (cmd == '#')
08422             newpassword2[0] = '\0';
08423          else {
08424             if (cmd < 0)
08425                break;
08426 
08427             if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#")) < 0) {
08428                break;
08429             }
08430          }
08431          if (strcmp(newpassword, newpassword2)) {
08432             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08433             cmd = ast_play_and_wait(chan, vm_mismatch);
08434             if (!cmd) {
08435                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08436             }
08437             break;
08438          }
08439          if (pwdchange & PWDCHANGE_INTERNAL)
08440             vm_change_password(vmu, newpassword);
08441          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08442             vm_change_password_shell(vmu, newpassword);
08443 
08444          ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08445          cmd = ast_play_and_wait(chan, vm_passchanged);
08446          break;
08447       case '*': 
08448          cmd = 't';
08449          break;
08450       default: 
08451          cmd = 0;
08452          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08453          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08454          if (ast_fileexists(prefile, NULL, NULL)) {
08455             cmd = ast_play_and_wait(chan, "vm-tmpexists");
08456          }
08457          DISPOSE(prefile, -1);
08458          if (!cmd) {
08459             cmd = ast_play_and_wait(chan, "vm-options");
08460          }
08461          if (!cmd) {
08462             cmd = ast_waitfordigit(chan,6000);
08463          }
08464          if (!cmd) {
08465             retries++;
08466          }
08467          if (retries > 3) {
08468             cmd = 't';
08469          }
08470       }
08471    }
08472    if (cmd == 't')
08473       cmd = 0;
08474    return cmd;
08475 }

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

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

07202 {
07203    int cmd;
07204 
07205    if (  !strncasecmp(chan->language, "it", 2) ||
07206         !strncasecmp(chan->language, "es", 2) ||
07207         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07208       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07209       return cmd ? cmd : ast_play_and_wait(chan, box);
07210    } else if (!strncasecmp(chan->language, "gr", 2)) {
07211       return vm_play_folder_name_gr(chan, box);
07212    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07213       return ast_play_and_wait(chan, box);
07214    } else if (!strncasecmp(chan->language, "pl", 2)) {
07215       return vm_play_folder_name_pl(chan, box);
07216    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07217       return vm_play_folder_name_ua(chan, box);
07218    } else {  /* Default English */
07219       cmd = ast_play_and_wait(chan, box);
07220       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07221    }
07222 }

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

Definition at line 7154 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07155 {
07156    int cmd;
07157    char *buf;
07158 
07159    buf = alloca(strlen(box)+2); 
07160    strcpy(buf, box);
07161    strcat(buf,"s");
07162 
07163    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07164       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07165       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07166    } else {
07167       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07168       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07169    }
07170 }

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

Definition at line 7172 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07173 {
07174    int cmd;
07175 
07176    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07177       if (!strcasecmp(box, "vm-INBOX"))
07178          cmd = ast_play_and_wait(chan, "vm-new-e");
07179       else
07180          cmd = ast_play_and_wait(chan, "vm-old-e");
07181       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07182    } else {
07183       cmd = ast_play_and_wait(chan, "vm-messages");
07184       return cmd ? cmd : ast_play_and_wait(chan, box);
07185    }
07186 }

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

Definition at line 7188 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07189 {
07190    int cmd;
07191 
07192    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07193       cmd = ast_play_and_wait(chan, "vm-messages");
07194       return cmd ? cmd : ast_play_and_wait(chan, box);
07195    } else {
07196       cmd = ast_play_and_wait(chan, box);
07197       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07198    }
07199 }

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

08494 {
08495    int cmd = 0;
08496    int retries = 0;
08497    int duration = 0;
08498    char prefile[PATH_MAX] = "";
08499    unsigned char buf[256];
08500    int bytes = 0;
08501 
08502    if (ast_adsi_available(chan)) {
08503       bytes += adsi_logo(buf + bytes);
08504       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
08505       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08506       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08507       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08508       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08509    }
08510 
08511    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08512    while ((cmd >= 0) && (cmd != 't')) {
08513       if (cmd)
08514          retries = 0;
08515       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08516       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
08517          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08518          cmd = 't';  
08519       } else {
08520          switch (cmd) {
08521          case '1':
08522             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08523             break;
08524          case '2':
08525             DELETE(prefile, -1, prefile, vmu);
08526             ast_play_and_wait(chan, "vm-tempremoved");
08527             cmd = 't';  
08528             break;
08529          case '*': 
08530             cmd = 't';
08531             break;
08532          default:
08533             cmd = ast_play_and_wait(chan,
08534                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
08535                   "vm-tempgreeting2" : "vm-tempgreeting");
08536             if (!cmd)
08537                cmd = ast_waitfordigit(chan,6000);
08538             if (!cmd)
08539                retries++;
08540             if (retries > 3)
08541                cmd = 't';
08542          }
08543       }
08544       DISPOSE(prefile, -1);
08545    }
08546    if (cmd == 't')
08547       cmd = 0;
08548    return cmd;
08549 }

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

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

09780 {
09781    char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
09782    struct ast_vm_user vmus;
09783    char *options = NULL;
09784    int silent = 0, skipuser = 0;
09785    int res = -1;
09786    
09787    if (s) {
09788       s = ast_strdupa(s);
09789       user = strsep(&s, ",");
09790       options = strsep(&s, ",");
09791       if (user) {
09792          s = user;
09793          user = strsep(&s, "@");
09794          context = strsep(&s, "");
09795          if (!ast_strlen_zero(user))
09796             skipuser++;
09797          ast_copy_string(mailbox, user, sizeof(mailbox));
09798       }
09799    }
09800 
09801    if (options) {
09802       silent = (strchr(options, 's')) != NULL;
09803    }
09804 
09805    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
09806       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
09807       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
09808       ast_play_and_wait(chan, "auth-thankyou");
09809       res = 0;
09810    }
09811 
09812    return res;
09813 }

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

03876 {
03877    const struct vm_zone *z = NULL;
03878    struct timeval t = ast_tvnow();
03879 
03880    /* Does this user have a timezone specified? */
03881    if (!ast_strlen_zero(vmu->zonetag)) {
03882       /* Find the zone in the list */
03883       AST_LIST_LOCK(&zones);
03884       AST_LIST_TRAVERSE(&zones, z, list) {
03885          if (!strcmp(z->name, vmu->zonetag))
03886             break;
03887       }
03888       AST_LIST_UNLOCK(&zones);
03889    }
03890    ast_localtime(&t, tm, z ? z->timezone : NULL);
03891    return tm;
03892 }

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

06606 {
06607    int res;
06608    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
06609       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
06610    return res;
06611 }


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

char* addesc = "Comedian Mail" [static]

Definition at line 507 of file app_voicemail.c.

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

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

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 702 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 592 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 595 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 597 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 598 of file app_voicemail.c.

Definition at line 11595 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 686 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

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

Definition at line 698 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 689 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 10011 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char* descrip_vm [static]

Definition at line 511 of file app_voicemail.c.

char* descrip_vm_box_exists [static]

Definition at line 569 of file app_voicemail.c.

char* descrip_vmain [static]

Definition at line 540 of file app_voicemail.c.

char* descrip_vmauthenticate [static]

Definition at line 581 of file app_voicemail.c.

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

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

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

char* emailsubject = NULL [static]

Definition at line 693 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

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

char ext_pass_cmd[128] [static]

Definition at line 486 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 609 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 696 of file app_voicemail.c.

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

struct ast_flags globalflags = {0} [static]
char listen_control_forward_key[12] [static]

Definition at line 666 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 668 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 669 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 667 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 670 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

Definition at line 9769 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char mailcmd[160] [static]

Definition at line 608 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 605 of file app_voicemail.c.

int maxgreet [static]

Definition at line 615 of file app_voicemail.c.

int maxlogins [static]

Definition at line 617 of file app_voicemail.c.

int maxmsg [static]

Definition at line 604 of file app_voicemail.c.

int maxsilence [static]

Definition at line 603 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 618 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 635 of file app_voicemail.c.

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

int my_umask [static]

Definition at line 489 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 694 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 697 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 695 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 630 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 625 of file app_voicemail.c.

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

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 631 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 632 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 493 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 683 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char serveremail[80] [static]

Definition at line 607 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 606 of file app_voicemail.c.

int skipms [static]

Definition at line 616 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 610 of file app_voicemail.c.

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

Definition at line 509 of file app_voicemail.c.

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

Definition at line 566 of file app_voicemail.c.

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

Definition at line 538 of file app_voicemail.c.

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

Definition at line 579 of file app_voicemail.c.

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

Definition at line 505 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 282 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 678 of file app_voicemail.c.

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

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

Definition at line 677 of file app_voicemail.c.

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

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

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

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

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

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

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

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

Definition at line 676 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 484 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 611 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 614 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 613 of file app_voicemail.c.

double volgain [static]

Definition at line 612 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 602 of file app_voicemail.c.

Referenced by build_peer().


Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1