Fri Nov 12 11:52:33 2010

Asterisk developer's documentation


app_voicemail.c File Reference

Comedian Mail - Voicemail System. More...

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

enum  {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER
}
enum  {
  OPT_SILENT = (1 << 0), OPT_BUSY_GREETING = (1 << 1), OPT_UNAVAIL_GREETING = (1 << 2), OPT_RECORDGAIN = (1 << 3),
  OPT_PREPEND_MAILBOX = (1 << 4), OPT_AUTOPLAY = (1 << 6), OPT_DTMFEXIT = (1 << 7), OPT_MESSAGE_Urgent = (1 << 8),
  OPT_MESSAGE_PRIORITY = (1 << 9)
}
enum  { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .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 dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_check_cmd [128]
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
struct ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static struct ast_custom_function mailbox_exists_acf
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerfromstring [100]
static char * pagersubject = NULL
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char 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 383 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 406 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 407 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 380 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 376 of file app_voicemail.c.

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

Definition at line 673 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 388 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 390 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 391 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 389 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 392 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

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

Referenced by base_encode(), and ochar().

#define ERROR_LOCK_PATH   -100

Definition at line 432 of file app_voicemail.c.

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

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

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

#define MAX_DATETIME_FORMAT   512

Definition at line 410 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 411 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 401 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

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

Referenced by load_config().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 686 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 685 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 672 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 397 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

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

#define VALID_DTMF   "1234567890*#"

Definition at line 393 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 426 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 424 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 425 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 423 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 417 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 421 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 420 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 431 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 430 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 429 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 414 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 422 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 413 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 415 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 418 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 427 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 419 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 416 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 428 of file app_voicemail.c.

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

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 612 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 382 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 378 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

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

00435      {
00436    NEW_FOLDER,
00437    OLD_FOLDER,
00438    WORK_FOLDER,
00439    FAMILY_FOLDER,
00440    FRIENDS_FOLDER,
00441    GREETINGS_FOLDER
00442 } 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 444 of file app_voicemail.c.

00444      {
00445    OPT_SILENT =           (1 << 0),
00446    OPT_BUSY_GREETING =    (1 << 1),
00447    OPT_UNAVAIL_GREETING = (1 << 2),
00448    OPT_RECORDGAIN =       (1 << 3),
00449    OPT_PREPEND_MAILBOX =  (1 << 4),
00450    OPT_AUTOPLAY =         (1 << 6),
00451    OPT_DTMFEXIT =         (1 << 7),
00452    OPT_MESSAGE_Urgent =   (1 << 8),
00453    OPT_MESSAGE_PRIORITY = (1 << 9)
00454 } vm_option_flags;

anonymous enum
Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 456 of file app_voicemail.c.

00456      {
00457    OPT_ARG_RECORDGAIN = 0,
00458    OPT_ARG_PLAYFOLDER = 1,
00459    OPT_ARG_DTMFEXIT   = 2,
00460    /* This *must* be the last value in this enum! */
00461    OPT_ARG_ARRAY_SIZE = 3,
00462 } vm_option_args;


Function Documentation

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

Definition at line 4940 of file app_voicemail.c.

References ast_strlen_zero().

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

04941 {
04942    DIR *dir;
04943    struct dirent *de;
04944    char fn[256];
04945    int ret = 0;
04946 
04947    /* If no mailbox, return immediately */
04948    if (ast_strlen_zero(mailbox))
04949       return 0;
04950 
04951    if (ast_strlen_zero(folder))
04952       folder = "INBOX";
04953    if (ast_strlen_zero(context))
04954       context = "default";
04955 
04956    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
04957 
04958    if (!(dir = opendir(fn)))
04959       return 0;
04960 
04961    while ((de = readdir(dir))) {
04962       if (!strncasecmp(de->d_name, "msg", 3)) {
04963          if (shortcircuit) {
04964             ret = 1;
04965             break;
04966          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
04967             ret++;
04968          }
04969       }
04970    }
04971 
04972    closedir(dir);
04973 
04974    return ret;
04975 }

static void __reg_module ( void   )  [static]

Definition at line 11840 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

09983 {
09984    struct ast_vm_user svm;
09985    AST_DECLARE_APP_ARGS(arg,
09986       AST_APP_ARG(mbox);
09987       AST_APP_ARG(context);
09988    );
09989 
09990    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
09991 
09992    if (ast_strlen_zero(arg.mbox)) {
09993       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
09994       return -1;
09995    }
09996 
09997    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
09998    return 0;
09999 }

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

04433 {
04434    char tmpdir[256], newtmp[256];
04435    char fname[256];
04436    char tmpcmd[256];
04437    int tmpfd = -1;
04438 
04439    /* Eww. We want formats to tell us their own MIME type */
04440    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04441 
04442    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04443       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04444       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04445       tmpfd = mkstemp(newtmp);
04446       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04447       ast_debug(3, "newtmp: %s\n", newtmp);
04448       if (tmpfd > -1) {
04449          int soxstatus;
04450          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04451          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04452             attach = newtmp;
04453             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04454          } else {
04455             ast_log(LOG_WARNING, "Sox failed to reencode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04456                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04457             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04458          }
04459       }
04460    }
04461    fprintf(p, "--%s" ENDL, bound);
04462    if (msgnum > -1)
04463       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04464    else
04465       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04466    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04467    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04468    if (msgnum > -1)
04469       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04470    else
04471       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04472    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04473    base_encode(fname, p);
04474    if (last)
04475       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04476    if (tmpfd > -1) {
04477       unlink(fname);
04478       close(tmpfd);
04479       unlink(newtmp);
04480    }
04481    return 0;
04482 }

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

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

05882 {
05883    int x;
05884    if (!ast_adsi_available(chan))
05885       return;
05886    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
05887    if (x < 0)
05888       return;
05889    if (!x) {
05890       if (adsi_load_vmail(chan, useadsi)) {
05891          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
05892          return;
05893       }
05894    } else
05895       *useadsi = 1;
05896 }

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

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

06071 {
06072    int bytes=0;
06073    unsigned char buf[256];
06074    unsigned char keys[8];
06075 
06076    int x;
06077 
06078    if (!ast_adsi_available(chan))
06079       return;
06080 
06081    /* New meaning for keys */
06082    for (x=0;x<5;x++)
06083       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06084 
06085    keys[6] = 0x0;
06086    keys[7] = 0x0;
06087 
06088    if (!vms->curmsg) {
06089       /* No prev key, provide "Folder" instead */
06090       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06091    }
06092    if (vms->curmsg >= vms->lastmsg) {
06093       /* If last message ... */
06094       if (vms->curmsg) {
06095          /* but not only message, provide "Folder" instead */
06096          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06097       } else {
06098          /* Otherwise if only message, leave blank */
06099          keys[3] = 1;
06100       }
06101    }
06102 
06103    /* If deleted, show "undeleted" */
06104    if (vms->deleted[vms->curmsg]) 
06105       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06106 
06107    /* Except "Exit" */
06108    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06109    bytes += ast_adsi_set_keys(buf + bytes, keys);
06110    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06111 
06112    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06113 }

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

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

05947 {
05948    unsigned char buf[256];
05949    int bytes=0;
05950    unsigned char keys[8];
05951    int x,y;
05952 
05953    if (!ast_adsi_available(chan))
05954       return;
05955 
05956    for (x=0;x<5;x++) {
05957       y = ADSI_KEY_APPS + 12 + start + x;
05958       if (y > ADSI_KEY_APPS + 12 + 4)
05959          y = 0;
05960       keys[x] = ADSI_KEY_SKT | y;
05961    }
05962    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
05963    keys[6] = 0;
05964    keys[7] = 0;
05965 
05966    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
05967    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
05968    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05969    bytes += ast_adsi_set_keys(buf + bytes, keys);
05970    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05971 
05972    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05973 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06219 {
06220    unsigned char buf[256];
06221    int bytes=0;
06222 
06223    if (!ast_adsi_available(chan))
06224       return;
06225    bytes += adsi_logo(buf + bytes);
06226    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06227    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06228    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06229    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06230 
06231    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06232 }

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

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

05753 {
05754    unsigned char buf[256];
05755    int bytes=0;
05756    int x;
05757    char num[5];
05758 
05759    *useadsi = 0;
05760    bytes += ast_adsi_data_mode(buf + bytes);
05761    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05762 
05763    bytes = 0;
05764    bytes += adsi_logo(buf);
05765    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05766 #ifdef DISPLAY
05767    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
05768 #endif
05769    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05770    bytes += ast_adsi_data_mode(buf + bytes);
05771    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05772 
05773    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
05774       bytes = 0;
05775       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
05776       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05777       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05778       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05779       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05780       return 0;
05781    }
05782 
05783 #ifdef DISPLAY
05784    /* Add a dot */
05785    bytes = 0;
05786    bytes += ast_adsi_logo(buf);
05787    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
05788    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
05789    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05790    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05791 #endif
05792    bytes = 0;
05793    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
05794    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
05795    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
05796    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
05797    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
05798    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
05799    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05800 
05801 #ifdef DISPLAY
05802    /* Add another dot */
05803    bytes = 0;
05804    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
05805    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05806 
05807    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05808    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05809 #endif
05810 
05811    bytes = 0;
05812    /* These buttons we load but don't use yet */
05813    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
05814    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
05815    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
05816    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
05817    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
05818    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
05819    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05820 
05821 #ifdef DISPLAY
05822    /* Add another dot */
05823    bytes = 0;
05824    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
05825    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05826    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05827 #endif
05828 
05829    bytes = 0;
05830    for (x=0;x<5;x++) {
05831       snprintf(num, sizeof(num), "%d", x);
05832       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
05833    }
05834    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
05835    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05836 
05837 #ifdef DISPLAY
05838    /* Add another dot */
05839    bytes = 0;
05840    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
05841    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05842    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05843 #endif
05844 
05845    if (ast_adsi_end_download(chan)) {
05846       bytes = 0;
05847       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
05848       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
05849       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05850       bytes += ast_adsi_voice_mode(buf + bytes, 0);
05851       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05852       return 0;
05853    }
05854    bytes = 0;
05855    bytes += ast_adsi_download_disconnect(buf + bytes);
05856    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05857    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
05858 
05859    ast_debug(1, "Done downloading scripts...\n");
05860 
05861 #ifdef DISPLAY
05862    /* Add last dot */
05863    bytes = 0;
05864    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
05865    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05866 #endif
05867    ast_debug(1, "Restarting session...\n");
05868 
05869    bytes = 0;
05870    /* Load the session now */
05871    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
05872       *useadsi = 1;
05873       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
05874    } else
05875       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
05876 
05877    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05878    return 0;
05879 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

05899 {
05900    unsigned char buf[256];
05901    int bytes=0;
05902    unsigned char keys[8];
05903    int x;
05904    if (!ast_adsi_available(chan))
05905       return;
05906 
05907    for (x=0;x<8;x++)
05908       keys[x] = 0;
05909    /* Set one key for next */
05910    keys[3] = ADSI_KEY_APPS + 3;
05911 
05912    bytes += adsi_logo(buf + bytes);
05913    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
05914    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
05915    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05916    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
05917    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
05918    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
05919    bytes += ast_adsi_set_keys(buf + bytes, keys);
05920    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05921    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05922 }

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

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

05745 {
05746    int bytes = 0;
05747    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
05748    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
05749    return bytes;
05750 }

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

Definition at line 5975 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(), buf1, buf2, vm_state::curbox, vm_state::curmsg, vm_state::deleted, vm_state::fn, vm_state::lastmsg, and num.

Referenced by play_message(), and vm_execmain().

05976 {
05977    int bytes=0;
05978    unsigned char buf[256]; 
05979    char buf1[256], buf2[256];
05980    char fn2[PATH_MAX];
05981 
05982    char cid[256]="";
05983    char *val;
05984    char *name, *num;
05985    char datetime[21]="";
05986    FILE *f;
05987 
05988    unsigned char keys[8];
05989 
05990    int x;
05991 
05992    if (!ast_adsi_available(chan))
05993       return;
05994 
05995    /* Retrieve important info */
05996    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
05997    f = fopen(fn2, "r");
05998    if (f) {
05999       while (!feof(f)) {   
06000          if (!fgets((char *)buf, sizeof(buf), f)) {
06001             continue;
06002          }
06003          if (!feof(f)) {
06004             char *stringp=NULL;
06005             stringp = (char *)buf;
06006             strsep(&stringp, "=");
06007             val = strsep(&stringp, "=");
06008             if (!ast_strlen_zero(val)) {
06009                if (!strcmp((char *)buf, "callerid"))
06010                   ast_copy_string(cid, val, sizeof(cid));
06011                if (!strcmp((char *)buf, "origdate"))
06012                   ast_copy_string(datetime, val, sizeof(datetime));
06013             }
06014          }
06015       }
06016       fclose(f);
06017    }
06018    /* New meaning for keys */
06019    for (x=0;x<5;x++)
06020       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06021    keys[6] = 0x0;
06022    keys[7] = 0x0;
06023 
06024    if (!vms->curmsg) {
06025       /* No prev key, provide "Folder" instead */
06026       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06027    }
06028    if (vms->curmsg >= vms->lastmsg) {
06029       /* If last message ... */
06030       if (vms->curmsg) {
06031          /* but not only message, provide "Folder" instead */
06032          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06033          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06034 
06035       } else {
06036          /* Otherwise if only message, leave blank */
06037          keys[3] = 1;
06038       }
06039    }
06040 
06041    if (!ast_strlen_zero(cid)) {
06042       ast_callerid_parse(cid, &name, &num);
06043       if (!name)
06044          name = num;
06045    } else
06046       name = "Unknown Caller";
06047 
06048    /* If deleted, show "undeleted" */
06049 
06050    if (vms->deleted[vms->curmsg])
06051       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06052 
06053    /* Except "Exit" */
06054    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06055    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06056       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06057    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06058 
06059    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06060    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06061    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06062    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06063    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06064    bytes += ast_adsi_set_keys(buf + bytes, keys);
06065    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06066 
06067    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06068 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

05925 {
05926    unsigned char buf[256];
05927    int bytes=0;
05928    unsigned char keys[8];
05929    int x;
05930    if (!ast_adsi_available(chan))
05931       return;
05932 
05933    for (x=0;x<8;x++)
05934       keys[x] = 0;
05935    /* Set one key for next */
05936    keys[3] = ADSI_KEY_APPS + 3;
05937 
05938    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05939    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
05940    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
05941    bytes += ast_adsi_set_keys(buf + bytes, keys);
05942    bytes += ast_adsi_voice_mode(buf + bytes, 0);
05943    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05944 }

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

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

Referenced by vm_execmain().

06116 {
06117    unsigned char buf[256] = "";
06118    char buf1[256] = "", buf2[256] = "";
06119    int bytes=0;
06120    unsigned char keys[8];
06121    int x;
06122 
06123    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06124    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06125    if (!ast_adsi_available(chan))
06126       return;
06127    if (vms->newmessages) {
06128       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06129       if (vms->oldmessages) {
06130          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06131          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06132       } else {
06133          snprintf(buf2, sizeof(buf2), "%s.", newm);
06134       }
06135    } else if (vms->oldmessages) {
06136       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06137       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06138    } else {
06139       strcpy(buf1, "You have no messages.");
06140       buf2[0] = ' ';
06141       buf2[1] = '\0';
06142    }
06143    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06144    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06145    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06146 
06147    for (x=0;x<6;x++)
06148       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06149    keys[6] = 0;
06150    keys[7] = 0;
06151 
06152    /* Don't let them listen if there are none */
06153    if (vms->lastmsg < 0)
06154       keys[0] = 1;
06155    bytes += ast_adsi_set_keys(buf + bytes, keys);
06156 
06157    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06158 
06159    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06160 }

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

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

Referenced by vm_execmain().

06163 {
06164    unsigned char buf[256] = "";
06165    char buf1[256] = "", buf2[256] = "";
06166    int bytes=0;
06167    unsigned char keys[8];
06168    int x;
06169 
06170    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06171 
06172    if (!ast_adsi_available(chan))
06173       return;
06174 
06175    /* Original command keys */
06176    for (x=0;x<6;x++)
06177       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06178 
06179    keys[6] = 0;
06180    keys[7] = 0;
06181 
06182    if ((vms->lastmsg + 1) < 1)
06183       keys[0] = 0;
06184 
06185    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06186       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06187 
06188    if (vms->lastmsg + 1)
06189       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06190    else
06191       strcpy(buf2, "no messages.");
06192    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06193    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06194    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06195    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06196    bytes += ast_adsi_set_keys(buf + bytes, keys);
06197 
06198    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06199 
06200    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06201    
06202 }

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 11416 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_strlen_zero(), ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), num, play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

11417 {
11418    int res = 0;
11419    char filename[PATH_MAX];
11420    struct ast_config *msg_cfg = NULL;
11421    const char *origtime, *context;
11422    char *name, *num;
11423    int retries = 0;
11424    char *cid;
11425    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
11426 
11427    vms->starting = 0; 
11428 
11429    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11430 
11431    /* Retrieve info from VM attribute file */
11432    snprintf(filename,sizeof(filename), "%s.txt", vms->fn);
11433    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
11434    msg_cfg = ast_config_load(filename, config_flags);
11435    DISPOSE(vms->curdir, vms->curmsg);
11436    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
11437       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
11438       return 0;
11439    }
11440 
11441    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
11442       ast_config_destroy(msg_cfg);
11443       return 0;
11444    }
11445 
11446    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
11447 
11448    context = ast_variable_retrieve(msg_cfg, "message", "context");
11449    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
11450       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
11451    switch (option) {
11452    case 3: /* Play message envelope */
11453       if (!res)
11454          res = play_message_datetime(chan, vmu, origtime, filename);
11455       if (!res)
11456          res = play_message_callerid(chan, vms, cid, context, 0);
11457 
11458       res = 't';
11459       break;
11460 
11461    case 2:  /* Call back */
11462 
11463       if (ast_strlen_zero(cid))
11464          break;
11465 
11466       ast_callerid_parse(cid, &name, &num);
11467       while ((res > -1) && (res != 't')) {
11468          switch (res) {
11469          case '1':
11470             if (num) {
11471                /* Dial the CID number */
11472                res = dialout(chan, vmu, num, vmu->callback);
11473                if (res) {
11474                   ast_config_destroy(msg_cfg);
11475                   return 9;
11476                }
11477             } else {
11478                res = '2';
11479             }
11480             break;
11481 
11482          case '2':
11483             /* Want to enter a different number, can only do this if there's a dialout context for this user */
11484             if (!ast_strlen_zero(vmu->dialout)) {
11485                res = dialout(chan, vmu, NULL, vmu->dialout);
11486                if (res) {
11487                   ast_config_destroy(msg_cfg);
11488                   return 9;
11489                }
11490             } else {
11491                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
11492                res = ast_play_and_wait(chan, "vm-sorry");
11493             }
11494             ast_config_destroy(msg_cfg);
11495             return res;
11496          case '*':
11497             res = 't';
11498             break;
11499          case '3':
11500          case '4':
11501          case '5':
11502          case '6':
11503          case '7':
11504          case '8':
11505          case '9':
11506          case '0':
11507 
11508             res = ast_play_and_wait(chan, "vm-sorry");
11509             retries++;
11510             break;
11511          default:
11512             if (num) {
11513                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
11514                res = ast_play_and_wait(chan, "vm-num-i-have");
11515                if (!res)
11516                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
11517                if (!res)
11518                   res = ast_play_and_wait(chan, "vm-tocallnum");
11519                /* Only prompt for a caller-specified number if there is a dialout context specified */
11520                if (!ast_strlen_zero(vmu->dialout)) {
11521                   if (!res)
11522                      res = ast_play_and_wait(chan, "vm-calldiffnum");
11523                }
11524             } else {
11525                res = ast_play_and_wait(chan, "vm-nonumber");
11526                if (!ast_strlen_zero(vmu->dialout)) {
11527                   if (!res)
11528                      res = ast_play_and_wait(chan, "vm-toenternumber");
11529                }
11530             }
11531             if (!res)
11532                res = ast_play_and_wait(chan, "vm-star-cancel");
11533             if (!res)
11534                res = ast_waitfordigit(chan, 6000);
11535             if (!res) {
11536                retries++;
11537                if (retries > 3)
11538                   res = 't';
11539             }
11540             break; 
11541             
11542          }
11543          if (res == 't')
11544             res = 0;
11545          else if (res == '*')
11546             res = -1;
11547       }
11548       break;
11549       
11550    case 1:  /* Reply */
11551       /* Send reply directly to sender */
11552       if (ast_strlen_zero(cid))
11553          break;
11554 
11555       ast_callerid_parse(cid, &name, &num);
11556       if (!num) {
11557          ast_verb(3, "No CID number available, no reply sent\n");
11558          if (!res)
11559             res = ast_play_and_wait(chan, "vm-nonumber");
11560          ast_config_destroy(msg_cfg);
11561          return res;
11562       } else {
11563          struct ast_vm_user vmu2;
11564          if (find_user(&vmu2, vmu->context, num)) {
11565             struct leave_vm_options leave_options;
11566             char mailbox[AST_MAX_EXTENSION * 2 + 2];
11567             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
11568 
11569             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
11570             
11571             memset(&leave_options, 0, sizeof(leave_options));
11572             leave_options.record_gain = record_gain;
11573             res = leave_voicemail(chan, mailbox, &leave_options);
11574             if (!res)
11575                res = 't';
11576             ast_config_destroy(msg_cfg);
11577             return res;
11578          } else {
11579             /* Sender has no mailbox, can't reply */
11580             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
11581             ast_play_and_wait(chan, "vm-nobox");
11582             res = 't';
11583             ast_config_destroy(msg_cfg);
11584             return res;
11585          }
11586       } 
11587       res = 0;
11588 
11589       break;
11590    }
11591 
11592 #ifndef IMAP_STORAGE
11593    ast_config_destroy(msg_cfg);
11594 
11595    if (!res) {
11596       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
11597       vms->heard[msg] = 1;
11598       res = wait_file(chan, vms, vms->fn);
11599    }
11600 #endif
11601    return res;
11602 }

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

Definition at line 9902 of file app_voicemail.c.

References apply_options(), ast_copy_string(), 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(), and s.

Referenced by load_config().

09903 {
09904    /* Assumes lock is already held */
09905    char *tmp;
09906    char *stringp;
09907    char *s;
09908    struct ast_vm_user *vmu;
09909    char *mailbox_full;
09910    int new = 0, old = 0, urgent = 0;
09911 
09912    tmp = ast_strdupa(data);
09913 
09914    if (!(vmu = find_or_create(context, box)))
09915       return -1;
09916    
09917    populate_defaults(vmu);
09918 
09919    stringp = tmp;
09920    if ((s = strsep(&stringp, ","))) 
09921       ast_copy_string(vmu->password, s, sizeof(vmu->password));
09922    if (stringp && (s = strsep(&stringp, ","))) 
09923       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
09924    if (stringp && (s = strsep(&stringp, ","))) 
09925       ast_copy_string(vmu->email, s, sizeof(vmu->email));
09926    if (stringp && (s = strsep(&stringp, ","))) 
09927       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
09928    if (stringp && (s = strsep(&stringp, ","))) 
09929       apply_options(vmu, s);
09930 
09931    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
09932    strcpy(mailbox_full, box);
09933    strcat(mailbox_full, "@");
09934    strcat(mailbox_full, context);
09935 
09936    inboxcount2(mailbox_full, &urgent, &new, &old);
09937    queue_mwi_event(mailbox_full, urgent, new, old);
09938 
09939    return 0;
09940 }

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

00950 {
00951    int x;
00952    if (!strcasecmp(var, "attach")) {
00953       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00954    } else if (!strcasecmp(var, "attachfmt")) {
00955       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00956    } else if (!strcasecmp(var, "serveremail")) {
00957       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00958    } else if (!strcasecmp(var, "language")) {
00959       ast_copy_string(vmu->language, value, sizeof(vmu->language));
00960    } else if (!strcasecmp(var, "tz")) {
00961       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00962 #ifdef IMAP_STORAGE
00963    } else if (!strcasecmp(var, "imapuser")) {
00964       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00965       vmu->imapversion = imapversion;
00966    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
00967       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00968       vmu->imapversion = imapversion;
00969    } else if (!strcasecmp(var, "imapvmshareid")) {
00970       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
00971       vmu->imapversion = imapversion;
00972 #endif
00973    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00974       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
00975    } else if (!strcasecmp(var, "saycid")){
00976       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
00977    } else if (!strcasecmp(var,"sendvoicemail")){
00978       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
00979    } else if (!strcasecmp(var, "review")){
00980       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00981    } else if (!strcasecmp(var, "tempgreetwarn")){
00982       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
00983    } else if (!strcasecmp(var, "messagewrap")){
00984       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
00985    } else if (!strcasecmp(var, "operator")) {
00986       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
00987    } else if (!strcasecmp(var, "envelope")){
00988       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
00989    } else if (!strcasecmp(var, "moveheard")){
00990       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
00991    } else if (!strcasecmp(var, "sayduration")){
00992       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
00993    } else if (!strcasecmp(var, "saydurationm")){
00994       if (sscanf(value, "%30d", &x) == 1) {
00995          vmu->saydurationm = x;
00996       } else {
00997          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
00998       }
00999    } else if (!strcasecmp(var, "forcename")){
01000       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01001    } else if (!strcasecmp(var, "forcegreetings")){
01002       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01003    } else if (!strcasecmp(var, "callback")) {
01004       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01005    } else if (!strcasecmp(var, "dialout")) {
01006       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01007    } else if (!strcasecmp(var, "exitcontext")) {
01008       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01009    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01010       vmu->maxsecs = atoi(value);
01011       if (vmu->maxsecs <= 0) {
01012          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01013          vmu->maxsecs = vmmaxsecs;
01014       } else {
01015          vmu->maxsecs = atoi(value);
01016       }
01017       if (!strcasecmp(var, "maxmessage"))
01018          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01019    } else if (!strcasecmp(var, "maxmsg")) {
01020       vmu->maxmsg = atoi(value);
01021       if (vmu->maxmsg <= 0) {
01022          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01023          vmu->maxmsg = MAXMSG;
01024       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01025          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01026          vmu->maxmsg = MAXMSGLIMIT;
01027       }
01028    } else if (!strcasecmp(var, "backupdeleted")) {
01029       if (sscanf(value, "%30d", &x) == 1)
01030          vmu->maxdeletedmsg = x;
01031       else if (ast_true(value))
01032          vmu->maxdeletedmsg = MAXMSG;
01033       else
01034          vmu->maxdeletedmsg = 0;
01035 
01036       if (vmu->maxdeletedmsg < 0) {
01037          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01038          vmu->maxdeletedmsg = MAXMSG;
01039       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01040          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01041          vmu->maxdeletedmsg = MAXMSGLIMIT;
01042       }
01043    } else if (!strcasecmp(var, "volgain")) {
01044       sscanf(value, "%30lf", &vmu->volgain);
01045    } else if (!strcasecmp(var, "options")) {
01046       apply_options(vmu, value);
01047    }
01048 }

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

Destructively Parse options and apply.

Definition at line 1162 of file app_voicemail.c.

References apply_option(), s, and var.

Referenced by append_mailbox(), and apply_option().

01163 {  
01164    char *stringp;
01165    char *s;
01166    char *var, *value;
01167    stringp = ast_strdupa(options);
01168    while ((s = strsep(&stringp, "|"))) {
01169       value = s;
01170       if ((var = strsep(&value, "=")) && value) {
01171          apply_option(vmu, var, value);
01172       }
01173    }  
01174 }

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

References apply_option(), ast_copy_string(), ast_strdup, ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::fullname, 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().

01182 {
01183    for (; var; var = var->next) {
01184       if (!strcasecmp(var->name, "vmsecret")) {
01185          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01186       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01187          if (ast_strlen_zero(retval->password))
01188             ast_copy_string(retval->password, var->value, sizeof(retval->password));
01189       } else if (!strcasecmp(var->name, "uniqueid")) {
01190          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01191       } else if (!strcasecmp(var->name, "pager")) {
01192          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01193       } else if (!strcasecmp(var->name, "email")) {
01194          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01195       } else if (!strcasecmp(var->name, "fullname")) {
01196          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01197       } else if (!strcasecmp(var->name, "context")) {
01198          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01199       } else if (!strcasecmp(var->name, "emailsubject")) {
01200          retval->emailsubject = ast_strdup(var->value);
01201       } else if (!strcasecmp(var->name, "emailbody")) {
01202          retval->emailbody = ast_strdup(var->value);
01203 #ifdef IMAP_STORAGE
01204       } else if (!strcasecmp(var->name, "imapuser")) {
01205          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01206          retval->imapversion = imapversion;
01207       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01208          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01209          retval->imapversion = imapversion;
01210       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01211          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01212          retval->imapversion = imapversion;
01213 #endif
01214       } else
01215          apply_option(retval, var->name, var->value);
01216    }
01217 }

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

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

Referenced by add_email_attachment().

03919 {
03920    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
03921       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
03922       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
03923       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
03924    int i,hiteof= 0;
03925    FILE *fi;
03926    struct baseio bio;
03927 
03928    memset(&bio, 0, sizeof(bio));
03929    bio.iocp = BASEMAXINLINE;
03930 
03931    if (!(fi = fopen(filename, "rb"))) {
03932       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
03933       return -1;
03934    }
03935 
03936    while (!hiteof){
03937       unsigned char igroup[3], ogroup[4];
03938       int c,n;
03939 
03940       igroup[0]= igroup[1]= igroup[2]= 0;
03941 
03942       for (n= 0;n<3;n++) {
03943          if ((c = inchar(&bio, fi)) == EOF) {
03944             hiteof= 1;
03945             break;
03946          }
03947 
03948          igroup[n]= (unsigned char)c;
03949       }
03950 
03951       if (n> 0) {
03952          ogroup[0]= dtable[igroup[0]>>2];
03953          ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
03954          ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
03955          ogroup[3]= dtable[igroup[2]&0x3F];
03956 
03957          if (n<3) {
03958             ogroup[3]= '=';
03959 
03960             if (n<2)
03961                ogroup[2]= '=';
03962          }
03963 
03964          for (i= 0;i<4;i++)
03965             ochar(&bio, ogroup[i], so);
03966       }
03967    }
03968 
03969    fclose(fi);
03970    
03971    if (fputs(eol,so)==EOF)
03972       return 0;
03973 
03974    return 1;
03975 }

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

References ast_copy_string(), ast_realtime_require_field(), ast_update2_realtime(), ast_vm_user::context, ast_vm_user::mailbox, ast_vm_user::password, RQ_CHAR, and SENTINEL.

Referenced by vm_change_password().

01142 {
01143    int res = -1;
01144    if (!strcmp(vmu->password, password)) {
01145       /* No change (but an update would return 0 rows updated, so we opt out here) */
01146       return 0;
01147    }
01148 
01149    if (strlen(password) > 10) {
01150       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01151    }
01152    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01153       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01154       res = 0;
01155    }
01156    return res;
01157 }

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

Referenced by make_email_file().

04084 {
04085    for (; *str; str++) {
04086       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04087          return 1;
04088       }
04089    }
04090    return 0;
04091 }

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

01104 {
01105    /* check minimum length */
01106    if (strlen(password) < minpassword)
01107       return 1;
01108    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01109       char cmd[255], buf[255];
01110 
01111       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01112 
01113       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01114       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01115          ast_debug(5, "Result: %s\n", buf);
01116          if (!strncasecmp(buf, "VALID", 5)) {
01117             ast_debug(3, "Passed password check: '%s'\n", buf);
01118             return 0;
01119          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01120             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01121             return 0;
01122          } else {
01123             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01124             return 1;
01125          }
01126       }
01127    }
01128    return 0;
01129 }

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

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

07297 {
07298    int x = 0;
07299 #ifndef IMAP_STORAGE
07300    int res = 0, nummsg;
07301    char fn2[PATH_MAX];
07302 #endif
07303 
07304    if (vms->lastmsg <= -1)
07305       goto done;
07306 
07307    vms->curmsg = -1; 
07308 #ifndef IMAP_STORAGE
07309    /* Get the deleted messages fixed */ 
07310    if (vm_lock_path(vms->curdir))
07311       return ERROR_LOCK_PATH;
07312 
07313    for (x = 0; x < vmu->maxmsg; x++) { 
07314       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) { 
07315          /* Save this message.  It's not in INBOX or hasn't been heard */ 
07316          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
07317          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
07318             break;
07319          vms->curmsg++; 
07320          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg); 
07321          if (strcmp(vms->fn, fn2)) { 
07322             RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07323          } 
07324       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { 
07325          /* Move to old folder before deleting */ 
07326          res = save_to_folder(vmu, vms, x, 1);
07327          if (res == ERROR_LOCK_PATH) {
07328             /* If save failed do not delete the message */
07329             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07330             vms->deleted[x] = 0;
07331             vms->heard[x] = 0;
07332             --x;
07333          }
07334       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07335          /* Move to deleted folder */ 
07336          res = save_to_folder(vmu, vms, x, 10);
07337          if (res == ERROR_LOCK_PATH) {
07338             /* If save failed do not delete the message */
07339             vms->deleted[x] = 0;
07340             vms->heard[x] = 0;
07341             --x;
07342          }
07343       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07344          /* If realtime storage enabled - we should explicitly delete this message,
07345          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07346          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07347          if (EXISTS(vms->curdir, x, vms->fn, NULL))
07348             DELETE(vms->curdir, x, vms->fn, vmu);
07349       }
07350    } 
07351 
07352    /* Delete ALL remaining messages */
07353    nummsg = x - 1;
07354    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07355       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07356       if (EXISTS(vms->curdir, x, vms->fn, NULL))
07357          DELETE(vms->curdir, x, vms->fn, vmu);
07358    }
07359    ast_unlock_path(vms->curdir);
07360 #else
07361    if (vms->deleted) {
07362       for (x=0;x < vmu->maxmsg;x++) { 
07363          if (vms->deleted[x]) { 
07364             ast_debug(3,"IMAP delete of %d\n",x);
07365             DELETE(vms->curdir, x, vms->fn, vmu);
07366          }
07367       }
07368    }
07369 #endif
07370 
07371 done:
07372    if (vms->deleted)
07373       memset(vms->deleted, 0, vmu->maxmsg * sizeof(int)); 
07374    if (vms->heard)
07375       memset(vms->heard, 0, vmu->maxmsg * sizeof(int)); 
07376 
07377    return 0;
07378 }

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

Definition at line 10081 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

10082 {
10083    int which = 0;
10084    int wordlen;
10085    struct ast_vm_user *vmu;
10086    const char *context = "";
10087 
10088    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
10089    if (pos > 4)
10090       return NULL;
10091    if (pos == 3)
10092       return (state == 0) ? ast_strdup("for") : NULL;
10093    wordlen = strlen(word);
10094    AST_LIST_TRAVERSE(&users, vmu, list) {
10095       if (!strncasecmp(word, vmu->context, wordlen)) {
10096          if (context && strcmp(context, vmu->context) && ++which > state)
10097             return ast_strdup(vmu->context);
10098          /* ignore repeated contexts ? */
10099          context = vmu->context;
10100       }
10101    }
10102    return NULL;
10103 }

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

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

Referenced by ast_func_read(), ast_func_write(), copy_plain_file(), iax2_register(), and vm_forwardoptions().

03725 {
03726    int ifd;
03727    int ofd;
03728    int res;
03729    int len;
03730    char buf[4096];
03731 
03732 #ifdef HARDLINK_WHEN_POSSIBLE
03733    /* Hard link if possible; saves disk space & is faster */
03734    if (link(infile, outfile)) {
03735 #endif
03736       if ((ifd = open(infile, O_RDONLY)) < 0) {
03737          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03738          return -1;
03739       }
03740       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03741          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03742          close(ifd);
03743          return -1;
03744       }
03745       do {
03746          len = read(ifd, buf, sizeof(buf));
03747          if (len < 0) {
03748             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03749             close(ifd);
03750             close(ofd);
03751             unlink(outfile);
03752          }
03753          if (len) {
03754             res = write(ofd, buf, len);
03755             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03756                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03757                close(ifd);
03758                close(ofd);
03759                unlink(outfile);
03760             }
03761          }
03762       } while (len);
03763       close(ifd);
03764       close(ofd);
03765       return 0;
03766 #ifdef HARDLINK_WHEN_POSSIBLE
03767    } else {
03768       /* Hard link succeeded */
03769       return 0;
03770    }
03771 #endif
03772 }

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

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

Referenced by forward_message(), and leave_voicemail().

04885 {
04886    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
04887    const char *frombox = mbox(imbox);
04888    int recipmsgnum;
04889 
04890    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
04891 
04892    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
04893       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
04894    } else {
04895       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04896    }
04897    
04898    if (!dir)
04899       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
04900    else
04901       ast_copy_string(fromdir, dir, sizeof(fromdir));
04902 
04903    make_file(frompath, sizeof(frompath), fromdir, msgnum);
04904    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
04905 
04906    if (vm_lock_path(todir))
04907       return ERROR_LOCK_PATH;
04908 
04909    recipmsgnum = last_message_index(recip, todir) + 1;
04910    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
04911       make_file(topath, sizeof(topath), todir, recipmsgnum);
04912       if (EXISTS(fromdir, msgnum, frompath, chan->language)) {
04913          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
04914       } else {
04915          /* For ODBC storage, if the file we want to copy isn't yet in the database, then the SQL
04916           * copy will fail. Instead, we need to create a local copy, store it, and delete the local
04917           * copy. We don't have to #ifdef this because if file storage reaches this point, there's a
04918           * much worse problem happening and IMAP storage doesn't call this function
04919           */
04920          copy_plain_file(frompath, topath);
04921          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
04922          vm_delete(topath);
04923       }
04924    } else {
04925       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
04926    }
04927    ast_unlock_path(todir);
04928    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
04929    
04930    return 0;
04931 }

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

03784 {
03785    char frompath2[PATH_MAX], topath2[PATH_MAX];
03786    struct ast_variable *tmp,*var = NULL;
03787    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
03788    ast_filecopy(frompath, topath, NULL);
03789    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
03790    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
03791    if (ast_check_realtime("voicemail_data")) {
03792       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
03793       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
03794       for (tmp = var; tmp; tmp = tmp->next) {
03795          if (!strcasecmp(tmp->name, "origmailbox")) {
03796             origmailbox = tmp->value;
03797          } else if (!strcasecmp(tmp->name, "context")) {
03798             context = tmp->value;
03799          } else if (!strcasecmp(tmp->name, "macrocontext")) {
03800             macrocontext = tmp->value;
03801          } else if (!strcasecmp(tmp->name, "exten")) {
03802             exten = tmp->value;
03803          } else if (!strcasecmp(tmp->name, "priority")) {
03804             priority = tmp->value;
03805          } else if (!strcasecmp(tmp->name, "callerchan")) {
03806             callerchan = tmp->value;
03807          } else if (!strcasecmp(tmp->name, "callerid")) {
03808             callerid = tmp->value;
03809          } else if (!strcasecmp(tmp->name, "origdate")) {
03810             origdate = tmp->value;
03811          } else if (!strcasecmp(tmp->name, "origtime")) {
03812             origtime = tmp->value;
03813          } else if (!strcasecmp(tmp->name, "category")) {
03814             category = tmp->value;
03815          } else if (!strcasecmp(tmp->name, "duration")) {
03816             duration = tmp->value;
03817          }
03818       }
03819       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);
03820    }
03821    copy(frompath2, topath2);
03822    ast_variables_destroy(var);
03823 }

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

03628 {
03629 
03630    int vmcount = 0;
03631    DIR *vmdir = NULL;
03632    struct dirent *vment = NULL;
03633 
03634    if (vm_lock_path(dir))
03635       return ERROR_LOCK_PATH;
03636 
03637    if ((vmdir = opendir(dir))) {
03638       while ((vment = readdir(vmdir))) {
03639          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03640             vmcount++;
03641          }
03642       }
03643       closedir(vmdir);
03644    }
03645    ast_unlock_path(dir);
03646    
03647    return vmcount;
03648 }

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

01493 {
01494    mode_t   mode = VOICEMAIL_DIR_MODE;
01495    int res;
01496 
01497    make_dir(dest, len, context, ext, folder);
01498    if ((res = ast_mkdir(dest, mode))) {
01499       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01500       return -1;
01501    }
01502    return 0;
01503 }

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

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

11345 {
11346    int cmd = 0;
11347    char destination[80] = "";
11348    int retries = 0;
11349 
11350    if (!num) {
11351       ast_verb(3, "Destination number will be entered manually\n");
11352       while (retries < 3 && cmd != 't') {
11353          destination[1] = '\0';
11354          destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
11355          if (!cmd)
11356             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
11357          if (!cmd)
11358             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
11359          if (!cmd) {
11360             cmd = ast_waitfordigit(chan, 6000);
11361             if (cmd)
11362                destination[0] = cmd;
11363          }
11364          if (!cmd) {
11365             retries++;
11366          } else {
11367 
11368             if (cmd < 0)
11369                return 0;
11370             if (cmd == '*') {
11371                ast_verb(3, "User hit '*' to cancel outgoing call\n");
11372                return 0;
11373             }
11374             if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0) 
11375                retries++;
11376             else
11377                cmd = 't';
11378          }
11379       }
11380       if (retries >= 3) {
11381          return 0;
11382       }
11383       
11384    } else {
11385       if (option_verbose > 2)
11386          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
11387       ast_copy_string(destination, num, sizeof(destination));
11388    }
11389 
11390    if (!ast_strlen_zero(destination)) {
11391       if (destination[strlen(destination) -1 ] == '*')
11392          return 0; 
11393       if (option_verbose > 2)
11394          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
11395       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
11396       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
11397       chan->priority = 0;
11398       return 9;
11399    }
11400    return 0;
11401 }

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

References charset.

Referenced by make_email_file().

04110 {
04111    char tmp[80];
04112    int first_section = 1;
04113    size_t endlen = 0, tmplen = 0;
04114    *end = '\0';
04115 
04116    tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
04117    for (; *start; start++) {
04118       int need_encoding = 0;
04119       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04120          need_encoding = 1;
04121       }
04122       if ((first_section && need_encoding && preamble + tmplen > 70) ||
04123          (first_section && !need_encoding && preamble + tmplen > 72) ||
04124          (!first_section && need_encoding && tmplen > 70) ||
04125          (!first_section && !need_encoding && tmplen > 72)) {
04126          /* Start new line */
04127          endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
04128          tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
04129          first_section = 0;
04130       }
04131       if (need_encoding && *start == ' ') {
04132          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
04133       } else if (need_encoding) {
04134          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
04135       } else {
04136          tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
04137       }
04138    }
04139    snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
04140    return end;
04141 }

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

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

09871 {
09872    struct ast_vm_user *vmu;
09873 
09874    AST_LIST_TRAVERSE(&users, vmu, list) {
09875       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
09876          if (strcasecmp(vmu->context, context)) {
09877             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
09878                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
09879                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
09880                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
09881          }
09882          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
09883          return NULL;
09884       }
09885       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
09886          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
09887          return NULL;
09888       }
09889    }
09890    
09891    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
09892       return NULL;
09893    
09894    ast_copy_string(vmu->context, context, sizeof(vmu->context));
09895    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
09896 
09897    AST_LIST_INSERT_TAIL(&users, vmu, list);
09898    
09899    return vmu;
09900 }

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

01289 {
01290    /* This function could be made to generate one from a database, too */
01291    struct ast_vm_user *vmu=NULL, *cur;
01292    AST_LIST_LOCK(&users);
01293 
01294    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01295       context = "default";
01296 
01297    AST_LIST_TRAVERSE(&users, cur, list) {
01298 #ifdef IMAP_STORAGE
01299       if (cur->imapversion != imapversion) {
01300          continue;
01301       }
01302 #endif
01303       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01304          break;
01305       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01306          break;
01307    }
01308    if (cur) {
01309       /* Make a copy, so that on a reload, we have no race */
01310       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01311          memcpy(vmu, cur, sizeof(*vmu));
01312          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01313          AST_LIST_NEXT(vmu, list) = NULL;
01314       }
01315    } else
01316       vmu = find_user_realtime(ivm, context, mailbox);
01317    AST_LIST_UNLOCK(&users);
01318    return vmu;
01319 }

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

01252 {
01253    struct ast_variable *var;
01254    struct ast_vm_user *retval;
01255 
01256    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01257       if (!ivm)
01258          ast_set_flag(retval, VM_ALLOCED);   
01259       else
01260          memset(retval, 0, sizeof(*retval));
01261       if (mailbox) 
01262          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01263       populate_defaults(retval);
01264       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01265          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01266       else
01267          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01268       if (var) {
01269          apply_options_full(retval, var);
01270          ast_variables_destroy(var);
01271       } else { 
01272          if (!ivm) 
01273             ast_free(retval);
01274          retval = NULL;
01275       }  
01276    } 
01277    return retval;
01278 }

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

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

Referenced by vm_execmain().

06583 {
06584 #ifdef IMAP_STORAGE
06585    int todircount=0;
06586    struct vm_state *dstvms;
06587 #endif
06588    char username[70]="";
06589    char fn[PATH_MAX]; /* for playback of name greeting */
06590    char ecodes[16] = "#";
06591    int res = 0, cmd = 0;
06592    struct ast_vm_user *receiver = NULL, *vmtmp;
06593    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06594    char *stringp;
06595    const char *s;
06596    int saved_messages = 0, found = 0;
06597    int valid_extensions = 0;
06598    char *dir;
06599    int curmsg;
06600    char urgent_str[7] = "";
06601    char tmptxtfile[PATH_MAX];
06602 #ifndef IMAP_STORAGE
06603    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06604 #endif
06605    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
06606       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
06607    }
06608 
06609    if (vms == NULL) return -1;
06610    dir = vms->curdir;
06611    curmsg = vms->curmsg;
06612 
06613    tmptxtfile[0] = '\0';
06614    while (!res && !valid_extensions) {
06615       int use_directory = 0;
06616       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
06617          int done = 0;
06618          int retries = 0;
06619          cmd=0;
06620          while ((cmd >= 0) && !done ){
06621             if (cmd)
06622                retries = 0;
06623             switch (cmd) {
06624             case '1': 
06625                use_directory = 0;
06626                done = 1;
06627                break;
06628             case '2': 
06629                use_directory = 1;
06630                done=1;
06631                break;
06632             case '*': 
06633                cmd = 't';
06634                done = 1;
06635                break;
06636             default: 
06637                /* Press 1 to enter an extension press 2 to use the directory */
06638                cmd = ast_play_and_wait(chan,"vm-forward");
06639                if (!cmd)
06640                   cmd = ast_waitfordigit(chan,3000);
06641                if (!cmd)
06642                   retries++;
06643                if (retries > 3) {
06644                   cmd = 't';
06645                   done = 1;
06646                }
06647                
06648             }
06649          }
06650          if (cmd < 0 || cmd == 't')
06651             break;
06652       }
06653       
06654       if (use_directory) {
06655          /* use app_directory */
06656          
06657          char old_context[sizeof(chan->context)];
06658          char old_exten[sizeof(chan->exten)];
06659          int old_priority;
06660          struct ast_app* directory_app;
06661 
06662          directory_app = pbx_findapp("Directory");
06663          if (directory_app) {
06664             char vmcontext[256];
06665             /* make backup copies */
06666             memcpy(old_context, chan->context, sizeof(chan->context));
06667             memcpy(old_exten, chan->exten, sizeof(chan->exten));
06668             old_priority = chan->priority;
06669             
06670             /* call the the Directory, changes the channel */
06671             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
06672             res = pbx_exec(chan, directory_app, vmcontext);
06673             
06674             ast_copy_string(username, chan->exten, sizeof(username));
06675             
06676             /* restore the old context, exten, and priority */
06677             memcpy(chan->context, old_context, sizeof(chan->context));
06678             memcpy(chan->exten, old_exten, sizeof(chan->exten));
06679             chan->priority = old_priority;
06680          } else {
06681             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
06682             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
06683          }
06684       } else {
06685          /* Ask for an extension */
06686          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
06687          if (res)
06688             break;
06689          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
06690             break;
06691       }
06692       
06693       /* start all over if no username */
06694       if (ast_strlen_zero(username))
06695          continue;
06696       stringp = username;
06697       s = strsep(&stringp, "*");
06698       /* start optimistic */
06699       valid_extensions = 1;
06700       while (s) {
06701          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
06702             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
06703             found++;
06704          } else {
06705             /* XXX Optimization for the future.  When we encounter a single bad extension,
06706              * bailing out on all of the extensions may not be the way to go.  We should
06707              * probably just bail on that single extension, then allow the user to enter
06708              * several more. XXX
06709              */
06710             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
06711                free_user(receiver);
06712             }
06713             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
06714             valid_extensions = 0;
06715             break;
06716          }
06717 
06718          /* play name if available, else play extension number */
06719          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
06720          RETRIEVE(fn, -1, s, receiver->context);
06721          if (ast_fileexists(fn, NULL, NULL) > 0) {
06722             res = ast_stream_and_wait(chan, fn, ecodes);
06723             if (res) {
06724                DISPOSE(fn, -1);
06725                return res;
06726             }
06727          } else {
06728             res = ast_say_digit_str(chan, s, ecodes, chan->language);
06729          }
06730          DISPOSE(fn, -1);
06731 
06732          s = strsep(&stringp, "*");
06733       }
06734       /* break from the loop of reading the extensions */
06735       if (valid_extensions)
06736          break;
06737       /* "I am sorry, that's not a valid extension.  Please try again." */
06738       res = ast_play_and_wait(chan, "pbx-invalid");
06739    }
06740    /* check if we're clear to proceed */
06741    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
06742       return res;
06743    if (is_new_message == 1) {
06744       struct leave_vm_options leave_options;
06745       char mailbox[AST_MAX_EXTENSION * 2 + 2];
06746       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
06747 
06748       /* Send VoiceMail */
06749       memset(&leave_options, 0, sizeof(leave_options));
06750       leave_options.record_gain = record_gain;
06751       cmd = leave_voicemail(chan, mailbox, &leave_options);
06752    } else {
06753       /* Forward VoiceMail */
06754       long duration = 0;
06755       struct vm_state vmstmp;
06756       memcpy(&vmstmp, vms, sizeof(vmstmp));
06757 
06758       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
06759 
06760       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
06761       if (!cmd) {
06762          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
06763 #ifdef IMAP_STORAGE
06764             int attach_user_voicemail;
06765             char *myserveremail = serveremail;
06766             
06767             /* get destination mailbox */
06768             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
06769             if (!dstvms) {
06770                dstvms = create_vm_state_from_user(vmtmp);
06771             }
06772             if (dstvms) {
06773                init_mailstream(dstvms, 0);
06774                if (!dstvms->mailstream) {
06775                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
06776                } else {
06777                   STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
06778                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
06779                }
06780             } else {
06781                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
06782             }
06783             if (!ast_strlen_zero(vmtmp->serveremail))
06784                myserveremail = vmtmp->serveremail;
06785             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
06786             /* NULL category for IMAP storage */
06787             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);
06788 #else
06789             copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
06790 #endif
06791             saved_messages++;
06792             AST_LIST_REMOVE_CURRENT(list);
06793             free_user(vmtmp);
06794             if (res)
06795                break;
06796          }
06797          AST_LIST_TRAVERSE_SAFE_END;
06798          if (saved_messages > 0) {
06799             /* give confirmation that the message was saved */
06800             /* commented out since we can't forward batches yet
06801             if (saved_messages == 1)
06802                res = ast_play_and_wait(chan, "vm-message");
06803             else
06804                res = ast_play_and_wait(chan, "vm-messages");
06805             if (!res)
06806                res = ast_play_and_wait(chan, "vm-saved"); */
06807 #ifdef IMAP_STORAGE
06808             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
06809             if (ast_strlen_zero(vmstmp.introfn))
06810 #endif
06811             res = ast_play_and_wait(chan, "vm-msgsaved");
06812          }  
06813 #ifndef IMAP_STORAGE
06814          /* Restore original message without prepended message if backup exists */
06815          make_file(msgfile, sizeof(msgfile), dir, curmsg);
06816          strcpy(textfile, msgfile);
06817          strcpy(backup, msgfile);
06818          strcpy(backup_textfile, msgfile);
06819          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06820          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06821          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06822          if (ast_fileexists(backup, NULL, NULL) > 0) {
06823             ast_filerename(backup, msgfile, NULL);
06824             rename(backup_textfile, textfile);
06825          }
06826 #endif
06827       }
06828       DISPOSE(dir, curmsg);
06829    }
06830 
06831    /* If anything failed above, we still have this list to free */
06832    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
06833       free_user(vmtmp);
06834    return res ? res : cmd;
06835 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1528 of file app_voicemail.c.

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

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

01529 {
01530    if (ast_test_flag(vmu, VM_ALLOCED)) {
01531       if (vmu->emailbody != NULL) {
01532          ast_free(vmu->emailbody);
01533          vmu->emailbody = NULL;
01534       }
01535       if (vmu->emailsubject != NULL) {
01536          ast_free(vmu->emailsubject);
01537          vmu->emailsubject = NULL;
01538       }
01539       ast_free(vmu);
01540    }
01541 }

static void free_vm_users ( void   )  [static]

Free the users structure.

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

10539 {
10540    struct ast_vm_user *current;
10541    AST_LIST_LOCK(&users);
10542    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
10543       ast_set_flag(current, VM_ALLOCED);
10544       free_user(current);
10545    }
10546    AST_LIST_UNLOCK(&users);
10547 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

10551 {
10552    struct vm_zone *zcur;
10553    AST_LIST_LOCK(&zones);
10554    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
10555       free_zone(zcur);
10556    AST_LIST_UNLOCK(&zones);
10557 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4652 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

04653 {
04654    ast_free(z);
04655 }

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

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

Referenced by leave_voicemail().

04609 {
04610    struct ast_tm tm;
04611    struct timeval t = ast_tvnow();
04612    
04613    ast_localtime(&t, &tm, "UTC");
04614 
04615    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04616 }

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

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

Referenced by get_folder2().

06239 {
06240    int x;
06241    int d;
06242    char fn[PATH_MAX];
06243    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06244    if (d)
06245       return d;
06246    for (x = start; x< 5; x++) {  /* For all folders */
06247       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06248          return d;
06249       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06250       if (d)
06251          return d;
06252       snprintf(fn, sizeof(fn), "vm-%s", mbox(x));  /* Folder name */
06253       d = vm_play_folder_name(chan, fn);
06254       if (d)
06255          return d;
06256       d = ast_waitfordigit(chan, 500);
06257       if (d)
06258          return d;
06259    }
06260    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06261    if (d)
06262       return d;
06263    d = ast_waitfordigit(chan, 4000);
06264    return d;
06265 }

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

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

06280 {
06281    int res = 0;
06282    res = ast_play_and_wait(chan, fn);  /* Folder name */
06283    while (((res < '0') || (res > '9')) &&
06284          (res != '#') && (res >= 0)) {
06285       res = get_folder(chan, 0);
06286    }
06287    return res;
06288 }

static int handle_subscribe ( void *  datap  )  [static]

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

10322 {
10323    unsigned int len;
10324    struct mwi_sub *mwi_sub;
10325    struct mwi_sub_task *p = datap;
10326 
10327    len = sizeof(*mwi_sub);
10328    if (!ast_strlen_zero(p->mailbox))
10329       len += strlen(p->mailbox);
10330 
10331    if (!ast_strlen_zero(p->context))
10332       len += strlen(p->context) + 1; /* Allow for seperator */
10333 
10334    if (!(mwi_sub = ast_calloc(1, len)))
10335       return -1;
10336 
10337    mwi_sub->uniqueid = p->uniqueid;
10338    if (!ast_strlen_zero(p->mailbox))
10339       strcpy(mwi_sub->mailbox, p->mailbox);
10340 
10341    if (!ast_strlen_zero(p->context)) {
10342       strcat(mwi_sub->mailbox, "@");
10343       strcat(mwi_sub->mailbox, p->context);
10344    }
10345 
10346    AST_RWLIST_WRLOCK(&mwi_subs);
10347    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
10348    AST_RWLIST_UNLOCK(&mwi_subs);
10349    ast_free((void *) p->mailbox);
10350    ast_free((void *) p->context);
10351    ast_free(p);
10352    poll_subscribed_mailbox(mwi_sub);
10353    return 0;
10354 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

10300 {
10301    struct mwi_sub *mwi_sub;
10302    uint32_t *uniqueid = datap;
10303    
10304    AST_RWLIST_WRLOCK(&mwi_subs);
10305    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
10306       if (mwi_sub->uniqueid == *uniqueid) {
10307          AST_LIST_REMOVE_CURRENT(entry);
10308          break;
10309       }
10310    }
10311    AST_RWLIST_TRAVERSE_SAFE_END
10312    AST_RWLIST_UNLOCK(&mwi_subs);
10313 
10314    if (mwi_sub)
10315       mwi_sub_destroy(mwi_sub);
10316 
10317    ast_free(uniqueid);  
10318    return 0;
10319 }

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

10217 {
10218    switch (cmd) {
10219    case CLI_INIT:
10220       e->command = "voicemail reload";
10221       e->usage =
10222          "Usage: voicemail reload\n"
10223          "       Reload voicemail configuration\n";
10224       return NULL;
10225    case CLI_GENERATE:
10226       return NULL;
10227    }
10228 
10229    if (a->argc != 2)
10230       return CLI_SHOWUSAGE;
10231 
10232    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
10233    load_config(1);
10234    
10235    return CLI_SUCCESS;
10236 }

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

10107 {
10108    struct ast_vm_user *vmu;
10109 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
10110    const char *context = NULL;
10111    int users_counter = 0;
10112 
10113    switch (cmd) {
10114    case CLI_INIT:
10115       e->command = "voicemail show users";
10116       e->usage =
10117          "Usage: voicemail show users [for <context>]\n"
10118          "       Lists all mailboxes currently set up\n";
10119       return NULL;
10120    case CLI_GENERATE:
10121       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10122    }  
10123 
10124    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10125       return CLI_SHOWUSAGE;
10126    if (a->argc == 5) {
10127       if (strcmp(a->argv[3],"for"))
10128          return CLI_SHOWUSAGE;
10129       context = a->argv[4];
10130    }
10131 
10132    if (ast_check_realtime("voicemail")) {
10133       if (!context) {
10134          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10135          return CLI_SHOWUSAGE;
10136       }
10137       return show_users_realtime(a->fd, context);
10138    }
10139 
10140    AST_LIST_LOCK(&users);
10141    if (AST_LIST_EMPTY(&users)) {
10142       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10143       AST_LIST_UNLOCK(&users);
10144       return CLI_FAILURE;
10145    }
10146    if (a->argc == 3)
10147       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10148    else {
10149       int count = 0;
10150       AST_LIST_TRAVERSE(&users, vmu, list) {
10151          if (!strcmp(context, vmu->context))
10152             count++;
10153       }
10154       if (count) {
10155          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10156       } else {
10157          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10158          AST_LIST_UNLOCK(&users);
10159          return CLI_FAILURE;
10160       }
10161    }
10162    AST_LIST_TRAVERSE(&users, vmu, list) {
10163       int newmsgs = 0, oldmsgs = 0;
10164       char count[12], tmp[256] = "";
10165 
10166       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10167          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10168          inboxcount(tmp, &newmsgs, &oldmsgs);
10169          snprintf(count, sizeof(count), "%d", newmsgs);
10170          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10171          users_counter++;
10172       }
10173    }
10174    AST_LIST_UNLOCK(&users);
10175    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10176    return CLI_SUCCESS;
10177 }

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

10181 {
10182    struct vm_zone *zone;
10183 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10184    char *res = CLI_SUCCESS;
10185 
10186    switch (cmd) {
10187    case CLI_INIT:
10188       e->command = "voicemail show zones";
10189       e->usage =
10190          "Usage: voicemail show zones\n"
10191          "       Lists zone message formats\n";
10192       return NULL;
10193    case CLI_GENERATE:
10194       return NULL;
10195    }
10196 
10197    if (a->argc != 3)
10198       return CLI_SHOWUSAGE;
10199 
10200    AST_LIST_LOCK(&zones);
10201    if (!AST_LIST_EMPTY(&zones)) {
10202       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10203       AST_LIST_TRAVERSE(&zones, zone, list) {
10204          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10205       }
10206    } else {
10207       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10208       res = CLI_FAILURE;
10209    }
10210    AST_LIST_UNLOCK(&zones);
10211 
10212    return res;
10213 }

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

Determines if the given folder has messages.

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

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

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

Definition at line 4986 of file app_voicemail.c.

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

Referenced by load_module(), and vm_execmain().

04987 {
04988    char tmp[256], *tmp2 = tmp, *box, *context;
04989    ast_copy_string(tmp, mailbox, sizeof(tmp));
04990    if (ast_strlen_zero(folder)) {
04991       folder = "INBOX";
04992    }
04993    while ((box = strsep(&tmp2, ",&"))) {
04994       if ((context = strchr(box, '@')))
04995          *context++ = '\0';
04996       else
04997          context = "default";
04998       if (__has_voicemail(context, box, folder, 1))
04999          return 1;
05000       /* If we are checking INBOX, we should check Urgent as well */
05001       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05002          return 1;
05003       }
05004    }
05005    return 0;
05006 }

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

Definition at line 5068 of file app_voicemail.c.

References inboxcount2().

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

05069 {
05070    int urgentmsgs = 0;
05071    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05072    if (newmsgs) {
05073       *newmsgs += urgentmsgs;
05074    }
05075    return res;
05076 }

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

Definition at line 5009 of file app_voicemail.c.

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

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

05010 {
05011    char tmp[256];
05012    char *context;
05013 
05014    /* If no mailbox, return immediately */
05015    if (ast_strlen_zero(mailbox))
05016       return 0;
05017 
05018    if (newmsgs)
05019       *newmsgs = 0;
05020    if (oldmsgs)
05021       *oldmsgs = 0;
05022    if (urgentmsgs)
05023       *urgentmsgs = 0;
05024 
05025    if (strchr(mailbox, ',')) {
05026       int tmpnew, tmpold, tmpurgent;
05027       char *mb, *cur;
05028 
05029       ast_copy_string(tmp, mailbox, sizeof(tmp));
05030       mb = tmp;
05031       while ((cur = strsep(&mb, ", "))) {
05032          if (!ast_strlen_zero(cur)) {
05033             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05034                return -1;
05035             else {
05036                if (newmsgs)
05037                   *newmsgs += tmpnew; 
05038                if (oldmsgs)
05039                   *oldmsgs += tmpold;
05040                if (urgentmsgs)
05041                   *urgentmsgs += tmpurgent;
05042             }
05043          }
05044       }
05045       return 0;
05046    }
05047 
05048    ast_copy_string(tmp, mailbox, sizeof(tmp));
05049    
05050    if ((context = strchr(tmp, '@')))
05051       *context++ = '\0';
05052    else
05053       context = "default";
05054 
05055    if (newmsgs)
05056       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05057    if (oldmsgs)
05058       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05059    if (urgentmsgs)
05060       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05061 
05062    return 0;
05063 }

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

utility used by inchar(), for base_encode()

Definition at line 3855 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(), sip_addheader(), and sip_removeheader().

03856 {
03857    int l;
03858 
03859    if (bio->ateof)
03860       return 0;
03861 
03862    if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
03863       if (ferror(fi))
03864          return -1;
03865 
03866       bio->ateof = 1;
03867       return 0;
03868    }
03869 
03870    bio->iolen= l;
03871    bio->iocp= 0;
03872 
03873    return 1;
03874 }

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

utility used by base_encode()

Definition at line 3879 of file app_voicemail.c.

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

Referenced by base_encode().

03880 {
03881    if (bio->iocp>=bio->iolen) {
03882       if (!inbuf(bio, fi))
03883          return EOF;
03884    }
03885 
03886    return bio->iobuf[bio->iocp++];
03887 }

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

Definition at line 846 of file app_voicemail.c.

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

Referenced by load_module().

00847 {
00848    struct inprocess *i = obj, *j = arg;
00849    if (!strcmp(i->mailbox, j->mailbox)) {
00850       return 0;
00851    }
00852    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00853 }

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

Definition at line 855 of file app_voicemail.c.

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

Referenced by copy_message(), and leave_voicemail().

00856 {
00857    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00858    arg->context = arg->mailbox + strlen(mailbox) + 1;
00859    strcpy(arg->mailbox, mailbox); /* SAFE */
00860    strcpy(arg->context, context); /* SAFE */
00861    ao2_lock(inprocess_container);
00862    if ((i = ao2_find(inprocess_container, arg, 0))) {
00863       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00864       ao2_unlock(inprocess_container);
00865       ao2_ref(i, -1);
00866       return ret;
00867    }
00868    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00869       ao2_unlock(inprocess_container);
00870       return 0;
00871    }
00872    i->context = i->mailbox + strlen(mailbox) + 1;
00873    strcpy(i->mailbox, mailbox); /* SAFE */
00874    strcpy(i->context, context); /* SAFE */
00875    i->count = delta;
00876    ao2_link(inprocess_container, i);
00877    ao2_unlock(inprocess_container);
00878    ao2_ref(i, -1);
00879    return 0;
00880 }

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

Definition at line 840 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

00841 {
00842    const struct inprocess *i = obj;
00843    return atoi(i->mailbox);
00844 }

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

Definition at line 4618 of file app_voicemail.c.

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

Referenced by leave_voicemail().

04619 {
04620    int res;
04621    char fn[PATH_MAX];
04622    char dest[PATH_MAX];
04623 
04624    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04625 
04626    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04627       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04628       return -1;
04629    }
04630 
04631    RETRIEVE(fn, -1, ext, context);
04632    if (ast_fileexists(fn, NULL, NULL) > 0) {
04633       res = ast_stream_and_wait(chan, fn, ecodes);
04634       if (res) {
04635          DISPOSE(fn, -1);
04636          return res;
04637       }
04638    } else {
04639       /* Dispose just in case */
04640       DISPOSE(fn, -1);
04641       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04642       if (res)
04643          return res;
04644       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04645       if (res)
04646          return res;
04647    }
04648    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04649    return res;
04650 }

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

References ast_log(), AST_LOG_WARNING, and VALID_DTMF.

Referenced by load_config().

01227 {
01228    int i;
01229    char *local_key = ast_strdupa(key);
01230 
01231    for (i = 0; i < strlen(key); ++i) {
01232       if (!strchr(VALID_DTMF, *local_key)) {
01233          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01234          return 0;
01235       }
01236       local_key++;
01237    }
01238    return 1;
01239 }

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

03682 {
03683    int x;
03684    unsigned char map[MAXMSGLIMIT] = "";
03685    DIR *msgdir;
03686    struct dirent *msgdirent;
03687    int msgdirint;
03688 
03689    /* Reading the entire directory into a file map scales better than
03690     * doing a stat repeatedly on a predicted sequence.  I suspect this
03691     * is partially due to stat(2) internally doing a readdir(2) itself to
03692     * find each file. */
03693    if (!(msgdir = opendir(dir))) {
03694       return -1;
03695    }
03696 
03697    while ((msgdirent = readdir(msgdir))) {
03698       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03699          map[msgdirint] = 1;
03700    }
03701    closedir(msgdir);
03702 
03703    for (x = 0; x < vmu->maxmsg; x++) {
03704       if (map[x] == 0)
03705          break;
03706    }
03707 
03708    return x - 1;
03709 }

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 5141 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_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verbose, ast_waitstream(), ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_channel::context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, ast_channel::exten, find_user(), free_user(), get_date(), inboxcount(), inprocess_count(), INTRO, invent_message(), ast_channel::language, last_message_index(), ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_channel::name, vm_state::newmessages, notify_new_message(), 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, transfer, VERBOSE_PREFIX_3, vm_lock_path(), VM_OPERATOR, and VOICEMAIL_FILE_MODE.

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

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

static int load_config ( int  reload  )  [static]

Definition at line 10603 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_strlen_zero(), ast_true(), ast_unload_realtime(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, 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(), 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().

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

static int load_module ( void   )  [static]

Definition at line 11306 of file app_voicemail.c.

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

11307 {
11308    int res;
11309    my_umask = umask(0);
11310    umask(my_umask);
11311 
11312    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
11313       return AST_MODULE_LOAD_DECLINE;
11314    }
11315 
11316    /* compute the location of the voicemail spool directory */
11317    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
11318    
11319    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
11320       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
11321    }
11322 
11323    if ((res = load_config(0)))
11324       return res;
11325 
11326    res = ast_register_application_xml(app, vm_exec);
11327    res |= ast_register_application_xml(app2, vm_execmain);
11328    res |= ast_register_application_xml(app3, vm_box_exists);
11329    res |= ast_register_application_xml(app4, vmauthenticate);
11330    res |= ast_custom_function_register(&mailbox_exists_acf);
11331    res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
11332    if (res)
11333       return res;
11334 
11335    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
11336 
11337    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
11338    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
11339    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
11340 
11341    return res;
11342 }

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

01449 {
01450    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01451 }

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 4163 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_strftime(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, encode_mime_str(), ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::mailbox, make_dir(), make_file(), ast_channel::name, pbx_substitute_variables_helper(), prep_email_sub_vars(), ast_channel::priority, quote(), strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

04164 {
04165    char date[256];
04166    char host[MAXHOSTNAMELEN] = "";
04167    char who[256];
04168    char bound[256];
04169    char dur[256];
04170    struct ast_tm tm;
04171    char enc_cidnum[256] = "", enc_cidname[256] = "";
04172    char *passdata = NULL, *passdata2;
04173    size_t len_passdata = 0, len_passdata2, tmplen;
04174    char *greeting_attachment; 
04175    char filename[256];
04176 
04177 #ifdef IMAP_STORAGE
04178 #define ENDL "\r\n"
04179 #else
04180 #define ENDL "\n"
04181 #endif
04182 
04183    /* One alloca for multiple fields */
04184    len_passdata2 = strlen(vmu->fullname);
04185    if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
04186       len_passdata2 = tmplen;
04187    }
04188    if ((tmplen = strlen(fromstring)) > len_passdata2) {
04189       len_passdata2 = tmplen;
04190    }
04191    len_passdata2 = len_passdata2 * 3 + 200;
04192    passdata2 = alloca(len_passdata2);
04193 
04194    if (cidnum) {
04195       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04196    }
04197    if (cidname) {
04198       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04199    }
04200    gethostname(host, sizeof(host) - 1);
04201 
04202    if (strchr(srcemail, '@'))
04203       ast_copy_string(who, srcemail, sizeof(who));
04204    else 
04205       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04206    
04207    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04208    if (greeting_attachment)
04209       *greeting_attachment++ = '\0';
04210 
04211    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04212    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04213    fprintf(p, "Date: %s" ENDL, date);
04214 
04215    /* Set date format for voicemail mail */
04216    ast_strftime(date, sizeof(date), emaildateformat, &tm);
04217 
04218    if (!ast_strlen_zero(fromstring)) {
04219       struct ast_channel *ast;
04220       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04221          char *ptr;
04222          memset(passdata2, 0, len_passdata2);
04223          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category, flag);
04224          pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
04225          len_passdata = strlen(passdata2) * 3 + 300;
04226          passdata = alloca(len_passdata);
04227          if (check_mime(passdata2)) {
04228             int first_line = 1;
04229             encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
04230             while ((ptr = strchr(passdata, ' '))) {
04231                *ptr = '\0';
04232                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
04233                first_line = 0;
04234                passdata = ptr + 1;
04235             }
04236             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
04237          } else {
04238             fprintf(p, "From: %s <%s>" ENDL, quote(passdata2, passdata, len_passdata), who);
04239          }
04240          ast_channel_free(ast);
04241       } else {
04242          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04243       }
04244    } else {
04245       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04246    }
04247 
04248    if (check_mime(vmu->fullname)) {
04249       int first_line = 1;
04250       char *ptr;
04251       encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
04252       while ((ptr = strchr(passdata2, ' '))) {
04253          *ptr = '\0';
04254          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
04255          first_line = 0;
04256          passdata2 = ptr + 1;
04257       }
04258       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
04259    } else {
04260       fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
04261    }
04262    if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
04263       char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
04264       struct ast_channel *ast;
04265       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04266          int vmlen = strlen(e_subj) * 3 + 200;
04267          /* Only allocate more space if the previous was not large enough */
04268          if (vmlen > len_passdata) {
04269             passdata = alloca(vmlen);
04270             len_passdata = vmlen;
04271          }
04272 
04273          memset(passdata, 0, len_passdata);
04274          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, len_passdata, category, flag);
04275          pbx_substitute_variables_helper(ast, e_subj, passdata, len_passdata);
04276          if (check_mime(passdata)) {
04277             int first_line = 1;
04278             char *ptr;
04279             encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
04280             while ((ptr = strchr(passdata2, ' '))) {
04281                *ptr = '\0';
04282                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
04283                first_line = 0;
04284                passdata2 = ptr + 1;
04285             }
04286             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
04287          } else {
04288             fprintf(p, "Subject: %s" ENDL, passdata);
04289          }
04290          ast_channel_free(ast);
04291       } else {
04292          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04293       }
04294    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04295       if (ast_strlen_zero(flag)) {
04296          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04297       } else {
04298          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04299       }
04300    } else {
04301       if (ast_strlen_zero(flag)) {
04302          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04303       } else {
04304          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04305       }
04306    }
04307 
04308    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1, (unsigned int)ast_random(), mailbox, (int)getpid(), host);
04309    if (imap) {
04310       /* additional information needed for IMAP searching */
04311       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04312       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04313       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04314       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04315 #ifdef IMAP_STORAGE
04316       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04317 #else
04318       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04319 #endif
04320       /* flag added for Urgent */
04321       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04322       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04323       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04324       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04325       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04326       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04327       if (!ast_strlen_zero(category)) {
04328          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04329       } else {
04330          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04331       }
04332       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04333       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04334       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long)time(NULL));
04335    }
04336    if (!ast_strlen_zero(cidnum)) {
04337       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04338    }
04339    if (!ast_strlen_zero(cidname)) {
04340       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04341    }
04342    fprintf(p, "MIME-Version: 1.0" ENDL);
04343    if (attach_user_voicemail) {
04344       /* Something unique. */
04345       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox, (int)getpid(), (unsigned int)ast_random());
04346 
04347       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04348       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04349       fprintf(p, "--%s" ENDL, bound);
04350    }
04351    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04352    if (emailbody || vmu->emailbody) {
04353       char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
04354       struct ast_channel *ast;
04355       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04356          char *passdata;
04357          int vmlen = strlen(e_body) * 3 + 200;
04358          passdata = alloca(vmlen);
04359          memset(passdata, 0, vmlen);
04360          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04361          pbx_substitute_variables_helper(ast, e_body, passdata, vmlen);
04362          fprintf(p, "%s" ENDL, passdata);
04363          ast_channel_free(ast);
04364       } else
04365          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04366    } else if (msgnum > -1) {
04367       if (strcmp(vmu->mailbox, mailbox)) {
04368          /* Forwarded type */
04369          struct ast_config *msg_cfg;
04370          const char *v;
04371          int inttime;
04372          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04373          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04374          /* Retrieve info from VM attribute file */
04375          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04376          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04377          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04378             strcat(fromfile, ".txt");
04379          }
04380          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04381             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04382                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04383             }
04384 
04385             /* You might be tempted to do origdate, except that a) it's in the wrong
04386              * format, and b) it's missing for IMAP recordings. */
04387             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04388                struct timeval tv = { inttime, };
04389                struct ast_tm tm;
04390                ast_localtime(&tv, &tm, NULL);
04391                ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
04392             }
04393             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04394                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04395                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04396                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04397                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04398                date, origcallerid, origdate);
04399             ast_config_destroy(msg_cfg);
04400          } else {
04401             goto plain_message;
04402          }
04403       } else {
04404 plain_message:
04405          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04406             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04407             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04408             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04409             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04410       }
04411    } else {
04412       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04413             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04414    }
04415 
04416    if (imap || attach_user_voicemail) {
04417       if (!ast_strlen_zero(attach2)) {
04418          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04419          ast_debug(5, "creating second attachment filename %s\n", filename);
04420          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04421          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04422          ast_debug(5, "creating attachment filename %s\n", filename);
04423          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04424       } else {
04425          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04426          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04427          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04428       }
04429    }
04430 }

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

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

01464 {
01465    return snprintf(dest, len, "%s/msg%04d", dir, num);
01466 }

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

Manager list voicemail users command.

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

10438 {
10439    struct ast_vm_user *vmu = NULL;
10440    const char *id = astman_get_header(m, "ActionID");
10441    char actionid[128] = "";
10442 
10443    if (!ast_strlen_zero(id))
10444       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
10445 
10446    AST_LIST_LOCK(&users);
10447 
10448    if (AST_LIST_EMPTY(&users)) {
10449       astman_send_ack(s, m, "There are no voicemail users currently defined.");
10450       AST_LIST_UNLOCK(&users);
10451       return RESULT_SUCCESS;
10452    }
10453    
10454    astman_send_ack(s, m, "Voicemail user list will follow");
10455    
10456    AST_LIST_TRAVERSE(&users, vmu, list) {
10457       char dirname[256];
10458 
10459 #ifdef IMAP_STORAGE
10460       int new, old;
10461       inboxcount(vmu->mailbox, &new, &old);
10462 #endif
10463       
10464       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
10465       astman_append(s,
10466          "%s"
10467          "Event: VoicemailUserEntry\r\n"
10468          "VMContext: %s\r\n"
10469          "VoiceMailbox: %s\r\n"
10470          "Fullname: %s\r\n"
10471          "Email: %s\r\n"
10472          "Pager: %s\r\n"
10473          "ServerEmail: %s\r\n"
10474          "MailCommand: %s\r\n"
10475          "Language: %s\r\n"
10476          "TimeZone: %s\r\n"
10477          "Callback: %s\r\n"
10478          "Dialout: %s\r\n"
10479          "UniqueID: %s\r\n"
10480          "ExitContext: %s\r\n"
10481          "SayDurationMinimum: %d\r\n"
10482          "SayEnvelope: %s\r\n"
10483          "SayCID: %s\r\n"
10484          "AttachMessage: %s\r\n"
10485          "AttachmentFormat: %s\r\n"
10486          "DeleteMessage: %s\r\n"
10487          "VolumeGain: %.2f\r\n"
10488          "CanReview: %s\r\n"
10489          "CallOperator: %s\r\n"
10490          "MaxMessageCount: %d\r\n"
10491          "MaxMessageLength: %d\r\n"
10492          "NewMessageCount: %d\r\n"
10493 #ifdef IMAP_STORAGE
10494          "OldMessageCount: %d\r\n"
10495          "IMAPUser: %s\r\n"
10496 #endif
10497          "\r\n",
10498          actionid,
10499          vmu->context,
10500          vmu->mailbox,
10501          vmu->fullname,
10502          vmu->email,
10503          vmu->pager,
10504          vmu->serveremail,
10505          vmu->mailcmd,
10506          vmu->language,
10507          vmu->zonetag,
10508          vmu->callback,
10509          vmu->dialout,
10510          vmu->uniqueid,
10511          vmu->exit,
10512          vmu->saydurationm,
10513          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
10514          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
10515          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
10516          vmu->attachfmt,
10517          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
10518          vmu->volgain,
10519          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
10520          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
10521          vmu->maxmsg,
10522          vmu->maxsecs,
10523 #ifdef IMAP_STORAGE
10524          new, old, vmu->imapuser
10525 #else
10526          count_messages(vmu, dirname)
10527 #endif
10528          );
10529    }     
10530    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
10531 
10532    AST_LIST_UNLOCK(&users);
10533 
10534    return RESULT_SUCCESS;
10535 }

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

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

10272 {
10273    while (poll_thread_run) {
10274       struct timespec ts = { 0, };
10275       struct timeval wait;
10276 
10277       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
10278       ts.tv_sec = wait.tv_sec;
10279       ts.tv_nsec = wait.tv_usec * 1000;
10280 
10281       ast_mutex_lock(&poll_lock);
10282       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
10283       ast_mutex_unlock(&poll_lock);
10284 
10285       if (!poll_thread_run)
10286          break;
10287 
10288       poll_subscribed_mailboxes();
10289    }
10290 
10291    return NULL;
10292 }

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

Definition at line 1505 of file app_voicemail.c.

References ARRAY_LEN.

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

01506 {
01507    static const char *msgs[] = {
01508 #ifdef IMAP_STORAGE
01509       imapfolder,
01510 #else
01511       "INBOX",
01512 #endif
01513       "Old",
01514       "Work",
01515       "Family",
01516       "Friends",
01517       "Cust1",
01518       "Cust2",
01519       "Cust3",
01520       "Cust4",
01521       "Cust5",
01522       "Deleted",
01523       "Urgent"
01524    };
01525    return (id >= 0 && id < ARRAY_LEN(msgs)) ? msgs[id] : "Unknown";
01526 }

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

Definition at line 4935 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

04936 {
04937    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
04938 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 10294 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

10295 {
10296    ast_free(mwi_sub);
10297 }

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

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

10373 {
10374    struct mwi_sub_task *mwist;
10375    
10376    if (ast_event_get_type(event) != AST_EVENT_SUB)
10377       return;
10378 
10379    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10380       return;
10381 
10382    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
10383       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
10384       return;
10385    }
10386    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
10387    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
10388    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10389    
10390    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
10391       ast_free(mwist);
10392    }
10393 }

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

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

10357 {
10358    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
10359    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
10360       return;
10361 
10362    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
10363       return;
10364 
10365    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
10366    *uniqueid = u;
10367    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
10368       ast_free(uniqueid);
10369    }
10370 }

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 6482 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_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, VM_ATTACH, vm_delete(), and VM_DELETE.

Referenced by copy_message(), and leave_voicemail().

06483 {
06484    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06485    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06486    const char *category;
06487    char *myserveremail = serveremail;
06488 
06489    ast_channel_lock(chan);
06490    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06491       category = ast_strdupa(category);
06492    }
06493    ast_channel_unlock(chan);
06494 
06495    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06496    make_file(fn, sizeof(fn), todir, msgnum);
06497    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06498 
06499    if (!ast_strlen_zero(vmu->attachfmt)) {
06500       if (strstr(fmt, vmu->attachfmt))
06501          fmt = vmu->attachfmt;
06502       else
06503          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);
06504    }
06505 
06506    /* Attach only the first format */
06507    fmt = ast_strdupa(fmt);
06508    stringp = fmt;
06509    strsep(&stringp, "|");
06510 
06511    if (!ast_strlen_zero(vmu->serveremail))
06512       myserveremail = vmu->serveremail;
06513 
06514    if (!ast_strlen_zero(vmu->email)) {
06515       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06516       if (!attach_user_voicemail)
06517          attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
06518 
06519       if (attach_user_voicemail)
06520          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06521 
06522       /* XXX possible imap issue, should category be NULL XXX */
06523       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06524 
06525       if (attach_user_voicemail)
06526          DISPOSE(todir, msgnum);
06527    }
06528 
06529    if (!ast_strlen_zero(vmu->pager)) {
06530       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
06531    }
06532 
06533    if (ast_test_flag(vmu, VM_DELETE))
06534       DELETE(todir, msgnum, fn, vmu);
06535 
06536    /* Leave voicemail for someone */
06537    if (ast_app_has_voicemail(ext_context, NULL)) 
06538       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06539 
06540    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06541 
06542    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);
06543    run_externnotify(vmu->context, vmu->mailbox, flag);
06544 
06545 #ifdef IMAP_STORAGE
06546    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06547    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06548       vm_imap_delete(NULL, vms->curmsg, vmu);
06549       vms->newmessages--;  /* Fix new message count */
06550    }
06551 #endif
06552 
06553    return 0;
06554 }

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

utility used by base_encode()

Definition at line 3892 of file app_voicemail.c.

References BASELINELEN, eol, and baseio::linelength.

Referenced by base_encode().

03893 {
03894    if (bio->linelength >= BASELINELEN) {
03895       if (fputs(eol,so) == EOF)
03896          return -1;
03897 
03898       bio->linelength= 0;
03899    }
03900 
03901    if (putc(((unsigned char)c),so) == EOF)
03902       return -1;
03903 
03904    bio->linelength++;
03905 
03906    return 1;
03907 }

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

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

07254 {
07255    int count_msg, last_msg;
07256 
07257    ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
07258    
07259    /* Rename the member vmbox HERE so that we don't try to return before
07260     * we know what's going on.
07261     */
07262    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07263    
07264    /* Faster to make the directory than to check if it exists. */
07265    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07266 
07267    count_msg = count_messages(vmu, vms->curdir);
07268    if (count_msg < 0)
07269       return count_msg;
07270    else
07271       vms->lastmsg = count_msg - 1;
07272 
07273    /*
07274    The following test is needed in case sequencing gets messed up.
07275    There appears to be more than one way to mess up sequence, so
07276    we will not try to find all of the root causes--just fix it when
07277    detected.
07278    */
07279 
07280    if (vm_lock_path(vms->curdir)) {
07281       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07282       return -1;
07283    }
07284 
07285    last_msg = last_message_index(vmu, vms->curdir);
07286    ast_unlock_path(vms->curdir);
07287 
07288    if (last_msg < 0) 
07289       return last_msg;
07290 
07291    return 0;
07292 }

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

Definition at line 7051 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_strlen_zero(), ast_test_flag, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, ast_channel::language, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

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

07052 {
07053    int res = 0;
07054    char filename[256], *cid;
07055    const char *origtime, *context, *category, *duration, *flag;
07056    struct ast_config *msg_cfg;
07057    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07058 
07059    vms->starting = 0;
07060    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07061    adsi_message(chan, vms);
07062    if (!vms->curmsg)
07063       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07064    else if (vms->curmsg == vms->lastmsg)
07065       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07066 
07067    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07068    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07069    msg_cfg = ast_config_load(filename, config_flags);
07070    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07071       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07072       return 0;
07073    }
07074    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07075 
07076    /* Play the word urgent if we are listening to urgent messages */
07077    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07078       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07079    }
07080 
07081    if (!res) {
07082       /* POLISH syntax */
07083       if (!strncasecmp(chan->language, "pl", 2)) {
07084          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07085             int ten, one;
07086             char nextmsg[256];
07087             ten = (vms->curmsg + 1) / 10;
07088             one = (vms->curmsg + 1) % 10;
07089 
07090             if (vms->curmsg < 20) {
07091                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07092                res = wait_file2(chan, vms, nextmsg);
07093             } else {
07094                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07095                res = wait_file2(chan, vms, nextmsg);
07096                if (one > 0) {
07097                   if (!res) {
07098                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07099                      res = wait_file2(chan, vms, nextmsg);
07100                   }
07101                }
07102             }
07103          }
07104          if (!res)
07105             res = wait_file2(chan, vms, "vm-message");
07106       /* HEBREW syntax */
07107       } else if (!strncasecmp(chan->language, "he", 2)) {
07108          if (!vms->curmsg) {
07109             res = wait_file2(chan, vms, "vm-message");
07110             res = wait_file2(chan, vms, "vm-first");
07111          } else if (vms->curmsg == vms->lastmsg) {
07112             res = wait_file2(chan, vms, "vm-message");
07113             res = wait_file2(chan, vms, "vm-last");
07114          } else {
07115             res = wait_file2(chan, vms, "vm-message");
07116             res = wait_file2(chan, vms, "vm-number");
07117             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07118          }
07119       } else {
07120          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07121             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07122          } else { /* DEFAULT syntax */
07123             res = wait_file2(chan, vms, "vm-message");
07124          }
07125          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07126             if (!res) {
07127                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07128             }
07129          }
07130       }
07131    }
07132 
07133    if (!msg_cfg) {
07134       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07135       return 0;
07136    }
07137 
07138    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07139       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07140       DISPOSE(vms->curdir, vms->curmsg);
07141       ast_config_destroy(msg_cfg);
07142       return 0;
07143    }
07144 
07145    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07146    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07147    category = ast_variable_retrieve(msg_cfg, "message", "category");
07148 
07149    context = ast_variable_retrieve(msg_cfg, "message", "context");
07150    if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
07151       context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
07152    if (!res) {
07153       res = play_message_category(chan, category);
07154    }
07155    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07156       res = play_message_datetime(chan, vmu, origtime, filename);
07157    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07158       res = play_message_callerid(chan, vms, cid, context, 0);
07159    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07160       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07161    /* Allow pressing '1' to skip envelope / callerid */
07162    if (res == '1')
07163       res = 0;
07164    ast_config_destroy(msg_cfg);
07165 
07166    if (!res) {
07167       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07168       vms->heard[vms->curmsg] = 1;
07169 #ifdef IMAP_STORAGE
07170       /*IMAP storage stores any prepended message from a forward
07171        * as a separate file from the rest of the message
07172        */
07173       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07174          wait_file(chan, vms, vms->introfn);
07175       }
07176 #endif
07177       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07178          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07179          res = 0;
07180       }
07181    }
07182    DISPOSE(vms->curdir, vms->curmsg);
07183    return res;
07184 }

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

Definition at line 6937 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, ast_channel::language, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

06938 {
06939    int res = 0;
06940    int i;
06941    char *callerid, *name;
06942    char prefile[PATH_MAX] = "";
06943    
06944 
06945    /* If voicemail cid is not enabled, or we didn't get cid or context from
06946     * the attribute file, leave now.
06947     *
06948     * TODO Still need to change this so that if this function is called by the
06949     * message envelope (and someone is explicitly requesting to hear the CID),
06950     * it does not check to see if CID is enabled in the config file.
06951     */
06952    if ((cid == NULL)||(context == NULL))
06953       return res;
06954 
06955    /* Strip off caller ID number from name */
06956    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
06957    ast_callerid_parse(cid, &name, &callerid);
06958    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
06959       /* Check for internal contexts and only */
06960       /* say extension when the call didn't come from an internal context in the list */
06961       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
06962          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
06963          if ((strcmp(cidinternalcontexts[i], context) == 0))
06964             break;
06965       }
06966       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
06967          if (!res) {
06968             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
06969             if (!ast_strlen_zero(prefile)) {
06970             /* See if we can find a recorded name for this person instead of their extension number */
06971                if (ast_fileexists(prefile, NULL, NULL) > 0) {
06972                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
06973                   if (!callback)
06974                      res = wait_file2(chan, vms, "vm-from");
06975                   res = ast_stream_and_wait(chan, prefile, "");
06976                } else {
06977                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
06978                   /* Say "from extension" as one saying to sound smoother */
06979                   if (!callback)
06980                      res = wait_file2(chan, vms, "vm-from-extension");
06981                   res = ast_say_digit_str(chan, callerid, "", chan->language);
06982                }
06983             }
06984          }
06985       } else if (!res) {
06986          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
06987          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
06988          if (!callback)
06989             res = wait_file2(chan, vms, "vm-from-phonenumber");
06990          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
06991       }
06992    } else {
06993       /* Number unknown */
06994       ast_debug(1, "VM-CID: From an unknown number\n");
06995       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
06996       res = wait_file2(chan, vms, "vm-unknown-caller");
06997    }
06998    return res;
06999 }

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

Definition at line 6850 of file app_voicemail.c.

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

Referenced by play_message().

06851 {
06852    int res = 0;
06853 
06854    if (!ast_strlen_zero(category))
06855       res = ast_play_and_wait(chan, category);
06856 
06857    if (res) {
06858       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
06859       res = 0;
06860    }
06861 
06862    return res;
06863 }

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

Definition at line 6865 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(), ast_channel::language, 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().

06866 {
06867    int res = 0;
06868    struct vm_zone *the_zone = NULL;
06869    time_t t;
06870 
06871    if (ast_get_time_t(origtime, &t, 0, NULL)) {
06872       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
06873       return 0;
06874    }
06875 
06876    /* Does this user have a timezone specified? */
06877    if (!ast_strlen_zero(vmu->zonetag)) {
06878       /* Find the zone in the list */
06879       struct vm_zone *z;
06880       AST_LIST_LOCK(&zones);
06881       AST_LIST_TRAVERSE(&zones, z, list) {
06882          if (!strcmp(z->name, vmu->zonetag)) {
06883             the_zone = z;
06884             break;
06885          }
06886       }
06887       AST_LIST_UNLOCK(&zones);
06888    }
06889 
06890 /* No internal variable parsing for now, so we'll comment it out for the time being */
06891 #if 0
06892    /* Set the DIFF_* variables */
06893    ast_localtime(&t, &time_now, NULL);
06894    tv_now = ast_tvnow();
06895    ast_localtime(&tv_now, &time_then, NULL);
06896 
06897    /* Day difference */
06898    if (time_now.tm_year == time_then.tm_year)
06899       snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
06900    else
06901       snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
06902    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
06903 
06904    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
06905 #endif
06906    if (the_zone) {
06907       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
06908    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
06909       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06910    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
06911       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
06912    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
06913       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);
06914    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
06915       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
06916    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
06917       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
06918    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
06919       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
06920    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
06921       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);
06922    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
06923       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
06924    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
06925       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
06926    } else {
06927       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
06928    }
06929 #if 0
06930    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
06931 #endif
06932    return res;
06933 }

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

Definition at line 7001 of file app_voicemail.c.

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

Referenced by play_message().

07002 {
07003    int res = 0;
07004    int durationm;
07005    int durations;
07006    /* Verify that we have a duration for the message */
07007    if (duration == NULL)
07008       return res;
07009 
07010    /* Convert from seconds to minutes */
07011    durations=atoi(duration);
07012    durationm=(durations / 60);
07013 
07014    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07015 
07016    if ((!res) && (durationm >= minduration)) {
07017       res = wait_file2(chan, vms, "vm-duration");
07018 
07019       /* POLISH syntax */
07020       if (!strncasecmp(chan->language, "pl", 2)) {
07021          div_t num = div(durationm, 10);
07022 
07023          if (durationm == 1) {
07024             res = ast_play_and_wait(chan, "digits/1z");
07025             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07026          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07027             if (num.rem == 2) {
07028                if (!num.quot) {
07029                   res = ast_play_and_wait(chan, "digits/2-ie");
07030                } else {
07031                   res = say_and_wait(chan, durationm - 2 , chan->language);
07032                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07033                }
07034             } else {
07035                res = say_and_wait(chan, durationm, chan->language);
07036             }
07037             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07038          } else {
07039             res = say_and_wait(chan, durationm, chan->language);
07040             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07041          }
07042       /* DEFAULT syntax */
07043       } else {
07044          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07045          res = wait_file2(chan, vms, "vm-minutes");
07046       }
07047    }
07048    return res;
07049 }

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

11607 {
11608    /* Record message & let caller review or re-record it, or set options if applicable */
11609    int res = 0;
11610    int cmd = 0;
11611    int max_attempts = 3;
11612    int attempts = 0;
11613    int recorded = 0;
11614    int msg_exists = 0;
11615    signed char zero_gain = 0;
11616    char tempfile[PATH_MAX];
11617    char *acceptdtmf = "#";
11618    char *canceldtmf = "";
11619 
11620    /* Note that urgent and private are for flagging messages as such in the future */
11621 
11622    /* barf if no pointer passed to store duration in */
11623    if (duration == NULL) {
11624       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
11625       return -1;
11626    }
11627 
11628    if (!outsidecaller)
11629       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
11630    else
11631       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
11632 
11633    cmd = '3';  /* Want to start by recording */
11634 
11635    while ((cmd >= 0) && (cmd != 't')) {
11636       switch (cmd) {
11637       case '1':
11638          if (!msg_exists) {
11639             /* In this case, 1 is to record a message */
11640             cmd = '3';
11641             break;
11642          } else {
11643             /* Otherwise 1 is to save the existing message */
11644             ast_verb(3, "Saving message as is\n");
11645             if (!outsidecaller) 
11646                ast_filerename(tempfile, recordfile, NULL);
11647             ast_stream_and_wait(chan, "vm-msgsaved", "");
11648             if (!outsidecaller) {
11649                /* Saves to IMAP server only if imapgreeting=yes */
11650                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
11651                DISPOSE(recordfile, -1);
11652             }
11653             cmd = 't';
11654             return res;
11655          }
11656       case '2':
11657          /* Review */
11658          ast_verb(3, "Reviewing the message\n");
11659          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
11660          break;
11661       case '3':
11662          msg_exists = 0;
11663          /* Record */
11664          if (recorded == 1) 
11665             ast_verb(3, "Re-recording the message\n");
11666          else  
11667             ast_verb(3, "Recording the message\n");
11668          
11669          if (recorded && outsidecaller) {
11670             cmd = ast_play_and_wait(chan, INTRO);
11671             cmd = ast_play_and_wait(chan, "beep");
11672          }
11673          recorded = 1;
11674          /* 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 */
11675          if (record_gain)
11676             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
11677          if (ast_test_flag(vmu, VM_OPERATOR))
11678             canceldtmf = "0";
11679          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
11680          if (record_gain)
11681             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
11682          if (cmd == -1) {
11683             /* User has hung up, no options to give */
11684             if (!outsidecaller) {
11685                /* user was recording a greeting and they hung up, so let's delete the recording. */
11686                ast_filedelete(tempfile, NULL);
11687             }     
11688             return cmd;
11689          }
11690          if (cmd == '0') {
11691             break;
11692          } else if (cmd == '*') {
11693             break;
11694 #if 0
11695          } else if (vmu->review && (*duration < 5)) {
11696             /* Message is too short */
11697             ast_verb(3, "Message too short\n");
11698             cmd = ast_play_and_wait(chan, "vm-tooshort");
11699             cmd = ast_filedelete(tempfile, NULL);
11700             break;
11701          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
11702             /* Message is all silence */
11703             ast_verb(3, "Nothing recorded\n");
11704             cmd = ast_filedelete(tempfile, NULL);
11705             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
11706             if (!cmd)
11707                cmd = ast_play_and_wait(chan, "vm-speakup");
11708             break;
11709 #endif
11710          } else {
11711             /* If all is well, a message exists */
11712             msg_exists = 1;
11713             cmd = 0;
11714          }
11715          break;
11716       case '4':
11717          if (outsidecaller) {  /* only mark vm messages */
11718             /* Mark Urgent */
11719             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11720                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
11721                ast_debug(1000, "This message is too urgent!\n");
11722                res = ast_play_and_wait(chan, "vm-marked-urgent");
11723                strcpy(flag, "Urgent");
11724             } else if (flag) {
11725                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
11726                res = ast_play_and_wait(chan, "vm-urgent-removed");
11727                strcpy(flag, "");
11728             } else {
11729                ast_play_and_wait(chan, "vm-sorry");
11730             }
11731             cmd = 0;
11732          } else {
11733             cmd = ast_play_and_wait(chan, "vm-sorry");
11734          }
11735          break;
11736       case '5':
11737       case '6':
11738       case '7':
11739       case '8':
11740       case '9':
11741       case '*':
11742       case '#':
11743          cmd = ast_play_and_wait(chan, "vm-sorry");
11744          break;
11745 #if 0 
11746 /*  XXX Commented out for the moment because of the dangers of deleting
11747     a message while recording (can put the message numbers out of sync) */
11748       case '*':
11749          /* Cancel recording, delete message, offer to take another message*/
11750          cmd = ast_play_and_wait(chan, "vm-deleted");
11751          cmd = ast_filedelete(tempfile, NULL);
11752          if (outsidecaller) {
11753             res = vm_exec(chan, NULL);
11754             return res;
11755          }
11756          else
11757             return 1;
11758 #endif
11759       case '0':
11760          if (!ast_test_flag(vmu, VM_OPERATOR)) {
11761             cmd = ast_play_and_wait(chan, "vm-sorry");
11762             break;
11763          }
11764          if (msg_exists || recorded) {
11765             cmd = ast_play_and_wait(chan, "vm-saveoper");
11766             if (!cmd)
11767                cmd = ast_waitfordigit(chan, 3000);
11768             if (cmd == '1') {
11769                ast_play_and_wait(chan, "vm-msgsaved");
11770                cmd = '0';
11771             } else if (cmd == '4') {
11772                if (flag) {
11773                   ast_play_and_wait(chan, "vm-marked-urgent");
11774                   strcpy(flag, "Urgent");
11775                }
11776                ast_play_and_wait(chan, "vm-msgsaved");
11777                cmd = '0';
11778             } else {
11779                ast_play_and_wait(chan, "vm-deleted");
11780                DELETE(recordfile, -1, recordfile, vmu);
11781                cmd = '0';
11782             }
11783          }
11784          return cmd;
11785       default:
11786          /* If the caller is an ouside caller, and the review option is enabled,
11787             allow them to review the message, but let the owner of the box review
11788             their OGM's */
11789          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
11790             return cmd;
11791          if (msg_exists) {
11792             cmd = ast_play_and_wait(chan, "vm-review");
11793             if (!cmd && outsidecaller) {
11794                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
11795                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
11796                } else if (flag) {
11797                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
11798                }
11799             }
11800          } else {
11801             cmd = ast_play_and_wait(chan, "vm-torerecord");
11802             if (!cmd)
11803                cmd = ast_waitfordigit(chan, 600);
11804          }
11805          
11806          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
11807             cmd = ast_play_and_wait(chan, "vm-reachoper");
11808             if (!cmd)
11809                cmd = ast_waitfordigit(chan, 600);
11810          }
11811 #if 0
11812          if (!cmd)
11813             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
11814 #endif
11815          if (!cmd)
11816             cmd = ast_waitfordigit(chan, 6000);
11817          if (!cmd) {
11818             attempts++;
11819          }
11820          if (attempts > max_attempts) {
11821             cmd = 't';
11822          }
11823       }
11824    }
11825    if (outsidecaller)
11826       ast_play_and_wait(chan, "vm-goodbye");
11827    if (cmd == 't')
11828       cmd = 0;
11829    return cmd;
11830 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

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

10245 {
10246    int new = 0, old = 0, urgent = 0;
10247 
10248    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
10249 
10250    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
10251       mwi_sub->old_urgent = urgent;
10252       mwi_sub->old_new = new;
10253       mwi_sub->old_old = old;
10254       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
10255    }
10256 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

10259 {
10260    struct mwi_sub *mwi_sub;
10261 
10262    AST_RWLIST_RDLOCK(&mwi_subs);
10263    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
10264       if (!ast_strlen_zero(mwi_sub->mailbox)) {
10265          poll_subscribed_mailbox(mwi_sub);
10266       }
10267    }
10268    AST_RWLIST_UNLOCK(&mwi_subs);
10269 }

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 921 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::emailbody, ast_vm_user::emailsubject, 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().

00922 {
00923    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00924    if (saydurationminfo)
00925       vmu->saydurationm = saydurationminfo;
00926    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00927    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00928    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00929    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00930    if (vmmaxsecs)
00931       vmu->maxsecs = vmmaxsecs;
00932    if (maxmsg)
00933       vmu->maxmsg = maxmsg;
00934    if (maxdeletedmsg)
00935       vmu->maxdeletedmsg = maxdeletedmsg;
00936    vmu->volgain = volgain;
00937    vmu->emailsubject = NULL;
00938    vmu->emailbody = NULL;
00939 }

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

References ast_callerid_merge(), ast_callerid_split(), ast_config_destroy(), ast_config_load, ast_localtime(), ast_log(), 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().

03978 {
03979    char callerid[256];
03980    char fromdir[256], fromfile[256];
03981    struct ast_config *msg_cfg;
03982    const char *origcallerid, *origtime;
03983    char origcidname[80], origcidnum[80], origdate[80];
03984    int inttime;
03985    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
03986 
03987    /* Prepare variables for substitution in email body and subject */
03988    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
03989    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
03990    snprintf(passdata, passdatasize, "%d", msgnum);
03991    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
03992    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
03993    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
03994    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
03995       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
03996    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
03997    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
03998    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
03999    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04000    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04001 
04002    /* Retrieve info from VM attribute file */
04003    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04004    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04005    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04006       strcat(fromfile, ".txt");
04007    }
04008    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04009       if (option_debug > 0) {
04010          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04011       }
04012       return;
04013    }
04014 
04015    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04016       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04017       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04018       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04019       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04020    }
04021 
04022    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04023       struct timeval tv = { inttime, };
04024       struct ast_tm tm;
04025       ast_localtime(&tv, &tm, NULL);
04026       ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
04027       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04028    }
04029    ast_config_destroy(msg_cfg);
04030 }

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

Definition at line 6446 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(), and ast_strlen_zero().

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

06447 {
06448    struct ast_event *event;
06449    char *mailbox, *context;
06450 
06451    /* Strip off @default */
06452    context = mailbox = ast_strdupa(box);
06453    strsep(&context, "@");
06454    if (ast_strlen_zero(context))
06455       context = "default";
06456 
06457    if (!(event = ast_event_new(AST_EVENT_MWI,
06458          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06459          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06460          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06461          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06462          AST_EVENT_IE_END))) {
06463       return;
06464    }
06465 
06466    ast_event_queue_and_cache(event);
06467 }

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

Referenced by __ast_app_separate_args(), and make_email_file().

04040 {
04041    char *ptr = to;
04042    *ptr++ = '"';
04043    for (; ptr < to + len - 1; from++) {
04044       if (*from == '"')
04045          *ptr++ = '\\';
04046       else if (*from == '\0')
04047          break;
04048       *ptr++ = *from;
04049    }
04050    if (ptr < to + len - 1)
04051       *ptr++ = '"';
04052    *ptr = '\0';
04053    return to;
04054 }

static int reload ( void   )  [static]

Definition at line 11275 of file app_voicemail.c.

References load_config().

11276 {
11277    return load_config(1);
11278 }

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

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

03658 {
03659    char stxt[PATH_MAX];
03660    char dtxt[PATH_MAX];
03661    ast_filerename(sfn,dfn,NULL);
03662    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03663    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03664    if (ast_check_realtime("voicemail_data")) {
03665       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03666    }
03667    rename(stxt, dtxt);
03668 }

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

01332 {
01333    /* This function could be made to generate one from a database, too */
01334    struct ast_vm_user *cur;
01335    int res = -1;
01336    AST_LIST_LOCK(&users);
01337    AST_LIST_TRAVERSE(&users, cur, list) {
01338       if ((!context || !strcasecmp(context, cur->context)) &&
01339          (!strcasecmp(mailbox, cur->mailbox)))
01340             break;
01341    }
01342    if (cur) {
01343       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01344       res = 0;
01345    }
01346    AST_LIST_UNLOCK(&users);
01347    return res;
01348 }

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

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

05079 {
05080    char arguments[255];
05081    char ext_context[256] = "";
05082    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05083    struct ast_smdi_mwi_message *mwi_msg;
05084 
05085    if (!ast_strlen_zero(context))
05086       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05087    else
05088       ast_copy_string(ext_context, extension, sizeof(ext_context));
05089 
05090    if (smdi_iface) {
05091       if (ast_app_has_voicemail(ext_context, NULL)) 
05092          ast_smdi_mwi_set(smdi_iface, extension);
05093       else
05094          ast_smdi_mwi_unset(smdi_iface, extension);
05095 
05096       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05097          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05098          if (!strncmp(mwi_msg->cause, "INV", 3))
05099             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05100          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05101             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05102          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05103          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05104       } else {
05105          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05106       }
05107    }
05108 
05109    if (!ast_strlen_zero(externnotify)) {
05110       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05111          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05112       } else {
05113          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05114          ast_debug(1, "Executing %s\n", arguments);
05115          ast_safe_system(arguments);
05116       }
05117    }
05118 }

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

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

05666 {
05667 #ifdef IMAP_STORAGE
05668    /* we must use mbox(x) folder names, and copy the message there */
05669    /* simple. huh? */
05670    char sequence[10];
05671    char mailbox[256];
05672    int res;
05673 
05674    /* get the real IMAP message number for this message */
05675    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
05676    
05677    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(box));
05678    ast_mutex_lock(&vms->lock);
05679    /* if save to Old folder, put in INBOX as read */
05680    if (box == OLD_FOLDER) {
05681       mail_setflag(vms->mailstream, sequence, "\\Seen");
05682       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
05683    } else if (box == NEW_FOLDER) {
05684       mail_setflag(vms->mailstream, sequence, "\\Unseen");
05685       mail_clearflag(vms->mailstream, sequence, "\\Seen");
05686    }
05687    if (!strcasecmp(mbox(NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
05688       ast_mutex_unlock(&vms->lock);
05689       return 0;
05690    }
05691    /* Create the folder if it don't exist */
05692    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
05693    ast_debug(5, "Checking if folder exists: %s\n",mailbox);
05694    if (mail_create(vms->mailstream, mailbox) == NIL) 
05695       ast_debug(5, "Folder exists.\n");
05696    else
05697       ast_log(AST_LOG_NOTICE, "Folder %s created!\n",mbox(box));
05698    res = !mail_copy(vms->mailstream, sequence, (char *)mbox(box));
05699    ast_mutex_unlock(&vms->lock);
05700    return res;
05701 #else
05702    char *dir = vms->curdir;
05703    char *username = vms->username;
05704    char *context = vmu->context;
05705    char sfn[PATH_MAX];
05706    char dfn[PATH_MAX];
05707    char ddir[PATH_MAX];
05708    const char *dbox = mbox(box);
05709    int x, i;
05710    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
05711 
05712    if (vm_lock_path(ddir))
05713       return ERROR_LOCK_PATH;
05714 
05715    x = last_message_index(vmu, ddir) + 1;
05716 
05717    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
05718       x--;
05719       for (i = 1; i <= x; i++) {
05720          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
05721          make_file(sfn, sizeof(sfn), ddir, i);
05722          make_file(dfn, sizeof(dfn), ddir, i - 1);
05723          if (EXISTS(ddir, i, sfn, NULL)) {
05724             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
05725          } else
05726             break;
05727       }
05728    } else {
05729       if (x >= vmu->maxmsg) {
05730          ast_unlock_path(ddir);
05731          return -1;
05732       }
05733    }
05734    make_file(sfn, sizeof(sfn), dir, msg);
05735    make_file(dfn, sizeof(dfn), ddir, x);
05736    if (strcmp(sfn, dfn)) {
05737       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
05738    }
05739    ast_unlock_path(ddir);
05740 #endif
05741    return 0;
05742 }

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

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

Referenced by load_module().

11262 {
11263    int res = -1;
11264    char dir[PATH_MAX];
11265    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
11266    ast_debug(2, "About to try retrieving name file %s\n", dir);
11267    RETRIEVE(dir, -1, mailbox, context);
11268    if (ast_fileexists(dir, NULL, NULL)) {
11269       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
11270    }
11271    DISPOSE(dir, -1);
11272    return res;
11273 }

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

04486 {
04487    FILE *p=NULL;
04488    char tmp[80] = "/tmp/astmail-XXXXXX";
04489    char tmp2[256];
04490 
04491    if (vmu && ast_strlen_zero(vmu->email)) {
04492       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04493       return(0);
04494    }
04495    if (!strcmp(format, "wav49"))
04496       format = "WAV";
04497    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));
04498    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04499       command hangs */
04500    if ((p = vm_mkftemp(tmp)) == NULL) {
04501       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04502       return -1;
04503    } else {
04504       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04505       fclose(p);
04506       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04507       ast_safe_system(tmp2);
04508       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04509    }
04510    return 0;
04511 }

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 4513 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, pagerbody, pagerfromstring, pagersubject, pbx_substitute_variables_helper(), prep_email_sub_vars(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

04514 {
04515    char date[256];
04516    char host[MAXHOSTNAMELEN] = "";
04517    char who[256];
04518    char dur[PATH_MAX];
04519    char tmp[80] = "/tmp/astmail-XXXXXX";
04520    char tmp2[PATH_MAX];
04521    struct ast_tm tm;
04522    FILE *p;
04523 
04524    if ((p = vm_mkftemp(tmp)) == NULL) {
04525       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04526       return -1;
04527    }
04528    gethostname(host, sizeof(host)-1);
04529    if (strchr(srcemail, '@'))
04530       ast_copy_string(who, srcemail, sizeof(who));
04531    else 
04532       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04533    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04534    ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
04535    fprintf(p, "Date: %s\n", date);
04536 
04537    if (*pagerfromstring) {
04538       struct ast_channel *ast;
04539       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04540          char *passdata;
04541          int vmlen = strlen(fromstring)*3 + 200;
04542          passdata = alloca(vmlen);
04543          memset(passdata, 0, vmlen);
04544          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04545          pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
04546          fprintf(p, "From: %s <%s>\n", passdata, who);
04547          ast_channel_free(ast);
04548       } else 
04549          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04550    } else
04551       fprintf(p, "From: Asterisk PBX <%s>\n", who);
04552    fprintf(p, "To: %s\n", pager);
04553    if (pagersubject) {
04554       struct ast_channel *ast;
04555       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04556          char *passdata;
04557          int vmlen = strlen(pagersubject) * 3 + 200;
04558          passdata = alloca(vmlen);
04559          memset(passdata, 0, vmlen);
04560          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04561          pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
04562          fprintf(p, "Subject: %s\n\n", passdata);
04563          ast_channel_free(ast);
04564       } else
04565          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04566    } else {
04567       if (ast_strlen_zero(flag)) {
04568          fprintf(p, "Subject: New VM\n\n");
04569       } else {
04570          fprintf(p, "Subject: New %s VM\n\n", flag);
04571       }
04572    }
04573 
04574    ast_strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
04575    if (pagerbody) {
04576       struct ast_channel *ast;
04577       if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
04578          char *passdata;
04579          int vmlen = strlen(pagerbody) * 3 + 200;
04580          passdata = alloca(vmlen);
04581          memset(passdata, 0, vmlen);
04582          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
04583          pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
04584          fprintf(p, "%s\n", passdata);
04585          ast_channel_free(ast);
04586       } else
04587          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04588    } else {
04589       fprintf(p, "New %s long %s msg in box %s\n"
04590             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04591    }
04592    fclose(p);
04593    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04594    ast_safe_system(tmp2);
04595    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04596    return 0;
04597 }

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

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

10043 {
10044    struct ast_config *cfg;
10045    const char *cat = NULL;
10046 
10047    if (!(cfg = ast_load_realtime_multientry("voicemail", 
10048       "context", context, SENTINEL))) {
10049       return CLI_FAILURE;
10050    }
10051 
10052    ast_cli(fd,
10053       "\n"
10054       "=============================================================\n"
10055       "=== Configured Voicemail Users ==============================\n"
10056       "=============================================================\n"
10057       "===\n");
10058 
10059    while ((cat = ast_category_browse(cfg, cat))) {
10060       struct ast_variable *var = NULL;
10061       ast_cli(fd,
10062          "=== Mailbox ...\n"
10063          "===\n");
10064       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
10065          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
10066       ast_cli(fd,
10067          "===\n"
10068          "=== ---------------------------------------------------------\n"
10069          "===\n");
10070    }
10071 
10072    ast_cli(fd,
10073       "=============================================================\n"
10074       "\n");
10075 
10076    ast_config_destroy(cfg);
10077 
10078    return CLI_SUCCESS;
10079 }

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

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

10414 {
10415    poll_thread_run = 0;
10416 
10417    if (mwi_sub_sub) {
10418       ast_event_unsubscribe(mwi_sub_sub);
10419       mwi_sub_sub = NULL;
10420    }
10421 
10422    if (mwi_unsub_sub) {
10423       ast_event_unsubscribe(mwi_unsub_sub);
10424       mwi_unsub_sub = NULL;
10425    }
10426 
10427    ast_mutex_lock(&poll_lock);
10428    ast_cond_signal(&poll_cond);
10429    ast_mutex_unlock(&poll_lock);
10430 
10431    pthread_join(poll_thread, NULL);
10432 
10433    poll_thread = AST_PTHREADT_NULL;
10434 }

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

Referenced by make_email_file().

00893 {
00894    char *bufptr = buf;
00895    for (; *input; input++) {
00896       if (*input < 32) {
00897          continue;
00898       }
00899       *bufptr++ = *input;
00900       if (bufptr == buf + buflen - 1) {
00901          break;
00902       }
00903    }
00904    *bufptr = '\0';
00905    return buf;
00906 }

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

Definition at line 10559 of file app_voicemail.c.

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

Referenced by load_config().

10560 {
10561    char *current;
10562 
10563    /* Add 16 for fudge factor */
10564    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
10565 
10566    ast_str_reset(str);
10567    
10568    /* Substitute strings \r, \n, and \t into the appropriate characters */
10569    for (current = (char *) value; *current; current++) {
10570       if (*current == '\\') {
10571          current++;
10572          if (!*current) {
10573             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
10574             break;
10575          }
10576          switch (*current) {
10577          case 'r':
10578             ast_str_append(&str, 0, "\r");
10579             break;
10580          case 'n':
10581 #ifdef IMAP_STORAGE
10582             if (!str->used || str->str[str->used - 1] != '\r') {
10583                ast_str_append(&str, 0, "\r");
10584             }
10585 #endif
10586             ast_str_append(&str, 0, "\n");
10587             break;
10588          case 't':
10589             ast_str_append(&str, 0, "\t");
10590             break;
10591          default:
10592             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
10593             break;
10594          }
10595       } else {
10596          ast_str_append(&str, 0, "%c", *current);
10597       }
10598    }
10599 
10600    return ast_str_buffer(str);
10601 }

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 8999 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_channel::language, ast_vm_user::password, and vm_password.

Referenced by vm_execmain(), and vmauthenticate().

09002 {
09003    int useadsi=0, valid=0, logretries=0;
09004    char password[AST_MAX_EXTENSION]="", *passptr;
09005    struct ast_vm_user vmus, *vmu = NULL;
09006 
09007    /* If ADSI is supported, setup login screen */
09008    adsi_begin(chan, &useadsi);
09009    if (!skipuser && useadsi)
09010       adsi_login(chan);
09011    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09012       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09013       return -1;
09014    }
09015    
09016    /* Authenticate them and get their mailbox/password */
09017    
09018    while (!valid && (logretries < max_logins)) {
09019       /* Prompt for, and read in the username */
09020       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09021          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09022          return -1;
09023       }
09024       if (ast_strlen_zero(mailbox)) {
09025          if (chan->cid.cid_num) {
09026             ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
09027          } else {
09028             ast_verb(3,"Username not entered\n");  
09029             return -1;
09030          }
09031       }
09032       if (useadsi)
09033          adsi_password(chan);
09034 
09035       if (!ast_strlen_zero(prefix)) {
09036          char fullusername[80] = "";
09037          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09038          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09039          ast_copy_string(mailbox, fullusername, mailbox_size);
09040       }
09041 
09042       ast_debug(1, "Before find user for mailbox %s\n",mailbox);
09043       vmu = find_user(&vmus, context, mailbox);
09044       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09045          /* saved password is blank, so don't bother asking */
09046          password[0] = '\0';
09047       } else {
09048          if (ast_streamfile(chan, vm_password, chan->language)) {
09049             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09050             return -1;
09051          }
09052          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09053             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09054             return -1;
09055          }
09056       }
09057 
09058       if (vmu) {
09059          passptr = vmu->password;
09060          if (passptr[0] == '-') passptr++;
09061       }
09062       if (vmu && !strcmp(passptr, password))
09063          valid++;
09064       else {
09065          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09066          if (!ast_strlen_zero(prefix))
09067             mailbox[0] = '\0';
09068       }
09069       logretries++;
09070       if (!valid) {
09071          if (skipuser || logretries >= max_logins) {
09072             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09073                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09074                return -1;
09075             }
09076          } else {
09077             if (useadsi)
09078                adsi_login(chan);
09079             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09080                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09081                return -1;
09082             }
09083          }
09084          if (ast_waitstream(chan, "")) /* Channel is hung up */
09085             return -1;
09086       }
09087    }
09088    if (!valid && (logretries >= max_logins)) {
09089       ast_stopstream(chan);
09090       ast_play_and_wait(chan, "vm-goodbye");
09091       return -1;
09092    }
09093    if (vmu && !skipuser) {
09094       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09095    }
09096    return 0;
09097 }

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

Definition at line 9942 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_strlen_zero(), find_user(), mbox(), and pbx_builtin_setvar_helper().

Referenced by load_module().

09943 {
09944    struct ast_vm_user svm;
09945    char *context, *box;
09946    AST_DECLARE_APP_ARGS(args,
09947       AST_APP_ARG(mbox);
09948       AST_APP_ARG(options);
09949    );
09950    static int dep_warning = 0;
09951 
09952    if (ast_strlen_zero(data)) {
09953       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
09954       return -1;
09955    }
09956 
09957    if (!dep_warning) {
09958       dep_warning = 1;
09959       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *)data);
09960    }
09961 
09962    box = ast_strdupa(data);
09963 
09964    AST_STANDARD_APP_ARGS(args, box);
09965 
09966    if (args.options) {
09967    }
09968 
09969    if ((context = strchr(args.mbox, '@'))) {
09970       *context = '\0';
09971       context++;
09972    }
09973 
09974    if (find_user(&svm, context, args.mbox)) {
09975       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
09976    } else
09977       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
09978 
09979    return 0;
09980 }

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

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

Referenced by vm_execmain().

08981 {
08982    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
08983       return vm_browse_messages_es(chan, vms, vmu);
08984    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
08985       return vm_browse_messages_gr(chan, vms, vmu);
08986    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
08987       return vm_browse_messages_he(chan, vms, vmu);
08988    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
08989       return vm_browse_messages_it(chan, vms, vmu);
08990    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
08991       return vm_browse_messages_pt(chan, vms, vmu);
08992    } else if (!strncasecmp(chan->language, "zh", 2)) {
08993       return vm_browse_messages_zh(chan, vms, vmu);   /* CHINESE (Taiwan) */
08994    } else {                                             /* Default to English syntax */
08995       return vm_browse_messages_en(chan, vms, vmu);
08996    }
08997 }

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

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

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

08898 {
08899    int cmd=0;
08900 
08901    if (vms->lastmsg > -1) {
08902       cmd = play_message(chan, vmu, vms);
08903    } else {
08904       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08905       if (!cmd)
08906          cmd = ast_play_and_wait(chan, "vm-messages");
08907       if (!cmd) {
08908          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08909          cmd = ast_play_and_wait(chan, vms->fn);
08910       }
08911    }
08912    return cmd;
08913 }

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

08792 {
08793    int cmd=0;
08794 
08795    if (vms->lastmsg > -1) {
08796       cmd = play_message(chan, vmu, vms);
08797    } else {
08798       cmd = ast_play_and_wait(chan, "vm-youhaveno");
08799       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
08800          if (!cmd) {
08801             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
08802             cmd = ast_play_and_wait(chan, vms->fn);
08803          }
08804          if (!cmd)
08805             cmd = ast_play_and_wait(chan, "vm-messages");
08806       } else {
08807          if (!cmd)
08808             cmd = ast_play_and_wait(chan, "vm-messages");
08809          if (!cmd) {
08810             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08811             cmd = ast_play_and_wait(chan, vms->fn);
08812          }
08813       }
08814    } 
08815    return cmd;
08816 }

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

Definition at line 8819 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

08820 {
08821    int cmd = 0;
08822 
08823    if (vms->lastmsg > -1) {
08824       cmd = play_message(chan, vmu, vms);
08825    } else {
08826       if (!strcasecmp(vms->fn, "INBOX")) {
08827          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
08828       } else {
08829          cmd = ast_play_and_wait(chan, "vm-nomessages");
08830       }
08831    }
08832    return cmd;
08833 }

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

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

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

08924 {
08925    int cmd=0;
08926 
08927    if (vms->lastmsg > -1) {
08928       cmd = play_message(chan, vmu, vms);
08929    } else {
08930       cmd = ast_play_and_wait(chan, "vm-no");
08931       if (!cmd) {
08932          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08933          cmd = ast_play_and_wait(chan, vms->fn);
08934       }
08935       if (!cmd)
08936          cmd = ast_play_and_wait(chan, "vm-messages");
08937    }
08938    return cmd;
08939 }

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

08950 {
08951    int cmd=0;
08952 
08953    if (vms->lastmsg > -1) {
08954       cmd = play_message(chan, vmu, vms);
08955    } else {
08956       cmd = ast_play_and_wait(chan, "vm-you");
08957       if (!cmd) 
08958          cmd = ast_play_and_wait(chan, "vm-haveno");
08959       if (!cmd)
08960          cmd = ast_play_and_wait(chan, "vm-messages");
08961       if (!cmd) {
08962          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
08963          cmd = ast_play_and_wait(chan, vms->fn);
08964       }
08965    }
08966    return cmd;
08967 }

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

References ast_category_browse(), ast_category_get(), ast_config_load, ast_config_text_file_save(), 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_STATUS_FILEINVALID, 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().

01358 {
01359    struct ast_config   *cfg=NULL;
01360    struct ast_variable *var=NULL;
01361    struct ast_category *cat=NULL;
01362    char *category=NULL, *value=NULL, *new=NULL;
01363    const char *tmp=NULL;
01364    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01365    if (!change_password_realtime(vmu, newpassword))
01366       return;
01367 
01368    /* check voicemail.conf */
01369    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01370       while ((category = ast_category_browse(cfg, category))) {
01371          if (!strcasecmp(category, vmu->context)) {
01372             if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01373                ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01374                break;
01375             }
01376             value = strstr(tmp,",");
01377             if (!value) {
01378                ast_log(AST_LOG_WARNING, "variable has bad format.\n");
01379                break;
01380             }
01381             new = alloca((strlen(value)+strlen(newpassword)+1));
01382             sprintf(new,"%s%s", newpassword, value);
01383             if (!(cat = ast_category_get(cfg, category))) {
01384                ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01385                break;
01386             }
01387             ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01388          }
01389       }
01390       /* save the results */
01391       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01392       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01393       ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01394    }
01395    category = NULL;
01396    var = NULL;
01397    /* check users.conf and update the password stored for the mailbox*/
01398    /* if no vmsecret entry exists create one. */
01399    if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01400       ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01401       while ((category = ast_category_browse(cfg, category))) {
01402          ast_debug(4, "users.conf: %s\n", category);
01403          if (!strcasecmp(category, vmu->mailbox)) {
01404             if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01405                ast_debug(3, "looks like we need to make vmsecret!\n");
01406                var = ast_variable_new("vmsecret", newpassword, "");
01407             } 
01408             new = alloca(strlen(newpassword)+1);
01409             sprintf(new, "%s", newpassword);
01410             if (!(cat = ast_category_get(cfg, category))) {
01411                ast_debug(4, "failed to get category!\n");
01412                break;
01413             }
01414             if (!var)      
01415                ast_variable_update(cat, "vmsecret", new, NULL, 0);
01416             else
01417                ast_variable_append(cat, var);
01418          }
01419       }
01420       /* save the results and clean things up */
01421       reset_user_pw(vmu->context, vmu->mailbox, newpassword);  
01422       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01423       ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01424    }
01425 }

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

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

01428 {
01429    char buf[255];
01430    snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
01431    if (!ast_safe_system(buf)) {
01432       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01433       /* Reset the password in memory, too */
01434       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01435    }
01436 }

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

Definition at line 1050 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(), errno, and LOG_WARNING.

Referenced by check_password().

01051 {
01052    int fds[2], pid = 0;
01053 
01054    memset(buf, 0, len);
01055 
01056    if (pipe(fds)) {
01057       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01058    } else {
01059       /* good to go*/
01060       pid = ast_safe_fork(0);
01061 
01062       if (pid < 0) {
01063          /* ok maybe not */
01064          close(fds[0]);
01065          close(fds[1]);
01066          snprintf(buf, len, "FAILURE: Fork failed");
01067       } else if (pid) {
01068          /* parent */
01069          close(fds[1]);
01070          if (read(fds[0], buf, len) < 0) {
01071             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01072          }
01073          close(fds[0]);
01074       } else {
01075          /*  child */
01076          AST_DECLARE_APP_ARGS(arg,
01077             AST_APP_ARG(v)[20];
01078          );
01079          char *mycmd = ast_strdupa(command);
01080 
01081          close(fds[0]);
01082          dup2(fds[1], STDOUT_FILENO);
01083          close(fds[1]);
01084          ast_close_fds_above_n(STDOUT_FILENO);
01085 
01086          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01087 
01088          execv(arg.v[0], arg.v); 
01089          printf("FAILURE: %s", strerror(errno));
01090          _exit(0);
01091       }
01092    }
01093    return buf;
01094 }

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

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

Referenced by copy_message(), and notify_new_message().

03835 {
03836    char *txt;
03837    int txtsize = 0;
03838 
03839    txtsize = (strlen(file) + 5)*sizeof(char);
03840    txt = alloca(txtsize);
03841    /* Sprintf here would safe because we alloca'd exactly the right length,
03842     * but trying to eliminate all sprintf's anyhow
03843     */
03844    if (ast_check_realtime("voicemail_data")) {
03845       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
03846    }
03847    snprintf(txt, txtsize, "%s.txt", file);
03848    unlink(txt);
03849    return ast_filedelete(file, NULL);
03850 }

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

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

09811 {
09812    int res = 0;
09813    char *tmp;
09814    struct leave_vm_options leave_options;
09815    struct ast_flags flags = { 0 };
09816    char *opts[OPT_ARG_ARRAY_SIZE];
09817    AST_DECLARE_APP_ARGS(args,
09818       AST_APP_ARG(argv0);
09819       AST_APP_ARG(argv1);
09820    );
09821    
09822    memset(&leave_options, 0, sizeof(leave_options));
09823 
09824    if (chan->_state != AST_STATE_UP)
09825       ast_answer(chan);
09826 
09827    if (!ast_strlen_zero(data)) {
09828       tmp = ast_strdupa(data);
09829       AST_STANDARD_APP_ARGS(args, tmp);
09830       if (args.argc == 2) {
09831          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09832             return -1;
09833          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
09834          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09835             int gain;
09836 
09837             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09838                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09839                return -1;
09840             } else {
09841                leave_options.record_gain = (signed char) gain;
09842             }
09843          }
09844          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
09845             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
09846                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
09847          }
09848       }
09849    } else {
09850       char temp[256];
09851       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
09852       if (res < 0)
09853          return res;
09854       if (ast_strlen_zero(temp))
09855          return 0;
09856       args.argv0 = ast_strdupa(temp);
09857    }
09858 
09859    res = leave_voicemail(chan, args.argv0, &leave_options);
09860 
09861    if (res == ERROR_LOCK_PATH) {
09862       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
09863       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
09864       res = 0;
09865    }
09866 
09867    return res;
09868 }

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

Definition at line 9099 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_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, ast_channel::language, 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().

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

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

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

Referenced by forward_message().

06309 {
06310 #ifdef IMAP_STORAGE
06311    int res;
06312 #endif
06313    int cmd = 0;
06314    int retries = 0, prepend_duration = 0, already_recorded = 0;
06315    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06316    char textfile[PATH_MAX];
06317    struct ast_config *msg_cfg;
06318    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06319 #ifndef IMAP_STORAGE
06320    signed char zero_gain = 0;
06321 #endif
06322    const char *duration_str;
06323 
06324    /* Must always populate duration correctly */
06325    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06326    strcpy(textfile, msgfile);
06327    strcpy(backup, msgfile);
06328    strcpy(backup_textfile, msgfile);
06329    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06330    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06331    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06332 
06333    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06334       *duration = atoi(duration_str);
06335    } else {
06336       *duration = 0;
06337    }
06338 
06339    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06340       if (cmd)
06341          retries = 0;
06342       switch (cmd) {
06343       case '1': 
06344 
06345 #ifdef IMAP_STORAGE
06346          /* Record new intro file */
06347          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06348          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06349          res = ast_play_and_wait(chan, INTRO);
06350          res = ast_play_and_wait(chan, "beep");
06351          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *)duration, NULL, record_gain, vms, flag);
06352          cmd = 't';
06353 #else
06354 
06355          /* prepend a message to the current message, update the metadata and return */
06356 
06357          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06358          strcpy(textfile, msgfile);
06359          strncat(textfile, ".txt", sizeof(textfile) - 1);
06360          *duration = 0;
06361 
06362          /* if we can't read the message metadata, stop now */
06363          if (!msg_cfg) {
06364             cmd = 0;
06365             break;
06366          }
06367          
06368          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06369          if (already_recorded) {
06370             ast_filecopy(backup, msgfile, NULL);
06371             copy(backup_textfile, textfile);
06372          }
06373          else {
06374             ast_filecopy(msgfile, backup, NULL);
06375             copy(textfile,backup_textfile);
06376          }
06377          already_recorded = 1;
06378 
06379          if (record_gain)
06380             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06381 
06382          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06383          if (record_gain)
06384             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06385 
06386          
06387          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06388             *duration = atoi(duration_str);
06389 
06390          if (prepend_duration) {
06391             struct ast_category *msg_cat;
06392             /* need enough space for a maximum-length message duration */
06393             char duration_buf[12];
06394 
06395             *duration += prepend_duration;
06396             msg_cat = ast_category_get(msg_cfg, "message");
06397             snprintf(duration_buf, 11, "%ld", *duration);
06398             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06399                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06400             }
06401          }
06402 
06403 #endif
06404          break;
06405       case '2': 
06406          /* NULL out introfile so we know there is no intro! */
06407 #ifdef IMAP_STORAGE
06408          *vms->introfn = '\0';
06409 #endif
06410          cmd = 't';
06411          break;
06412       case '*':
06413          cmd = '*';
06414          break;
06415       default: 
06416          cmd = ast_play_and_wait(chan,"vm-forwardoptions");
06417             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06418          if (!cmd)
06419             cmd = ast_play_and_wait(chan,"vm-starmain");
06420             /* "press star to return to the main menu" */
06421          if (!cmd)
06422             cmd = ast_waitfordigit(chan,6000);
06423          if (!cmd)
06424             retries++;
06425          if (retries > 3)
06426             cmd = 't';
06427       }
06428    }
06429 
06430    if (msg_cfg)
06431       ast_config_destroy(msg_cfg);
06432    if (prepend_duration)
06433       *duration = prepend_duration;
06434 
06435    if (already_recorded && cmd == -1) {
06436       /* restore original message if prepention cancelled */
06437       ast_filerename(backup, msgfile, NULL);
06438       rename(backup_textfile, textfile);
06439    }
06440 
06441    if (cmd == 't' || cmd == 'S')
06442       cmd = 0;
06443    return cmd;
06444 }

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

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

Referenced by vm_execmain().

08484 {
08485    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08486       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08487    } else {             /* Default to ENGLISH */
08488       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08489    }
08490 }

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

08383 {
08384    int res = 0;
08385    /* Play instructions and wait for new command */
08386    while (!res) {
08387       if (vms->starting) {
08388          if (vms->lastmsg > -1) {
08389             if (skipadvanced)
08390                res = ast_play_and_wait(chan, "vm-onefor-full");
08391             else
08392                res = ast_play_and_wait(chan, "vm-onefor");
08393             if (!res)
08394                res = vm_play_folder_name(chan, vms->vmbox);
08395          }
08396          if (!res) {
08397             if (skipadvanced)
08398                res = ast_play_and_wait(chan, "vm-opts-full");
08399             else
08400                res = ast_play_and_wait(chan, "vm-opts");
08401          }
08402       } else {
08403          /* Added for additional help */
08404          if (skipadvanced) {
08405             res = ast_play_and_wait(chan, "vm-onefor-full");
08406             if (!res)
08407                res = vm_play_folder_name(chan, vms->vmbox);
08408             res = ast_play_and_wait(chan, "vm-opts-full");
08409          }
08410          /* Logic:
08411           * If the current message is not the first OR
08412           * if we're listening to the first new message and there are
08413           * also urgent messages, then prompt for navigation to the
08414           * previous message
08415           */
08416          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08417             res = ast_play_and_wait(chan, "vm-prev");
08418          }
08419          if (!res && !skipadvanced)
08420             res = ast_play_and_wait(chan, "vm-advopts");
08421          if (!res)
08422             res = ast_play_and_wait(chan, "vm-repeat");
08423          /* Logic:
08424           * If we're not listening to the last message OR
08425           * we're listening to the last urgent message and there are
08426           * also new non-urgent messages, then prompt for navigation
08427           * to the next message
08428           */
08429          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08430             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08431             res = ast_play_and_wait(chan, "vm-next");
08432          }
08433          if (!res) {
08434             if (!vms->deleted[vms->curmsg])
08435                res = ast_play_and_wait(chan, "vm-delete");
08436             else
08437                res = ast_play_and_wait(chan, "vm-undelete");
08438             if (!res)
08439                res = ast_play_and_wait(chan, "vm-toforward");
08440             if (!res)
08441                res = ast_play_and_wait(chan, "vm-savemessage");
08442          }
08443       }
08444       if (!res) {
08445          res = ast_play_and_wait(chan, "vm-helpexit");
08446       }
08447       if (!res)
08448          res = ast_waitfordigit(chan, 6000);
08449       if (!res) {
08450          vms->repeats++;
08451          if (vms->repeats > 2) {
08452             res = 't';
08453          }
08454       }
08455    }
08456    return res;
08457 }

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

08460 {
08461    int res = 0;
08462    /* Play instructions and wait for new command */
08463    while (!res) {
08464       if (vms->lastmsg > -1) {
08465          res = ast_play_and_wait(chan, "vm-listen");
08466          if (!res)
08467             res = vm_play_folder_name(chan, vms->vmbox);
08468          if (!res)
08469             res = ast_play_and_wait(chan, "press");
08470          if (!res)
08471             res = ast_play_and_wait(chan, "digits/1");
08472       }
08473       if (!res)
08474          res = ast_play_and_wait(chan, "vm-opts");
08475       if (!res) {
08476          vms->starting = 0;
08477          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08478       }
08479    }
08480    return res;
08481 }

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

Definition at line 8323 of file app_voicemail.c.

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

Referenced by vm_execmain().

08324 {
08325    char prefile[256];
08326    
08327    /* Notify the user that the temp greeting is set and give them the option to remove it */
08328    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08329    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08330       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08331       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08332          ast_play_and_wait(chan, "vm-tempgreetactive");
08333       }
08334       DISPOSE(prefile, -1);
08335    }
08336 
08337    /* Play voicemail intro - syntax is different for different languages */
08338    if (0) {
08339    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08340       return vm_intro_cs(chan, vms);
08341    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08342       static int deprecation_warning = 0;
08343       if (deprecation_warning++ % 10 == 0) {
08344          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08345       }
08346       return vm_intro_cs(chan, vms);
08347    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08348       return vm_intro_de(chan, vms);
08349    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08350       return vm_intro_es(chan, vms);
08351    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08352       return vm_intro_fr(chan, vms);
08353    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08354       return vm_intro_gr(chan, vms);
08355    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08356       return vm_intro_he(chan, vms);
08357    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08358       return vm_intro_it(chan, vms);
08359    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08360       return vm_intro_nl(chan, vms);
08361    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08362       return vm_intro_no(chan, vms);
08363    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08364       return vm_intro_pl(chan, vms);
08365    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08366       return vm_intro_pt_BR(chan, vms);
08367    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08368       return vm_intro_pt(chan, vms);
08369    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08370       return vm_intro_multilang(chan, vms, "n");
08371    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08372       return vm_intro_se(chan, vms);
08373    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08374       return vm_intro_multilang(chan, vms, "n");
08375    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08376       return vm_intro_zh(chan, vms);
08377    } else {                                             /* Default to ENGLISH */
08378       return vm_intro_en(chan, vms);
08379    }
08380 }

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

Definition at line 8224 of file app_voicemail.c.

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

Referenced by vm_intro().

08225 {
08226    int res;
08227    res = ast_play_and_wait(chan, "vm-youhave");
08228    if (!res) {
08229       if (vms->newmessages) {
08230          if (vms->newmessages == 1) {
08231             res = ast_play_and_wait(chan, "digits/jednu");
08232          } else {
08233             res = say_and_wait(chan, vms->newmessages, chan->language);
08234          }
08235          if (!res) {
08236             if ((vms->newmessages == 1))
08237                res = ast_play_and_wait(chan, "vm-novou");
08238             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08239                res = ast_play_and_wait(chan, "vm-nove");
08240             if (vms->newmessages > 4)
08241                res = ast_play_and_wait(chan, "vm-novych");
08242          }
08243          if (vms->oldmessages && !res)
08244             res = ast_play_and_wait(chan, "vm-and");
08245          else if (!res) {
08246             if ((vms->newmessages == 1))
08247                res = ast_play_and_wait(chan, "vm-zpravu");
08248             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08249                res = ast_play_and_wait(chan, "vm-zpravy");
08250             if (vms->newmessages > 4)
08251                res = ast_play_and_wait(chan, "vm-zprav");
08252          }
08253       }
08254       if (!res && vms->oldmessages) {
08255          res = say_and_wait(chan, vms->oldmessages, chan->language);
08256          if (!res) {
08257             if ((vms->oldmessages == 1))
08258                res = ast_play_and_wait(chan, "vm-starou");
08259             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08260                res = ast_play_and_wait(chan, "vm-stare");
08261             if (vms->oldmessages > 4)
08262                res = ast_play_and_wait(chan, "vm-starych");
08263          }
08264          if (!res) {
08265             if ((vms->oldmessages == 1))
08266                res = ast_play_and_wait(chan, "vm-zpravu");
08267             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08268                res = ast_play_and_wait(chan, "vm-zpravy");
08269             if (vms->oldmessages > 4)
08270                res = ast_play_and_wait(chan, "vm-zprav");
08271          }
08272       }
08273       if (!res) {
08274          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08275             res = ast_play_and_wait(chan, "vm-no");
08276             if (!res)
08277                res = ast_play_and_wait(chan, "vm-zpravy");
08278          }
08279       }
08280    }
08281    return res;
08282 }

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

Definition at line 7920 of file app_voicemail.c.

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

Referenced by vm_intro().

07921 {
07922    /* Introduce messages they have */
07923    int res;
07924    res = ast_play_and_wait(chan, "vm-youhave");
07925    if (!res) {
07926       if (vms->newmessages) {
07927          if ((vms->newmessages == 1))
07928             res = ast_play_and_wait(chan, "digits/1F");
07929          else
07930             res = say_and_wait(chan, vms->newmessages, chan->language);
07931          if (!res)
07932             res = ast_play_and_wait(chan, "vm-INBOX");
07933          if (vms->oldmessages && !res)
07934             res = ast_play_and_wait(chan, "vm-and");
07935          else if (!res) {
07936             if ((vms->newmessages == 1))
07937                res = ast_play_and_wait(chan, "vm-message");
07938             else
07939                res = ast_play_and_wait(chan, "vm-messages");
07940          }
07941             
07942       }
07943       if (!res && vms->oldmessages) {
07944          if (vms->oldmessages == 1)
07945             res = ast_play_and_wait(chan, "digits/1F");
07946          else
07947             res = say_and_wait(chan, vms->oldmessages, chan->language);
07948          if (!res)
07949             res = ast_play_and_wait(chan, "vm-Old");
07950          if (!res) {
07951             if (vms->oldmessages == 1)
07952                res = ast_play_and_wait(chan, "vm-message");
07953             else
07954                res = ast_play_and_wait(chan, "vm-messages");
07955          }
07956       }
07957       if (!res) {
07958          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07959             res = ast_play_and_wait(chan, "vm-no");
07960             if (!res)
07961                res = ast_play_and_wait(chan, "vm-messages");
07962          }
07963       }
07964    }
07965    return res;
07966 }

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

Definition at line 7669 of file app_voicemail.c.

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

Referenced by vm_intro().

07670 {
07671    int res;
07672 
07673    /* Introduce messages they have */
07674    res = ast_play_and_wait(chan, "vm-youhave");
07675    if (!res) {
07676       if (vms->urgentmessages) {
07677          res = say_and_wait(chan, vms->urgentmessages, chan->language);
07678          if (!res)
07679             res = ast_play_and_wait(chan, "vm-Urgent");
07680          if ((vms->oldmessages || vms->newmessages) && !res) {
07681             res = ast_play_and_wait(chan, "vm-and");
07682          } else if (!res) {
07683             if ((vms->urgentmessages == 1))
07684                res = ast_play_and_wait(chan, "vm-message");
07685             else
07686                res = ast_play_and_wait(chan, "vm-messages");
07687          }
07688       }
07689       if (vms->newmessages) {
07690          res = say_and_wait(chan, vms->newmessages, chan->language);
07691          if (!res)
07692             res = ast_play_and_wait(chan, "vm-INBOX");
07693          if (vms->oldmessages && !res)
07694             res = ast_play_and_wait(chan, "vm-and");
07695          else if (!res) {
07696             if ((vms->newmessages == 1))
07697                res = ast_play_and_wait(chan, "vm-message");
07698             else
07699                res = ast_play_and_wait(chan, "vm-messages");
07700          }
07701             
07702       }
07703       if (!res && vms->oldmessages) {
07704          res = say_and_wait(chan, vms->oldmessages, chan->language);
07705          if (!res)
07706             res = ast_play_and_wait(chan, "vm-Old");
07707          if (!res) {
07708             if (vms->oldmessages == 1)
07709                res = ast_play_and_wait(chan, "vm-message");
07710             else
07711                res = ast_play_and_wait(chan, "vm-messages");
07712          }
07713       }
07714       if (!res) {
07715          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
07716             res = ast_play_and_wait(chan, "vm-no");
07717             if (!res)
07718                res = ast_play_and_wait(chan, "vm-messages");
07719          }
07720       }
07721    }
07722    return res;
07723 }

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

Definition at line 7969 of file app_voicemail.c.

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

Referenced by vm_intro().

07970 {
07971    /* Introduce messages they have */
07972    int res;
07973    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07974       res = ast_play_and_wait(chan, "vm-youhaveno");
07975       if (!res)
07976          res = ast_play_and_wait(chan, "vm-messages");
07977    } else {
07978       res = ast_play_and_wait(chan, "vm-youhave");
07979    }
07980    if (!res) {
07981       if (vms->newmessages) {
07982          if (!res) {
07983             if ((vms->newmessages == 1)) {
07984                res = ast_play_and_wait(chan, "digits/1M");
07985                if (!res)
07986                   res = ast_play_and_wait(chan, "vm-message");
07987                if (!res)
07988                   res = ast_play_and_wait(chan, "vm-INBOXs");
07989             } else {
07990                res = say_and_wait(chan, vms->newmessages, chan->language);
07991                if (!res)
07992                   res = ast_play_and_wait(chan, "vm-messages");
07993                if (!res)
07994                   res = ast_play_and_wait(chan, "vm-INBOX");
07995             }
07996          }
07997          if (vms->oldmessages && !res)
07998             res = ast_play_and_wait(chan, "vm-and");
07999       }
08000       if (vms->oldmessages) {
08001          if (!res) {
08002             if (vms->oldmessages == 1) {
08003                res = ast_play_and_wait(chan, "digits/1M");
08004                if (!res)
08005                   res = ast_play_and_wait(chan, "vm-message");
08006                if (!res)
08007                   res = ast_play_and_wait(chan, "vm-Olds");
08008             } else {
08009                res = say_and_wait(chan, vms->oldmessages, chan->language);
08010                if (!res)
08011                   res = ast_play_and_wait(chan, "vm-messages");
08012                if (!res)
08013                   res = ast_play_and_wait(chan, "vm-Old");
08014             }
08015          }
08016       }
08017    }
08018 return res;
08019 }

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

Definition at line 8067 of file app_voicemail.c.

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

Referenced by vm_intro().

08068 {
08069    /* Introduce messages they have */
08070    int res;
08071    res = ast_play_and_wait(chan, "vm-youhave");
08072    if (!res) {
08073       if (vms->newmessages) {
08074          res = say_and_wait(chan, vms->newmessages, chan->language);
08075          if (!res)
08076             res = ast_play_and_wait(chan, "vm-INBOX");
08077          if (vms->oldmessages && !res)
08078             res = ast_play_and_wait(chan, "vm-and");
08079          else if (!res) {
08080             if ((vms->newmessages == 1))
08081                res = ast_play_and_wait(chan, "vm-message");
08082             else
08083                res = ast_play_and_wait(chan, "vm-messages");
08084          }
08085             
08086       }
08087       if (!res && vms->oldmessages) {
08088          res = say_and_wait(chan, vms->oldmessages, chan->language);
08089          if (!res)
08090             res = ast_play_and_wait(chan, "vm-Old");
08091          if (!res) {
08092             if (vms->oldmessages == 1)
08093                res = ast_play_and_wait(chan, "vm-message");
08094             else
08095                res = ast_play_and_wait(chan, "vm-messages");
08096          }
08097       }
08098       if (!res) {
08099          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08100             res = ast_play_and_wait(chan, "vm-no");
08101             if (!res)
08102                res = ast_play_and_wait(chan, "vm-messages");
08103          }
08104       }
08105    }
08106    return res;
08107 }

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

Definition at line 7468 of file app_voicemail.c.

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

Referenced by vm_intro().

07469 {
07470    int res = 0;
07471 
07472    if (vms->newmessages) {
07473       res = ast_play_and_wait(chan, "vm-youhave");
07474       if (!res) 
07475          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07476       if (!res) {
07477          if ((vms->newmessages == 1)) {
07478             res = ast_play_and_wait(chan, "vm-INBOX");
07479             if (!res)
07480                res = ast_play_and_wait(chan, "vm-message");
07481          } else {
07482             res = ast_play_and_wait(chan, "vm-INBOXs");
07483             if (!res)
07484                res = ast_play_and_wait(chan, "vm-messages");
07485          }
07486       }
07487    } else if (vms->oldmessages){
07488       res = ast_play_and_wait(chan, "vm-youhave");
07489       if (!res)
07490          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07491       if ((vms->oldmessages == 1)){
07492          res = ast_play_and_wait(chan, "vm-Old");
07493          if (!res)
07494             res = ast_play_and_wait(chan, "vm-message");
07495       } else {
07496          res = ast_play_and_wait(chan, "vm-Olds");
07497          if (!res)
07498             res = ast_play_and_wait(chan, "vm-messages");
07499       }
07500    } else if (!vms->oldmessages && !vms->newmessages) 
07501       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07502    return res;
07503 }

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

Definition at line 7602 of file app_voicemail.c.

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

Referenced by vm_intro().

07603 {
07604    int res = 0;
07605 
07606    /* Introduce messages they have */
07607    if (!res) {
07608       if ((vms->newmessages) || (vms->oldmessages)) {
07609          res = ast_play_and_wait(chan, "vm-youhave");
07610       }
07611       /*
07612        * The word "shtei" refers to the number 2 in hebrew when performing a count
07613        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
07614        * an element, this is one of them.
07615        */
07616       if (vms->newmessages) {
07617          if (!res) {
07618             if (vms->newmessages == 1) {
07619                res = ast_play_and_wait(chan, "vm-INBOX1");
07620             } else {
07621                if (vms->newmessages == 2) {
07622                   res = ast_play_and_wait(chan, "vm-shtei");
07623                } else {
07624                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
07625                }
07626                res = ast_play_and_wait(chan, "vm-INBOX");
07627             }
07628          }
07629          if (vms->oldmessages && !res) {
07630             res = ast_play_and_wait(chan, "vm-and");
07631             if (vms->oldmessages == 1) {
07632                res = ast_play_and_wait(chan, "vm-Old1");
07633             } else {
07634                if (vms->oldmessages == 2) {
07635                   res = ast_play_and_wait(chan, "vm-shtei");
07636                } else {
07637                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
07638                }
07639                res = ast_play_and_wait(chan, "vm-Old");
07640             }
07641          }
07642       }
07643       if (!res && vms->oldmessages && !vms->newmessages) {
07644          if (!res) {
07645             if (vms->oldmessages == 1) {
07646                res = ast_play_and_wait(chan, "vm-Old1");
07647             } else {
07648                if (vms->oldmessages == 2) {
07649                   res = ast_play_and_wait(chan, "vm-shtei");
07650                } else {
07651                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
07652                }
07653                res = ast_play_and_wait(chan, "vm-Old");
07654             }
07655          }
07656       }
07657       if (!res) {
07658          if (!vms->oldmessages && !vms->newmessages) {
07659             if (!res) {
07660                res = ast_play_and_wait(chan, "vm-nomessages");
07661             }
07662          }
07663       }
07664    }
07665    return res;
07666 }

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

Definition at line 7726 of file app_voicemail.c.

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

Referenced by vm_intro().

07727 {
07728    /* Introduce messages they have */
07729    int res;
07730    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
07731       res = ast_play_and_wait(chan, "vm-no") ||
07732          ast_play_and_wait(chan, "vm-message");
07733    else
07734       res = ast_play_and_wait(chan, "vm-youhave");
07735    if (!res && vms->newmessages) {
07736       res = (vms->newmessages == 1) ?
07737          ast_play_and_wait(chan, "digits/un") ||
07738          ast_play_and_wait(chan, "vm-nuovo") ||
07739          ast_play_and_wait(chan, "vm-message") :
07740          /* 2 or more new messages */
07741          say_and_wait(chan, vms->newmessages, chan->language) ||
07742          ast_play_and_wait(chan, "vm-nuovi") ||
07743          ast_play_and_wait(chan, "vm-messages");
07744       if (!res && vms->oldmessages)
07745          res = ast_play_and_wait(chan, "vm-and");
07746    }
07747    if (!res && vms->oldmessages) {
07748       res = (vms->oldmessages == 1) ?
07749          ast_play_and_wait(chan, "digits/un") ||
07750          ast_play_and_wait(chan, "vm-vecchio") ||
07751          ast_play_and_wait(chan, "vm-message") :
07752          /* 2 or more old messages */
07753          say_and_wait(chan, vms->oldmessages, chan->language) ||
07754          ast_play_and_wait(chan, "vm-vecchi") ||
07755          ast_play_and_wait(chan, "vm-messages");
07756    }
07757    return res;
07758 }

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

Definition at line 7562 of file app_voicemail.c.

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

Referenced by vm_intro().

07563 {
07564    int res;
07565    int lastnum = 0;
07566 
07567    res = ast_play_and_wait(chan, "vm-youhave");
07568 
07569    if (!res && vms->newmessages) {
07570       lastnum = vms->newmessages;
07571 
07572       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07573          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
07574       }
07575 
07576       if (!res && vms->oldmessages) {
07577          res = ast_play_and_wait(chan, "vm-and");
07578       }
07579    }
07580 
07581    if (!res && vms->oldmessages) {
07582       lastnum = vms->oldmessages;
07583 
07584       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
07585          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
07586       }
07587    }
07588 
07589    if (!res) {
07590       if (lastnum == 0) {
07591          res = ast_play_and_wait(chan, "vm-no");
07592       }
07593       if (!res) {
07594          res = ast_say_counted_noun(chan, lastnum, "vm-message");
07595       }
07596    }
07597 
07598    return res;
07599 }

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

Definition at line 8110 of file app_voicemail.c.

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

Referenced by vm_intro().

08111 {
08112    /* Introduce messages they have */
08113    int res;
08114    res = ast_play_and_wait(chan, "vm-youhave");
08115    if (!res) {
08116       if (vms->newmessages) {
08117          res = say_and_wait(chan, vms->newmessages, chan->language);
08118          if (!res) {
08119             if (vms->newmessages == 1)
08120                res = ast_play_and_wait(chan, "vm-INBOXs");
08121             else
08122                res = ast_play_and_wait(chan, "vm-INBOX");
08123          }
08124          if (vms->oldmessages && !res)
08125             res = ast_play_and_wait(chan, "vm-and");
08126          else if (!res) {
08127             if ((vms->newmessages == 1))
08128                res = ast_play_and_wait(chan, "vm-message");
08129             else
08130                res = ast_play_and_wait(chan, "vm-messages");
08131          }
08132             
08133       }
08134       if (!res && vms->oldmessages) {
08135          res = say_and_wait(chan, vms->oldmessages, chan->language);
08136          if (!res) {
08137             if (vms->oldmessages == 1)
08138                res = ast_play_and_wait(chan, "vm-Olds");
08139             else
08140                res = ast_play_and_wait(chan, "vm-Old");
08141          }
08142          if (!res) {
08143             if (vms->oldmessages == 1)
08144                res = ast_play_and_wait(chan, "vm-message");
08145             else
08146                res = ast_play_and_wait(chan, "vm-messages");
08147          }
08148       }
08149       if (!res) {
08150          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08151             res = ast_play_and_wait(chan, "vm-no");
08152             if (!res)
08153                res = ast_play_and_wait(chan, "vm-messages");
08154          }
08155       }
08156    }
08157    return res;
08158 }

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

Definition at line 7876 of file app_voicemail.c.

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

Referenced by vm_intro().

07877 {
07878    /* Introduce messages they have */
07879    int res;
07880 
07881    res = ast_play_and_wait(chan, "vm-youhave");
07882    if (res)
07883       return res;
07884 
07885    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
07886       res = ast_play_and_wait(chan, "vm-no");
07887       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07888       return res;
07889    }
07890 
07891    if (vms->newmessages) {
07892       if ((vms->newmessages == 1)) {
07893          res = ast_play_and_wait(chan, "digits/1");
07894          res = res ? res : ast_play_and_wait(chan, "vm-ny");
07895          res = res ? res : ast_play_and_wait(chan, "vm-message");
07896       } else {
07897          res = say_and_wait(chan, vms->newmessages, chan->language);
07898          res = res ? res : ast_play_and_wait(chan, "vm-nye");
07899          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07900       }
07901       if (!res && vms->oldmessages)
07902          res = ast_play_and_wait(chan, "vm-and");
07903    }
07904    if (!res && vms->oldmessages) {
07905       if (vms->oldmessages == 1) {
07906          res = ast_play_and_wait(chan, "digits/1");
07907          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
07908          res = res ? res : ast_play_and_wait(chan, "vm-message");
07909       } else {
07910          res = say_and_wait(chan, vms->oldmessages, chan->language);
07911          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
07912          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07913       }
07914    }
07915 
07916    return res;
07917 }

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

Definition at line 7761 of file app_voicemail.c.

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

Referenced by vm_intro().

07762 {
07763    /* Introduce messages they have */
07764    int res;
07765    div_t num;
07766 
07767    if (!vms->oldmessages && !vms->newmessages) {
07768       res = ast_play_and_wait(chan, "vm-no");
07769       res = res ? res : ast_play_and_wait(chan, "vm-messages");
07770       return res;
07771    } else {
07772       res = ast_play_and_wait(chan, "vm-youhave");
07773    }
07774 
07775    if (vms->newmessages) {
07776       num = div(vms->newmessages, 10);
07777       if (vms->newmessages == 1) {
07778          res = ast_play_and_wait(chan, "digits/1-a");
07779          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
07780          res = res ? res : ast_play_and_wait(chan, "vm-message");
07781       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07782          if (num.rem == 2) {
07783             if (!num.quot) {
07784                res = ast_play_and_wait(chan, "digits/2-ie");
07785             } else {
07786                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
07787                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07788             }
07789          } else {
07790             res = say_and_wait(chan, vms->newmessages, chan->language);
07791          }
07792          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
07793          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07794       } else {
07795          res = say_and_wait(chan, vms->newmessages, chan->language);
07796          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
07797          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07798       }
07799       if (!res && vms->oldmessages)
07800          res = ast_play_and_wait(chan, "vm-and");
07801    }
07802    if (!res && vms->oldmessages) {
07803       num = div(vms->oldmessages, 10);
07804       if (vms->oldmessages == 1) {
07805          res = ast_play_and_wait(chan, "digits/1-a");
07806          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
07807          res = res ? res : ast_play_and_wait(chan, "vm-message");
07808       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07809          if (num.rem == 2) {
07810             if (!num.quot) {
07811                res = ast_play_and_wait(chan, "digits/2-ie");
07812             } else {
07813                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
07814                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07815             }
07816          } else {
07817             res = say_and_wait(chan, vms->oldmessages, chan->language);
07818          }
07819          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
07820          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07821       } else {
07822          res = say_and_wait(chan, vms->oldmessages, chan->language);
07823          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
07824          res = res ? res : ast_play_and_wait(chan, "vm-messages");
07825       }
07826    }
07827 
07828    return res;
07829 }

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

Definition at line 8161 of file app_voicemail.c.

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

Referenced by vm_intro().

08162 {
08163    /* Introduce messages they have */
08164    int res;
08165    res = ast_play_and_wait(chan, "vm-youhave");
08166    if (!res) {
08167       if (vms->newmessages) {
08168          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08169          if (!res) {
08170             if ((vms->newmessages == 1)) {
08171                res = ast_play_and_wait(chan, "vm-message");
08172                if (!res)
08173                   res = ast_play_and_wait(chan, "vm-INBOXs");
08174             } else {
08175                res = ast_play_and_wait(chan, "vm-messages");
08176                if (!res)
08177                   res = ast_play_and_wait(chan, "vm-INBOX");
08178             }
08179          }
08180          if (vms->oldmessages && !res)
08181             res = ast_play_and_wait(chan, "vm-and");
08182       }
08183       if (!res && vms->oldmessages) {
08184          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08185          if (!res) {
08186             if (vms->oldmessages == 1) {
08187                res = ast_play_and_wait(chan, "vm-message");
08188                if (!res)
08189                   res = ast_play_and_wait(chan, "vm-Olds");
08190             } else {
08191                res = ast_play_and_wait(chan, "vm-messages");
08192                if (!res)
08193                   res = ast_play_and_wait(chan, "vm-Old");
08194             }
08195          }
08196       }
08197       if (!res) {
08198          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08199             res = ast_play_and_wait(chan, "vm-no");
08200             if (!res)
08201                res = ast_play_and_wait(chan, "vm-messages");
08202          }
08203       }
08204    }
08205    return res;
08206 }

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

Definition at line 8022 of file app_voicemail.c.

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

Referenced by vm_intro().

08022                                                                          {
08023    /* Introduce messages they have */
08024    int res;
08025    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08026       res = ast_play_and_wait(chan, "vm-nomessages");
08027       return res;
08028    } else {
08029       res = ast_play_and_wait(chan, "vm-youhave");
08030    }
08031    if (vms->newmessages) {
08032       if (!res)
08033          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08034       if ((vms->newmessages == 1)) {
08035          if (!res)
08036             res = ast_play_and_wait(chan, "vm-message");
08037          if (!res)
08038             res = ast_play_and_wait(chan, "vm-INBOXs");
08039       } else {
08040          if (!res)
08041             res = ast_play_and_wait(chan, "vm-messages");
08042          if (!res)
08043             res = ast_play_and_wait(chan, "vm-INBOX");
08044       }
08045       if (vms->oldmessages && !res)
08046          res = ast_play_and_wait(chan, "vm-and");
08047    }
08048    if (vms->oldmessages) {
08049       if (!res)
08050          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08051       if (vms->oldmessages == 1) {
08052          if (!res)
08053             res = ast_play_and_wait(chan, "vm-message");
08054          if (!res)
08055             res = ast_play_and_wait(chan, "vm-Olds");
08056       } else {
08057          if (!res)
08058             res = ast_play_and_wait(chan, "vm-messages");
08059          if (!res)
08060             res = ast_play_and_wait(chan, "vm-Old");
08061       }
08062    }
08063    return res;
08064 }

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

Definition at line 7832 of file app_voicemail.c.

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

Referenced by vm_intro().

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

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

Definition at line 8285 of file app_voicemail.c.

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

Referenced by vm_intro().

08286 {
08287    int res;
08288    /* Introduce messages they have */
08289    res = ast_play_and_wait(chan, "vm-you");
08290 
08291    if (!res && vms->newmessages) {
08292       res = ast_play_and_wait(chan, "vm-have");
08293       if (!res)
08294          res = say_and_wait(chan, vms->newmessages, chan->language);
08295       if (!res)
08296          res = ast_play_and_wait(chan, "vm-tong");
08297       if (!res)
08298          res = ast_play_and_wait(chan, "vm-INBOX");
08299       if (vms->oldmessages && !res)
08300          res = ast_play_and_wait(chan, "vm-and");
08301       else if (!res) 
08302          res = ast_play_and_wait(chan, "vm-messages");
08303    }
08304    if (!res && vms->oldmessages) {
08305       res = ast_play_and_wait(chan, "vm-have");
08306       if (!res)
08307          res = say_and_wait(chan, vms->oldmessages, chan->language);
08308       if (!res)
08309          res = ast_play_and_wait(chan, "vm-tong");
08310       if (!res)
08311          res = ast_play_and_wait(chan, "vm-Old");
08312       if (!res)
08313          res = ast_play_and_wait(chan, "vm-messages");
08314    }
08315    if (!res && !vms->oldmessages && !vms->newmessages) {
08316       res = ast_play_and_wait(chan, "vm-haveno");
08317       if (!res)
08318          res = ast_play_and_wait(chan, "vm-messages");
08319    }
08320    return res;
08321 }

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

02967 {
02968    switch (ast_lock_path(path)) {
02969    case AST_LOCK_TIMEOUT:
02970       return -1;
02971    default:
02972       return 0;
02973    }
02974 }

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

Definition at line 1469 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01470 {
01471    FILE *p = NULL;
01472    int pfd = mkstemp(template);
01473    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01474    if (pfd > -1) {
01475       p = fdopen(pfd, "w+");
01476       if (!p) {
01477          close(pfd);
01478          pfd = -1;
01479       }
01480    }
01481    return p;
01482 }

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

08494 {
08495    int cmd = 0;
08496    int duration = 0;
08497    int tries = 0;
08498    char newpassword[80] = "";
08499    char newpassword2[80] = "";
08500    char prefile[PATH_MAX] = "";
08501    unsigned char buf[256];
08502    int bytes=0;
08503 
08504    if (ast_adsi_available(chan)) {
08505       bytes += adsi_logo(buf + bytes);
08506       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08507       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08508       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08509       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08510       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08511    }
08512 
08513    /* First, have the user change their password 
08514       so they won't get here again */
08515    for (;;) {
08516       newpassword[1] = '\0';
08517       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08518       if (cmd == '#')
08519          newpassword[0] = '\0';
08520       if (cmd < 0 || cmd == 't' || cmd == '#')
08521          return cmd;
08522       cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
08523       if (cmd < 0 || cmd == 't' || cmd == '#')
08524          return cmd;
08525       cmd = check_password(vmu, newpassword); /* perform password validation */
08526       if (cmd != 0) {
08527          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08528          cmd = ast_play_and_wait(chan, vm_invalid_password);
08529       } else {
08530          newpassword2[1] = '\0';
08531          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08532          if (cmd == '#')
08533             newpassword2[0] = '\0';
08534          if (cmd < 0 || cmd == 't' || cmd == '#')
08535             return cmd;
08536          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
08537          if (cmd < 0 || cmd == 't' || cmd == '#')
08538             return cmd;
08539          if (!strcmp(newpassword, newpassword2))
08540             break;
08541          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08542          cmd = ast_play_and_wait(chan, vm_mismatch);
08543       }
08544       if (++tries == 3)
08545          return -1;
08546       if (cmd != 0) {
08547          cmd = ast_play_and_wait(chan, vm_pls_try_again);
08548       }
08549    }
08550    if (pwdchange & PWDCHANGE_INTERNAL)
08551       vm_change_password(vmu, newpassword);
08552    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08553       vm_change_password_shell(vmu, newpassword);
08554 
08555    ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08556    cmd = ast_play_and_wait(chan, vm_passchanged);
08557 
08558    /* If forcename is set, have the user record their name */  
08559    if (ast_test_flag(vmu, VM_FORCENAME)) {
08560       snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08561       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08562          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08563          if (cmd < 0 || cmd == 't' || cmd == '#')
08564             return cmd;
08565       }
08566    }
08567 
08568    /* If forcegreetings is set, have the user record their greetings */
08569    if (ast_test_flag(vmu, VM_FORCEGREET)) {
08570       snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08571       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08572          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08573          if (cmd < 0 || cmd == 't' || cmd == '#')
08574             return cmd;
08575       }
08576 
08577       snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08578       if (ast_fileexists(prefile, NULL, NULL) < 1) {
08579          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08580          if (cmd < 0 || cmd == 't' || cmd == '#')
08581             return cmd;
08582       }
08583    }
08584 
08585    return cmd;
08586 }

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

08589 {
08590    int cmd = 0;
08591    int retries = 0;
08592    int duration = 0;
08593    char newpassword[80] = "";
08594    char newpassword2[80] = "";
08595    char prefile[PATH_MAX] = "";
08596    unsigned char buf[256];
08597    int bytes=0;
08598 
08599    if (ast_adsi_available(chan)) {
08600       bytes += adsi_logo(buf + bytes);
08601       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
08602       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08603       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08604       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08605       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08606    }
08607    while ((cmd >= 0) && (cmd != 't')) {
08608       if (cmd)
08609          retries = 0;
08610       switch (cmd) {
08611       case '1': /* Record your unavailable message */
08612          snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
08613          cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08614          break;
08615       case '2':  /* Record your busy message */
08616          snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
08617          cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08618          break;
08619       case '3': /* Record greeting */
08620          snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
08621          cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08622          break;
08623       case '4':  /* manage the temporary greeting */
08624          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
08625          break;
08626       case '5': /* change password */
08627          if (vmu->password[0] == '-') {
08628             cmd = ast_play_and_wait(chan, "vm-no");
08629             break;
08630          }
08631          newpassword[1] = '\0';
08632          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
08633          if (cmd == '#')
08634             newpassword[0] = '\0';
08635          else {
08636             if (cmd < 0)
08637                break;
08638             if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
08639                break;
08640             }
08641          }
08642          cmd = check_password(vmu, newpassword); /* perform password validation */
08643          if (cmd != 0) {
08644             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
08645             cmd = ast_play_and_wait(chan, vm_invalid_password);
08646             if (!cmd) {
08647                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08648             }
08649             break;
08650          }
08651          newpassword2[1] = '\0';
08652          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
08653          if (cmd == '#')
08654             newpassword2[0] = '\0';
08655          else {
08656             if (cmd < 0)
08657                break;
08658 
08659             if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#")) < 0) {
08660                break;
08661             }
08662          }
08663          if (strcmp(newpassword, newpassword2)) {
08664             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
08665             cmd = ast_play_and_wait(chan, vm_mismatch);
08666             if (!cmd) {
08667                cmd = ast_play_and_wait(chan, vm_pls_try_again);
08668             }
08669             break;
08670          }
08671          if (pwdchange & PWDCHANGE_INTERNAL)
08672             vm_change_password(vmu, newpassword);
08673          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
08674             vm_change_password_shell(vmu, newpassword);
08675 
08676          ast_debug(1,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
08677          cmd = ast_play_and_wait(chan, vm_passchanged);
08678          break;
08679       case '*': 
08680          cmd = 't';
08681          break;
08682       default: 
08683          cmd = 0;
08684          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08685          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08686          if (ast_fileexists(prefile, NULL, NULL)) {
08687             cmd = ast_play_and_wait(chan, "vm-tmpexists");
08688          }
08689          DISPOSE(prefile, -1);
08690          if (!cmd) {
08691             cmd = ast_play_and_wait(chan, "vm-options");
08692          }
08693          if (!cmd) {
08694             cmd = ast_waitfordigit(chan,6000);
08695          }
08696          if (!cmd) {
08697             retries++;
08698          }
08699          if (retries > 3) {
08700             cmd = 't';
08701          }
08702       }
08703    }
08704    if (cmd == 't')
08705       cmd = 0;
08706    return cmd;
08707 }

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

Definition at line 7433 of file app_voicemail.c.

References ast_play_and_wait(), ast_channel::language, vm_play_folder_name_gr(), vm_play_folder_name_pl(), and vm_play_folder_name_ua().

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

07434 {
07435    int cmd;
07436 
07437    if (  !strncasecmp(chan->language, "it", 2) ||
07438         !strncasecmp(chan->language, "es", 2) ||
07439         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07440       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07441       return cmd ? cmd : ast_play_and_wait(chan, box);
07442    } else if (!strncasecmp(chan->language, "gr", 2)) {
07443       return vm_play_folder_name_gr(chan, box);
07444    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07445       return ast_play_and_wait(chan, box);
07446    } else if (!strncasecmp(chan->language, "pl", 2)) {
07447       return vm_play_folder_name_pl(chan, box);
07448    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07449       return vm_play_folder_name_ua(chan, box);
07450    } else {  /* Default English */
07451       cmd = ast_play_and_wait(chan, box);
07452       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07453    }
07454 }

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

Definition at line 7386 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07387 {
07388    int cmd;
07389    char *buf;
07390 
07391    buf = alloca(strlen(box)+2); 
07392    strcpy(buf, box);
07393    strcat(buf,"s");
07394 
07395    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07396       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07397       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07398    } else {
07399       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07400       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07401    }
07402 }

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

Definition at line 7404 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07405 {
07406    int cmd;
07407 
07408    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07409       if (!strcasecmp(box, "vm-INBOX"))
07410          cmd = ast_play_and_wait(chan, "vm-new-e");
07411       else
07412          cmd = ast_play_and_wait(chan, "vm-old-e");
07413       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07414    } else {
07415       cmd = ast_play_and_wait(chan, "vm-messages");
07416       return cmd ? cmd : ast_play_and_wait(chan, box);
07417    }
07418 }

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

Definition at line 7420 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07421 {
07422    int cmd;
07423 
07424    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07425       cmd = ast_play_and_wait(chan, "vm-messages");
07426       return cmd ? cmd : ast_play_and_wait(chan, box);
07427    } else {
07428       cmd = ast_play_and_wait(chan, box);
07429       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07430    }
07431 }

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

08726 {
08727    int cmd = 0;
08728    int retries = 0;
08729    int duration = 0;
08730    char prefile[PATH_MAX] = "";
08731    unsigned char buf[256];
08732    int bytes = 0;
08733 
08734    if (ast_adsi_available(chan)) {
08735       bytes += adsi_logo(buf + bytes);
08736       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
08737       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08738       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08739       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08740       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
08741    }
08742 
08743    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08744    while ((cmd >= 0) && (cmd != 't')) {
08745       if (cmd)
08746          retries = 0;
08747       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08748       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
08749          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08750          cmd = 't';  
08751       } else {
08752          switch (cmd) {
08753          case '1':
08754             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
08755             break;
08756          case '2':
08757             DELETE(prefile, -1, prefile, vmu);
08758             ast_play_and_wait(chan, "vm-tempremoved");
08759             cmd = 't';  
08760             break;
08761          case '*': 
08762             cmd = 't';
08763             break;
08764          default:
08765             cmd = ast_play_and_wait(chan,
08766                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
08767                   "vm-tempgreeting2" : "vm-tempgreeting");
08768             if (!cmd)
08769                cmd = ast_waitfordigit(chan,6000);
08770             if (!cmd)
08771                retries++;
08772             if (retries > 3)
08773                cmd = 't';
08774          }
08775       }
08776       DISPOSE(prefile, -1);
08777    }
08778    if (cmd == 't')
08779       cmd = 0;
08780    return cmd;
08781 }

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

Definition at line 10006 of file app_voicemail.c.

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

Referenced by load_module().

10007 {
10008    char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
10009    struct ast_vm_user vmus;
10010    char *options = NULL;
10011    int silent = 0, skipuser = 0;
10012    int res = -1;
10013    
10014    if (s) {
10015       s = ast_strdupa(s);
10016       user = strsep(&s, ",");
10017       options = strsep(&s, ",");
10018       if (user) {
10019          s = user;
10020          user = strsep(&s, "@");
10021          context = strsep(&s, "");
10022          if (!ast_strlen_zero(user))
10023             skipuser++;
10024          ast_copy_string(mailbox, user, sizeof(mailbox));
10025       }
10026    }
10027 
10028    if (options) {
10029       silent = (strchr(options, 's')) != NULL;
10030    }
10031 
10032    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
10033       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
10034       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
10035       ast_play_and_wait(chan, "auth-thankyou");
10036       res = 0;
10037    }
10038 
10039    return res;
10040 }

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

04061 {
04062    const struct vm_zone *z = NULL;
04063    struct timeval t = ast_tvnow();
04064 
04065    /* Does this user have a timezone specified? */
04066    if (!ast_strlen_zero(vmu->zonetag)) {
04067       /* Find the zone in the list */
04068       AST_LIST_LOCK(&zones);
04069       AST_LIST_TRAVERSE(&zones, z, list) {
04070          if (!strcmp(z->name, vmu->zonetag))
04071             break;
04072       }
04073       AST_LIST_UNLOCK(&zones);
04074    }
04075    ast_localtime(&t, tm, z ? z->timezone : NULL);
04076    return tm;
04077 }

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

06838 {
06839    int res;
06840    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
06841       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
06842    return res;
06843 }


Variable Documentation

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

Definition at line 11840 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 701 of file app_voicemail.c.

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

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

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 814 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 704 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 707 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 709 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 710 of file app_voicemail.c.

Definition at line 11840 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 798 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

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

Definition at line 810 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 801 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 10238 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

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

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

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

char* emailsubject = NULL [static]

Definition at line 805 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

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

char ext_pass_cmd[128] [static]

Definition at line 680 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 721 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 808 of file app_voicemail.c.

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

struct ast_flags globalflags = {0} [static]

Definition at line 832 of file app_voicemail.c.

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

char listen_control_forward_key[12] [static]

Definition at line 778 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 780 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 781 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 779 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 782 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

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

Definition at line 10001 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char mailcmd[160] [static]

Definition at line 720 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 717 of file app_voicemail.c.

int maxgreet [static]

Definition at line 727 of file app_voicemail.c.

int maxlogins [static]

Definition at line 729 of file app_voicemail.c.

int maxmsg [static]

Definition at line 716 of file app_voicemail.c.

int maxsilence [static]

Definition at line 715 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 730 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 747 of file app_voicemail.c.

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

int my_umask [static]

Definition at line 683 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 806 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 809 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 807 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 742 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 737 of file app_voicemail.c.

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

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 743 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 744 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 687 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 795 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char serveremail[80] [static]

Definition at line 719 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 718 of file app_voicemail.c.

Referenced by ast_record_review(), and setup_privacy_args().

int skipms [static]

Definition at line 728 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 722 of file app_voicemail.c.

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

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

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

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

Definition at line 789 of file app_voicemail.c.

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

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

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

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

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

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

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

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

Definition at line 788 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 678 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 723 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 726 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 725 of file app_voicemail.c.

double volgain [static]

Definition at line 724 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 714 of file app_voicemail.c.

Referenced by build_peer().


Generated by  doxygen 1.6.2