Sat Feb 11 06:34:05 2012

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

Enumerations

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

Functions

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

Variables

static 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", }
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 char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char * sayname_app = "VMSayName"
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_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 struct ast_data_entry vm_data_providers []
static struct ast_custom_function vm_info_acf
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_prepend_timeout [80] = "vm-then-pound"
static char vm_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
static struct ast_data_handler vm_users_data_provider
static char vmfmts [80]
static int vmmaxsecs
static int vmminsecs
static double volgain
static char zonetag [80]


Detailed Description

Comedian Mail - Voicemail System.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
unixODBC (http://www.unixodbc.org/)
ExtRef:
A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/)
See also
Note:
For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage

This module requires res_adsi to load. This needs to be optional during compilation.

This file is now almost impossible to work with, due to all #ifdefs. Feels like the database code before realtime. Someone - please come up with a plan to clean this up.

Definition in file app_voicemail.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 499 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 522 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 523 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 496 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 492 of file app_voicemail.c.

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

Definition at line 816 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11492 of file app_voicemail.c.

#define DATA_EXPORT_VM_ZONES ( ZONE   ) 

Value:

ZONE(vm_zone, name, AST_DATA_STRING)      \
   ZONE(vm_zone, timezone, AST_DATA_STRING)  \
   ZONE(vm_zone, msg_format, AST_DATA_STRING)

Definition at line 11520 of file app_voicemail.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 504 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 506 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 507 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 505 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 508 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 886 of file app_voicemail.c.

Referenced by actual_load_config().

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

#define DISPOSE ( a,
 ) 

#define ENDL   "\n"

Definition at line 527 of file app_voicemail.c.

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

#define ERROR_LOCK_PATH   -100

Definition at line 552 of file app_voicemail.c.

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

Definition at line 814 of file app_voicemail.c.

Referenced by close_mailbox(), copy_message(), resequence_mailbox(), 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 515 of file app_voicemail.c.

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

#define MAX_DATETIME_FORMAT   512

Definition at line 530 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 531 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 517 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

#define MAXMSGLIMIT   9999

Definition at line 518 of file app_voicemail.c.

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

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 520 of file app_voicemail.c.

Referenced by actual_load_config().

#define OPERATOR_EXIT   300

Definition at line 553 of file app_voicemail.c.

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

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 829 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 828 of file app_voicemail.c.

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

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

#define RETRIEVE ( a,
b,
c,
 ) 

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

Definition at line 513 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

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

#define VALID_DTMF   "1234567890*#"

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

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

#define VM_ATTACH   (1 << 11)

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 545 of file app_voicemail.c.

Referenced by apply_option(), AST_TEST_DEFINE(), 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 543 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 537 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_message().

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 541 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_newuser().

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 540 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_newuser().

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 551 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 550 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), vm_execmain(), and vm_instructions_en().

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 549 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and close_mailbox().

#define VM_OPERATOR   (1 << 1)

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

Definition at line 534 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), leave_voicemail(), 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 542 of file app_voicemail.c.

Referenced by actual_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 533 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_record_review().

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 535 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), manager_list_voicemail_users(), and play_message().

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 538 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and play_message().

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 547 of file app_voicemail.c.

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

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 539 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_execmain().

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 536 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_execmain().

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 548 of file app_voicemail.c.

Referenced by actual_load_config(), apply_option(), AST_TEST_DEFINE(), and vm_intro().

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 750 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 498 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 494 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 495 of file app_voicemail.c.

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


Enumeration Type Documentation

enum vm_box

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 556 of file app_voicemail.c.

00556             {
00557    NEW_FOLDER,
00558    OLD_FOLDER,
00559    WORK_FOLDER,
00560    FAMILY_FOLDER,
00561    FRIENDS_FOLDER,
00562    GREETINGS_FOLDER
00563 };

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 577 of file app_voicemail.c.

00577                     {
00578    OPT_ARG_RECORDGAIN = 0,
00579    OPT_ARG_PLAYFOLDER = 1,
00580    OPT_ARG_DTMFEXIT   = 2,
00581    /* This *must* be the last value in this enum! */
00582    OPT_ARG_ARRAY_SIZE = 3,
00583 };

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

00565                      {
00566    OPT_SILENT =           (1 << 0),
00567    OPT_BUSY_GREETING =    (1 << 1),
00568    OPT_UNAVAIL_GREETING = (1 << 2),
00569    OPT_RECORDGAIN =       (1 << 3),
00570    OPT_PREPEND_MAILBOX =  (1 << 4),
00571    OPT_AUTOPLAY =         (1 << 6),
00572    OPT_DTMFEXIT =         (1 << 7),
00573    OPT_MESSAGE_Urgent =   (1 << 8),
00574    OPT_MESSAGE_PRIORITY = (1 << 9)
00575 };

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 585 of file app_voicemail.c.

00585                          {
00586    OPT_PWLOC_VOICEMAILCONF = 0,
00587    OPT_PWLOC_SPOOLDIR      = 1,
00588    OPT_PWLOC_USERSCONF     = 2,
00589 };


Function Documentation

static void __fini_mwi_subs ( void   )  [static]

Definition at line 922 of file app_voicemail.c.

00941 :
 * 1. create a sound along the lines of "Please try again.  When done, press the pound key" which could be spliced

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

Definition at line 5474 of file app_voicemail.c.

References ast_strlen_zero().

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

05475 {
05476    DIR *dir;
05477    struct dirent *de;
05478    char fn[256];
05479    int ret = 0;
05480 
05481    /* If no mailbox, return immediately */
05482    if (ast_strlen_zero(mailbox))
05483       return 0;
05484 
05485    if (ast_strlen_zero(folder))
05486       folder = "INBOX";
05487    if (ast_strlen_zero(context))
05488       context = "default";
05489 
05490    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05491 
05492    if (!(dir = opendir(fn)))
05493       return 0;
05494 
05495    while ((de = readdir(dir))) {
05496       if (!strncasecmp(de->d_name, "msg", 3)) {
05497          if (shortcircuit) {
05498             ret = 1;
05499             break;
05500          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05501             ret++;
05502          }
05503       }
05504    }
05505 
05506    closedir(dir);
05507 
05508    return ret;
05509 }

static void __init_mwi_subs ( void   )  [static]

Definition at line 922 of file app_voicemail.c.

00941 :
 * 1. create a sound along the lines of "Please try again.  When done, press the pound key" which could be spliced

static void __reg_module ( void   )  [static]

Definition at line 13910 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_WARNING, AST_NONSTANDARD_APP_ARGS, ast_strlen_zero(), find_user(), LOG_ERROR, and mbox().

11112 {
11113    struct ast_vm_user svm;
11114    AST_DECLARE_APP_ARGS(arg,
11115       AST_APP_ARG(mbox);
11116       AST_APP_ARG(context);
11117    );
11118    static int dep_warning = 0;
11119 
11120    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11121 
11122    if (ast_strlen_zero(arg.mbox)) {
11123       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11124       return -1;
11125    }
11126 
11127    if (!dep_warning) {
11128       dep_warning = 1;
11129       ast_log(AST_LOG_WARNING, "MAILBOX_EXISTS is deprecated.  Please use ${VM_INFO(%s,exists)} instead.\n", args);
11130    }
11131 
11132    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11133    return 0;
11134 }

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

Definition at line 11136 of file app_voicemail.c.

References AST_APP_ARG, ast_channel_language(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_vm_user::email, find_user(), ast_vm_user::fullname, ast_vm_user::language, ast_vm_user::locale, LOG_ERROR, messagecount(), ast_vm_user::pager, parse(), ast_vm_user::password, S_OR, strsep(), and ast_vm_user::zonetag.

11137 {
11138    struct ast_vm_user *vmu = NULL;
11139    char *tmp, *mailbox, *context, *parse;
11140    int res = 0;
11141 
11142    AST_DECLARE_APP_ARGS(arg,
11143       AST_APP_ARG(mailbox_context);
11144       AST_APP_ARG(attribute);
11145       AST_APP_ARG(folder);
11146    );
11147 
11148    buf[0] = '\0';
11149 
11150    if (ast_strlen_zero(args)) {
11151       ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
11152       return -1;
11153    }
11154 
11155    parse = ast_strdupa(args);
11156    AST_STANDARD_APP_ARGS(arg, parse);
11157 
11158    if (ast_strlen_zero(arg.mailbox_context) || ast_strlen_zero(arg.attribute)) {
11159       ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
11160       return -1;
11161    }
11162 
11163    tmp = ast_strdupa(arg.mailbox_context);
11164    mailbox = strsep(&tmp, "@");
11165    context = strsep(&tmp, "");
11166 
11167    if (ast_strlen_zero(context)) {
11168        context = "default";
11169    }
11170 
11171    vmu = find_user(NULL, context, mailbox);
11172 
11173    if (!strncasecmp(arg.attribute, "exists", 5)) {
11174       ast_copy_string(buf, vmu ? "1" : "0", len);
11175       return 0;
11176    }
11177 
11178    if (vmu) {
11179       if (!strncasecmp(arg.attribute, "password", 8)) {
11180          ast_copy_string(buf, vmu->password, len);
11181       } else if (!strncasecmp(arg.attribute, "fullname", 8)) {
11182          ast_copy_string(buf, vmu->fullname, len);
11183       } else if (!strncasecmp(arg.attribute, "email", 5)) {
11184          ast_copy_string(buf, vmu->email, len);
11185       } else if (!strncasecmp(arg.attribute, "pager", 5)) {
11186          ast_copy_string(buf, vmu->pager, len);
11187       } else if (!strncasecmp(arg.attribute, "language", 8)) {
11188          ast_copy_string(buf, S_OR(vmu->language, ast_channel_language(chan)), len);
11189       } else if (!strncasecmp(arg.attribute, "locale", 6)) {
11190          ast_copy_string(buf, vmu->locale, len);
11191       } else if (!strncasecmp(arg.attribute, "tz", 2)) {
11192          ast_copy_string(buf, vmu->zonetag, len);
11193       } else if (!strncasecmp(arg.attribute, "count", 5)) {
11194          /* If mbxfolder is empty messagecount will default to INBOX */
11195          res = messagecount(context, mailbox, arg.folder);
11196          if (res < 0) {
11197             ast_log(LOG_ERROR, "Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
11198             return -1;
11199          }
11200          snprintf(buf, len, "%d", res);
11201       } else {
11202          ast_log(LOG_ERROR, "Unknown attribute '%s' for VM_INFO\n", arg.attribute);
11203          return -1;
11204       }
11205    }
11206 
11207    return 0;
11208 }

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

Definition at line 12024 of file app_voicemail.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, 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, ast_vm_user::mailbox, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, vm_zone::msg_format, vm_zone::name, ast_variable::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, vm_zone::timezone, ast_variable::value, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_prepend_timeout, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, and VM_TEMPGREETWARN.

Referenced by load_config().

12025 {
12026    struct ast_vm_user *current;
12027    char *cat;
12028    struct ast_variable *var;
12029    const char *val;
12030    char *q, *stringp, *tmp;
12031    int x;
12032    int tmpadsi[4];
12033    char secretfn[PATH_MAX] = "";
12034 
12035 #ifdef IMAP_STORAGE
12036    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
12037 #endif
12038    /* set audio control prompts */
12039    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
12040    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
12041    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
12042    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
12043    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
12044 
12045    /* Free all the users structure */  
12046    free_vm_users();
12047 
12048    /* Free all the zones structure */
12049    free_vm_zones();
12050 
12051    AST_LIST_LOCK(&users);  
12052 
12053    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
12054    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
12055 
12056    if (cfg) {
12057       /* General settings */
12058 
12059       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
12060          val = "default";
12061       ast_copy_string(userscontext, val, sizeof(userscontext));
12062       /* Attach voice message to mail message ? */
12063       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
12064          val = "yes";
12065       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
12066 
12067       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
12068          val = "no";
12069       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
12070 
12071       volgain = 0.0;
12072       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
12073          sscanf(val, "%30lf", &volgain);
12074 
12075 #ifdef ODBC_STORAGE
12076       strcpy(odbc_database, "asterisk");
12077       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
12078          ast_copy_string(odbc_database, val, sizeof(odbc_database));
12079       }
12080       strcpy(odbc_table, "voicemessages");
12081       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
12082          ast_copy_string(odbc_table, val, sizeof(odbc_table));
12083       }
12084 #endif      
12085       /* Mail command */
12086       strcpy(mailcmd, SENDMAIL);
12087       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
12088          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
12089 
12090       maxsilence = 0;
12091       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
12092          maxsilence = atoi(val);
12093          if (maxsilence > 0)
12094             maxsilence *= 1000;
12095       }
12096       
12097       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
12098          maxmsg = MAXMSG;
12099       } else {
12100          maxmsg = atoi(val);
12101          if (maxmsg < 0) {
12102             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
12103             maxmsg = MAXMSG;
12104          } else if (maxmsg > MAXMSGLIMIT) {
12105             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
12106             maxmsg = MAXMSGLIMIT;
12107          }
12108       }
12109 
12110       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
12111          maxdeletedmsg = 0;
12112       } else {
12113          if (sscanf(val, "%30d", &x) == 1)
12114             maxdeletedmsg = x;
12115          else if (ast_true(val))
12116             maxdeletedmsg = MAXMSG;
12117          else
12118             maxdeletedmsg = 0;
12119 
12120          if (maxdeletedmsg < 0) {
12121             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
12122             maxdeletedmsg = MAXMSG;
12123          } else if (maxdeletedmsg > MAXMSGLIMIT) {
12124             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
12125             maxdeletedmsg = MAXMSGLIMIT;
12126          }
12127       }
12128 
12129       /* Load date format config for voicemail mail */
12130       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
12131          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
12132       }
12133 
12134       /* Load date format config for voicemail pager mail */
12135       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
12136          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
12137       }
12138 
12139       /* External password changing command */
12140       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
12141          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
12142          pwdchange = PWDCHANGE_EXTERNAL;
12143       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
12144          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
12145          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
12146       }
12147 
12148       /* External password validation command */
12149       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
12150          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
12151          ast_debug(1, "found externpasscheck: %s\n", ext_pass_check_cmd);
12152       }
12153 
12154 #ifdef IMAP_STORAGE
12155       /* IMAP server address */
12156       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
12157          ast_copy_string(imapserver, val, sizeof(imapserver));
12158       } else {
12159          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
12160       }
12161       /* IMAP server port */
12162       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
12163          ast_copy_string(imapport, val, sizeof(imapport));
12164       } else {
12165          ast_copy_string(imapport, "143", sizeof(imapport));
12166       }
12167       /* IMAP server flags */
12168       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
12169          ast_copy_string(imapflags, val, sizeof(imapflags));
12170       }
12171       /* IMAP server master username */
12172       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
12173          ast_copy_string(authuser, val, sizeof(authuser));
12174       }
12175       /* IMAP server master password */
12176       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
12177          ast_copy_string(authpassword, val, sizeof(authpassword));
12178       }
12179       /* Expunge on exit */
12180       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
12181          if (ast_false(val))
12182             expungeonhangup = 0;
12183          else
12184             expungeonhangup = 1;
12185       } else {
12186          expungeonhangup = 1;
12187       }
12188       /* IMAP voicemail folder */
12189       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
12190          ast_copy_string(imapfolder, val, sizeof(imapfolder));
12191       } else {
12192          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
12193       }
12194       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
12195          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
12196       }
12197       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
12198          imapgreetings = ast_true(val);
12199       } else {
12200          imapgreetings = 0;
12201       }
12202       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
12203          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
12204       } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
12205          /* Also support greetingsfolder as documented in voicemail.conf.sample */
12206          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
12207       } else {
12208          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
12209       }
12210 
12211       /* There is some very unorthodox casting done here. This is due
12212        * to the way c-client handles the argument passed in. It expects a 
12213        * void pointer and casts the pointer directly to a long without
12214        * first dereferencing it. */
12215       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
12216          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
12217       } else {
12218          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
12219       }
12220 
12221       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
12222          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
12223       } else {
12224          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
12225       }
12226 
12227       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
12228          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
12229       } else {
12230          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
12231       }
12232 
12233       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
12234          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
12235       } else {
12236          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
12237       }
12238 
12239       /* Increment configuration version */
12240       imapversion++;
12241 #endif
12242       /* External voicemail notify application */
12243       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
12244          ast_copy_string(externnotify, val, sizeof(externnotify));
12245          ast_debug(1, "found externnotify: %s\n", externnotify);
12246       } else {
12247          externnotify[0] = '\0';
12248       }
12249 
12250       /* SMDI voicemail notification */
12251       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
12252          ast_debug(1, "Enabled SMDI voicemail notification\n");
12253          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
12254             smdi_iface = ast_smdi_interface_find(val);
12255          } else {
12256             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
12257             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
12258          }
12259          if (!smdi_iface) {
12260             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
12261          }
12262       }
12263 
12264       /* Silence treshold */
12265       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
12266       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
12267          silencethreshold = atoi(val);
12268 
12269       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
12270          val = ASTERISK_USERNAME;
12271       ast_copy_string(serveremail, val, sizeof(serveremail));
12272 
12273       vmmaxsecs = 0;
12274       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
12275          if (sscanf(val, "%30d", &x) == 1) {
12276             vmmaxsecs = x;
12277          } else {
12278             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
12279          }
12280       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
12281          static int maxmessage_deprecate = 0;
12282          if (maxmessage_deprecate == 0) {
12283             maxmessage_deprecate = 1;
12284             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
12285          }
12286          if (sscanf(val, "%30d", &x) == 1) {
12287             vmmaxsecs = x;
12288          } else {
12289             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
12290          }
12291       }
12292 
12293       vmminsecs = 0;
12294       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
12295          if (sscanf(val, "%30d", &x) == 1) {
12296             vmminsecs = x;
12297             if (maxsilence / 1000 >= vmminsecs) {
12298                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
12299             }
12300          } else {
12301             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
12302          }
12303       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
12304          static int maxmessage_deprecate = 0;
12305          if (maxmessage_deprecate == 0) {
12306             maxmessage_deprecate = 1;
12307             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
12308          }
12309          if (sscanf(val, "%30d", &x) == 1) {
12310             vmminsecs = x;
12311             if (maxsilence / 1000 >= vmminsecs) {
12312                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
12313             }
12314          } else {
12315             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
12316          }
12317       }
12318 
12319       val = ast_variable_retrieve(cfg, "general", "format");
12320       if (!val) {
12321          val = "wav";   
12322       } else {
12323          tmp = ast_strdupa(val);
12324          val = ast_format_str_reduce(tmp);
12325          if (!val) {
12326             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
12327             val = "wav";
12328          }
12329       }
12330       ast_copy_string(vmfmts, val, sizeof(vmfmts));
12331 
12332       skipms = 3000;
12333       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
12334          if (sscanf(val, "%30d", &x) == 1) {
12335             maxgreet = x;
12336          } else {
12337             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
12338          }
12339       }
12340 
12341       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
12342          if (sscanf(val, "%30d", &x) == 1) {
12343             skipms = x;
12344          } else {
12345             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
12346          }
12347       }
12348 
12349       maxlogins = 3;
12350       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
12351          if (sscanf(val, "%30d", &x) == 1) {
12352             maxlogins = x;
12353          } else {
12354             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
12355          }
12356       }
12357 
12358       minpassword = MINPASSWORD;
12359       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
12360          if (sscanf(val, "%30d", &x) == 1) {
12361             minpassword = x;
12362          } else {
12363             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
12364          }
12365       }
12366 
12367       /* Force new user to record name ? */
12368       if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
12369          val = "no";
12370       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
12371 
12372       /* Force new user to record greetings ? */
12373       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
12374          val = "no";
12375       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
12376 
12377       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
12378          ast_debug(1, "VM_CID Internal context string: %s\n", val);
12379          stringp = ast_strdupa(val);
12380          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
12381             if (!ast_strlen_zero(stringp)) {
12382                q = strsep(&stringp, ",");
12383                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
12384                   q++;
12385                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
12386                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
12387             } else {
12388                cidinternalcontexts[x][0] = '\0';
12389             }
12390          }
12391       }
12392       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
12393          ast_debug(1, "VM Review Option disabled globally\n");
12394          val = "no";
12395       }
12396       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW);
12397 
12398       /* Temporary greeting reminder */
12399       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
12400          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
12401          val = "no";
12402       } else {
12403          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
12404       }
12405       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
12406       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
12407          ast_debug(1, "VM next message wrap disabled globally\n");
12408          val = "no";
12409       }
12410       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);
12411 
12412       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
12413          ast_debug(1, "VM Operator break disabled globally\n");
12414          val = "no";
12415       }
12416       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);
12417 
12418       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
12419          ast_debug(1, "VM CID Info before msg disabled globally\n");
12420          val = "no";
12421       }
12422       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID);
12423 
12424       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
12425          ast_debug(1, "Send Voicemail msg disabled globally\n");
12426          val = "no";
12427       }
12428       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
12429 
12430       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
12431          ast_debug(1, "ENVELOPE before msg enabled globally\n");
12432          val = "yes";
12433       }
12434       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);
12435 
12436       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
12437          ast_debug(1, "Move Heard enabled globally\n");
12438          val = "yes";
12439       }
12440       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD);
12441 
12442       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
12443          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
12444          val = "no";
12445       }
12446       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);
12447 
12448       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
12449          ast_debug(1, "Duration info before msg enabled globally\n");
12450          val = "yes";
12451       }
12452       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);
12453 
12454       saydurationminfo = 2;
12455       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
12456          if (sscanf(val, "%30d", &x) == 1) {
12457             saydurationminfo = x;
12458          } else {
12459             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
12460          }
12461       }
12462 
12463       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
12464          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
12465          val = "no";
12466       }
12467       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
12468 
12469       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
12470          ast_copy_string(dialcontext, val, sizeof(dialcontext));
12471          ast_debug(1, "found dialout context: %s\n", dialcontext);
12472       } else {
12473          dialcontext[0] = '\0';
12474       }
12475 
12476       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
12477          ast_copy_string(callcontext, val, sizeof(callcontext));
12478          ast_debug(1, "found callback context: %s\n", callcontext);
12479       } else {
12480          callcontext[0] = '\0';
12481       }
12482 
12483       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
12484          ast_copy_string(exitcontext, val, sizeof(exitcontext));
12485          ast_debug(1, "found operator context: %s\n", exitcontext);
12486       } else {
12487          exitcontext[0] = '\0';
12488       }
12489 
12490       /* load password sounds configuration */
12491       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
12492          ast_copy_string(vm_password, val, sizeof(vm_password));
12493       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
12494          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
12495       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
12496          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
12497       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
12498          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
12499       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
12500          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
12501       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
12502          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
12503       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
12504          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
12505       }
12506       if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
12507          ast_copy_string(vm_prepend_timeout, val, sizeof(vm_prepend_timeout));
12508       }
12509       /* load configurable audio prompts */
12510       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
12511          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
12512       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
12513          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
12514       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
12515          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
12516       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
12517          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
12518       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
12519          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
12520 
12521       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
12522          val = "no";
12523       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
12524 
12525       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
12526          val = "voicemail.conf";
12527       }
12528       if (!(strcmp(val, "spooldir"))) {
12529          passwordlocation = OPT_PWLOC_SPOOLDIR;
12530       } else {
12531          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
12532       }
12533 
12534       poll_freq = DEFAULT_POLL_FREQ;
12535       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
12536          if (sscanf(val, "%30u", &poll_freq) != 1) {
12537             poll_freq = DEFAULT_POLL_FREQ;
12538             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
12539          }
12540       }
12541 
12542       poll_mailboxes = 0;
12543       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
12544          poll_mailboxes = ast_true(val);
12545 
12546       memset(fromstring, 0, sizeof(fromstring));
12547       memset(pagerfromstring, 0, sizeof(pagerfromstring));
12548       strcpy(charset, "ISO-8859-1");
12549       if (emailbody) {
12550          ast_free(emailbody);
12551          emailbody = NULL;
12552       }
12553       if (emailsubject) {
12554          ast_free(emailsubject);
12555          emailsubject = NULL;
12556       }
12557       if (pagerbody) {
12558          ast_free(pagerbody);
12559          pagerbody = NULL;
12560       }
12561       if (pagersubject) {
12562          ast_free(pagersubject);
12563          pagersubject = NULL;
12564       }
12565       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
12566          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
12567       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
12568          ast_copy_string(fromstring, val, sizeof(fromstring));
12569       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
12570          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
12571       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
12572          ast_copy_string(charset, val, sizeof(charset));
12573       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
12574          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12575          for (x = 0; x < 4; x++) {
12576             memcpy(&adsifdn[x], &tmpadsi[x], 1);
12577          }
12578       }
12579       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
12580          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12581          for (x = 0; x < 4; x++) {
12582             memcpy(&adsisec[x], &tmpadsi[x], 1);
12583          }
12584       }
12585       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
12586          if (atoi(val)) {
12587             adsiver = atoi(val);
12588          }
12589       }
12590       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
12591          ast_copy_string(zonetag, val, sizeof(zonetag));
12592       }
12593       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
12594          ast_copy_string(locale, val, sizeof(locale));
12595       }
12596       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
12597          emailsubject = ast_strdup(substitute_escapes(val));
12598       }
12599       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
12600          emailbody = ast_strdup(substitute_escapes(val));
12601       }
12602       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
12603          pagersubject = ast_strdup(substitute_escapes(val));
12604       }
12605       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
12606          pagerbody = ast_strdup(substitute_escapes(val));
12607       }
12608 
12609       /* load mailboxes from users.conf */
12610       if (ucfg) { 
12611          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
12612             if (!strcasecmp(cat, "general")) {
12613                continue;
12614             }
12615             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
12616                continue;
12617             if ((current = find_or_create(userscontext, cat))) {
12618                populate_defaults(current);
12619                apply_options_full(current, ast_variable_browse(ucfg, cat));
12620                ast_copy_string(current->context, userscontext, sizeof(current->context));
12621                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
12622                   current->passwordlocation = OPT_PWLOC_USERSCONF;
12623                }
12624 
12625                switch (current->passwordlocation) {
12626                case OPT_PWLOC_SPOOLDIR:
12627                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
12628                   read_password_from_file(secretfn, current->password, sizeof(current->password));
12629                }
12630             }
12631          }
12632       }
12633 
12634       /* load mailboxes from voicemail.conf */
12635       cat = ast_category_browse(cfg, NULL);
12636       while (cat) {
12637          if (strcasecmp(cat, "general")) {
12638             var = ast_variable_browse(cfg, cat);
12639             if (strcasecmp(cat, "zonemessages")) {
12640                /* Process mailboxes in this context */
12641                while (var) {
12642                   append_mailbox(cat, var->name, var->value);
12643                   var = var->next;
12644                }
12645             } else {
12646                /* Timezones in this context */
12647                while (var) {
12648                   struct vm_zone *z;
12649                   if ((z = ast_malloc(sizeof(*z)))) {
12650                      char *msg_format, *tzone;
12651                      msg_format = ast_strdupa(var->value);
12652                      tzone = strsep(&msg_format, "|,");
12653                      if (msg_format) {
12654                         ast_copy_string(z->name, var->name, sizeof(z->name));
12655                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
12656                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
12657                         AST_LIST_LOCK(&zones);
12658                         AST_LIST_INSERT_HEAD(&zones, z, list);
12659                         AST_LIST_UNLOCK(&zones);
12660                      } else {
12661                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
12662                         ast_free(z);
12663                      }
12664                   } else {
12665                      AST_LIST_UNLOCK(&users);
12666                      return -1;
12667                   }
12668                   var = var->next;
12669                }
12670             }
12671          }
12672          cat = ast_category_browse(cfg, cat);
12673       }
12674 
12675       AST_LIST_UNLOCK(&users);
12676 
12677       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
12678          start_poll_thread();
12679       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
12680          stop_poll_thread();;
12681 
12682       return 0;
12683    } else {
12684       AST_LIST_UNLOCK(&users);
12685       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
12686       return 0;
12687    }
12688 }

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

04885 {
04886    char tmpdir[256], newtmp[256];
04887    char fname[256];
04888    char tmpcmd[256];
04889    int tmpfd = -1;
04890    int soxstatus = 0;
04891 
04892    /* Eww. We want formats to tell us their own MIME type */
04893    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04894 
04895    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04896       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04897       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04898       tmpfd = mkstemp(newtmp);
04899       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04900       ast_debug(3, "newtmp: %s\n", newtmp);
04901       if (tmpfd > -1) {
04902          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04903          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04904             attach = newtmp;
04905             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04906          } else {
04907             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04908                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04909             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04910          }
04911       }
04912    }
04913    fprintf(p, "--%s" ENDL, bound);
04914    if (msgnum > -1)
04915       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04916    else
04917       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04918    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04919    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04920    if (msgnum > -1)
04921       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04922    else
04923       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04924    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04925    base_encode(fname, p);
04926    if (last)
04927       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04928    if (tmpfd > -1) {
04929       if (soxstatus == 0) {
04930          unlink(fname);
04931       }
04932       close(tmpfd);
04933       unlink(newtmp);
04934    }
04935    return 0;
04936 }

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

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

06492 {
06493    int x;
06494    if (!ast_adsi_available(chan))
06495       return;
06496    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06497    if (x < 0)
06498       return;
06499    if (!x) {
06500       if (adsi_load_vmail(chan, useadsi)) {
06501          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06502          return;
06503       }
06504    } else
06505       *useadsi = 1;
06506 }

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

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

06681 {
06682    int bytes = 0;
06683    unsigned char buf[256];
06684    unsigned char keys[8];
06685 
06686    int x;
06687 
06688    if (!ast_adsi_available(chan))
06689       return;
06690 
06691    /* New meaning for keys */
06692    for (x = 0; x < 5; x++)
06693       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06694 
06695    keys[6] = 0x0;
06696    keys[7] = 0x0;
06697 
06698    if (!vms->curmsg) {
06699       /* No prev key, provide "Folder" instead */
06700       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06701    }
06702    if (vms->curmsg >= vms->lastmsg) {
06703       /* If last message ... */
06704       if (vms->curmsg) {
06705          /* but not only message, provide "Folder" instead */
06706          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06707       } else {
06708          /* Otherwise if only message, leave blank */
06709          keys[3] = 1;
06710       }
06711    }
06712 
06713    /* If deleted, show "undeleted" */
06714    if (vms->deleted[vms->curmsg]) 
06715       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06716 
06717    /* Except "Exit" */
06718    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06719    bytes += ast_adsi_set_keys(buf + bytes, keys);
06720    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06721 
06722    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06723 }

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

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

06557 {
06558    unsigned char buf[256];
06559    int bytes = 0;
06560    unsigned char keys[8];
06561    int x, y;
06562 
06563    if (!ast_adsi_available(chan))
06564       return;
06565 
06566    for (x = 0; x < 5; x++) {
06567       y = ADSI_KEY_APPS + 12 + start + x;
06568       if (y > ADSI_KEY_APPS + 12 + 4)
06569          y = 0;
06570       keys[x] = ADSI_KEY_SKT | y;
06571    }
06572    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06573    keys[6] = 0;
06574    keys[7] = 0;
06575 
06576    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06577    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06578    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06579    bytes += ast_adsi_set_keys(buf + bytes, keys);
06580    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06581 
06582    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06583 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06829 {
06830    unsigned char buf[256];
06831    int bytes = 0;
06832 
06833    if (!ast_adsi_available(chan))
06834       return;
06835    bytes += adsi_logo(buf + bytes);
06836    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06837    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06838    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06839    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06840 
06841    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06842 }

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

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

Referenced by adsi_begin().

06363 {
06364    unsigned char buf[256];
06365    int bytes = 0;
06366    int x;
06367    char num[5];
06368 
06369    *useadsi = 0;
06370    bytes += ast_adsi_data_mode(buf + bytes);
06371    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06372 
06373    bytes = 0;
06374    bytes += adsi_logo(buf);
06375    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06376 #ifdef DISPLAY
06377    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06378 #endif
06379    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06380    bytes += ast_adsi_data_mode(buf + bytes);
06381    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06382 
06383    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06384       bytes = 0;
06385       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06386       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06387       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06388       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06389       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06390       return 0;
06391    }
06392 
06393 #ifdef DISPLAY
06394    /* Add a dot */
06395    bytes = 0;
06396    bytes += ast_adsi_logo(buf);
06397    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06398    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06399    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06400    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06401 #endif
06402    bytes = 0;
06403    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06404    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06405    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06406    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06407    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06408    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06409    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06410 
06411 #ifdef DISPLAY
06412    /* Add another dot */
06413    bytes = 0;
06414    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06415    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06416 
06417    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06418    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06419 #endif
06420 
06421    bytes = 0;
06422    /* These buttons we load but don't use yet */
06423    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06424    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06425    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06426    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06427    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06428    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06429    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06430 
06431 #ifdef DISPLAY
06432    /* Add another dot */
06433    bytes = 0;
06434    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06435    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06436    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06437 #endif
06438 
06439    bytes = 0;
06440    for (x = 0; x < 5; x++) {
06441       snprintf(num, sizeof(num), "%d", x);
06442       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06443    }
06444    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06445    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06446 
06447 #ifdef DISPLAY
06448    /* Add another dot */
06449    bytes = 0;
06450    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06451    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06452    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06453 #endif
06454 
06455    if (ast_adsi_end_download(chan)) {
06456       bytes = 0;
06457       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06458       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06459       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06460       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06461       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06462       return 0;
06463    }
06464    bytes = 0;
06465    bytes += ast_adsi_download_disconnect(buf + bytes);
06466    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06467    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06468 
06469    ast_debug(1, "Done downloading scripts...\n");
06470 
06471 #ifdef DISPLAY
06472    /* Add last dot */
06473    bytes = 0;
06474    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06475    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06476 #endif
06477    ast_debug(1, "Restarting session...\n");
06478 
06479    bytes = 0;
06480    /* Load the session now */
06481    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06482       *useadsi = 1;
06483       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06484    } else
06485       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06486 
06487    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06488    return 0;
06489 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06509 {
06510    unsigned char buf[256];
06511    int bytes = 0;
06512    unsigned char keys[8];
06513    int x;
06514    if (!ast_adsi_available(chan))
06515       return;
06516 
06517    for (x = 0; x < 8; x++)
06518       keys[x] = 0;
06519    /* Set one key for next */
06520    keys[3] = ADSI_KEY_APPS + 3;
06521 
06522    bytes += adsi_logo(buf + bytes);
06523    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06524    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06525    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06526    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06527    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06528    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06529    bytes += ast_adsi_set_keys(buf + bytes, keys);
06530    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06531    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06532 }

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

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

06355 {
06356    int bytes = 0;
06357    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06358    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06359    return bytes;
06360 }

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

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

Referenced by play_message(), and vm_execmain().

06586 {
06587    int bytes = 0;
06588    unsigned char buf[256]; 
06589    char buf1[256], buf2[256];
06590    char fn2[PATH_MAX];
06591 
06592    char cid[256] = "";
06593    char *val;
06594    char *name, *num;
06595    char datetime[21] = "";
06596    FILE *f;
06597 
06598    unsigned char keys[8];
06599 
06600    int x;
06601 
06602    if (!ast_adsi_available(chan))
06603       return;
06604 
06605    /* Retrieve important info */
06606    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06607    f = fopen(fn2, "r");
06608    if (f) {
06609       while (!feof(f)) {   
06610          if (!fgets((char *) buf, sizeof(buf), f)) {
06611             continue;
06612          }
06613          if (!feof(f)) {
06614             char *stringp = NULL;
06615             stringp = (char *) buf;
06616             strsep(&stringp, "=");
06617             val = strsep(&stringp, "=");
06618             if (!ast_strlen_zero(val)) {
06619                if (!strcmp((char *) buf, "callerid"))
06620                   ast_copy_string(cid, val, sizeof(cid));
06621                if (!strcmp((char *) buf, "origdate"))
06622                   ast_copy_string(datetime, val, sizeof(datetime));
06623             }
06624          }
06625       }
06626       fclose(f);
06627    }
06628    /* New meaning for keys */
06629    for (x = 0; x < 5; x++)
06630       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06631    keys[6] = 0x0;
06632    keys[7] = 0x0;
06633 
06634    if (!vms->curmsg) {
06635       /* No prev key, provide "Folder" instead */
06636       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06637    }
06638    if (vms->curmsg >= vms->lastmsg) {
06639       /* If last message ... */
06640       if (vms->curmsg) {
06641          /* but not only message, provide "Folder" instead */
06642          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06643          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06644 
06645       } else {
06646          /* Otherwise if only message, leave blank */
06647          keys[3] = 1;
06648       }
06649    }
06650 
06651    if (!ast_strlen_zero(cid)) {
06652       ast_callerid_parse(cid, &name, &num);
06653       if (!name)
06654          name = num;
06655    } else
06656       name = "Unknown Caller";
06657 
06658    /* If deleted, show "undeleted" */
06659 
06660    if (vms->deleted[vms->curmsg])
06661       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06662 
06663    /* Except "Exit" */
06664    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06665    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06666       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06667    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06668 
06669    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06670    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06671    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06672    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06673    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06674    bytes += ast_adsi_set_keys(buf + bytes, keys);
06675    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06676 
06677    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06678 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06535 {
06536    unsigned char buf[256];
06537    int bytes = 0;
06538    unsigned char keys[8];
06539    int x;
06540    if (!ast_adsi_available(chan))
06541       return;
06542 
06543    for (x = 0; x < 8; x++)
06544       keys[x] = 0;
06545    /* Set one key for next */
06546    keys[3] = ADSI_KEY_APPS + 3;
06547 
06548    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06549    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06550    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06551    bytes += ast_adsi_set_keys(buf + bytes, keys);
06552    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06553    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06554 }

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

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

06726 {
06727    unsigned char buf[256] = "";
06728    char buf1[256] = "", buf2[256] = "";
06729    int bytes = 0;
06730    unsigned char keys[8];
06731    int x;
06732 
06733    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06734    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06735    if (!ast_adsi_available(chan))
06736       return;
06737    if (vms->newmessages) {
06738       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06739       if (vms->oldmessages) {
06740          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06741          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06742       } else {
06743          snprintf(buf2, sizeof(buf2), "%s.", newm);
06744       }
06745    } else if (vms->oldmessages) {
06746       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06747       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06748    } else {
06749       strcpy(buf1, "You have no messages.");
06750       buf2[0] = ' ';
06751       buf2[1] = '\0';
06752    }
06753    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06754    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06755    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06756 
06757    for (x = 0; x < 6; x++)
06758       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06759    keys[6] = 0;
06760    keys[7] = 0;
06761 
06762    /* Don't let them listen if there are none */
06763    if (vms->lastmsg < 0)
06764       keys[0] = 1;
06765    bytes += ast_adsi_set_keys(buf + bytes, keys);
06766 
06767    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06768 
06769    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06770 }

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

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

06773 {
06774    unsigned char buf[256] = "";
06775    char buf1[256] = "", buf2[256] = "";
06776    int bytes = 0;
06777    unsigned char keys[8];
06778    int x;
06779 
06780    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06781 
06782    if (!ast_adsi_available(chan))
06783       return;
06784 
06785    /* Original command keys */
06786    for (x = 0; x < 6; x++)
06787       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06788 
06789    keys[6] = 0;
06790    keys[7] = 0;
06791 
06792    if ((vms->lastmsg + 1) < 1)
06793       keys[0] = 0;
06794 
06795    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06796       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06797 
06798    if (vms->lastmsg + 1)
06799       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06800    else
06801       strcpy(buf2, "no messages.");
06802    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06803    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06804    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06805    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06806    bytes += ast_adsi_set_keys(buf + bytes, keys);
06807 
06808    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06809 
06810    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06811    
06812 }

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

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log(), AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_test_suite_event_notify, 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(), play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, and wait_file().

Referenced by vm_execmain().

13471 {
13472    int res = 0;
13473    char filename[PATH_MAX];
13474    struct ast_config *msg_cfg = NULL;
13475    const char *origtime, *context;
13476    char *name, *num;
13477    int retries = 0;
13478    char *cid;
13479    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
13480 
13481    vms->starting = 0; 
13482 
13483    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13484 
13485    /* Retrieve info from VM attribute file */
13486    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
13487    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
13488    msg_cfg = ast_config_load(filename, config_flags);
13489    DISPOSE(vms->curdir, vms->curmsg);
13490    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
13491       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
13492       return 0;
13493    }
13494 
13495    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
13496       ast_config_destroy(msg_cfg);
13497       return 0;
13498    }
13499 
13500    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
13501 
13502    context = ast_variable_retrieve(msg_cfg, "message", "context");
13503    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
13504       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
13505    switch (option) {
13506    case 3: /* Play message envelope */
13507       if (!res) {
13508          res = play_message_datetime(chan, vmu, origtime, filename);
13509       }
13510       if (!res) {
13511          res = play_message_callerid(chan, vms, cid, context, 0, 1);
13512       }
13513 
13514       res = 't';
13515       break;
13516 
13517    case 2:  /* Call back */
13518 
13519       if (ast_strlen_zero(cid))
13520          break;
13521 
13522       ast_callerid_parse(cid, &name, &num);
13523       while ((res > -1) && (res != 't')) {
13524          switch (res) {
13525          case '1':
13526             if (num) {
13527                /* Dial the CID number */
13528                res = dialout(chan, vmu, num, vmu->callback);
13529                if (res) {
13530                   ast_config_destroy(msg_cfg);
13531                   return 9;
13532                }
13533             } else {
13534                res = '2';
13535             }
13536             break;
13537 
13538          case '2':
13539             /* Want to enter a different number, can only do this if there's a dialout context for this user */
13540             if (!ast_strlen_zero(vmu->dialout)) {
13541                res = dialout(chan, vmu, NULL, vmu->dialout);
13542                if (res) {
13543                   ast_config_destroy(msg_cfg);
13544                   return 9;
13545                }
13546             } else {
13547                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
13548                res = ast_play_and_wait(chan, "vm-sorry");
13549             }
13550             ast_config_destroy(msg_cfg);
13551             return res;
13552          case '*':
13553             res = 't';
13554             break;
13555          case '3':
13556          case '4':
13557          case '5':
13558          case '6':
13559          case '7':
13560          case '8':
13561          case '9':
13562          case '0':
13563 
13564             res = ast_play_and_wait(chan, "vm-sorry");
13565             retries++;
13566             break;
13567          default:
13568             if (num) {
13569                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
13570                res = ast_play_and_wait(chan, "vm-num-i-have");
13571                if (!res)
13572                   res = play_message_callerid(chan, vms, num, vmu->context, 1, 1);
13573                if (!res)
13574                   res = ast_play_and_wait(chan, "vm-tocallnum");
13575                /* Only prompt for a caller-specified number if there is a dialout context specified */
13576                if (!ast_strlen_zero(vmu->dialout)) {
13577                   if (!res)
13578                      res = ast_play_and_wait(chan, "vm-calldiffnum");
13579                }
13580             } else {
13581                res = ast_play_and_wait(chan, "vm-nonumber");
13582                if (!ast_strlen_zero(vmu->dialout)) {
13583                   if (!res)
13584                      res = ast_play_and_wait(chan, "vm-toenternumber");
13585                }
13586             }
13587             if (!res) {
13588                res = ast_play_and_wait(chan, "vm-star-cancel");
13589             }
13590             if (!res) {
13591                res = ast_waitfordigit(chan, 6000);
13592             }
13593             if (!res) {
13594                retries++;
13595                if (retries > 3) {
13596                   res = 't';
13597                }
13598             }
13599             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
13600             break; 
13601             
13602          }
13603          if (res == 't')
13604             res = 0;
13605          else if (res == '*')
13606             res = -1;
13607       }
13608       break;
13609       
13610    case 1:  /* Reply */
13611       /* Send reply directly to sender */
13612       if (ast_strlen_zero(cid))
13613          break;
13614 
13615       ast_callerid_parse(cid, &name, &num);
13616       if (!num) {
13617          ast_verb(3, "No CID number available, no reply sent\n");
13618          if (!res)
13619             res = ast_play_and_wait(chan, "vm-nonumber");
13620          ast_config_destroy(msg_cfg);
13621          return res;
13622       } else {
13623          struct ast_vm_user vmu2;
13624          if (find_user(&vmu2, vmu->context, num)) {
13625             struct leave_vm_options leave_options;
13626             char mailbox[AST_MAX_EXTENSION * 2 + 2];
13627             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
13628 
13629             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
13630             
13631             memset(&leave_options, 0, sizeof(leave_options));
13632             leave_options.record_gain = record_gain;
13633             res = leave_voicemail(chan, mailbox, &leave_options);
13634             if (!res)
13635                res = 't';
13636             ast_config_destroy(msg_cfg);
13637             return res;
13638          } else {
13639             /* Sender has no mailbox, can't reply */
13640             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
13641             ast_play_and_wait(chan, "vm-nobox");
13642             res = 't';
13643             ast_config_destroy(msg_cfg);
13644             return res;
13645          }
13646       } 
13647       res = 0;
13648 
13649       break;
13650    }
13651 
13652 #ifndef IMAP_STORAGE
13653    ast_config_destroy(msg_cfg);
13654 
13655    if (!res) {
13656       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13657       vms->heard[msg] = 1;
13658       res = wait_file(chan, vms, vms->fn);
13659    }
13660 #endif
13661    return res;
13662 }

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

Definition at line 10826 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, find_or_create(), ast_vm_user::fullname, inboxcount2(), LOG_WARNING, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, ast_vm_user::pager, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), queue_mwi_event(), read_password_from_file(), and strsep().

Referenced by actual_load_config().

10827 {
10828    /* Assumes lock is already held */
10829    char *tmp;
10830    char *stringp;
10831    char *s;
10832    struct ast_vm_user *vmu;
10833    char *mailbox_full;
10834    int new = 0, old = 0, urgent = 0;
10835    char secretfn[PATH_MAX] = "";
10836 
10837    tmp = ast_strdupa(data);
10838 
10839    if (!(vmu = find_or_create(context, box)))
10840       return -1;
10841 
10842    populate_defaults(vmu);
10843 
10844    stringp = tmp;
10845    if ((s = strsep(&stringp, ","))) {
10846       if (!ast_strlen_zero(s) && s[0] == '*') {
10847          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10848             "\n\tmust be reset in voicemail.conf.\n", box);
10849       }
10850       /* assign password regardless of validity to prevent NULL password from being assigned */
10851       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10852    }
10853    if (stringp && (s = strsep(&stringp, ","))) {
10854       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10855    }
10856    if (stringp && (s = strsep(&stringp, ","))) {
10857       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10858    }
10859    if (stringp && (s = strsep(&stringp, ","))) {
10860       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10861    }
10862    if (stringp && (s = strsep(&stringp, ","))) {
10863       apply_options(vmu, s);
10864    }
10865 
10866    switch (vmu->passwordlocation) {
10867    case OPT_PWLOC_SPOOLDIR:
10868       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10869       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10870    }
10871 
10872    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10873    strcpy(mailbox_full, box);
10874    strcat(mailbox_full, "@");
10875    strcat(mailbox_full, context);
10876 
10877    inboxcount2(mailbox_full, &urgent, &new, &old);
10878    queue_mwi_event(mailbox_full, urgent, new, old);
10879 
10880    return 0;
10881 }

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

References apply_options(), ast_copy_string(), ast_free, ast_log(), AST_LOG_WARNING, ast_set2_flag, ast_strdup, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, ast_vm_user::language, ast_vm_user::locale, LOG_WARNING, ast_vm_user::maxdeletedmsg, MAXMSG, ast_vm_user::maxmsg, MAXMSGLIMIT, ast_vm_user::maxsecs, ast_vm_user::minsecs, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, ast_vm_user::serveremail, substitute_escapes(), VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, ast_vm_user::volgain, and ast_vm_user::zonetag.

Referenced by apply_options(), and apply_options_full().

01134 {
01135    int x;
01136    if (!strcasecmp(var, "attach")) {
01137       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01138    } else if (!strcasecmp(var, "attachfmt")) {
01139       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01140    } else if (!strcasecmp(var, "serveremail")) {
01141       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01142    } else if (!strcasecmp(var, "emailbody")) {
01143       ast_free(vmu->emailbody);
01144       vmu->emailbody = ast_strdup(substitute_escapes(value));
01145    } else if (!strcasecmp(var, "emailsubject")) {
01146       ast_free(vmu->emailsubject);
01147       vmu->emailsubject = ast_strdup(substitute_escapes(value));
01148    } else if (!strcasecmp(var, "language")) {
01149       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01150    } else if (!strcasecmp(var, "tz")) {
01151       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01152    } else if (!strcasecmp(var, "locale")) {
01153       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01154 #ifdef IMAP_STORAGE
01155    } else if (!strcasecmp(var, "imapuser")) {
01156       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01157       vmu->imapversion = imapversion;
01158    } else if (!strcasecmp(var, "imapserver")) {
01159       ast_copy_string(vmu->imapserver, value, sizeof(vmu->imapserver));
01160       vmu->imapversion = imapversion;
01161    } else if (!strcasecmp(var, "imapport")) {
01162       ast_copy_string(vmu->imapport, value, sizeof(vmu->imapport));
01163       vmu->imapversion = imapversion;
01164    } else if (!strcasecmp(var, "imapflags")) {
01165       ast_copy_string(vmu->imapflags, value, sizeof(vmu->imapflags));
01166       vmu->imapversion = imapversion;
01167    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01168       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01169       vmu->imapversion = imapversion;
01170    } else if (!strcasecmp(var, "imapfolder")) {
01171       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01172       vmu->imapversion = imapversion;
01173    } else if (!strcasecmp(var, "imapvmshareid")) {
01174       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01175       vmu->imapversion = imapversion;
01176 #endif
01177    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01178       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01179    } else if (!strcasecmp(var, "saycid")){
01180       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01181    } else if (!strcasecmp(var, "sendvoicemail")){
01182       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01183    } else if (!strcasecmp(var, "review")){
01184       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01185    } else if (!strcasecmp(var, "tempgreetwarn")){
01186       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01187    } else if (!strcasecmp(var, "messagewrap")){
01188       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01189    } else if (!strcasecmp(var, "operator")) {
01190       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01191    } else if (!strcasecmp(var, "envelope")){
01192       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01193    } else if (!strcasecmp(var, "moveheard")){
01194       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01195    } else if (!strcasecmp(var, "sayduration")){
01196       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01197    } else if (!strcasecmp(var, "saydurationm")){
01198       if (sscanf(value, "%30d", &x) == 1) {
01199          vmu->saydurationm = x;
01200       } else {
01201          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01202       }
01203    } else if (!strcasecmp(var, "forcename")){
01204       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01205    } else if (!strcasecmp(var, "forcegreetings")){
01206       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01207    } else if (!strcasecmp(var, "callback")) {
01208       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01209    } else if (!strcasecmp(var, "dialout")) {
01210       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01211    } else if (!strcasecmp(var, "exitcontext")) {
01212       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01213    } else if (!strcasecmp(var, "minsecs")) {
01214       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01215          vmu->minsecs = x;
01216       } else {
01217          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01218          vmu->minsecs = vmminsecs;
01219       }
01220    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01221       vmu->maxsecs = atoi(value);
01222       if (vmu->maxsecs <= 0) {
01223          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01224          vmu->maxsecs = vmmaxsecs;
01225       } else {
01226          vmu->maxsecs = atoi(value);
01227       }
01228       if (!strcasecmp(var, "maxmessage"))
01229          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01230    } else if (!strcasecmp(var, "maxmsg")) {
01231       vmu->maxmsg = atoi(value);
01232       /* Accept maxmsg=0 (Greetings only voicemail) */
01233       if (vmu->maxmsg < 0) {
01234          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01235          vmu->maxmsg = MAXMSG;
01236       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01237          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01238          vmu->maxmsg = MAXMSGLIMIT;
01239       }
01240    } else if (!strcasecmp(var, "nextaftercmd")) {
01241       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01242    } else if (!strcasecmp(var, "backupdeleted")) {
01243       if (sscanf(value, "%30d", &x) == 1)
01244          vmu->maxdeletedmsg = x;
01245       else if (ast_true(value))
01246          vmu->maxdeletedmsg = MAXMSG;
01247       else
01248          vmu->maxdeletedmsg = 0;
01249 
01250       if (vmu->maxdeletedmsg < 0) {
01251          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01252          vmu->maxdeletedmsg = MAXMSG;
01253       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01254          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01255          vmu->maxdeletedmsg = MAXMSGLIMIT;
01256       }
01257    } else if (!strcasecmp(var, "volgain")) {
01258       sscanf(value, "%30lf", &vmu->volgain);
01259    } else if (!strcasecmp(var, "passwordlocation")) {
01260       if (!strcasecmp(value, "spooldir")) {
01261          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01262       } else {
01263          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01264       }
01265    } else if (!strcasecmp(var, "options")) {
01266       apply_options(vmu, value);
01267    }
01268 }

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

Destructively Parse options and apply.

Definition at line 1386 of file app_voicemail.c.

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

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

01387 {  
01388    char *stringp;
01389    char *s;
01390    char *var, *value;
01391    stringp = ast_strdupa(options);
01392    while ((s = strsep(&stringp, "|"))) {
01393       value = s;
01394       if ((var = strsep(&value, "=")) && value) {
01395          apply_option(vmu, var, value);
01396       }
01397    }  
01398 }

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

References apply_option(), ast_copy_string(), ast_free, ast_log(), ast_strdup, ast_strlen_zero(), ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::fullname, LOG_WARNING, ast_vm_user::mailbox, ast_variable::name, ast_variable::next, ast_vm_user::pager, ast_vm_user::password, substitute_escapes(), ast_vm_user::uniqueid, and ast_variable::value.

Referenced by actual_load_config(), and find_user_realtime().

01406 {
01407    for (; var; var = var->next) {
01408       if (!strcasecmp(var->name, "vmsecret")) {
01409          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01410       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01411          if (ast_strlen_zero(retval->password)) {
01412             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01413                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01414                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01415             } else {
01416                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01417             }
01418          }
01419       } else if (!strcasecmp(var->name, "uniqueid")) {
01420          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01421       } else if (!strcasecmp(var->name, "pager")) {
01422          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01423       } else if (!strcasecmp(var->name, "email")) {
01424          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01425       } else if (!strcasecmp(var->name, "fullname")) {
01426          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01427       } else if (!strcasecmp(var->name, "context")) {
01428          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01429       } else if (!strcasecmp(var->name, "emailsubject")) {
01430          ast_free(retval->emailsubject);
01431          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01432       } else if (!strcasecmp(var->name, "emailbody")) {
01433          ast_free(retval->emailbody);
01434          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01435 #ifdef IMAP_STORAGE
01436       } else if (!strcasecmp(var->name, "imapuser")) {
01437          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01438          retval->imapversion = imapversion;
01439       } else if (!strcasecmp(var->name, "imapserver")) {
01440          ast_copy_string(retval->imapserver, var->value, sizeof(retval->imapserver));
01441          retval->imapversion = imapversion;
01442       } else if (!strcasecmp(var->name, "imapport")) {
01443          ast_copy_string(retval->imapport, var->value, sizeof(retval->imapport));
01444          retval->imapversion = imapversion;
01445       } else if (!strcasecmp(var->name, "imapflags")) {
01446          ast_copy_string(retval->imapflags, var->value, sizeof(retval->imapflags));
01447          retval->imapversion = imapversion;
01448       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01449          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01450          retval->imapversion = imapversion;
01451       } else if (!strcasecmp(var->name, "imapfolder")) {
01452          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01453          retval->imapversion = imapversion;
01454       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01455          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01456          retval->imapversion = imapversion;
01457 #endif
01458       } else
01459          apply_option(retval, var->name, var->value);
01460    }
01461 }

AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)

AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)

static const char* ast_str_encode_mime ( struct ast_str **  end,
ssize_t  maxlen,
const char *  start,
size_t  preamble,
size_t  postamble 
) [static]

Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain control characters.

Additionally, if the encoded string would exceed the MIME limit of 76 characters per line, then the encoding will be broken up into multiple sections, separated by a space character, in order to facilitate breaking up the associated header across multiple lines.

Parameters:
end An expandable buffer for holding the result
maxlen Always zero, but see
See also:
ast_str
Parameters:
start A string to be encoded
preamble The length of the first line already used for this string, to ensure that each line maintains a maximum length of 76 chars.
postamble the length of any additional characters appended to the line, used to ensure proper field wrapping.
Return values:
The encoded string.

Definition at line 4559 of file app_voicemail.c.

References ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set(), ast_str_strlen(), and charset.

04560 {
04561    struct ast_str *tmp = ast_str_alloca(80);
04562    int first_section = 1;
04563 
04564    ast_str_reset(*end);
04565    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04566    for (; *start; start++) {
04567       int need_encoding = 0;
04568       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04569          need_encoding = 1;
04570       }
04571       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04572          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04573          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04574          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04575          /* Start new line */
04576          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04577          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04578          first_section = 0;
04579       }
04580       if (need_encoding && *start == ' ') {
04581          ast_str_append(&tmp, -1, "_");
04582       } else if (need_encoding) {
04583          ast_str_append(&tmp, -1, "=%hhX", *start);
04584       } else {
04585          ast_str_append(&tmp, -1, "%c", *start);
04586       }
04587    }
04588    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04589    return ast_str_buffer(*end);
04590 }

static const char* ast_str_quote ( struct ast_str **  buf,
ssize_t  maxlen,
const char *  from 
) [static]

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

Parameters:
from The string to work with.
buf The buffer into which to write the modified quoted string.
maxlen Always zero, but see
See also:
ast_str
Returns:
The destination string with quotes wrapped on it (the to field).

Definition at line 4487 of file app_voicemail.c.

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

04488 {
04489    const char *ptr;
04490 
04491    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04492    ast_str_set(buf, maxlen, "\"");
04493    for (ptr = from; *ptr; ptr++) {
04494       if (*ptr == '"' || *ptr == '\\') {
04495          ast_str_append(buf, maxlen, "\\%c", *ptr);
04496       } else {
04497          ast_str_append(buf, maxlen, "%c", *ptr);
04498       }
04499    }
04500    ast_str_append(buf, maxlen, "\"");
04501 
04502    return ast_str_buffer(*buf);
04503 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10883 of file app_voicemail.c.

References apply_options(), ast_calloc, ast_set_flag, AST_TEST_FAIL, ast_test_flag, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, free_user(), ast_vm_user::maxdeletedmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, OPT_PWLOC_SPOOLDIR, ast_vm_user::passwordlocation, populate_defaults(), ast_vm_user::saydurationm, ast_vm_user::serveremail, TEST_EXECUTE, TEST_INIT, VM_ALLOCED, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, ast_vm_user::volgain, and ast_vm_user::zonetag.

10884 {
10885    int res = 0;
10886    struct ast_vm_user *vmu;
10887    /* language parameter seems to only be used for display in manager action */
10888    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10889       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10890       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10891       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10892       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10893       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10894       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
10895       "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
10896       "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
10897 #ifdef IMAP_STORAGE
10898    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10899       "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
10900 #endif
10901 
10902    switch (cmd) {
10903    case TEST_INIT:
10904       info->name = "vmuser";
10905       info->category = "/apps/app_voicemail/";
10906       info->summary = "Vmuser unit test";
10907       info->description =
10908          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10909       return AST_TEST_NOT_RUN;
10910    case TEST_EXECUTE:
10911       break;
10912    }
10913 
10914    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10915       return AST_TEST_NOT_RUN;
10916    }
10917    ast_set_flag(vmu, VM_ALLOCED);
10918    populate_defaults(vmu);
10919 
10920    apply_options(vmu, options_string);
10921 
10922    if (!ast_test_flag(vmu, VM_ATTACH)) {
10923       ast_test_status_update(test, "Parse failure for attach option\n");
10924       res = 1;
10925    }
10926    if (strcasecmp(vmu->attachfmt, "wav49")) {
10927       ast_test_status_update(test, "Parse failure for attachftm option\n");
10928       res = 1;
10929    }
10930    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10931       ast_test_status_update(test, "Parse failure for serveremail option\n");
10932       res = 1;
10933    }
10934    if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
10935       ast_test_status_update(test, "Parse failure for emailsubject option\n");
10936       res = 1;
10937    }
10938    if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
10939       ast_test_status_update(test, "Parse failure for emailbody option\n");
10940       res = 1;
10941    }
10942    if (strcasecmp(vmu->zonetag, "central")) {
10943       ast_test_status_update(test, "Parse failure for tz option\n");
10944       res = 1;
10945    }
10946    if (!ast_test_flag(vmu, VM_DELETE)) {
10947       ast_test_status_update(test, "Parse failure for delete option\n");
10948       res = 1;
10949    }
10950    if (!ast_test_flag(vmu, VM_SAYCID)) {
10951       ast_test_status_update(test, "Parse failure for saycid option\n");
10952       res = 1;
10953    }
10954    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10955       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10956       res = 1;
10957    }
10958    if (!ast_test_flag(vmu, VM_REVIEW)) {
10959       ast_test_status_update(test, "Parse failure for review option\n");
10960       res = 1;
10961    }
10962    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10963       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10964       res = 1;
10965    }
10966    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10967       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10968       res = 1;
10969    }
10970    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10971       ast_test_status_update(test, "Parse failure for operator option\n");
10972       res = 1;
10973    }
10974    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10975       ast_test_status_update(test, "Parse failure for envelope option\n");
10976       res = 1;
10977    }
10978    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10979       ast_test_status_update(test, "Parse failure for moveheard option\n");
10980       res = 1;
10981    }
10982    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10983       ast_test_status_update(test, "Parse failure for sayduration option\n");
10984       res = 1;
10985    }
10986    if (vmu->saydurationm != 5) {
10987       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10988       res = 1;
10989    }
10990    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10991       ast_test_status_update(test, "Parse failure for forcename option\n");
10992       res = 1;
10993    }
10994    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10995       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10996       res = 1;
10997    }
10998    if (strcasecmp(vmu->callback, "somecontext")) {
10999       ast_test_status_update(test, "Parse failure for callbacks option\n");
11000       res = 1;
11001    }
11002    if (strcasecmp(vmu->dialout, "somecontext2")) {
11003       ast_test_status_update(test, "Parse failure for dialout option\n");
11004       res = 1;
11005    }
11006    if (strcasecmp(vmu->exit, "somecontext3")) {
11007       ast_test_status_update(test, "Parse failure for exitcontext option\n");
11008       res = 1;
11009    }
11010    if (vmu->minsecs != 10) {
11011       ast_test_status_update(test, "Parse failure for minsecs option\n");
11012       res = 1;
11013    }
11014    if (vmu->maxsecs != 100) {
11015       ast_test_status_update(test, "Parse failure for maxsecs option\n");
11016       res = 1;
11017    }
11018    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
11019       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
11020       res = 1;
11021    }
11022    if (vmu->maxdeletedmsg != 50) {
11023       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
11024       res = 1;
11025    }
11026    if (vmu->volgain != 1.3) {
11027       ast_test_status_update(test, "Parse failure for volgain option\n");
11028       res = 1;
11029    }
11030    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
11031       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
11032       res = 1;
11033    }
11034 #ifdef IMAP_STORAGE
11035    apply_options(vmu, option_string2);
11036 
11037    if (strcasecmp(vmu->imapuser, "imapuser")) {
11038       ast_test_status_update(test, "Parse failure for imapuser option\n");
11039       res = 1;
11040    }
11041    if (strcasecmp(vmu->imappassword, "imappasswd")) {
11042       ast_test_status_update(test, "Parse failure for imappasswd option\n");
11043       res = 1;
11044    }
11045    if (strcasecmp(vmu->imapfolder, "INBOX")) {
11046       ast_test_status_update(test, "Parse failure for imappasswd option\n");
11047       res = 1;
11048    }
11049    if (strcasecmp(vmu->imapvmshareid, "6000")) {
11050       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
11051       res = 1;
11052    }
11053    if (strcasecmp(vmu->imapserver, "imapserver")) {
11054       ast_test_status_update(test, "Parse failure for imapserver option\n");
11055       res = 1;
11056    }
11057    if (strcasecmp(vmu->imapport, "1234")) {
11058       ast_test_status_update(test, "Parse failure for imapport option\n");
11059       res = 1;
11060    }
11061    if (strcasecmp(vmu->imapflags, "flagged")) {
11062       ast_test_status_update(test, "Parse failure for imapflags option\n");
11063       res = 1;
11064    }
11065 #endif
11066 
11067    free_user(vmu);
11068    return res ? AST_TEST_FAIL : AST_TEST_PASS;
11069 }

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

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

04366 {
04367    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04368       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04369       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04370       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04371    int i, hiteof = 0;
04372    FILE *fi;
04373    struct baseio bio;
04374 
04375    memset(&bio, 0, sizeof(bio));
04376    bio.iocp = BASEMAXINLINE;
04377 
04378    if (!(fi = fopen(filename, "rb"))) {
04379       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04380       return -1;
04381    }
04382 
04383    while (!hiteof){
04384       unsigned char igroup[3], ogroup[4];
04385       int c, n;
04386 
04387       memset(igroup, 0, sizeof(igroup));
04388 
04389       for (n = 0; n < 3; n++) {
04390          if ((c = inchar(&bio, fi)) == EOF) {
04391             hiteof = 1;
04392             break;
04393          }
04394 
04395          igroup[n] = (unsigned char) c;
04396       }
04397 
04398       if (n > 0) {
04399          ogroup[0]= dtable[igroup[0] >> 2];
04400          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04401          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04402          ogroup[3]= dtable[igroup[2] & 0x3F];
04403 
04404          if (n < 3) {
04405             ogroup[3] = '=';
04406 
04407             if (n < 2)
04408                ogroup[2] = '=';
04409          }
04410 
04411          for (i = 0; i < 4; i++)
04412             ochar(&bio, ogroup[i], so);
04413       }
04414    }
04415 
04416    fclose(fi);
04417    
04418    if (fputs(ENDL, so) == EOF) {
04419       return 0;
04420    }
04421 
04422    return 1;
04423 }

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

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

Referenced by vm_change_password().

01365 {
01366    int res = -1;
01367    if (!strcmp(vmu->password, password)) {
01368       /* No change (but an update would return 0 rows updated, so we opt out here) */
01369       return 0;
01370    }
01371 
01372    if (strlen(password) > 10) {
01373       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01374    }
01375    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01376       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01377       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01378       res = 0;
01379    }
01380    return res;
01381 }

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

04533 {
04534    for (; *str; str++) {
04535       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04536          return 1;
04537       }
04538    }
04539    return 0;
04540 }

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

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

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

01324 {
01325    /* check minimum length */
01326    if (strlen(password) < minpassword)
01327       return 1;
01328    /* check that password does not contain '*' character */
01329    if (!ast_strlen_zero(password) && password[0] == '*')
01330       return 1;
01331    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01332       char cmd[255], buf[255];
01333 
01334       ast_debug(1, "Verify password policies for %s\n", password);
01335 
01336       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01337       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01338          ast_debug(5, "Result: %s\n", buf);
01339          if (!strncasecmp(buf, "VALID", 5)) {
01340             ast_debug(3, "Passed password check: '%s'\n", buf);
01341             return 0;
01342          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01343             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01344             return 0;
01345          } else {
01346             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01347             return 1;
01348          }
01349       }
01350    }
01351    return 0;
01352 }

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

Definition at line 8044 of file app_voicemail.c.

References ast_check_realtime(), ast_debug, ast_free, ast_log(), AST_LOG_NOTICE, 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, vm_state::dh_arraysize, ERROR_LOCK_PATH, EXISTS, vm_state::fn, vm_state::heard, last_message_index(), vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by vm_execmain().

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

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

Definition at line 11300 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11301 {
11302    int which = 0;
11303    int wordlen;
11304    struct ast_vm_user *vmu;
11305    const char *context = "";
11306 
11307    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11308    if (pos > 4)
11309       return NULL;
11310    if (pos == 3)
11311       return (state == 0) ? ast_strdup("for") : NULL;
11312    wordlen = strlen(word);
11313    AST_LIST_TRAVERSE(&users, vmu, list) {
11314       if (!strncasecmp(word, vmu->context, wordlen)) {
11315          if (context && strcmp(context, vmu->context) && ++which > state)
11316             return ast_strdup(vmu->context);
11317          /* ignore repeated contexts ? */
11318          context = vmu->context;
11319       }
11320    }
11321    return NULL;
11322 }

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

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

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

04170 {
04171    int ifd;
04172    int ofd;
04173    int res;
04174    int len;
04175    char buf[4096];
04176 
04177 #ifdef HARDLINK_WHEN_POSSIBLE
04178    /* Hard link if possible; saves disk space & is faster */
04179    if (link(infile, outfile)) {
04180 #endif
04181       if ((ifd = open(infile, O_RDONLY)) < 0) {
04182          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04183          return -1;
04184       }
04185       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04186          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04187          close(ifd);
04188          return -1;
04189       }
04190       do {
04191          len = read(ifd, buf, sizeof(buf));
04192          if (len < 0) {
04193             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04194             close(ifd);
04195             close(ofd);
04196             unlink(outfile);
04197          }
04198          if (len) {
04199             res = write(ofd, buf, len);
04200             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04201                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04202                close(ifd);
04203                close(ofd);
04204                unlink(outfile);
04205             }
04206          }
04207       } while (len);
04208       close(ifd);
04209       close(ofd);
04210       return 0;
04211 #ifdef HARDLINK_WHEN_POSSIBLE
04212    } else {
04213       /* Hard link succeeded */
04214       return 0;
04215    }
04216 #endif
04217 }

static int copy_message ( struct ast_channel chan,
struct ast_vm_user vmu,
int  imbox,
int  msgnum,
long  duration,
struct ast_vm_user recip,
char *  fmt,
char *  dir,
const char *  flag 
) [static]

Copies a message from one mailbox to another.

Parameters:
chan 
vmu 
imbox 
msgnum 
duration 
recip 
fmt 
dir 
flag This is only used by file storage based mailboxes.
Returns:
zero on success, -1 on error.

Definition at line 5408 of file app_voicemail.c.

References ast_channel_language(), ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), ast_channel::caller, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), mbox(), ast_party_id::name, notify_new_message(), ast_party_id::number, S_COR, STORE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, ast_party_number::valid, vm_delete(), and vm_lock_path().

Referenced by forward_message(), and leave_voicemail().

05409 {
05410    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05411    const char *frombox = mbox(vmu, imbox);
05412    const char *userfolder;
05413    int recipmsgnum;
05414    int res = 0;
05415 
05416    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05417 
05418    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05419       userfolder = "Urgent";
05420    } else {
05421       userfolder = "INBOX";
05422    }
05423 
05424    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05425 
05426    if (!dir)
05427       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05428    else
05429       ast_copy_string(fromdir, dir, sizeof(fromdir));
05430 
05431    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05432    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05433 
05434    if (vm_lock_path(todir))
05435       return ERROR_LOCK_PATH;
05436 
05437    recipmsgnum = last_message_index(recip, todir) + 1;
05438    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05439       make_file(topath, sizeof(topath), todir, recipmsgnum);
05440 #ifndef ODBC_STORAGE
05441       if (EXISTS(fromdir, msgnum, frompath, ast_channel_language(chan))) { 
05442          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05443       } else {
05444 #endif
05445          /* If we are prepending a message for ODBC, then the message already
05446           * exists in the database, but we want to force copying from the
05447           * filesystem (since only the FS contains the prepend). */
05448          copy_plain_file(frompath, topath);
05449          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05450          vm_delete(topath);
05451 #ifndef ODBC_STORAGE
05452       }
05453 #endif
05454    } else {
05455       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05456       res = -1;
05457    }
05458    ast_unlock_path(todir);
05459    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05460       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05461       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05462       flag);
05463    
05464    return res;
05465 }

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

04229 {
04230    char frompath2[PATH_MAX], topath2[PATH_MAX];
04231    struct ast_variable *tmp,*var = NULL;
04232    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04233    ast_filecopy(frompath, topath, NULL);
04234    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04235    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04236    if (ast_check_realtime("voicemail_data")) {
04237       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04238       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04239       for (tmp = var; tmp; tmp = tmp->next) {
04240          if (!strcasecmp(tmp->name, "origmailbox")) {
04241             origmailbox = tmp->value;
04242          } else if (!strcasecmp(tmp->name, "context")) {
04243             context = tmp->value;
04244          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04245             macrocontext = tmp->value;
04246          } else if (!strcasecmp(tmp->name, "exten")) {
04247             exten = tmp->value;
04248          } else if (!strcasecmp(tmp->name, "priority")) {
04249             priority = tmp->value;
04250          } else if (!strcasecmp(tmp->name, "callerchan")) {
04251             callerchan = tmp->value;
04252          } else if (!strcasecmp(tmp->name, "callerid")) {
04253             callerid = tmp->value;
04254          } else if (!strcasecmp(tmp->name, "origdate")) {
04255             origdate = tmp->value;
04256          } else if (!strcasecmp(tmp->name, "origtime")) {
04257             origtime = tmp->value;
04258          } else if (!strcasecmp(tmp->name, "category")) {
04259             category = tmp->value;
04260          } else if (!strcasecmp(tmp->name, "duration")) {
04261             duration = tmp->value;
04262          }
04263       }
04264       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);
04265    }
04266    copy(frompath2, topath2);
04267    ast_variables_destroy(var);
04268 }

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

04065 {
04066 
04067    int vmcount = 0;
04068    DIR *vmdir = NULL;
04069    struct dirent *vment = NULL;
04070 
04071    if (vm_lock_path(dir))
04072       return ERROR_LOCK_PATH;
04073 
04074    if ((vmdir = opendir(dir))) {
04075       while ((vment = readdir(vmdir))) {
04076          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
04077             vmcount++;
04078          }
04079       }
04080       closedir(vmdir);
04081    }
04082    ast_unlock_path(dir);
04083    
04084    return vmcount;
04085 }

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

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

01781 {
01782    mode_t   mode = VOICEMAIL_DIR_MODE;
01783    int res;
01784 
01785    make_dir(dest, len, context, ext, folder);
01786    if ((res = ast_mkdir(dest, mode))) {
01787       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01788       return -1;
01789    }
01790    return 0;
01791 }

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

Definition at line 13399 of file app_voicemail.c.

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

Referenced by advanced_options(), and vm_execmain().

13400 {
13401    int cmd = 0;
13402    char destination[80] = "";
13403    int retries = 0;
13404 
13405    if (!num) {
13406       ast_verb(3, "Destination number will be entered manually\n");
13407       while (retries < 3 && cmd != 't') {
13408          destination[1] = '\0';
13409          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13410          if (!cmd)
13411             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13412          if (!cmd)
13413             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13414          if (!cmd) {
13415             cmd = ast_waitfordigit(chan, 6000);
13416             if (cmd)
13417                destination[0] = cmd;
13418          }
13419          if (!cmd) {
13420             retries++;
13421          } else {
13422 
13423             if (cmd < 0)
13424                return 0;
13425             if (cmd == '*') {
13426                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13427                return 0;
13428             }
13429             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13430                retries++;
13431             else
13432                cmd = 't';
13433          }
13434          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13435       }
13436       if (retries >= 3) {
13437          return 0;
13438       }
13439       
13440    } else {
13441       ast_verb(3, "Destination number is CID number '%s'\n", num);
13442       ast_copy_string(destination, num, sizeof(destination));
13443    }
13444 
13445    if (!ast_strlen_zero(destination)) {
13446       if (destination[strlen(destination) -1 ] == '*')
13447          return 0; 
13448       ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13449       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13450       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13451       chan->priority = 0;
13452       return 9;
13453    }
13454    return 0;
13455 }

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

Definition at line 10786 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

10787 {
10788    struct ast_vm_user *vmu;
10789 
10790    if (!ast_strlen_zero(box) && box[0] == '*') {
10791       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10792             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10793             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10794             "\n\tand will be ignored.\n", box, context);
10795       return NULL;
10796    }
10797 
10798    AST_LIST_TRAVERSE(&users, vmu, list) {
10799       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10800          if (strcasecmp(vmu->context, context)) {
10801             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10802                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10803                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10804                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10805          }
10806          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10807          return NULL;
10808       }
10809       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10810          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10811          return NULL;
10812       }
10813    }
10814    
10815    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10816       return NULL;
10817    
10818    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10819    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10820 
10821    AST_LIST_INSERT_TAIL(&users, vmu, list);
10822    
10823    return vmu;
10824 }

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

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

01533 {
01534    /* This function could be made to generate one from a database, too */
01535    struct ast_vm_user *vmu = NULL, *cur;
01536    AST_LIST_LOCK(&users);
01537 
01538    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01539       context = "default";
01540 
01541    AST_LIST_TRAVERSE(&users, cur, list) {
01542 #ifdef IMAP_STORAGE
01543       if (cur->imapversion != imapversion) {
01544          continue;
01545       }
01546 #endif
01547       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01548          break;
01549       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01550          break;
01551    }
01552    if (cur) {
01553       /* Make a copy, so that on a reload, we have no race */
01554       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01555          *vmu = *cur;
01556          if (!ivm) {
01557             vmu->emailbody = ast_strdup(cur->emailbody);
01558             vmu->emailsubject = ast_strdup(cur->emailsubject);
01559          }
01560          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01561          AST_LIST_NEXT(vmu, list) = NULL;
01562       }
01563    } else
01564       vmu = find_user_realtime(ivm, context, mailbox);
01565    AST_LIST_UNLOCK(&users);
01566    return vmu;
01567 }

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

01496 {
01497    struct ast_variable *var;
01498    struct ast_vm_user *retval;
01499 
01500    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01501       if (!ivm)
01502          ast_set_flag(retval, VM_ALLOCED);   
01503       else
01504          memset(retval, 0, sizeof(*retval));
01505       if (mailbox) 
01506          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01507       populate_defaults(retval);
01508       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01509          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01510       else
01511          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01512       if (var) {
01513          apply_options_full(retval, var);
01514          ast_variables_destroy(var);
01515       } else { 
01516          if (!ivm) 
01517             ast_free(retval);
01518          retval = NULL;
01519       }  
01520    } 
01521    return retval;
01522 }

static int forward_message ( struct ast_channel chan,
char *  context,
struct vm_state vms,
struct ast_vm_user sender,
char *  fmt,
int  is_new_message,
signed char  record_gain,
int  urgent 
) [static]

Sends a voicemail message to a mailbox recipient.

Parameters:
chan 
context 
vms 
sender 
fmt 
is_new_message Used to indicate the mode for which this method was invoked. Will be 0 when called to forward an existing message (option 8) Will be 1 when called to leave a message (option 3->5)
record_gain 
urgent Reads the destination mailbox(es) from keypad input for CID, or if use_directory feature is enabled, the Directory.
When in the leave message mode (is_new_message == 1):
  • allow the leaving of a message for ourselves. (Will not allow us to forward a message to ourselves, when is_new_message == 0).
  • attempt to determine the context and and mailbox, and then invoke leave_message() function to record and store the message.

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

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

Returns:
zero on success, -1 on error.

Definition at line 7236 of file app_voicemail.c.

References ast_channel_language(), ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_waitfordigit(), ast_channel::caller, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), vm_state::fn, free_user(), globalflags, ast_party_caller::id, inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), STORE, ast_party_name::str, ast_party_number::str, strsep(), vm_state::username, ast_party_name::valid, ast_party_number::valid, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

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

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1835 of file app_voicemail.c.

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

01836 {
01837    if (ast_test_flag(vmu, VM_ALLOCED)) {
01838 
01839       ast_free(vmu->emailbody);
01840       vmu->emailbody = NULL;
01841 
01842       ast_free(vmu->emailsubject);
01843       vmu->emailsubject = NULL;
01844 
01845       ast_free(vmu);
01846    }
01847 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11906 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 actual_load_config(), and unload_module().

11907 {
11908    struct ast_vm_user *current;
11909    AST_LIST_LOCK(&users);
11910    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11911       ast_set_flag(current, VM_ALLOCED);
11912       free_user(current);
11913    }
11914    AST_LIST_UNLOCK(&users);
11915 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11918 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11919 {
11920    struct vm_zone *zcur;
11921    AST_LIST_LOCK(&zones);
11922    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11923       free_zone(zcur);
11924    AST_LIST_UNLOCK(&zones);
11925 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5172 of file app_voicemail.c.

References ast_free.

05173 {
05174    ast_free(z);
05175 }

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

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

05129 {
05130    struct ast_tm tm;
05131    struct timeval t = ast_tvnow();
05132 
05133    ast_localtime(&t, &tm, "UTC");
05134 
05135    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05136 }

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

References ast_channel_language(), AST_DIGIT_ANY, ast_fileexists(), ast_play_and_wait(), ast_say_number(), ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), mbox(), and vm_play_folder_name().

Referenced by get_folder2().

06849 {
06850    int x;
06851    int d;
06852    char fn[PATH_MAX];
06853    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06854    if (d)
06855       return d;
06856    for (x = start; x < 5; x++) { /* For all folders */
06857       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
06858          return d;
06859       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06860       if (d)
06861          return d;
06862       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06863 
06864       /* The inbox folder can have its name changed under certain conditions
06865        * so this checks if the sound file exists for the inbox folder name and
06866        * if it doesn't, plays the default name instead. */
06867       if (x == 0) {
06868          if (ast_fileexists(fn, NULL, NULL)) {
06869             d = vm_play_folder_name(chan, fn);
06870          } else {
06871             ast_verb(1, "failed to find %s\n", fn);
06872             d = vm_play_folder_name(chan, "vm-INBOX");
06873          }
06874       } else {
06875          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06876          d = vm_play_folder_name(chan, fn);
06877       }
06878 
06879       if (d)
06880          return d;
06881       d = ast_waitfordigit(chan, 500);
06882       if (d)
06883          return d;
06884    }
06885 
06886    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06887    if (d)
06888       return d;
06889    d = ast_waitfordigit(chan, 4000);
06890    return d;
06891 }

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

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

Referenced by vm_execmain().

06906 {
06907    int res = 0;
06908    int loops = 0;
06909 
06910    res = ast_play_and_wait(chan, fn);  /* Folder name */
06911    while (((res < '0') || (res > '9')) &&
06912          (res != '#') && (res >= 0) &&
06913          loops < 4) {
06914       res = get_folder(chan, 0);
06915       loops++;
06916    }
06917    if (loops == 4) { /* give up */
06918       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06919       return '#';
06920    }
06921    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06922    return res;
06923 }

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

Definition at line 1822 of file app_voicemail.c.

References ARRAY_LEN, and mailbox_folders.

Referenced by vm_execmain().

01823 {
01824    size_t i;
01825 
01826    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01827       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01828          return i;
01829       }
01830    }
01831 
01832    return -1;
01833 }

static int handle_subscribe ( void *  datap  )  [static]

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

11683 {
11684    unsigned int len;
11685    struct mwi_sub *mwi_sub;
11686    struct mwi_sub_task *p = datap;
11687 
11688    len = sizeof(*mwi_sub);
11689    if (!ast_strlen_zero(p->mailbox))
11690       len += strlen(p->mailbox);
11691 
11692    if (!ast_strlen_zero(p->context))
11693       len += strlen(p->context) + 1; /* Allow for seperator */
11694 
11695    if (!(mwi_sub = ast_calloc(1, len)))
11696       return -1;
11697 
11698    mwi_sub->uniqueid = p->uniqueid;
11699    if (!ast_strlen_zero(p->mailbox))
11700       strcpy(mwi_sub->mailbox, p->mailbox);
11701 
11702    if (!ast_strlen_zero(p->context)) {
11703       strcat(mwi_sub->mailbox, "@");
11704       strcat(mwi_sub->mailbox, p->context);
11705    }
11706 
11707    AST_RWLIST_WRLOCK(&mwi_subs);
11708    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11709    AST_RWLIST_UNLOCK(&mwi_subs);
11710    ast_free((void *) p->mailbox);
11711    ast_free((void *) p->context);
11712    ast_free(p);
11713    poll_subscribed_mailbox(mwi_sub);
11714    return 0;
11715 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

11661 {
11662    struct mwi_sub *mwi_sub;
11663    uint32_t *uniqueid = datap;
11664    
11665    AST_RWLIST_WRLOCK(&mwi_subs);
11666    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11667       if (mwi_sub->uniqueid == *uniqueid) {
11668          AST_LIST_REMOVE_CURRENT(entry);
11669          break;
11670       }
11671    }
11672    AST_RWLIST_TRAVERSE_SAFE_END
11673    AST_RWLIST_UNLOCK(&mwi_subs);
11674 
11675    if (mwi_sub)
11676       mwi_sub_destroy(mwi_sub);
11677 
11678    ast_free(uniqueid);  
11679    return 0;
11680 }

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

11436 {
11437    switch (cmd) {
11438    case CLI_INIT:
11439       e->command = "voicemail reload";
11440       e->usage =
11441          "Usage: voicemail reload\n"
11442          "       Reload voicemail configuration\n";
11443       return NULL;
11444    case CLI_GENERATE:
11445       return NULL;
11446    }
11447 
11448    if (a->argc != 2)
11449       return CLI_SHOWUSAGE;
11450 
11451    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11452    load_config(1);
11453    
11454    return CLI_SUCCESS;
11455 }

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

11326 {
11327    struct ast_vm_user *vmu;
11328 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11329    const char *context = NULL;
11330    int users_counter = 0;
11331 
11332    switch (cmd) {
11333    case CLI_INIT:
11334       e->command = "voicemail show users";
11335       e->usage =
11336          "Usage: voicemail show users [for <context>]\n"
11337          "       Lists all mailboxes currently set up\n";
11338       return NULL;
11339    case CLI_GENERATE:
11340       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11341    }  
11342 
11343    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11344       return CLI_SHOWUSAGE;
11345    if (a->argc == 5) {
11346       if (strcmp(a->argv[3],"for"))
11347          return CLI_SHOWUSAGE;
11348       context = a->argv[4];
11349    }
11350 
11351    if (ast_check_realtime("voicemail")) {
11352       if (!context) {
11353          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11354          return CLI_SHOWUSAGE;
11355       }
11356       return show_users_realtime(a->fd, context);
11357    }
11358 
11359    AST_LIST_LOCK(&users);
11360    if (AST_LIST_EMPTY(&users)) {
11361       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11362       AST_LIST_UNLOCK(&users);
11363       return CLI_FAILURE;
11364    }
11365    if (a->argc == 3)
11366       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11367    else {
11368       int count = 0;
11369       AST_LIST_TRAVERSE(&users, vmu, list) {
11370          if (!strcmp(context, vmu->context))
11371             count++;
11372       }
11373       if (count) {
11374          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11375       } else {
11376          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11377          AST_LIST_UNLOCK(&users);
11378          return CLI_FAILURE;
11379       }
11380    }
11381    AST_LIST_TRAVERSE(&users, vmu, list) {
11382       int newmsgs = 0, oldmsgs = 0;
11383       char count[12], tmp[256] = "";
11384 
11385       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
11386          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11387          inboxcount(tmp, &newmsgs, &oldmsgs);
11388          snprintf(count, sizeof(count), "%d", newmsgs);
11389          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11390          users_counter++;
11391       }
11392    }
11393    AST_LIST_UNLOCK(&users);
11394    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11395    return CLI_SUCCESS;
11396 }

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

11400 {
11401    struct vm_zone *zone;
11402 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11403    char *res = CLI_SUCCESS;
11404 
11405    switch (cmd) {
11406    case CLI_INIT:
11407       e->command = "voicemail show zones";
11408       e->usage =
11409          "Usage: voicemail show zones\n"
11410          "       Lists zone message formats\n";
11411       return NULL;
11412    case CLI_GENERATE:
11413       return NULL;
11414    }
11415 
11416    if (a->argc != 3)
11417       return CLI_SHOWUSAGE;
11418 
11419    AST_LIST_LOCK(&zones);
11420    if (!AST_LIST_EMPTY(&zones)) {
11421       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11422       AST_LIST_TRAVERSE(&zones, zone, list) {
11423          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11424       }
11425    } else {
11426       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11427       res = CLI_FAILURE;
11428    }
11429    AST_LIST_UNLOCK(&zones);
11430 
11431    return res;
11432 }

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

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

Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), mwi_send_init(), my_has_voicemail(), and vm_execmain().

05521 {
05522    char tmp[256], *tmp2 = tmp, *box, *context;
05523    ast_copy_string(tmp, mailbox, sizeof(tmp));
05524    if (ast_strlen_zero(folder)) {
05525       folder = "INBOX";
05526    }
05527    while ((box = strsep(&tmp2, ",&"))) {
05528       if ((context = strchr(box, '@')))
05529          *context++ = '\0';
05530       else
05531          context = "default";
05532       if (__has_voicemail(context, box, folder, 1))
05533          return 1;
05534       /* If we are checking INBOX, we should check Urgent as well */
05535       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05536          return 1;
05537       }
05538    }
05539    return 0;
05540 }

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

Definition at line 5602 of file app_voicemail.c.

References inboxcount2().

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

05603 {
05604    int urgentmsgs = 0;
05605    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05606    if (newmsgs) {
05607       *newmsgs += urgentmsgs;
05608    }
05609    return res;
05610 }

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

Definition at line 5543 of file app_voicemail.c.

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

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

05544 {
05545    char tmp[256];
05546    char *context;
05547 
05548    /* If no mailbox, return immediately */
05549    if (ast_strlen_zero(mailbox))
05550       return 0;
05551 
05552    if (newmsgs)
05553       *newmsgs = 0;
05554    if (oldmsgs)
05555       *oldmsgs = 0;
05556    if (urgentmsgs)
05557       *urgentmsgs = 0;
05558 
05559    if (strchr(mailbox, ',')) {
05560       int tmpnew, tmpold, tmpurgent;
05561       char *mb, *cur;
05562 
05563       ast_copy_string(tmp, mailbox, sizeof(tmp));
05564       mb = tmp;
05565       while ((cur = strsep(&mb, ", "))) {
05566          if (!ast_strlen_zero(cur)) {
05567             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05568                return -1;
05569             else {
05570                if (newmsgs)
05571                   *newmsgs += tmpnew; 
05572                if (oldmsgs)
05573                   *oldmsgs += tmpold;
05574                if (urgentmsgs)
05575                   *urgentmsgs += tmpurgent;
05576             }
05577          }
05578       }
05579       return 0;
05580    }
05581 
05582    ast_copy_string(tmp, mailbox, sizeof(tmp));
05583    
05584    if ((context = strchr(tmp, '@')))
05585       *context++ = '\0';
05586    else
05587       context = "default";
05588 
05589    if (newmsgs)
05590       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05591    if (oldmsgs)
05592       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05593    if (urgentmsgs)
05594       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05595 
05596    return 0;
05597 }

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

utility used by inchar(), for base_encode()

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

04301 {
04302    int l;
04303 
04304    if (bio->ateof)
04305       return 0;
04306 
04307    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04308       if (ferror(fi))
04309          return -1;
04310 
04311       bio->ateof = 1;
04312       return 0;
04313    }
04314 
04315    bio->iolen = l;
04316    bio->iocp = 0;
04317 
04318    return 1;
04319 }

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

utility used by base_encode()

Definition at line 4324 of file app_voicemail.c.

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

Referenced by base_encode().

04325 {
04326    if (bio->iocp>=bio->iolen) {
04327       if (!inbuf(bio, fi))
04328          return EOF;
04329    }
04330 
04331    return bio->iobuf[bio->iocp++];
04332 }

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

Definition at line 1009 of file app_voicemail.c.

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

Referenced by load_module().

01010 {
01011    struct inprocess *i = obj, *j = arg;
01012    if (strcmp(i->mailbox, j->mailbox)) {
01013       return 0;
01014    }
01015    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
01016 }

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

Definition at line 1018 of file app_voicemail.c.

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

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

01019 {
01020    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
01021    arg->context = arg->mailbox + strlen(mailbox) + 1;
01022    strcpy(arg->mailbox, mailbox); /* SAFE */
01023    strcpy(arg->context, context); /* SAFE */
01024    ao2_lock(inprocess_container);
01025    if ((i = ao2_find(inprocess_container, arg, 0))) {
01026       int ret = ast_atomic_fetchadd_int(&i->count, delta);
01027       ao2_unlock(inprocess_container);
01028       ao2_ref(i, -1);
01029       return ret;
01030    }
01031    if (delta < 0) {
01032       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
01033    }
01034    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
01035       ao2_unlock(inprocess_container);
01036       return 0;
01037    }
01038    i->context = i->mailbox + strlen(mailbox) + 1;
01039    strcpy(i->mailbox, mailbox); /* SAFE */
01040    strcpy(i->context, context); /* SAFE */
01041    i->count = delta;
01042    ao2_link(inprocess_container, i);
01043    ao2_unlock(inprocess_container);
01044    ao2_ref(i, -1);
01045    return 0;
01046 }

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

Definition at line 1003 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

01004 {
01005    const struct inprocess *i = obj;
01006    return atoi(i->mailbox);
01007 }

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

Definition at line 5138 of file app_voicemail.c.

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

05139 {
05140    int res;
05141    char fn[PATH_MAX];
05142    char dest[PATH_MAX];
05143 
05144    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05145 
05146    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05147       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05148       return -1;
05149    }
05150 
05151    RETRIEVE(fn, -1, ext, context);
05152    if (ast_fileexists(fn, NULL, NULL) > 0) {
05153       res = ast_stream_and_wait(chan, fn, ecodes);
05154       if (res) {
05155          DISPOSE(fn, -1);
05156          return res;
05157       }
05158    } else {
05159       /* Dispose just in case */
05160       DISPOSE(fn, -1);
05161       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05162       if (res)
05163          return res;
05164       res = ast_say_digit_str(chan, ext, ecodes, ast_channel_language(chan));
05165       if (res)
05166          return res;
05167    }
05168    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05169    return res;
05170 }

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

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

Referenced by actual_load_config().

01471 {
01472    int i;
01473    char *local_key = ast_strdupa(key);
01474 
01475    for (i = 0; i < strlen(key); ++i) {
01476       if (!strchr(VALID_DTMF, *local_key)) {
01477          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01478          return 0;
01479       }
01480       local_key++;
01481    }
01482    return 1;
01483 }

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

References ast_debug, map, ast_vm_user::maxmsg, and MAXMSGLIMIT.

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

04119 {
04120    int x;
04121    unsigned char map[MAXMSGLIMIT] = "";
04122    DIR *msgdir;
04123    struct dirent *msgdirent;
04124    int msgdirint;
04125    char extension[4];
04126    int stopcount = 0;
04127 
04128    /* Reading the entire directory into a file map scales better than
04129     * doing a stat repeatedly on a predicted sequence.  I suspect this
04130     * is partially due to stat(2) internally doing a readdir(2) itself to
04131     * find each file. */
04132    if (!(msgdir = opendir(dir))) {
04133       return -1;
04134    }
04135 
04136    while ((msgdirent = readdir(msgdir))) {
04137       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04138          map[msgdirint] = 1;
04139          stopcount++;
04140          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04141       }
04142    }
04143    closedir(msgdir);
04144 
04145    for (x = 0; x < vmu->maxmsg; x++) {
04146       if (map[x] == 1) {
04147          stopcount--;
04148       } else if (map[x] == 0 && !stopcount) {
04149          break;
04150       }
04151    }
04152 
04153    return x - 1;
04154 }

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

References ast_callerid_merge(), ast_canmatch_extension(), ast_channel_language(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, ast_stopstream(), ast_store_realtime(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_unlock_path(), ast_update_realtime(), ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, ast_channel::exten, find_user(), free_user(), ast_party_redirecting::from, get_date(), ast_party_caller::id, inboxcount(), inprocess_count(), INTRO, invent_message(), last_message_index(), LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_party_id::name, vm_state::newmessages, notify_new_message(), ast_party_id::number, OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), ast_channel::priority, leave_vm_options::record_gain, ast_channel::redirecting, RENAME, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, ast_party_name::str, ast_party_number::str, strsep(), transfer, ast_party_name::valid, ast_party_number::valid, vm_lock_path(), VM_OPERATOR, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

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

static int load_config ( int  reload  )  [static]

Definition at line 11974 of file app_voicemail.c.

References actual_load_config(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_unload_realtime(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, and VOICEMAIL_CONFIG.

11975 {
11976    struct ast_config *cfg, *ucfg;
11977    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11978    int res;
11979 
11980    ast_unload_realtime("voicemail");
11981    ast_unload_realtime("voicemail_data");
11982 
11983    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11984       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11985          return 0;
11986       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11987          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11988          ucfg = NULL;
11989       }
11990       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11991       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11992          ast_config_destroy(ucfg);
11993          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11994          return 0;
11995       }
11996    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11997       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11998       return 0;
11999    } else {
12000       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
12001       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
12002          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
12003          ucfg = NULL;
12004       }
12005    }
12006 
12007    res = actual_load_config(reload, cfg, ucfg);
12008 
12009    ast_config_destroy(cfg);
12010    ast_config_destroy(ucfg);
12011 
12012    return res;
12013 }

static int load_module ( void   )  [static]

Definition at line 13349 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_data_register_multiple, ast_install_vm_functions(), ast_log(), AST_LOG_WARNING, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application_xml, ast_taskprocessor_get(), AST_TEST_REGISTER, 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_data_providers, vm_exec(), vm_execmain(), vm_info_acf, vmauthenticate(), and vmsayname_exec().

13350 {
13351    int res;
13352    my_umask = umask(0);
13353    umask(my_umask);
13354 
13355    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13356       return AST_MODULE_LOAD_DECLINE;
13357    }
13358 
13359    /* compute the location of the voicemail spool directory */
13360    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13361    
13362    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13363       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13364    }
13365 
13366    if ((res = load_config(0)))
13367       return res;
13368 
13369    res = ast_register_application_xml(app, vm_exec);
13370    res |= ast_register_application_xml(app2, vm_execmain);
13371    res |= ast_register_application_xml(app3, vm_box_exists);
13372    res |= ast_register_application_xml(app4, vmauthenticate);
13373    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13374    res |= ast_custom_function_register(&mailbox_exists_acf);
13375    res |= ast_custom_function_register(&vm_info_acf);
13376    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13377 #ifdef TEST_FRAMEWORK
13378    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13379    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13380    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13381    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13382    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13383    res |= AST_TEST_REGISTER(test_voicemail_vm_info);
13384 #endif
13385 
13386    if (res)
13387       return res;
13388 
13389    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13390    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13391 
13392    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13393    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13394    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13395 
13396    return res;
13397 }

static int make_dir ( char *  dest,
int  len,
const char *  context,
const char *  ext,
const char *  folder 
) [static]

Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.

Parameters:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The length of the path string that was written out.
context 
ext 
folder 
The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1734 of file app_voicemail.c.

01735 {
01736    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01737 }

static void make_email_file ( FILE *  p,
char *  srcemail,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  attach,
char *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
int  imap,
const char *  flag 
) [static]

Creates the email file to be sent to indicate a new voicemail exists for a user.

Parameters:
p The output file to generate the email contents into.
srcemail The email address to send the email to, presumably the email address for the owner of the mailbox.
vmu The voicemail user who is sending the voicemail.
msgnum The message index in the mailbox folder.
context 
mailbox The voicemail box to read the voicemail to be notified in this email.
fromfolder 
cidnum The caller ID number.
cidname The caller ID name.
attach the name of the sound file to be attached to the email, if attach_user_voicemail == 1.
attach2 
format The message sound file format. i.e. .wav
duration The time of the message content, in seconds.
attach_user_voicemail if 1, the sound file is attached to the email.
chan 
category 
imap if == 1, indicates the target folder for the email notification to be sent to will be an IMAP mailstore. This causes additional mailbox headers to be set, which would facilitate searching for the email in the destination IMAP folder.
flag The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.

Definition at line 4615 of file app_voicemail.c.

References add_email_attachment(), ast_channel_name(), ast_channel_unref, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_localtime(), ast_log(), AST_LOG_WARNING, ast_random(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime_locale(), 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, ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

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

static int make_file ( char *  dest,
const int  len,
const char *  dir,
const int  num 
) [static]

Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.

Parameters:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The length of the path string that was written out.
dir 
num 
The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns:
zero on success, -1 on error.

Definition at line 1751 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(), resequence_mailbox(), save_to_folder(), vm_execmain(), and vm_forwardoptions().

01752 {
01753    return snprintf(dest, len, "%s/msg%04d", dir, num);
01754 }

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

Manager list voicemail users command.

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

11799 {
11800    struct ast_vm_user *vmu = NULL;
11801    const char *id = astman_get_header(m, "ActionID");
11802    char actionid[128] = "";
11803 
11804    if (!ast_strlen_zero(id))
11805       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11806 
11807    AST_LIST_LOCK(&users);
11808 
11809    if (AST_LIST_EMPTY(&users)) {
11810       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11811       AST_LIST_UNLOCK(&users);
11812       return RESULT_SUCCESS;
11813    }
11814    
11815    astman_send_ack(s, m, "Voicemail user list will follow");
11816    
11817    AST_LIST_TRAVERSE(&users, vmu, list) {
11818       char dirname[256];
11819 
11820 #ifdef IMAP_STORAGE
11821       int new, old;
11822       inboxcount(vmu->mailbox, &new, &old);
11823 #endif
11824       
11825       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11826       astman_append(s,
11827          "%s"
11828          "Event: VoicemailUserEntry\r\n"
11829          "VMContext: %s\r\n"
11830          "VoiceMailbox: %s\r\n"
11831          "Fullname: %s\r\n"
11832          "Email: %s\r\n"
11833          "Pager: %s\r\n"
11834          "ServerEmail: %s\r\n"
11835          "MailCommand: %s\r\n"
11836          "Language: %s\r\n"
11837          "TimeZone: %s\r\n"
11838          "Callback: %s\r\n"
11839          "Dialout: %s\r\n"
11840          "UniqueID: %s\r\n"
11841          "ExitContext: %s\r\n"
11842          "SayDurationMinimum: %d\r\n"
11843          "SayEnvelope: %s\r\n"
11844          "SayCID: %s\r\n"
11845          "AttachMessage: %s\r\n"
11846          "AttachmentFormat: %s\r\n"
11847          "DeleteMessage: %s\r\n"
11848          "VolumeGain: %.2f\r\n"
11849          "CanReview: %s\r\n"
11850          "CallOperator: %s\r\n"
11851          "MaxMessageCount: %d\r\n"
11852          "MaxMessageLength: %d\r\n"
11853          "NewMessageCount: %d\r\n"
11854 #ifdef IMAP_STORAGE
11855          "OldMessageCount: %d\r\n"
11856          "IMAPUser: %s\r\n"
11857          "IMAPServer: %s\r\n"
11858          "IMAPPort: %s\r\n"
11859          "IMAPFlags: %s\r\n"
11860 #endif
11861          "\r\n",
11862          actionid,
11863          vmu->context,
11864          vmu->mailbox,
11865          vmu->fullname,
11866          vmu->email,
11867          vmu->pager,
11868          vmu->serveremail,
11869          vmu->mailcmd,
11870          vmu->language,
11871          vmu->zonetag,
11872          vmu->callback,
11873          vmu->dialout,
11874          vmu->uniqueid,
11875          vmu->exit,
11876          vmu->saydurationm,
11877          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11878          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11879          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11880          vmu->attachfmt,
11881          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11882          vmu->volgain,
11883          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11884          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11885          vmu->maxmsg,
11886          vmu->maxsecs,
11887 #ifdef IMAP_STORAGE
11888          new, old,
11889          vmu->imapuser,
11890          vmu->imapserver,
11891          vmu->imapport,
11892          vmu->imapflags
11893 #else
11894          count_messages(vmu, dirname)
11895 #endif
11896          );
11897    }     
11898    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11899 
11900    AST_LIST_UNLOCK(&users);
11901 
11902    return RESULT_SUCCESS;
11903 }

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

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

11633 {
11634    while (poll_thread_run) {
11635       struct timespec ts = { 0, };
11636       struct timeval wait;
11637 
11638       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11639       ts.tv_sec = wait.tv_sec;
11640       ts.tv_nsec = wait.tv_usec * 1000;
11641 
11642       ast_mutex_lock(&poll_lock);
11643       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11644       ast_mutex_unlock(&poll_lock);
11645 
11646       if (!poll_thread_run)
11647          break;
11648 
11649       poll_subscribed_mailboxes();
11650    }
11651 
11652    return NULL;
11653 }

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

Definition at line 1812 of file app_voicemail.c.

References ARRAY_LEN, and mailbox_folders.

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

01813 {
01814 #ifdef IMAP_STORAGE
01815    if (vmu && id == 0) {
01816       return vmu->imapfolder;
01817    }
01818 #endif
01819    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01820 }

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

Definition at line 5469 of file app_voicemail.c.

References __has_voicemail().

Referenced by acf_vm_info(), and load_module().

05470 {
05471    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05472 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11655 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

11656 {
11657    ast_free(mwi_sub);
11658 }

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

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

11734 {
11735    struct mwi_sub_task *mwist;
11736    
11737    if (ast_event_get_type(event) != AST_EVENT_SUB)
11738       return;
11739 
11740    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11741       return;
11742 
11743    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11744       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11745       return;
11746    }
11747    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11748    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11749    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11750    
11751    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11752       ast_free(mwist);
11753    }
11754 }

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

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

11718 {
11719    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11720    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11721       return;
11722 
11723    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11724       return;
11725 
11726    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11727    *uniqueid = u;
11728    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11729       ast_free(uniqueid);
11730    }
11731 }

static int notify_new_message ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  msgnum,
long  duration,
char *  fmt,
char *  cidnum,
char *  cidname,
const char *  flag 
) [static]

Sends email notification that a user has a new voicemail waiting for them.

Parameters:
chan 
vmu 
vms 
msgnum 
duration 
fmt 
cidnum The Caller ID phone number value.
cidname The Caller ID name value.
flag 
Returns:
zero on success, -1 on error.

Definition at line 7133 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_manager_event, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_vm_user::attachfmt, ast_vm_user::context, vm_state::curmsg, DELETE, DISPOSE, ast_vm_user::email, EVENT_FLAG_CALL, ast_vm_user::mailbox, make_dir(), make_file(), mbox(), vm_state::newmessages, ast_vm_user::pager, pbx_builtin_getvar_helper(), queue_mwi_event(), RETRIEVE, run_externnotify(), sendmail(), sendpage(), ast_vm_user::serveremail, strsep(), VM_ATTACH, vm_delete(), and VM_DELETE.

07134 {
07135    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07136    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07137    const char *category;
07138    char *myserveremail = serveremail;
07139 
07140    ast_channel_lock(chan);
07141    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07142       category = ast_strdupa(category);
07143    }
07144    ast_channel_unlock(chan);
07145 
07146 #ifndef IMAP_STORAGE
07147    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07148 #else
07149    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07150 #endif
07151    make_file(fn, sizeof(fn), todir, msgnum);
07152    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07153 
07154    if (!ast_strlen_zero(vmu->attachfmt)) {
07155       if (strstr(fmt, vmu->attachfmt))
07156          fmt = vmu->attachfmt;
07157       else
07158          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);
07159    }
07160 
07161    /* Attach only the first format */
07162    fmt = ast_strdupa(fmt);
07163    stringp = fmt;
07164    strsep(&stringp, "|");
07165 
07166    if (!ast_strlen_zero(vmu->serveremail))
07167       myserveremail = vmu->serveremail;
07168 
07169    if (!ast_strlen_zero(vmu->email)) {
07170       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07171 
07172       if (attach_user_voicemail)
07173          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07174 
07175       /* XXX possible imap issue, should category be NULL XXX */
07176       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07177 
07178       if (attach_user_voicemail)
07179          DISPOSE(todir, msgnum);
07180    }
07181 
07182    if (!ast_strlen_zero(vmu->pager)) {
07183       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07184    }
07185 
07186    if (ast_test_flag(vmu, VM_DELETE))
07187       DELETE(todir, msgnum, fn, vmu);
07188 
07189    /* Leave voicemail for someone */
07190    if (ast_app_has_voicemail(ext_context, NULL)) 
07191       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07192 
07193    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07194 
07195    ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
07196    run_externnotify(vmu->context, vmu->mailbox, flag);
07197 
07198 #ifdef IMAP_STORAGE
07199    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07200    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07201       vm_imap_delete(NULL, vms->curmsg, vmu);
07202       vms->newmessages--;  /* Fix new message count */
07203    }
07204 #endif
07205 
07206    return 0;
07207 }

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

utility used by base_encode()

Definition at line 4337 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04338 {
04339    if (bio->linelength >= BASELINELEN) {
04340       if (fputs(ENDL, so) == EOF) {
04341          return -1;
04342       }
04343 
04344       bio->linelength = 0;
04345    }
04346 
04347    if (putc(((unsigned char) c), so) == EOF) {
04348       return -1;
04349    }
04350 
04351    bio->linelength++;
04352 
04353    return 1;
04354 }

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

Definition at line 7991 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, ERROR_LOCK_PATH, last_message_index(), vm_state::lastmsg, LOG_NOTICE, ast_vm_user::maxmsg, mbox(), resequence_mailbox(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

Referenced by vm_execmain().

07992 {
07993    int count_msg, last_msg;
07994 
07995    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07996 
07997    /* Rename the member vmbox HERE so that we don't try to return before
07998     * we know what's going on.
07999     */
08000    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
08001 
08002    /* Faster to make the directory than to check if it exists. */
08003    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
08004 
08005    /* traverses directory using readdir (or select query for ODBC) */
08006    count_msg = count_messages(vmu, vms->curdir);
08007    if (count_msg < 0) {
08008       return count_msg;
08009    } else {
08010       vms->lastmsg = count_msg - 1;
08011    }
08012 
08013    if (vm_allocate_dh(vms, vmu, count_msg)) {
08014       return -1;
08015    }
08016 
08017    /*
08018    The following test is needed in case sequencing gets messed up.
08019    There appears to be more than one way to mess up sequence, so
08020    we will not try to find all of the root causes--just fix it when
08021    detected.
08022    */
08023 
08024    if (vm_lock_path(vms->curdir)) {
08025       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
08026       return ERROR_LOCK_PATH;
08027    }
08028 
08029    /* for local storage, checks directory for messages up to maxmsg limit */
08030    last_msg = last_message_index(vmu, vms->curdir);
08031    ast_unlock_path(vms->curdir);
08032 
08033    if (last_msg < -1) {
08034       return last_msg;
08035    } else if (vms->lastmsg != last_msg) {
08036       ast_log(LOG_NOTICE, "Resequencing Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
08037       resequence_mailbox(vmu, vms->curdir, count_msg);
08038    }
08039 
08040    return 0;
08041 }

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

Definition at line 7769 of file app_voicemail.c.

References adsi_message(), ast_channel_language(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), AST_LOG_WARNING, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, 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, 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_vi(), vm_browse_messages_zh(), and vm_execmain().

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

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

Definition at line 7642 of file app_voicemail.c.

References ast_callerid_parse(), ast_channel_language(), ast_config_AST_SPOOL_DIR, ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_say_digit_str(), ast_stream_and_wait(), ast_strlen_zero(), ast_verb, cidinternalcontexts, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

07643 {
07644    int res = 0;
07645    int i;
07646    char *callerid, *name;
07647    char prefile[PATH_MAX] = "";
07648 
07649    /* If voicemail cid is not enabled, or we didn't get cid or context from
07650     * the attribute file, leave now.
07651     *
07652     * TODO Still need to change this so that if this function is called by the
07653     * message envelope (and someone is explicitly requesting to hear the CID),
07654     * it does not check to see if CID is enabled in the config file.
07655     */
07656    if ((cid == NULL)||(context == NULL))
07657       return res;
07658 
07659    /* Strip off caller ID number from name */
07660    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07661    ast_callerid_parse(cid, &name, &callerid);
07662    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07663       /* Check for internal contexts and only */
07664       /* say extension when the call didn't come from an internal context in the list */
07665       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07666          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07667          if ((strcmp(cidinternalcontexts[i], context) == 0))
07668             break;
07669       }
07670       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07671          if (!res) {
07672             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07673             if (!ast_strlen_zero(prefile)) {
07674                /* See if we can find a recorded name for this callerid
07675                 * and if found, use that instead of saying number. */
07676                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07677                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07678                   if (!callback)
07679                      res = wait_file2(chan, vms, "vm-from");
07680                   res = ast_stream_and_wait(chan, prefile, "");
07681                } else {
07682                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07683                   /* Say "from extension" as one saying to sound smoother */
07684                   if (!callback)
07685                      res = wait_file2(chan, vms, "vm-from-extension");
07686                   res = ast_say_digit_str(chan, callerid, "", ast_channel_language(chan));
07687                }
07688             }
07689          }
07690       } else if (!res) {
07691          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07692          /* If there is a recording for this numeric callerid then play that */
07693          if (!callback) {
07694             /* See if we can find a recorded name for this person instead of their extension number */
07695             snprintf(prefile, sizeof(prefile), "%s/recordings/callerids/%s", ast_config_AST_SPOOL_DIR, callerid);
07696             if (!saycidnumber && ast_fileexists(prefile, NULL, NULL) > 0) {
07697                ast_verb(3, "Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
07698                wait_file2(chan, vms, "vm-from");
07699                res = ast_stream_and_wait(chan, prefile, "");
07700                ast_verb(3, "Played recorded name result '%d'\n", res);
07701             } else {
07702                /* Since this is all nicely figured out, why not say "from phone number" in this case" */
07703                wait_file2(chan, vms, "vm-from-phonenumber");
07704                res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
07705             }
07706          } else {
07707             res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
07708          }
07709       }
07710    } else {
07711       /* Number unknown */
07712       ast_debug(1, "VM-CID: From an unknown number\n");
07713       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07714       res = wait_file2(chan, vms, "vm-unknown-caller");
07715    }
07716    return res;
07717 }

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

Definition at line 7553 of file app_voicemail.c.

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

Referenced by play_message().

07554 {
07555    int res = 0;
07556 
07557    if (!ast_strlen_zero(category))
07558       res = ast_play_and_wait(chan, category);
07559 
07560    if (res) {
07561       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07562       res = 0;
07563    }
07564 
07565    return res;
07566 }

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

Definition at line 7568 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

07569 {
07570    int res = 0;
07571    struct vm_zone *the_zone = NULL;
07572    time_t t;
07573 
07574    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07575       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07576       return 0;
07577    }
07578 
07579    /* Does this user have a timezone specified? */
07580    if (!ast_strlen_zero(vmu->zonetag)) {
07581       /* Find the zone in the list */
07582       struct vm_zone *z;
07583       AST_LIST_LOCK(&zones);
07584       AST_LIST_TRAVERSE(&zones, z, list) {
07585          if (!strcmp(z->name, vmu->zonetag)) {
07586             the_zone = z;
07587             break;
07588          }
07589       }
07590       AST_LIST_UNLOCK(&zones);
07591    }
07592 
07593 /* No internal variable parsing for now, so we'll comment it out for the time being */
07594 #if 0
07595    /* Set the DIFF_* variables */
07596    ast_localtime(&t, &time_now, NULL);
07597    tv_now = ast_tvnow();
07598    ast_localtime(&tv_now, &time_then, NULL);
07599 
07600    /* Day difference */
07601    if (time_now.tm_year == time_then.tm_year)
07602       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07603    else
07604       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07605    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07606 
07607    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07608 #endif
07609    if (the_zone) {
07610       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), the_zone->msg_format, the_zone->timezone);
07611    } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) {     /* GERMAN syntax */
07612       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
07613    } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {     /* GREEK syntax */
07614       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q  H 'digits/kai' M ", NULL);
07615    } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) {     /* ITALIAN syntax */
07616       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
07617    } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) {     /* DUTCH syntax */
07618       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/nl-om' HM", NULL);
07619    } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) {     /* NORWEGIAN syntax */
07620       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
07621    } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {     /* POLISH syntax */
07622       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q HM", NULL);
07623    } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07624       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
07625    } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) {     /* SWEDISH syntax */
07626       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' dB 'digits/at' k 'and' M", NULL);
07627    } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07628       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "qR 'vm-received'", NULL);
07629    } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {     /* VIETNAMESE syntax */
07630       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL);
07631    } else {
07632       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' IMp", NULL);
07633    }
07634 #if 0
07635    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07636 #endif
07637    return res;
07638 }

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

Definition at line 7719 of file app_voicemail.c.

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

Referenced by play_message().

07720 {
07721    int res = 0;
07722    int durationm;
07723    int durations;
07724    /* Verify that we have a duration for the message */
07725    if (duration == NULL)
07726       return res;
07727 
07728    /* Convert from seconds to minutes */
07729    durations = atoi(duration);
07730    durationm = (durations / 60);
07731 
07732    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07733 
07734    if ((!res) && (durationm >= minduration)) {
07735       res = wait_file2(chan, vms, "vm-duration");
07736 
07737       /* POLISH syntax */
07738       if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
07739          div_t num = div(durationm, 10);
07740 
07741          if (durationm == 1) {
07742             res = ast_play_and_wait(chan, "digits/1z");
07743             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07744          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07745             if (num.rem == 2) {
07746                if (!num.quot) {
07747                   res = ast_play_and_wait(chan, "digits/2-ie");
07748                } else {
07749                   res = say_and_wait(chan, durationm - 2 , ast_channel_language(chan));
07750                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07751                }
07752             } else {
07753                res = say_and_wait(chan, durationm, ast_channel_language(chan));
07754             }
07755             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07756          } else {
07757             res = say_and_wait(chan, durationm, ast_channel_language(chan));
07758             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07759          }
07760       /* DEFAULT syntax */
07761       } else {
07762          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
07763          res = wait_file2(chan, vms, "vm-minutes");
07764       }
07765    }
07766    return res;
07767 }

static int play_record_review ( struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime,
char *  fmt,
int  outsidecaller,
struct ast_vm_user vmu,
int *  duration,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 13664 of file app_voicemail.c.

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

13667 {
13668    /* Record message & let caller review or re-record it, or set options if applicable */
13669    int res = 0;
13670    int cmd = 0;
13671    int max_attempts = 3;
13672    int attempts = 0;
13673    int recorded = 0;
13674    int msg_exists = 0;
13675    signed char zero_gain = 0;
13676    char tempfile[PATH_MAX];
13677    char *acceptdtmf = "#";
13678    char *canceldtmf = "";
13679    int canceleddtmf = 0;
13680 
13681    /* Note that urgent and private are for flagging messages as such in the future */
13682 
13683    /* barf if no pointer passed to store duration in */
13684    if (duration == NULL) {
13685       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13686       return -1;
13687    }
13688 
13689    if (!outsidecaller)
13690       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13691    else
13692       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13693 
13694    cmd = '3';  /* Want to start by recording */
13695 
13696    while ((cmd >= 0) && (cmd != 't')) {
13697       switch (cmd) {
13698       case '1':
13699          if (!msg_exists) {
13700             /* In this case, 1 is to record a message */
13701             cmd = '3';
13702             break;
13703          } else {
13704             /* Otherwise 1 is to save the existing message */
13705             ast_verb(3, "Saving message as is\n");
13706             if (!outsidecaller) 
13707                ast_filerename(tempfile, recordfile, NULL);
13708             ast_stream_and_wait(chan, "vm-msgsaved", "");
13709             if (!outsidecaller) {
13710                /* Saves to IMAP server only if imapgreeting=yes */
13711                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13712                DISPOSE(recordfile, -1);
13713             }
13714             cmd = 't';
13715             return res;
13716          }
13717       case '2':
13718          /* Review */
13719          ast_verb(3, "Reviewing the message\n");
13720          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13721          break;
13722       case '3':
13723          msg_exists = 0;
13724          /* Record */
13725          if (recorded == 1) 
13726             ast_verb(3, "Re-recording the message\n");
13727          else  
13728             ast_verb(3, "Recording the message\n");
13729          
13730          if (recorded && outsidecaller) {
13731             cmd = ast_play_and_wait(chan, INTRO);
13732             cmd = ast_play_and_wait(chan, "beep");
13733          }
13734          recorded = 1;
13735          /* 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 */
13736          if (record_gain)
13737             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13738          if (ast_test_flag(vmu, VM_OPERATOR))
13739             canceldtmf = "0";
13740          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13741          if (strchr(canceldtmf, cmd)) {
13742          /* need this flag here to distinguish between pressing '0' during message recording or after */
13743             canceleddtmf = 1;
13744          }
13745          if (record_gain)
13746             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13747          if (cmd == -1) {
13748             /* User has hung up, no options to give */
13749             if (!outsidecaller) {
13750                /* user was recording a greeting and they hung up, so let's delete the recording. */
13751                ast_filedelete(tempfile, NULL);
13752             }     
13753             return cmd;
13754          }
13755          if (cmd == '0') {
13756             break;
13757          } else if (cmd == '*') {
13758             break;
13759 #if 0
13760          } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13761             /* Message is too short */
13762             ast_verb(3, "Message too short\n");
13763             cmd = ast_play_and_wait(chan, "vm-tooshort");
13764             cmd = ast_filedelete(tempfile, NULL);
13765             break;
13766          } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13767             /* Message is all silence */
13768             ast_verb(3, "Nothing recorded\n");
13769             cmd = ast_filedelete(tempfile, NULL);
13770             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13771             if (!cmd)
13772                cmd = ast_play_and_wait(chan, "vm-speakup");
13773             break;
13774 #endif
13775          } else {
13776             /* If all is well, a message exists */
13777             msg_exists = 1;
13778             cmd = 0;
13779          }
13780          break;
13781       case '4':
13782          if (outsidecaller) {  /* only mark vm messages */
13783             /* Mark Urgent */
13784             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13785                ast_verb(3, "marking message as Urgent\n");
13786                res = ast_play_and_wait(chan, "vm-marked-urgent");
13787                strcpy(flag, "Urgent");
13788             } else if (flag) {
13789                ast_verb(3, "UNmarking message as Urgent\n");
13790                res = ast_play_and_wait(chan, "vm-urgent-removed");
13791                strcpy(flag, "");
13792             } else {
13793                ast_play_and_wait(chan, "vm-sorry");
13794             }
13795             cmd = 0;
13796          } else {
13797             cmd = ast_play_and_wait(chan, "vm-sorry");
13798          }
13799          break;
13800       case '5':
13801       case '6':
13802       case '7':
13803       case '8':
13804       case '9':
13805       case '*':
13806       case '#':
13807          cmd = ast_play_and_wait(chan, "vm-sorry");
13808          break;
13809 #if 0 
13810 /*  XXX Commented out for the moment because of the dangers of deleting
13811     a message while recording (can put the message numbers out of sync) */
13812       case '*':
13813          /* Cancel recording, delete message, offer to take another message*/
13814          cmd = ast_play_and_wait(chan, "vm-deleted");
13815          cmd = ast_filedelete(tempfile, NULL);
13816          if (outsidecaller) {
13817             res = vm_exec(chan, NULL);
13818             return res;
13819          }
13820          else
13821             return 1;
13822 #endif
13823       case '0':
13824          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13825             cmd = ast_play_and_wait(chan, "vm-sorry");
13826             break;
13827          }
13828          if (msg_exists || recorded) {
13829             cmd = ast_play_and_wait(chan, "vm-saveoper");
13830             if (!cmd)
13831                cmd = ast_waitfordigit(chan, 3000);
13832             if (cmd == '1') {
13833                ast_filerename(tempfile, recordfile, NULL);
13834                ast_play_and_wait(chan, "vm-msgsaved");
13835                cmd = '0';
13836             } else if (cmd == '4') {
13837                if (flag) {
13838                   ast_play_and_wait(chan, "vm-marked-urgent");
13839                   strcpy(flag, "Urgent");
13840                }
13841                ast_play_and_wait(chan, "vm-msgsaved");
13842                cmd = '0';
13843             } else {
13844                ast_play_and_wait(chan, "vm-deleted");
13845                DELETE(tempfile, -1, tempfile, vmu);
13846                cmd = '0';
13847             }
13848          }
13849          return cmd;
13850       default:
13851          /* If the caller is an ouside caller, and the review option is enabled,
13852             allow them to review the message, but let the owner of the box review
13853             their OGM's */
13854          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13855             return cmd;
13856          if (msg_exists) {
13857             cmd = ast_play_and_wait(chan, "vm-review");
13858             if (!cmd && outsidecaller) {
13859                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13860                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13861                } else if (flag) {
13862                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13863                }
13864             }
13865          } else {
13866             cmd = ast_play_and_wait(chan, "vm-torerecord");
13867             if (!cmd)
13868                cmd = ast_waitfordigit(chan, 600);
13869          }
13870          
13871          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13872             cmd = ast_play_and_wait(chan, "vm-reachoper");
13873             if (!cmd)
13874                cmd = ast_waitfordigit(chan, 600);
13875          }
13876 #if 0
13877          if (!cmd)
13878             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13879 #endif
13880          if (!cmd)
13881             cmd = ast_waitfordigit(chan, 6000);
13882          if (!cmd) {
13883             attempts++;
13884          }
13885          if (attempts > max_attempts) {
13886             cmd = 't';
13887          }
13888       }
13889    }
13890    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13891       /* Hang up or timeout, so delete the recording. */
13892       ast_filedelete(tempfile, NULL);
13893    }
13894 
13895    if (cmd != 't' && outsidecaller)
13896       ast_play_and_wait(chan, "vm-goodbye");
13897 
13898    return cmd;
13899 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11604 of file app_voicemail.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11605 {
11606    int new = 0, old = 0, urgent = 0;
11607 
11608    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11609 
11610    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11611       mwi_sub->old_urgent = urgent;
11612       mwi_sub->old_new = new;
11613       mwi_sub->old_old = old;
11614       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11615       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11616    }
11617 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11620 {
11621    struct mwi_sub *mwi_sub;
11622 
11623    AST_RWLIST_RDLOCK(&mwi_subs);
11624    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11625       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11626          poll_subscribed_mailbox(mwi_sub);
11627       }
11628    }
11629    AST_RWLIST_UNLOCK(&mwi_subs);
11630 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

  • all the globalflags
  • the saydurationminfo
  • the callcontext
  • the dialcontext
  • the exitcontext
  • vmmaxsecs, vmmaxmsg, maxdeletedmsg
  • volume gain.
  • emailsubject, emailbody set to NULL

Definition at line 1088 of file app_voicemail.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_free, 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::locale, ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, saydurationminfo, ast_vm_user::volgain, and ast_vm_user::zonetag.

01089 {
01090    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
01091    vmu->passwordlocation = passwordlocation;
01092    if (saydurationminfo) {
01093       vmu->saydurationm = saydurationminfo;
01094    }
01095    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
01096    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
01097    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
01098    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
01099    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
01100    if (vmminsecs) {
01101       vmu->minsecs = vmminsecs;
01102    }
01103    if (vmmaxsecs) {
01104       vmu->maxsecs = vmmaxsecs;
01105    }
01106    if (maxmsg) {
01107       vmu->maxmsg = maxmsg;
01108    }
01109    if (maxdeletedmsg) {
01110       vmu->maxdeletedmsg = maxdeletedmsg;
01111    }
01112    vmu->volgain = volgain;
01113    ast_free(vmu->emailsubject);
01114    vmu->emailsubject = NULL;
01115    ast_free(vmu->emailbody);
01116    vmu->emailbody = NULL;
01117 #ifdef IMAP_STORAGE
01118    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
01119    ast_copy_string(vmu->imapserver, imapserver, sizeof(vmu->imapserver));
01120    ast_copy_string(vmu->imapport, imapport, sizeof(vmu->imapport));
01121    ast_copy_string(vmu->imapflags, imapflags, sizeof(vmu->imapflags));
01122 #endif
01123 }

static void prep_email_sub_vars ( struct ast_channel ast,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  dur,
char *  date,
const char *  category,
const char *  flag 
) [static]

Definition at line 4425 of file app_voicemail.c.

References ast_callerid_merge(), ast_callerid_split(), ast_config_destroy(), ast_config_load, ast_debug, ast_localtime(), ast_strdupa, ast_strftime_locale(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, emaildateformat, ast_vm_user::fullname, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), pbx_builtin_setvar_helper(), and S_OR.

04426 {
04427    char callerid[256];
04428    char num[12];
04429    char fromdir[256], fromfile[256];
04430    struct ast_config *msg_cfg;
04431    const char *origcallerid, *origtime;
04432    char origcidname[80], origcidnum[80], origdate[80];
04433    int inttime;
04434    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04435 
04436    /* Prepare variables for substitution in email body and subject */
04437    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04438    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04439    snprintf(num, sizeof(num), "%d", msgnum);
04440    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04441    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04442    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04443    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04444       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04445    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04446    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04447    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04448    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04449    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04450 
04451    /* Retrieve info from VM attribute file */
04452    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04453    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04454    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04455       strcat(fromfile, ".txt");
04456    }
04457    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04458       ast_debug(1, "Config load for message text file '%s' failed\n", fromfile);
04459       return;
04460    }
04461 
04462    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04463       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04464       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04465       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04466       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04467    }
04468 
04469    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04470       struct timeval tv = { inttime, };
04471       struct ast_tm tm;
04472       ast_localtime(&tv, &tm, NULL);
04473       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04474       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04475    }
04476    ast_config_destroy(msg_cfg);
04477 }

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

Definition at line 7096 of file app_voicemail.c.

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

07097 {
07098    struct ast_event *event;
07099    char *mailbox, *context;
07100 
07101    /* Strip off @default */
07102    context = mailbox = ast_strdupa(box);
07103    strsep(&context, "@");
07104    if (ast_strlen_zero(context))
07105       context = "default";
07106 
07107    if (!(event = ast_event_new(AST_EVENT_MWI,
07108          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07109          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07110          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07111          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07112          AST_EVENT_IE_END))) {
07113       return;
07114    }
07115 
07116    ast_event_queue_and_cache(event);
07117 }

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

Definition at line 12704 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

12704                                                                                            {
12705    struct ast_config *pwconf;
12706    struct ast_flags config_flags = { 0 };
12707 
12708    pwconf = ast_config_load(secretfn, config_flags);
12709    if (pwconf) {
12710       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12711       if (val) {
12712          ast_copy_string(password, val, passwordlen);
12713          return;
12714       }
12715    }
12716    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12717 }

static int reload ( void   )  [static]

Definition at line 13307 of file app_voicemail.c.

References load_config().

13308 {
13309    return load_config(1);
13310 }

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

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

04095 {
04096    char stxt[PATH_MAX];
04097    char dtxt[PATH_MAX];
04098    ast_filerename(sfn, dfn, NULL);
04099    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04100    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04101    if (ast_check_realtime("voicemail_data")) {
04102       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04103    }
04104    rename(stxt, dtxt);
04105 }

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

Definition at line 6238 of file app_voicemail.c.

References ast_unlock_path(), ast_vm_user::context, ERROR_LOCK_PATH, EXISTS, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, RENAME, and vm_lock_path().

Referenced by open_mailbox().

06239 {
06240    /* we know the actual number of messages, so stop process when number is hit */
06241 
06242    int x, dest;
06243    char sfn[PATH_MAX];
06244    char dfn[PATH_MAX];
06245 
06246    if (vm_lock_path(dir)) {
06247       return ERROR_LOCK_PATH;
06248    }
06249 
06250    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06251       make_file(sfn, sizeof(sfn), dir, x);
06252       if (EXISTS(dir, x, sfn, NULL)) {
06253 
06254          if (x != dest) {
06255             make_file(dfn, sizeof(dfn), dir, dest);
06256             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06257          }
06258 
06259          dest++;
06260       }
06261    }
06262    ast_unlock_path(dir);
06263 
06264    return dest;
06265 }

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

01580 {
01581    /* This function could be made to generate one from a database, too */
01582    struct ast_vm_user *cur;
01583    int res = -1;
01584    AST_LIST_LOCK(&users);
01585    AST_LIST_TRAVERSE(&users, cur, list) {
01586       if ((!context || !strcasecmp(context, cur->context)) &&
01587          (!strcasecmp(mailbox, cur->mailbox)))
01588             break;
01589    }
01590    if (cur) {
01591       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01592       res = 0;
01593    }
01594    AST_LIST_UNLOCK(&users);
01595    return res;
01596 }

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

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

05613 {
05614    char arguments[255];
05615    char ext_context[256] = "";
05616    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05617    struct ast_smdi_mwi_message *mwi_msg;
05618 
05619    if (!ast_strlen_zero(context))
05620       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05621    else
05622       ast_copy_string(ext_context, extension, sizeof(ext_context));
05623 
05624    if (smdi_iface) {
05625       if (ast_app_has_voicemail(ext_context, NULL)) 
05626          ast_smdi_mwi_set(smdi_iface, extension);
05627       else
05628          ast_smdi_mwi_unset(smdi_iface, extension);
05629 
05630       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05631          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05632          if (!strncmp(mwi_msg->cause, "INV", 3))
05633             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05634          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05635             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05636          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05637          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05638       } else {
05639          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05640       }
05641    }
05642 
05643    if (!ast_strlen_zero(externnotify)) {
05644       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05645          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05646       } else {
05647          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05648          ast_debug(1, "Executing %s\n", arguments);
05649          ast_safe_system(arguments);
05650       }
05651    }
05652 }

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

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

06276 {
06277 #ifdef IMAP_STORAGE
06278    /* we must use mbox(x) folder names, and copy the message there */
06279    /* simple. huh? */
06280    char sequence[10];
06281    char mailbox[256];
06282    int res;
06283 
06284    /* get the real IMAP message number for this message */
06285    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06286 
06287    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06288    ast_mutex_lock(&vms->lock);
06289    /* if save to Old folder, put in INBOX as read */
06290    if (box == OLD_FOLDER) {
06291       mail_setflag(vms->mailstream, sequence, "\\Seen");
06292       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06293    } else if (box == NEW_FOLDER) {
06294       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06295       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06296    }
06297    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06298       ast_mutex_unlock(&vms->lock);
06299       return 0;
06300    }
06301    /* Create the folder if it don't exist */
06302    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06303    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06304    if (mail_create(vms->mailstream, mailbox) == NIL)
06305       ast_debug(5, "Folder exists.\n");
06306    else
06307       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06308    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06309    ast_mutex_unlock(&vms->lock);
06310    return res;
06311 #else
06312    char *dir = vms->curdir;
06313    char *username = vms->username;
06314    char *context = vmu->context;
06315    char sfn[PATH_MAX];
06316    char dfn[PATH_MAX];
06317    char ddir[PATH_MAX];
06318    const char *dbox = mbox(vmu, box);
06319    int x, i;
06320    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06321 
06322    if (vm_lock_path(ddir))
06323       return ERROR_LOCK_PATH;
06324 
06325    x = last_message_index(vmu, ddir) + 1;
06326 
06327    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06328       x--;
06329       for (i = 1; i <= x; i++) {
06330          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06331          make_file(sfn, sizeof(sfn), ddir, i);
06332          make_file(dfn, sizeof(dfn), ddir, i - 1);
06333          if (EXISTS(ddir, i, sfn, NULL)) {
06334             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06335          } else
06336             break;
06337       }
06338    } else {
06339       if (x >= vmu->maxmsg) {
06340          ast_unlock_path(ddir);
06341          return -1;
06342       }
06343    }
06344    make_file(sfn, sizeof(sfn), dir, msg);
06345    make_file(dfn, sizeof(dfn), ddir, x);
06346    if (strcmp(sfn, dfn)) {
06347       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06348    }
06349    ast_unlock_path(ddir);
06350    return 0;
06351 #endif
06352 }

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

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

Referenced by load_module(), and vmsayname_exec().

12691 {
12692    int res = -1;
12693    char dir[PATH_MAX];
12694    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12695    ast_debug(2, "About to try retrieving name file %s\n", dir);
12696    RETRIEVE(dir, -1, mailbox, context);
12697    if (ast_fileexists(dir, NULL, NULL)) {
12698       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12699    }
12700    DISPOSE(dir, -1);
12701    return res;
12702 }

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

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

04939 {
04940    FILE *p = NULL;
04941    char tmp[80] = "/tmp/astmail-XXXXXX";
04942    char tmp2[256];
04943    char *stringp;
04944 
04945    if (vmu && ast_strlen_zero(vmu->email)) {
04946       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04947       return(0);
04948    }
04949 
04950    /* Mail only the first format */
04951    format = ast_strdupa(format);
04952    stringp = format;
04953    strsep(&stringp, "|");
04954 
04955    if (!strcmp(format, "wav49"))
04956       format = "WAV";
04957    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));
04958    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04959       command hangs */
04960    if ((p = vm_mkftemp(tmp)) == NULL) {
04961       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04962       return -1;
04963    } else {
04964       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04965       fclose(p);
04966       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04967       ast_safe_system(tmp2);
04968       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04969    }
04970    return 0;
04971 }

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

References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_log(), AST_LOG_WARNING, ast_safe_system(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strftime_locale(), ast_strlen_zero(), check_mime(), ENDL, ast_vm_user::fullname, ast_vm_user::locale, MAXHOSTNAMELEN, pagerbody, pagerdateformat, pagerfromstring, pagersubject, prep_email_sub_vars(), S_OR, strip_control_and_high(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

04974 {
04975    char enc_cidnum[256], enc_cidname[256];
04976    char date[256];
04977    char host[MAXHOSTNAMELEN] = "";
04978    char who[256];
04979    char dur[PATH_MAX];
04980    char tmp[80] = "/tmp/astmail-XXXXXX";
04981    char tmp2[PATH_MAX];
04982    struct ast_tm tm;
04983    FILE *p;
04984    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04985 
04986    if (!str1 || !str2) {
04987       ast_free(str1);
04988       ast_free(str2);
04989       return -1;
04990    }
04991 
04992    if (cidnum) {
04993       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04994    }
04995    if (cidname) {
04996       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04997    }
04998 
04999    if ((p = vm_mkftemp(tmp)) == NULL) {
05000       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
05001       ast_free(str1);
05002       ast_free(str2);
05003       return -1;
05004    }
05005    gethostname(host, sizeof(host)-1);
05006    if (strchr(srcemail, '@')) {
05007       ast_copy_string(who, srcemail, sizeof(who));
05008    } else {
05009       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
05010    }
05011    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
05012    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
05013    fprintf(p, "Date: %s\n", date);
05014 
05015    /* Reformat for custom pager format */
05016    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
05017 
05018    if (!ast_strlen_zero(pagerfromstring)) {
05019       struct ast_channel *ast;
05020       if ((ast = ast_dummy_channel_alloc())) {
05021          char *ptr;
05022          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
05023          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
05024 
05025          if (check_mime(ast_str_buffer(str1))) {
05026             int first_line = 1;
05027             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
05028             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
05029                *ptr = '\0';
05030                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
05031                first_line = 0;
05032                /* Substring is smaller, so this will never grow */
05033                ast_str_set(&str2, 0, "%s", ptr + 1);
05034             }
05035             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
05036          } else {
05037             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
05038          }
05039          ast = ast_channel_unref(ast);
05040       } else {
05041          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05042       }
05043    } else {
05044       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
05045    }
05046 
05047    if (check_mime(vmu->fullname)) {
05048       int first_line = 1;
05049       char *ptr;
05050       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
05051       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
05052          *ptr = '\0';
05053          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
05054          first_line = 0;
05055          /* Substring is smaller, so this will never grow */
05056          ast_str_set(&str2, 0, "%s", ptr + 1);
05057       }
05058       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
05059    } else {
05060       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
05061    }
05062 
05063    if (!ast_strlen_zero(pagersubject)) {
05064       struct ast_channel *ast;
05065       if ((ast = ast_dummy_channel_alloc())) {
05066          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05067          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
05068          if (check_mime(ast_str_buffer(str1))) {
05069             int first_line = 1;
05070             char *ptr;
05071             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
05072             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
05073                *ptr = '\0';
05074                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
05075                first_line = 0;
05076                /* Substring is smaller, so this will never grow */
05077                ast_str_set(&str2, 0, "%s", ptr + 1);
05078             }
05079             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
05080          } else {
05081             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
05082          }
05083          ast = ast_channel_unref(ast);
05084       } else {
05085          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05086       }
05087    } else {
05088       if (ast_strlen_zero(flag)) {
05089          fprintf(p, "Subject: New VM\n\n");
05090       } else {
05091          fprintf(p, "Subject: New %s VM\n\n", flag);
05092       }
05093    }
05094 
05095    if (pagerbody) {
05096       struct ast_channel *ast;
05097       if ((ast = ast_dummy_channel_alloc())) {
05098          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05099          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
05100          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
05101          ast = ast_channel_unref(ast);
05102       } else {
05103          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05104       }
05105    } else {
05106       fprintf(p, "New %s long %s msg in box %s\n"
05107             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
05108    }
05109 
05110    fclose(p);
05111    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
05112    ast_safe_system(tmp2);
05113    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
05114    ast_free(str1);
05115    ast_free(str2);
05116    return 0;
05117 }

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

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

11262 {
11263    struct ast_config *cfg;
11264    const char *cat = NULL;
11265 
11266    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11267       "context", context, SENTINEL))) {
11268       return CLI_FAILURE;
11269    }
11270 
11271    ast_cli(fd,
11272       "\n"
11273       "=============================================================\n"
11274       "=== Configured Voicemail Users ==============================\n"
11275       "=============================================================\n"
11276       "===\n");
11277 
11278    while ((cat = ast_category_browse(cfg, cat))) {
11279       struct ast_variable *var = NULL;
11280       ast_cli(fd,
11281          "=== Mailbox ...\n"
11282          "===\n");
11283       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11284          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11285       ast_cli(fd,
11286          "===\n"
11287          "=== ---------------------------------------------------------\n"
11288          "===\n");
11289    }
11290 
11291    ast_cli(fd,
11292       "=============================================================\n"
11293       "\n");
11294 
11295    ast_config_destroy(cfg);
11296 
11297    return CLI_SUCCESS;
11298 }

static void start_poll_thread ( void   )  [static]

static void stop_poll_thread ( void   )  [static]

Definition at line 11774 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 actual_load_config(), and unload_module().

11775 {
11776    poll_thread_run = 0;
11777 
11778    if (mwi_sub_sub) {
11779       ast_event_unsubscribe(mwi_sub_sub);
11780       mwi_sub_sub = NULL;
11781    }
11782 
11783    if (mwi_unsub_sub) {
11784       ast_event_unsubscribe(mwi_unsub_sub);
11785       mwi_unsub_sub = NULL;
11786    }
11787 
11788    ast_mutex_lock(&poll_lock);
11789    ast_cond_signal(&poll_cond);
11790    ast_mutex_unlock(&poll_lock);
11791 
11792    pthread_join(poll_thread, NULL);
11793 
11794    poll_thread = AST_PTHREADT_NULL;
11795 }

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

Referenced by make_email_file(), and sendpage().

01059 {
01060    char *bufptr = buf;
01061    for (; *input; input++) {
01062       if (*input < 32) {
01063          continue;
01064       }
01065       *bufptr++ = *input;
01066       if (bufptr == buf + buflen - 1) {
01067          break;
01068       }
01069    }
01070    *bufptr = '\0';
01071    return buf;
01072 }

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

Definition at line 11927 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 actual_load_config(), apply_option(), and apply_options_full().

11928 {
11929    char *current;
11930 
11931    /* Add 16 for fudge factor */
11932    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11933 
11934    ast_str_reset(str);
11935    
11936    /* Substitute strings \r, \n, and \t into the appropriate characters */
11937    for (current = (char *) value; *current; current++) {
11938       if (*current == '\\') {
11939          current++;
11940          if (!*current) {
11941             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11942             break;
11943          }
11944          switch (*current) {
11945          case '\\':
11946             ast_str_append(&str, 0, "\\");
11947             break;
11948          case 'r':
11949             ast_str_append(&str, 0, "\r");
11950             break;
11951          case 'n':
11952 #ifdef IMAP_STORAGE
11953             if (!str->used || str->str[str->used - 1] != '\r') {
11954                ast_str_append(&str, 0, "\r");
11955             }
11956 #endif
11957             ast_str_append(&str, 0, "\n");
11958             break;
11959          case 't':
11960             ast_str_append(&str, 0, "\t");
11961             break;
11962          default:
11963             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11964             break;
11965          }
11966       } else {
11967          ast_str_append(&str, 0, "%c", *current);
11968       }
11969    }
11970 
11971    return ast_str_buffer(str);
11972 }

static int unload_module ( void   )  [static]

Definition at line 13312 of file app_voicemail.c.

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

13313 {
13314    int res;
13315 
13316    res = ast_unregister_application(app);
13317    res |= ast_unregister_application(app2);
13318    res |= ast_unregister_application(app3);
13319    res |= ast_unregister_application(app4);
13320    res |= ast_unregister_application(sayname_app);
13321    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13322    res |= ast_custom_function_unregister(&vm_info_acf);
13323    res |= ast_manager_unregister("VoicemailUsersList");
13324    res |= ast_data_unregister(NULL);
13325 #ifdef TEST_FRAMEWORK
13326    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13327    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13328    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13329    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13330    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13331    res |= AST_TEST_UNREGISTER(test_voicemail_vm_info);
13332 #endif
13333    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13334    ast_uninstall_vm_functions();
13335    ao2_ref(inprocess_container, -1);
13336 
13337    if (poll_thread != AST_PTHREADT_NULL)
13338       stop_poll_thread();
13339 
13340    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13341    ast_unload_realtime("voicemail");
13342    ast_unload_realtime("voicemail_data");
13343 
13344    free_vm_users();
13345    free_vm_zones();
13346    return res;
13347 }

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

Definition at line 1849 of file app_voicemail.c.

References ast_calloc, ast_realloc, vm_state::deleted, vm_state::dh_arraysize, vm_state::heard, and ast_vm_user::maxmsg.

Referenced by open_mailbox().

01849                                                                                         {
01850 
01851    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01852    if (!vms->dh_arraysize) {
01853       /* initial allocation */
01854       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01855          return -1;
01856       }
01857       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01858          return -1;
01859       }
01860       vms->dh_arraysize = arraysize;
01861    } else if (vms->dh_arraysize < arraysize) {
01862       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01863          return -1;
01864       }
01865       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01866          return -1;
01867       }
01868       memset(vms->deleted, 0, arraysize * sizeof(int));
01869       memset(vms->heard, 0, arraysize * sizeof(int));
01870       vms->dh_arraysize = arraysize;
01871    }
01872 
01873    return 0;
01874 }

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

References adsi_begin(), adsi_login(), adsi_password(), ast_channel_language(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::context, find_user(), ast_party_caller::id, ast_party_id::number, ast_vm_user::password, S_COR, ast_party_number::str, ast_party_number::valid, and vm_password.

Referenced by vm_execmain(), and vmauthenticate().

09844 {
09845    int useadsi = 0, valid = 0, logretries = 0;
09846    char password[AST_MAX_EXTENSION]="", *passptr;
09847    struct ast_vm_user vmus, *vmu = NULL;
09848 
09849    /* If ADSI is supported, setup login screen */
09850    adsi_begin(chan, &useadsi);
09851    if (!skipuser && useadsi)
09852       adsi_login(chan);
09853    ast_test_suite_event_notify("PLAYBACK", "Message: vm-login");
09854    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", ast_channel_language(chan))) {
09855       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09856       return -1;
09857    }
09858 
09859    /* Authenticate them and get their mailbox/password */
09860 
09861    while (!valid && (logretries < max_logins)) {
09862       /* Prompt for, and read in the username */
09863       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09864          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09865          return -1;
09866       }
09867       if (ast_strlen_zero(mailbox)) {
09868          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09869             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09870          } else {
09871             ast_verb(3, "Username not entered\n"); 
09872             return -1;
09873          }
09874       } else if (mailbox[0] == '*') {
09875          /* user entered '*' */
09876          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09877          if (ast_exists_extension(chan, chan->context, "a", 1,
09878             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09879             return -1;
09880          }
09881          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09882          mailbox[0] = '\0';
09883       }
09884 
09885       if (useadsi)
09886          adsi_password(chan);
09887 
09888       if (!ast_strlen_zero(prefix)) {
09889          char fullusername[80] = "";
09890          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09891          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09892          ast_copy_string(mailbox, fullusername, mailbox_size);
09893       }
09894 
09895       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09896       vmu = find_user(&vmus, context, mailbox);
09897       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09898          /* saved password is blank, so don't bother asking */
09899          password[0] = '\0';
09900       } else {
09901          ast_test_suite_event_notify("PLAYBACK", "Message: %s", vm_password);
09902          if (ast_streamfile(chan, vm_password, ast_channel_language(chan))) {
09903             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09904             return -1;
09905          }
09906          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09907             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09908             return -1;
09909          } else if (password[0] == '*') {
09910             /* user entered '*' */
09911             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09912             if (ast_exists_extension(chan, chan->context, "a", 1,
09913                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09914                mailbox[0] = '*';
09915                return -1;
09916             }
09917             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09918             mailbox[0] = '\0';
09919             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09920             vmu = NULL;
09921          }
09922       }
09923 
09924       if (vmu) {
09925          passptr = vmu->password;
09926          if (passptr[0] == '-') passptr++;
09927       }
09928       if (vmu && !strcmp(passptr, password))
09929          valid++;
09930       else {
09931          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09932          if (!ast_strlen_zero(prefix))
09933             mailbox[0] = '\0';
09934       }
09935       logretries++;
09936       if (!valid) {
09937          if (skipuser || logretries >= max_logins) {
09938             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect");
09939             if (ast_streamfile(chan, "vm-incorrect", ast_channel_language(chan))) {
09940                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09941                return -1;
09942             }
09943          } else {
09944             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect-mailbox");
09945             if (useadsi)
09946                adsi_login(chan);
09947             if (ast_streamfile(chan, "vm-incorrect-mailbox", ast_channel_language(chan))) {
09948                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09949                return -1;
09950             }
09951          }
09952          if (ast_waitstream(chan, "")) /* Channel is hung up */
09953             return -1;
09954       }
09955    }
09956    if (!valid && (logretries >= max_logins)) {
09957       ast_stopstream(chan);
09958       ast_play_and_wait(chan, "vm-goodbye");
09959       return -1;
09960    }
09961    if (vmu && !skipuser) {
09962       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09963    }
09964    return 0;
09965 }

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

Definition at line 11071 of file app_voicemail.c.

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

Referenced by load_module().

11072 {
11073    struct ast_vm_user svm;
11074    char *context, *box;
11075    AST_DECLARE_APP_ARGS(args,
11076       AST_APP_ARG(mbox);
11077       AST_APP_ARG(options);
11078    );
11079    static int dep_warning = 0;
11080 
11081    if (ast_strlen_zero(data)) {
11082       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
11083       return -1;
11084    }
11085 
11086    if (!dep_warning) {
11087       dep_warning = 1;
11088       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${VM_INFO(%s,exists)} instead.\n", data);
11089    }
11090 
11091    box = ast_strdupa(data);
11092 
11093    AST_STANDARD_APP_ARGS(args, box);
11094 
11095    if (args.options) {
11096    }
11097 
11098    if ((context = strchr(args.mbox, '@'))) {
11099       *context = '\0';
11100       context++;
11101    }
11102 
11103    if (find_user(&svm, context, args.mbox)) {
11104       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
11105    } else
11106       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
11107 
11108    return 0;
11109 }

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 9820 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(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

09821 {
09822    if (!strncasecmp(ast_channel_language(chan), "es", 2)) {         /* SPANISH */
09823       return vm_browse_messages_es(chan, vms, vmu);
09824    } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {  /* GREEK */
09825       return vm_browse_messages_gr(chan, vms, vmu);
09826    } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) {  /* HEBREW */
09827       return vm_browse_messages_he(chan, vms, vmu);
09828    } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) {  /* ITALIAN */
09829       return vm_browse_messages_it(chan, vms, vmu);
09830    } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) {  /* PORTUGUESE */
09831       return vm_browse_messages_pt(chan, vms, vmu);
09832    } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {  /* VIETNAMESE */
09833       return vm_browse_messages_vi(chan, vms, vmu);
09834    } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) {  /* CHINESE (Taiwan) */
09835       return vm_browse_messages_zh(chan, vms, vmu);
09836    } else {                                             /* Default to English syntax */
09837       return vm_browse_messages_en(chan, vms, vmu);
09838    }
09839 }

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

09660 {
09661    int cmd = 0;
09662 
09663    if (vms->lastmsg > -1) {
09664       cmd = play_message(chan, vmu, vms);
09665    } else {
09666       cmd = ast_play_and_wait(chan, "vm-youhave");
09667       if (!cmd) 
09668          cmd = ast_play_and_wait(chan, "vm-no");
09669       if (!cmd) {
09670          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09671          cmd = ast_play_and_wait(chan, vms->fn);
09672       }
09673       if (!cmd)
09674          cmd = ast_play_and_wait(chan, "vm-messages");
09675    }
09676    return cmd;
09677 }

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

09714 {
09715    int cmd;
09716 
09717    if (vms->lastmsg > -1) {
09718       cmd = play_message(chan, vmu, vms);
09719    } else {
09720       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09721       if (!cmd)
09722          cmd = ast_play_and_wait(chan, "vm-messages");
09723       if (!cmd) {
09724          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09725          cmd = ast_play_and_wait(chan, vms->fn);
09726       }
09727    }
09728    return cmd;
09729 }

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

09608 {
09609    int cmd = 0;
09610 
09611    if (vms->lastmsg > -1) {
09612       cmd = play_message(chan, vmu, vms);
09613    } else {
09614       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09615       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09616          if (!cmd) {
09617             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09618             cmd = ast_play_and_wait(chan, vms->fn);
09619          }
09620          if (!cmd)
09621             cmd = ast_play_and_wait(chan, "vm-messages");
09622       } else {
09623          if (!cmd)
09624             cmd = ast_play_and_wait(chan, "vm-messages");
09625          if (!cmd) {
09626             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09627             cmd = ast_play_and_wait(chan, vms->fn);
09628          }
09629       }
09630    } 
09631    return cmd;
09632 }

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

Definition at line 9635 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09636 {
09637    int cmd = 0;
09638 
09639    if (vms->lastmsg > -1) {
09640       cmd = play_message(chan, vmu, vms);
09641    } else {
09642       if (!strcasecmp(vms->fn, "INBOX")) {
09643          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09644       } else {
09645          cmd = ast_play_and_wait(chan, "vm-nomessages");
09646       }
09647    }
09648    return cmd;
09649 }

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

09688 {
09689    int cmd;
09690 
09691    if (vms->lastmsg > -1) {
09692       cmd = play_message(chan, vmu, vms);
09693    } else {
09694       cmd = ast_play_and_wait(chan, "vm-no");
09695       if (!cmd)
09696          cmd = ast_play_and_wait(chan, "vm-message");
09697       if (!cmd) {
09698          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09699          cmd = ast_play_and_wait(chan, vms->fn);
09700       }
09701    }
09702    return cmd;
09703 }

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

09740 {
09741    int cmd;
09742 
09743    if (vms->lastmsg > -1) {
09744       cmd = play_message(chan, vmu, vms);
09745    } else {
09746       cmd = ast_play_and_wait(chan, "vm-no");
09747       if (!cmd) {
09748          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09749          cmd = ast_play_and_wait(chan, vms->fn);
09750       }
09751       if (!cmd)
09752          cmd = ast_play_and_wait(chan, "vm-messages");
09753    }
09754    return cmd;
09755 }

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

Vietnamese syntax for 'You have N messages' greeting.

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

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

09794 {
09795    int cmd = 0;
09796 
09797    if (vms->lastmsg > -1) {
09798       cmd = play_message(chan, vmu, vms);
09799    } else {
09800       cmd = ast_play_and_wait(chan, "vm-no");
09801       if (!cmd) {
09802          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09803          cmd = ast_play_and_wait(chan, vms->fn);
09804       }
09805    }
09806    return cmd;
09807 }

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

09766 {
09767    int cmd;
09768 
09769    if (vms->lastmsg > -1) {
09770       cmd = play_message(chan, vmu, vms);
09771    } else {
09772       cmd = ast_play_and_wait(chan, "vm-you");
09773       if (!cmd) 
09774          cmd = ast_play_and_wait(chan, "vm-haveno");
09775       if (!cmd)
09776          cmd = ast_play_and_wait(chan, "vm-messages");
09777       if (!cmd) {
09778          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09779          cmd = ast_play_and_wait(chan, vms->fn);
09780       }
09781    }
09782    return cmd;
09783 }

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 1605 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_free, ast_log(), AST_LOG_WARNING, ast_test_suite_event_notify, ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, reset_user_pw(), value, var, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser(), and vm_options().

01606 {
01607    struct ast_config   *cfg = NULL;
01608    struct ast_variable *var = NULL;
01609    struct ast_category *cat = NULL;
01610    char *category = NULL, *value = NULL, *new = NULL;
01611    const char *tmp = NULL;
01612    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01613    char secretfn[PATH_MAX] = "";
01614    int found = 0;
01615 
01616    if (!change_password_realtime(vmu, newpassword))
01617       return;
01618 
01619    /* check if we should store the secret in the spool directory next to the messages */
01620    switch (vmu->passwordlocation) {
01621    case OPT_PWLOC_SPOOLDIR:
01622       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01623       if (write_password_to_file(secretfn, newpassword) == 0) {
01624          ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
01625          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01626          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01627          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01628          break;
01629       } else {
01630          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01631       }
01632       /* Fall-through */
01633    case OPT_PWLOC_VOICEMAILCONF:
01634       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01635          while ((category = ast_category_browse(cfg, category))) {
01636             if (!strcasecmp(category, vmu->context)) {
01637                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01638                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01639                   break;
01640                }
01641                value = strstr(tmp, ",");
01642                if (!value) {
01643                   new = alloca(strlen(newpassword)+1);
01644                   sprintf(new, "%s", newpassword);
01645                } else {
01646                   new = alloca((strlen(value) + strlen(newpassword) + 1));
01647                   sprintf(new, "%s%s", newpassword, value);
01648                }
01649                if (!(cat = ast_category_get(cfg, category))) {
01650                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01651                   break;
01652                }
01653                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01654                found = 1;
01655             }
01656          }
01657          /* save the results */
01658          if (found) {
01659             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
01660             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01661             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01662             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01663             break;
01664          }
01665       }
01666       /* Fall-through */
01667    case OPT_PWLOC_USERSCONF:
01668       /* check users.conf and update the password stored for the mailbox */
01669       /* if no vmsecret entry exists create one. */
01670       if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01671          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01672          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01673             ast_debug(4, "users.conf: %s\n", category);
01674             if (!strcasecmp(category, vmu->mailbox)) {
01675                if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01676                   ast_debug(3, "looks like we need to make vmsecret!\n");
01677                   var = ast_variable_new("vmsecret", newpassword, "");
01678                } else {
01679                   var = NULL;
01680                }
01681                new = alloca(strlen(newpassword) + 1);
01682                sprintf(new, "%s", newpassword);
01683                if (!(cat = ast_category_get(cfg, category))) {
01684                   ast_debug(4, "failed to get category!\n");
01685                   ast_free(var);
01686                   break;
01687                }
01688                if (!var) {
01689                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01690                } else {
01691                   ast_variable_append(cat, var);
01692                }
01693                found = 1;
01694                break;
01695             }
01696          }
01697          /* save the results and clean things up */
01698          if (found) {
01699             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
01700             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01701             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01702             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01703          }
01704       }
01705    }
01706 }

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

Definition at line 1708 of file app_voicemail.c.

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

Referenced by vm_newuser(), and vm_options().

01709 {
01710    char buf[255];
01711    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01712    ast_debug(1, "External password: %s\n",buf);
01713    if (!ast_safe_system(buf)) {
01714       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01715       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01716       /* Reset the password in memory, too */
01717       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01718    }
01719 }

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

Definition at line 1270 of file app_voicemail.c.

References AST_APP_ARG, ast_close_fds_above_n(), AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_safe_fork(), ast_strdupa, errno, and LOG_WARNING.

Referenced by check_password().

01271 {
01272    int fds[2], pid = 0;
01273 
01274    memset(buf, 0, len);
01275 
01276    if (pipe(fds)) {
01277       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01278    } else {
01279       /* good to go*/
01280       pid = ast_safe_fork(0);
01281 
01282       if (pid < 0) {
01283          /* ok maybe not */
01284          close(fds[0]);
01285          close(fds[1]);
01286          snprintf(buf, len, "FAILURE: Fork failed");
01287       } else if (pid) {
01288          /* parent */
01289          close(fds[1]);
01290          if (read(fds[0], buf, len) < 0) {
01291             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01292          }
01293          close(fds[0]);
01294       } else {
01295          /*  child */
01296          AST_DECLARE_APP_ARGS(arg,
01297             AST_APP_ARG(v)[20];
01298          );
01299          char *mycmd = ast_strdupa(command);
01300 
01301          close(fds[0]);
01302          dup2(fds[1], STDOUT_FILENO);
01303          close(fds[1]);
01304          ast_close_fds_above_n(STDOUT_FILENO);
01305 
01306          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01307 
01308          execv(arg.v[0], arg.v); 
01309          printf("FAILURE: %s", strerror(errno));
01310          _exit(0);
01311       }
01312    }
01313    return buf;
01314 }

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

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

04280 {
04281    char *txt;
04282    int txtsize = 0;
04283 
04284    txtsize = (strlen(file) + 5)*sizeof(char);
04285    txt = alloca(txtsize);
04286    /* Sprintf here would safe because we alloca'd exactly the right length,
04287     * but trying to eliminate all sprintf's anyhow
04288     */
04289    if (ast_check_realtime("voicemail_data")) {
04290       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04291    }
04292    snprintf(txt, txtsize, "%s.txt", file);
04293    unlink(txt);
04294    return ast_filedelete(file, NULL);
04295 }

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

Definition at line 10718 of file app_voicemail.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), ast_copy_flags, AST_DECLARE_APP_ARGS, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, ast_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, leave_vm_options::exitcontext, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), leave_vm_options::record_gain, and vm_app_options.

Referenced by load_module(), and play_record_review().

10719 {
10720    int res = 0;
10721    char *tmp;
10722    struct leave_vm_options leave_options;
10723    struct ast_flags flags = { 0 };
10724    char *opts[OPT_ARG_ARRAY_SIZE];
10725    AST_DECLARE_APP_ARGS(args,
10726       AST_APP_ARG(argv0);
10727       AST_APP_ARG(argv1);
10728    );
10729    
10730    memset(&leave_options, 0, sizeof(leave_options));
10731 
10732    if (chan->_state != AST_STATE_UP)
10733       ast_answer(chan);
10734 
10735    if (!ast_strlen_zero(data)) {
10736       tmp = ast_strdupa(data);
10737       AST_STANDARD_APP_ARGS(args, tmp);
10738       if (args.argc == 2) {
10739          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10740             return -1;
10741          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10742          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10743             int gain;
10744 
10745             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10746                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10747                return -1;
10748             } else {
10749                leave_options.record_gain = (signed char) gain;
10750             }
10751          }
10752          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10753             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10754                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10755          }
10756       }
10757    } else {
10758       char temp[256];
10759       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10760       if (res < 0)
10761          return res;
10762       if (ast_strlen_zero(temp))
10763          return 0;
10764       args.argv0 = ast_strdupa(temp);
10765    }
10766 
10767    res = leave_voicemail(chan, args.argv0, &leave_options);
10768    if (res == 't') {
10769       ast_play_and_wait(chan, "vm-goodbye");
10770       res = 0;
10771    }
10772 
10773    if (res == OPERATOR_EXIT) {
10774       res = 0;
10775    }
10776 
10777    if (res == ERROR_LOCK_PATH) {
10778       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10779       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10780       res = 0;
10781    }
10782 
10783    return res;
10784 }

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

Definition at line 9967 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(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_channel_language(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_LOG_WARNING, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_assert, ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, vm_state::context, ast_channel::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), vm_state::fn, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, has_voicemail(), vm_state::heard, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, OLD_FOLDER, vm_state::oldmessages, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), vm_state::repeats, run_externnotify(), save_to_folder(), say_and_wait(), vm_state::starting, vm_state::urgentmessages, vm_state::username, vm_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().

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

static int vm_forwardoptions ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  curdir,
int  curmsg,
char *  vm_fmts,
char *  context,
signed char  record_gain,
long *  duration,
struct vm_state vms,
char *  flag 
) [static]

presents the option to prepend to an existing message when forwarding it.

Parameters:
chan 
vmu 
curdir 
curmsg 
vm_fmts 
context 
record_gain 
duration 
vms 
flag 
Presents a prompt for 1 to prepend the current message, 2 to forward the message without prepending, or * to return to the main menu.

This is invoked from forward_message() when performing a forward operation (option 8 from main menu).

Returns:
zero on success, -1 on error.

Definition at line 6943 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_stream_and_wait(), ast_test_suite_event_notify, ast_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, play_record_review(), vm_pls_try_again, and vm_prepend_timeout.

Referenced by forward_message().

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

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

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

Referenced by vm_execmain().

09286 {
09287    if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
09288       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09289    } else {             /* Default to ENGLISH */
09290       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09291    }
09292 }

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

09185 {
09186    int res = 0;
09187    /* Play instructions and wait for new command */
09188    while (!res) {
09189       if (vms->starting) {
09190          if (vms->lastmsg > -1) {
09191             if (skipadvanced)
09192                res = ast_play_and_wait(chan, "vm-onefor-full");
09193             else
09194                res = ast_play_and_wait(chan, "vm-onefor");
09195             if (!res)
09196                res = vm_play_folder_name(chan, vms->vmbox);
09197          }
09198          if (!res) {
09199             if (skipadvanced)
09200                res = ast_play_and_wait(chan, "vm-opts-full");
09201             else
09202                res = ast_play_and_wait(chan, "vm-opts");
09203          }
09204       } else {
09205          /* Added for additional help */
09206          if (skipadvanced) {
09207             res = ast_play_and_wait(chan, "vm-onefor-full");
09208             if (!res)
09209                res = vm_play_folder_name(chan, vms->vmbox);
09210             res = ast_play_and_wait(chan, "vm-opts-full");
09211          }
09212          /* Logic:
09213           * If the current message is not the first OR
09214           * if we're listening to the first new message and there are
09215           * also urgent messages, then prompt for navigation to the
09216           * previous message
09217           */
09218          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09219             res = ast_play_and_wait(chan, "vm-prev");
09220          }
09221          if (!res && !skipadvanced)
09222             res = ast_play_and_wait(chan, "vm-advopts");
09223          if (!res)
09224             res = ast_play_and_wait(chan, "vm-repeat");
09225          /* Logic:
09226           * If we're not listening to the last message OR
09227           * we're listening to the last urgent message and there are
09228           * also new non-urgent messages, then prompt for navigation
09229           * to the next message
09230           */
09231          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09232             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09233             res = ast_play_and_wait(chan, "vm-next");
09234          }
09235          if (!res) {
09236             if (!vms->deleted[vms->curmsg])
09237                res = ast_play_and_wait(chan, "vm-delete");
09238             else
09239                res = ast_play_and_wait(chan, "vm-undelete");
09240             if (!res)
09241                res = ast_play_and_wait(chan, "vm-toforward");
09242             if (!res)
09243                res = ast_play_and_wait(chan, "vm-savemessage");
09244          }
09245       }
09246       if (!res) {
09247          res = ast_play_and_wait(chan, "vm-helpexit");
09248       }
09249       if (!res)
09250          res = ast_waitfordigit(chan, 6000);
09251       if (!res) {
09252          vms->repeats++;
09253          if (vms->repeats > 2) {
09254             res = 't';
09255          }
09256       }
09257    }
09258    return res;
09259 }

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

09262 {
09263    int res = 0;
09264    /* Play instructions and wait for new command */
09265    while (!res) {
09266       if (vms->lastmsg > -1) {
09267          res = ast_play_and_wait(chan, "vm-listen");
09268          if (!res)
09269             res = vm_play_folder_name(chan, vms->vmbox);
09270          if (!res)
09271             res = ast_play_and_wait(chan, "press");
09272          if (!res)
09273             res = ast_play_and_wait(chan, "digits/1");
09274       }
09275       if (!res)
09276          res = ast_play_and_wait(chan, "vm-opts");
09277       if (!res) {
09278          vms->starting = 0;
09279          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09280       }
09281    }
09282    return res;
09283 }

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

Definition at line 9122 of file app_voicemail.c.

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

Referenced by vm_execmain().

09123 {
09124    char prefile[256];
09125    
09126    /* Notify the user that the temp greeting is set and give them the option to remove it */
09127    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09128    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09129       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09130       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09131          ast_play_and_wait(chan, "vm-tempgreetactive");
09132       }
09133       DISPOSE(prefile, -1);
09134    }
09135 
09136    /* Play voicemail intro - syntax is different for different languages */
09137    if (0) {
09138       return 0;
09139    } else if (!strncasecmp(ast_channel_language(chan), "cs", 2)) {  /* CZECH syntax */
09140       return vm_intro_cs(chan, vms);
09141    } else if (!strncasecmp(ast_channel_language(chan), "cz", 2)) {  /* deprecated CZECH syntax */
09142       static int deprecation_warning = 0;
09143       if (deprecation_warning++ % 10 == 0) {
09144          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09145       }
09146       return vm_intro_cs(chan, vms);
09147    } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) {  /* GERMAN syntax */
09148       return vm_intro_de(chan, vms);
09149    } else if (!strncasecmp(ast_channel_language(chan), "es", 2)) {  /* SPANISH syntax */
09150       return vm_intro_es(chan, vms);
09151    } else if (!strncasecmp(ast_channel_language(chan), "fr", 2)) {  /* FRENCH syntax */
09152       return vm_intro_fr(chan, vms);
09153    } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {  /* GREEK syntax */
09154       return vm_intro_gr(chan, vms);
09155    } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) {  /* HEBREW syntax */
09156       return vm_intro_he(chan, vms);
09157    } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) {  /* ITALIAN syntax */
09158       return vm_intro_it(chan, vms);
09159    } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) {  /* DUTCH syntax */
09160       return vm_intro_nl(chan, vms);
09161    } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) {  /* NORWEGIAN syntax */
09162       return vm_intro_no(chan, vms);
09163    } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {  /* POLISH syntax */
09164       return vm_intro_pl(chan, vms);
09165    } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09166       return vm_intro_pt_BR(chan, vms);
09167    } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) {  /* PORTUGUESE syntax */
09168       return vm_intro_pt(chan, vms);
09169    } else if (!strncasecmp(ast_channel_language(chan), "ru", 2)) {  /* RUSSIAN syntax */
09170       return vm_intro_multilang(chan, vms, "n");
09171    } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) {  /* SWEDISH syntax */
09172       return vm_intro_se(chan, vms);
09173    } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) {  /* UKRAINIAN syntax */
09174       return vm_intro_multilang(chan, vms, "n");
09175    } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
09176       return vm_intro_vi(chan, vms);
09177    } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
09178       return vm_intro_zh(chan, vms);
09179    } else {                                             /* Default to ENGLISH */
09180       return vm_intro_en(chan, vms);
09181    }
09182 }

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

Definition at line 8992 of file app_voicemail.c.

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

Referenced by vm_intro().

08993 {
08994    int res;
08995    res = ast_play_and_wait(chan, "vm-youhave");
08996    if (!res) {
08997       if (vms->newmessages) {
08998          if (vms->newmessages == 1) {
08999             res = ast_play_and_wait(chan, "digits/jednu");
09000          } else {
09001             res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
09002          }
09003          if (!res) {
09004             if ((vms->newmessages == 1))
09005                res = ast_play_and_wait(chan, "vm-novou");
09006             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
09007                res = ast_play_and_wait(chan, "vm-nove");
09008             if (vms->newmessages > 4)
09009                res = ast_play_and_wait(chan, "vm-novych");
09010          }
09011          if (vms->oldmessages && !res)
09012             res = ast_play_and_wait(chan, "vm-and");
09013          else if (!res) {
09014             if ((vms->newmessages == 1))
09015                res = ast_play_and_wait(chan, "vm-zpravu");
09016             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
09017                res = ast_play_and_wait(chan, "vm-zpravy");
09018             if (vms->newmessages > 4)
09019                res = ast_play_and_wait(chan, "vm-zprav");
09020          }
09021       }
09022       if (!res && vms->oldmessages) {
09023          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
09024          if (!res) {
09025             if ((vms->oldmessages == 1))
09026                res = ast_play_and_wait(chan, "vm-starou");
09027             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
09028                res = ast_play_and_wait(chan, "vm-stare");
09029             if (vms->oldmessages > 4)
09030                res = ast_play_and_wait(chan, "vm-starych");
09031          }
09032          if (!res) {
09033             if ((vms->oldmessages == 1))
09034                res = ast_play_and_wait(chan, "vm-zpravu");
09035             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
09036                res = ast_play_and_wait(chan, "vm-zpravy");
09037             if (vms->oldmessages > 4)
09038                res = ast_play_and_wait(chan, "vm-zprav");
09039          }
09040       }
09041       if (!res) {
09042          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
09043             res = ast_play_and_wait(chan, "vm-no");
09044             if (!res)
09045                res = ast_play_and_wait(chan, "vm-zpravy");
09046          }
09047       }
09048    }
09049    return res;
09050 }

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

Definition at line 8688 of file app_voicemail.c.

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

Referenced by vm_intro().

08689 {
08690    /* Introduce messages they have */
08691    int res;
08692    res = ast_play_and_wait(chan, "vm-youhave");
08693    if (!res) {
08694       if (vms->newmessages) {
08695          if ((vms->newmessages == 1))
08696             res = ast_play_and_wait(chan, "digits/1F");
08697          else
08698             res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08699          if (!res)
08700             res = ast_play_and_wait(chan, "vm-INBOX");
08701          if (vms->oldmessages && !res)
08702             res = ast_play_and_wait(chan, "vm-and");
08703          else if (!res) {
08704             if ((vms->newmessages == 1))
08705                res = ast_play_and_wait(chan, "vm-message");
08706             else
08707                res = ast_play_and_wait(chan, "vm-messages");
08708          }
08709             
08710       }
08711       if (!res && vms->oldmessages) {
08712          if (vms->oldmessages == 1)
08713             res = ast_play_and_wait(chan, "digits/1F");
08714          else
08715             res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08716          if (!res)
08717             res = ast_play_and_wait(chan, "vm-Old");
08718          if (!res) {
08719             if (vms->oldmessages == 1)
08720                res = ast_play_and_wait(chan, "vm-message");
08721             else
08722                res = ast_play_and_wait(chan, "vm-messages");
08723          }
08724       }
08725       if (!res) {
08726          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08727             res = ast_play_and_wait(chan, "vm-no");
08728             if (!res)
08729                res = ast_play_and_wait(chan, "vm-messages");
08730          }
08731       }
08732    }
08733    return res;
08734 }

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

Definition at line 8437 of file app_voicemail.c.

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

Referenced by vm_intro().

08438 {
08439    int res;
08440 
08441    /* Introduce messages they have */
08442    res = ast_play_and_wait(chan, "vm-youhave");
08443    if (!res) {
08444       if (vms->urgentmessages) {
08445          res = say_and_wait(chan, vms->urgentmessages, ast_channel_language(chan));
08446          if (!res)
08447             res = ast_play_and_wait(chan, "vm-Urgent");
08448          if ((vms->oldmessages || vms->newmessages) && !res) {
08449             res = ast_play_and_wait(chan, "vm-and");
08450          } else if (!res) {
08451             if ((vms->urgentmessages == 1))
08452                res = ast_play_and_wait(chan, "vm-message");
08453             else
08454                res = ast_play_and_wait(chan, "vm-messages");
08455          }
08456       }
08457       if (vms->newmessages) {
08458          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08459          if (!res)
08460             res = ast_play_and_wait(chan, "vm-INBOX");
08461          if (vms->oldmessages && !res)
08462             res = ast_play_and_wait(chan, "vm-and");
08463          else if (!res) {
08464             if ((vms->newmessages == 1))
08465                res = ast_play_and_wait(chan, "vm-message");
08466             else
08467                res = ast_play_and_wait(chan, "vm-messages");
08468          }
08469             
08470       }
08471       if (!res && vms->oldmessages) {
08472          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08473          if (!res)
08474             res = ast_play_and_wait(chan, "vm-Old");
08475          if (!res) {
08476             if (vms->oldmessages == 1)
08477                res = ast_play_and_wait(chan, "vm-message");
08478             else
08479                res = ast_play_and_wait(chan, "vm-messages");
08480          }
08481       }
08482       if (!res) {
08483          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08484             res = ast_play_and_wait(chan, "vm-no");
08485             if (!res)
08486                res = ast_play_and_wait(chan, "vm-messages");
08487          }
08488       }
08489    }
08490    return res;
08491 }

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

Definition at line 8737 of file app_voicemail.c.

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

Referenced by vm_intro().

08738 {
08739    /* Introduce messages they have */
08740    int res;
08741    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08742       res = ast_play_and_wait(chan, "vm-youhaveno");
08743       if (!res)
08744          res = ast_play_and_wait(chan, "vm-messages");
08745    } else {
08746       res = ast_play_and_wait(chan, "vm-youhave");
08747    }
08748    if (!res) {
08749       if (vms->newmessages) {
08750          if (!res) {
08751             if ((vms->newmessages == 1)) {
08752                res = ast_play_and_wait(chan, "digits/1M");
08753                if (!res)
08754                   res = ast_play_and_wait(chan, "vm-message");
08755                if (!res)
08756                   res = ast_play_and_wait(chan, "vm-INBOXs");
08757             } else {
08758                res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08759                if (!res)
08760                   res = ast_play_and_wait(chan, "vm-messages");
08761                if (!res)
08762                   res = ast_play_and_wait(chan, "vm-INBOX");
08763             }
08764          }
08765          if (vms->oldmessages && !res)
08766             res = ast_play_and_wait(chan, "vm-and");
08767       }
08768       if (vms->oldmessages) {
08769          if (!res) {
08770             if (vms->oldmessages == 1) {
08771                res = ast_play_and_wait(chan, "digits/1M");
08772                if (!res)
08773                   res = ast_play_and_wait(chan, "vm-message");
08774                if (!res)
08775                   res = ast_play_and_wait(chan, "vm-Olds");
08776             } else {
08777                res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08778                if (!res)
08779                   res = ast_play_and_wait(chan, "vm-messages");
08780                if (!res)
08781                   res = ast_play_and_wait(chan, "vm-Old");
08782             }
08783          }
08784       }
08785    }
08786 return res;
08787 }

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

Definition at line 8835 of file app_voicemail.c.

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

Referenced by vm_intro().

08836 {
08837    /* Introduce messages they have */
08838    int res;
08839    res = ast_play_and_wait(chan, "vm-youhave");
08840    if (!res) {
08841       if (vms->newmessages) {
08842          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08843          if (!res)
08844             res = ast_play_and_wait(chan, "vm-INBOX");
08845          if (vms->oldmessages && !res)
08846             res = ast_play_and_wait(chan, "vm-and");
08847          else if (!res) {
08848             if ((vms->newmessages == 1))
08849                res = ast_play_and_wait(chan, "vm-message");
08850             else
08851                res = ast_play_and_wait(chan, "vm-messages");
08852          }
08853             
08854       }
08855       if (!res && vms->oldmessages) {
08856          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08857          if (!res)
08858             res = ast_play_and_wait(chan, "vm-Old");
08859          if (!res) {
08860             if (vms->oldmessages == 1)
08861                res = ast_play_and_wait(chan, "vm-message");
08862             else
08863                res = ast_play_and_wait(chan, "vm-messages");
08864          }
08865       }
08866       if (!res) {
08867          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08868             res = ast_play_and_wait(chan, "vm-no");
08869             if (!res)
08870                res = ast_play_and_wait(chan, "vm-messages");
08871          }
08872       }
08873    }
08874    return res;
08875 }

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

Definition at line 8236 of file app_voicemail.c.

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

Referenced by vm_intro().

08237 {
08238    int res = 0;
08239 
08240    if (vms->newmessages) {
08241       res = ast_play_and_wait(chan, "vm-youhave");
08242       if (!res) 
08243          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
08244       if (!res) {
08245          if ((vms->newmessages == 1)) {
08246             res = ast_play_and_wait(chan, "vm-INBOX");
08247             if (!res)
08248                res = ast_play_and_wait(chan, "vm-message");
08249          } else {
08250             res = ast_play_and_wait(chan, "vm-INBOXs");
08251             if (!res)
08252                res = ast_play_and_wait(chan, "vm-messages");
08253          }
08254       }
08255    } else if (vms->oldmessages){
08256       res = ast_play_and_wait(chan, "vm-youhave");
08257       if (!res)
08258          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
08259       if ((vms->oldmessages == 1)){
08260          res = ast_play_and_wait(chan, "vm-Old");
08261          if (!res)
08262             res = ast_play_and_wait(chan, "vm-message");
08263       } else {
08264          res = ast_play_and_wait(chan, "vm-Olds");
08265          if (!res)
08266             res = ast_play_and_wait(chan, "vm-messages");
08267       }
08268    } else if (!vms->oldmessages && !vms->newmessages) 
08269       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08270    return res;
08271 }

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

Definition at line 8370 of file app_voicemail.c.

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

Referenced by vm_intro().

08371 {
08372    int res = 0;
08373 
08374    /* Introduce messages they have */
08375    if (!res) {
08376       if ((vms->newmessages) || (vms->oldmessages)) {
08377          res = ast_play_and_wait(chan, "vm-youhave");
08378       }
08379       /*
08380        * The word "shtei" refers to the number 2 in hebrew when performing a count
08381        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08382        * an element, this is one of them.
08383        */
08384       if (vms->newmessages) {
08385          if (!res) {
08386             if (vms->newmessages == 1) {
08387                res = ast_play_and_wait(chan, "vm-INBOX1");
08388             } else {
08389                if (vms->newmessages == 2) {
08390                   res = ast_play_and_wait(chan, "vm-shtei");
08391                } else {
08392                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
08393                }
08394                res = ast_play_and_wait(chan, "vm-INBOX");
08395             }
08396          }
08397          if (vms->oldmessages && !res) {
08398             res = ast_play_and_wait(chan, "vm-and");
08399             if (vms->oldmessages == 1) {
08400                res = ast_play_and_wait(chan, "vm-Old1");
08401             } else {
08402                if (vms->oldmessages == 2) {
08403                   res = ast_play_and_wait(chan, "vm-shtei");
08404                } else {
08405                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
08406                }
08407                res = ast_play_and_wait(chan, "vm-Old");
08408             }
08409          }
08410       }
08411       if (!res && vms->oldmessages && !vms->newmessages) {
08412          if (!res) {
08413             if (vms->oldmessages == 1) {
08414                res = ast_play_and_wait(chan, "vm-Old1");
08415             } else {
08416                if (vms->oldmessages == 2) {
08417                   res = ast_play_and_wait(chan, "vm-shtei");
08418                } else {
08419                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");            
08420                }
08421                res = ast_play_and_wait(chan, "vm-Old");
08422             }
08423          }
08424       }
08425       if (!res) {
08426          if (!vms->oldmessages && !vms->newmessages) {
08427             if (!res) {
08428                res = ast_play_and_wait(chan, "vm-nomessages");
08429             }
08430          }
08431       }
08432    }
08433    return res;
08434 }

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

Definition at line 8494 of file app_voicemail.c.

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

Referenced by vm_intro().

08495 {
08496    /* Introduce messages they have */
08497    int res;
08498    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08499       res = ast_play_and_wait(chan, "vm-no") ||
08500          ast_play_and_wait(chan, "vm-message");
08501    else
08502       res = ast_play_and_wait(chan, "vm-youhave");
08503    if (!res && vms->newmessages) {
08504       res = (vms->newmessages == 1) ?
08505          ast_play_and_wait(chan, "digits/un") ||
08506          ast_play_and_wait(chan, "vm-nuovo") ||
08507          ast_play_and_wait(chan, "vm-message") :
08508          /* 2 or more new messages */
08509          say_and_wait(chan, vms->newmessages, ast_channel_language(chan)) ||
08510          ast_play_and_wait(chan, "vm-nuovi") ||
08511          ast_play_and_wait(chan, "vm-messages");
08512       if (!res && vms->oldmessages)
08513          res = ast_play_and_wait(chan, "vm-and");
08514    }
08515    if (!res && vms->oldmessages) {
08516       res = (vms->oldmessages == 1) ?
08517          ast_play_and_wait(chan, "digits/un") ||
08518          ast_play_and_wait(chan, "vm-vecchio") ||
08519          ast_play_and_wait(chan, "vm-message") :
08520          /* 2 or more old messages */
08521          say_and_wait(chan, vms->oldmessages, ast_channel_language(chan)) ||
08522          ast_play_and_wait(chan, "vm-vecchi") ||
08523          ast_play_and_wait(chan, "vm-messages");
08524    }
08525    return res;
08526 }

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

Definition at line 8330 of file app_voicemail.c.

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

Referenced by vm_intro().

08331 {
08332    int res;
08333    int lastnum = 0;
08334 
08335    res = ast_play_and_wait(chan, "vm-youhave");
08336 
08337    if (!res && vms->newmessages) {
08338       lastnum = vms->newmessages;
08339 
08340       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
08341          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08342       }
08343 
08344       if (!res && vms->oldmessages) {
08345          res = ast_play_and_wait(chan, "vm-and");
08346       }
08347    }
08348 
08349    if (!res && vms->oldmessages) {
08350       lastnum = vms->oldmessages;
08351 
08352       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
08353          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08354       }
08355    }
08356 
08357    if (!res) {
08358       if (lastnum == 0) {
08359          res = ast_play_and_wait(chan, "vm-no");
08360       }
08361       if (!res) {
08362          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08363       }
08364    }
08365 
08366    return res;
08367 }

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

Definition at line 8878 of file app_voicemail.c.

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

Referenced by vm_intro().

08879 {
08880    /* Introduce messages they have */
08881    int res;
08882    res = ast_play_and_wait(chan, "vm-youhave");
08883    if (!res) {
08884       if (vms->newmessages) {
08885          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08886          if (!res) {
08887             if (vms->newmessages == 1)
08888                res = ast_play_and_wait(chan, "vm-INBOXs");
08889             else
08890                res = ast_play_and_wait(chan, "vm-INBOX");
08891          }
08892          if (vms->oldmessages && !res)
08893             res = ast_play_and_wait(chan, "vm-and");
08894          else if (!res) {
08895             if ((vms->newmessages == 1))
08896                res = ast_play_and_wait(chan, "vm-message");
08897             else
08898                res = ast_play_and_wait(chan, "vm-messages");
08899          }
08900             
08901       }
08902       if (!res && vms->oldmessages) {
08903          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08904          if (!res) {
08905             if (vms->oldmessages == 1)
08906                res = ast_play_and_wait(chan, "vm-Olds");
08907             else
08908                res = ast_play_and_wait(chan, "vm-Old");
08909          }
08910          if (!res) {
08911             if (vms->oldmessages == 1)
08912                res = ast_play_and_wait(chan, "vm-message");
08913             else
08914                res = ast_play_and_wait(chan, "vm-messages");
08915          }
08916       }
08917       if (!res) {
08918          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08919             res = ast_play_and_wait(chan, "vm-no");
08920             if (!res)
08921                res = ast_play_and_wait(chan, "vm-messages");
08922          }
08923       }
08924    }
08925    return res;
08926 }

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

Definition at line 8644 of file app_voicemail.c.

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

Referenced by vm_intro().

08645 {
08646    /* Introduce messages they have */
08647    int res;
08648 
08649    res = ast_play_and_wait(chan, "vm-youhave");
08650    if (res)
08651       return res;
08652 
08653    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08654       res = ast_play_and_wait(chan, "vm-no");
08655       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08656       return res;
08657    }
08658 
08659    if (vms->newmessages) {
08660       if ((vms->newmessages == 1)) {
08661          res = ast_play_and_wait(chan, "digits/1");
08662          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08663          res = res ? res : ast_play_and_wait(chan, "vm-message");
08664       } else {
08665          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08666          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08667          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08668       }
08669       if (!res && vms->oldmessages)
08670          res = ast_play_and_wait(chan, "vm-and");
08671    }
08672    if (!res && vms->oldmessages) {
08673       if (vms->oldmessages == 1) {
08674          res = ast_play_and_wait(chan, "digits/1");
08675          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08676          res = res ? res : ast_play_and_wait(chan, "vm-message");
08677       } else {
08678          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08679          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08680          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08681       }
08682    }
08683 
08684    return res;
08685 }

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

Definition at line 8529 of file app_voicemail.c.

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

Referenced by vm_intro().

08530 {
08531    /* Introduce messages they have */
08532    int res;
08533    div_t num;
08534 
08535    if (!vms->oldmessages && !vms->newmessages) {
08536       res = ast_play_and_wait(chan, "vm-no");
08537       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08538       return res;
08539    } else {
08540       res = ast_play_and_wait(chan, "vm-youhave");
08541    }
08542 
08543    if (vms->newmessages) {
08544       num = div(vms->newmessages, 10);
08545       if (vms->newmessages == 1) {
08546          res = ast_play_and_wait(chan, "digits/1-a");
08547          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08548          res = res ? res : ast_play_and_wait(chan, "vm-message");
08549       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08550          if (num.rem == 2) {
08551             if (!num.quot) {
08552                res = ast_play_and_wait(chan, "digits/2-ie");
08553             } else {
08554                res = say_and_wait(chan, vms->newmessages - 2 , ast_channel_language(chan));
08555                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08556             }
08557          } else {
08558             res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08559          }
08560          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08561          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08562       } else {
08563          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08564          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08565          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08566       }
08567       if (!res && vms->oldmessages)
08568          res = ast_play_and_wait(chan, "vm-and");
08569    }
08570    if (!res && vms->oldmessages) {
08571       num = div(vms->oldmessages, 10);
08572       if (vms->oldmessages == 1) {
08573          res = ast_play_and_wait(chan, "digits/1-a");
08574          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08575          res = res ? res : ast_play_and_wait(chan, "vm-message");
08576       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08577          if (num.rem == 2) {
08578             if (!num.quot) {
08579                res = ast_play_and_wait(chan, "digits/2-ie");
08580             } else {
08581                res = say_and_wait(chan, vms->oldmessages - 2 , ast_channel_language(chan));
08582                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08583             }
08584          } else {
08585             res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08586          }
08587          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08588          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08589       } else {
08590          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08591          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08592          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08593       }
08594    }
08595 
08596    return res;
08597 }

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

Definition at line 8929 of file app_voicemail.c.

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

Referenced by vm_intro().

08930 {
08931    /* Introduce messages they have */
08932    int res;
08933    res = ast_play_and_wait(chan, "vm-youhave");
08934    if (!res) {
08935       if (vms->newmessages) {
08936          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
08937          if (!res) {
08938             if ((vms->newmessages == 1)) {
08939                res = ast_play_and_wait(chan, "vm-message");
08940                if (!res)
08941                   res = ast_play_and_wait(chan, "vm-INBOXs");
08942             } else {
08943                res = ast_play_and_wait(chan, "vm-messages");
08944                if (!res)
08945                   res = ast_play_and_wait(chan, "vm-INBOX");
08946             }
08947          }
08948          if (vms->oldmessages && !res)
08949             res = ast_play_and_wait(chan, "vm-and");
08950       }
08951       if (!res && vms->oldmessages) {
08952          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
08953          if (!res) {
08954             if (vms->oldmessages == 1) {
08955                res = ast_play_and_wait(chan, "vm-message");
08956                if (!res)
08957                   res = ast_play_and_wait(chan, "vm-Olds");
08958             } else {
08959                res = ast_play_and_wait(chan, "vm-messages");
08960                if (!res)
08961                   res = ast_play_and_wait(chan, "vm-Old");
08962             }
08963          }
08964       }
08965       if (!res) {
08966          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08967             res = ast_play_and_wait(chan, "vm-no");
08968             if (!res)
08969                res = ast_play_and_wait(chan, "vm-messages");
08970          }
08971       }
08972    }
08973    return res;
08974 }

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

Definition at line 8790 of file app_voicemail.c.

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

Referenced by vm_intro().

08790                                                                           {
08791    /* Introduce messages they have */
08792    int res;
08793    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08794       res = ast_play_and_wait(chan, "vm-nomessages");
08795       return res;
08796    } else {
08797       res = ast_play_and_wait(chan, "vm-youhave");
08798    }
08799    if (vms->newmessages) {
08800       if (!res)
08801          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
08802       if ((vms->newmessages == 1)) {
08803          if (!res)
08804             res = ast_play_and_wait(chan, "vm-message");
08805          if (!res)
08806             res = ast_play_and_wait(chan, "vm-INBOXs");
08807       } else {
08808          if (!res)
08809             res = ast_play_and_wait(chan, "vm-messages");
08810          if (!res)
08811             res = ast_play_and_wait(chan, "vm-INBOX");
08812       }
08813       if (vms->oldmessages && !res)
08814          res = ast_play_and_wait(chan, "vm-and");
08815    }
08816    if (vms->oldmessages) {
08817       if (!res)
08818          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
08819       if (vms->oldmessages == 1) {
08820          if (!res)
08821             res = ast_play_and_wait(chan, "vm-message");
08822          if (!res)
08823             res = ast_play_and_wait(chan, "vm-Olds");
08824       } else {
08825          if (!res)
08826             res = ast_play_and_wait(chan, "vm-messages");
08827          if (!res)
08828             res = ast_play_and_wait(chan, "vm-Old");
08829       }
08830    }
08831    return res;
08832 }

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

Definition at line 8600 of file app_voicemail.c.

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

Referenced by vm_intro().

08601 {
08602    /* Introduce messages they have */
08603    int res;
08604 
08605    res = ast_play_and_wait(chan, "vm-youhave");
08606    if (res)
08607       return res;
08608 
08609    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08610       res = ast_play_and_wait(chan, "vm-no");
08611       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08612       return res;
08613    }
08614 
08615    if (vms->newmessages) {
08616       if ((vms->newmessages == 1)) {
08617          res = ast_play_and_wait(chan, "digits/ett");
08618          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08619          res = res ? res : ast_play_and_wait(chan, "vm-message");
08620       } else {
08621          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
08622          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08623          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08624       }
08625       if (!res && vms->oldmessages)
08626          res = ast_play_and_wait(chan, "vm-and");
08627    }
08628    if (!res && vms->oldmessages) {
08629       if (vms->oldmessages == 1) {
08630          res = ast_play_and_wait(chan, "digits/ett");
08631          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08632          res = res ? res : ast_play_and_wait(chan, "vm-message");
08633       } else {
08634          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
08635          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08636          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08637       }
08638    }
08639 
08640    return res;
08641 }

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

Definition at line 9092 of file app_voicemail.c.

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

Referenced by vm_intro().

09093 {
09094    int res;
09095 
09096    /* Introduce messages they have */
09097    res = ast_play_and_wait(chan, "vm-youhave");
09098    if (!res) {
09099       if (vms->newmessages) {
09100          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
09101          if (!res)
09102             res = ast_play_and_wait(chan, "vm-INBOX");
09103          if (vms->oldmessages && !res)
09104             res = ast_play_and_wait(chan, "vm-and");
09105       }
09106       if (!res && vms->oldmessages) {
09107          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
09108          if (!res)
09109             res = ast_play_and_wait(chan, "vm-Old");        
09110       }
09111       if (!res) {
09112          if (!vms->oldmessages && !vms->newmessages) {
09113             res = ast_play_and_wait(chan, "vm-no");
09114             if (!res)
09115                res = ast_play_and_wait(chan, "vm-message");
09116          }
09117       }
09118    }
09119    return res;
09120 }

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

Definition at line 9053 of file app_voicemail.c.

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

Referenced by vm_intro().

09054 {
09055    int res;
09056    /* Introduce messages they have */
09057    res = ast_play_and_wait(chan, "vm-you");
09058 
09059    if (!res && vms->newmessages) {
09060       res = ast_play_and_wait(chan, "vm-have");
09061       if (!res)
09062          res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
09063       if (!res)
09064          res = ast_play_and_wait(chan, "vm-tong");
09065       if (!res)
09066          res = ast_play_and_wait(chan, "vm-INBOX");
09067       if (vms->oldmessages && !res)
09068          res = ast_play_and_wait(chan, "vm-and");
09069       else if (!res) 
09070          res = ast_play_and_wait(chan, "vm-messages");
09071    }
09072    if (!res && vms->oldmessages) {
09073       res = ast_play_and_wait(chan, "vm-have");
09074       if (!res)
09075          res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
09076       if (!res)
09077          res = ast_play_and_wait(chan, "vm-tong");
09078       if (!res)
09079          res = ast_play_and_wait(chan, "vm-Old");
09080       if (!res)
09081          res = ast_play_and_wait(chan, "vm-messages");
09082    }
09083    if (!res && !vms->oldmessages && !vms->newmessages) {
09084       res = ast_play_and_wait(chan, "vm-haveno");
09085       if (!res)
09086          res = ast_play_and_wait(chan, "vm-messages");
09087    }
09088    return res;
09089 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03357 {
03358    switch (ast_lock_path(path)) {
03359    case AST_LOCK_TIMEOUT:
03360       return -1;
03361    default:
03362       return 0;
03363    }
03364 }

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

Definition at line 1757 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01758 {
01759    FILE *p = NULL;
01760    int pfd = mkstemp(template);
01761    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01762    if (pfd > -1) {
01763       p = fdopen(pfd, "w+");
01764       if (!p) {
01765          close(pfd);
01766          pfd = -1;
01767       }
01768    }
01769    return p;
01770 }

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

Referenced by vm_execmain().

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

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

Referenced by vm_execmain().

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

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

Definition at line 8199 of file app_voicemail.c.

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

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

08200 {
08201    int cmd;
08202 
08203    if (  !strncasecmp(ast_channel_language(chan), "it", 2) ||
08204         !strncasecmp(ast_channel_language(chan), "es", 2) ||
08205         !strncasecmp(ast_channel_language(chan), "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08206       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08207       return cmd ? cmd : ast_play_and_wait(chan, box);
08208    } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {
08209       return vm_play_folder_name_gr(chan, box);
08210    } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) {  /* Hebrew syntax */
08211       return ast_play_and_wait(chan, box);
08212    } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
08213       return vm_play_folder_name_pl(chan, box);
08214    } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) {  /* Ukrainian syntax */
08215       return vm_play_folder_name_ua(chan, box);
08216    } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
08217       return ast_play_and_wait(chan, box);
08218    } else {  /* Default English */
08219       cmd = ast_play_and_wait(chan, box);
08220       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08221    }
08222 }

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

Definition at line 8152 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08153 {
08154    int cmd;
08155    char *buf;
08156 
08157    buf = alloca(strlen(box) + 2);
08158    strcpy(buf, box);
08159    strcat(buf, "s");
08160 
08161    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08162       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08163       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08164    } else {
08165       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08166       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08167    }
08168 }

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

Definition at line 8170 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08171 {
08172    int cmd;
08173 
08174    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08175       if (!strcasecmp(box, "vm-INBOX"))
08176          cmd = ast_play_and_wait(chan, "vm-new-e");
08177       else
08178          cmd = ast_play_and_wait(chan, "vm-old-e");
08179       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08180    } else {
08181       cmd = ast_play_and_wait(chan, "vm-messages");
08182       return cmd ? cmd : ast_play_and_wait(chan, box);
08183    }
08184 }

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

Definition at line 8186 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

08187 {
08188    int cmd;
08189 
08190    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08191       cmd = ast_play_and_wait(chan, "vm-messages");
08192       return cmd ? cmd : ast_play_and_wait(chan, box);
08193    } else {
08194       cmd = ast_play_and_wait(chan, box);
08195       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08196    }
08197 }

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

Referenced by vm_options().

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

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

Definition at line 11581 of file app_voicemail.c.

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

11583 {
11584    struct ast_vm_user *user;
11585 
11586    AST_LIST_LOCK(&users);
11587    AST_LIST_TRAVERSE(&users, user, list) {
11588       vm_users_data_provider_get_helper(search, data_root, user);
11589    }
11590    AST_LIST_UNLOCK(&users);
11591 
11592    return 0;
11593 }

static int vm_users_data_provider_get_helper ( const struct ast_data_search search,
struct ast_data data_root,
struct ast_vm_user user 
) [static]

Definition at line 11534 of file app_voicemail.c.

References ast_data_add_int(), ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::context, inboxcount2(), ast_vm_user::mailbox, vm_zone::name, and ast_vm_user::zonetag.

Referenced by vm_users_data_provider_get().

11536 {
11537    struct ast_data *data_user, *data_zone;
11538    struct ast_data *data_state;
11539    struct vm_zone *zone = NULL;
11540    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11541    char ext_context[256] = "";
11542 
11543    data_user = ast_data_add_node(data_root, "user");
11544    if (!data_user) {
11545       return -1;
11546    }
11547 
11548    ast_data_add_structure(ast_vm_user, data_user, user);
11549 
11550    AST_LIST_LOCK(&zones);
11551    AST_LIST_TRAVERSE(&zones, zone, list) {
11552       if (!strcmp(zone->name, user->zonetag)) {
11553          break;
11554       }
11555    }
11556    AST_LIST_UNLOCK(&zones);
11557 
11558    /* state */
11559    data_state = ast_data_add_node(data_user, "state");
11560    if (!data_state) {
11561       return -1;
11562    }
11563    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11564    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11565    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11566    ast_data_add_int(data_state, "newmsg", newmsg);
11567    ast_data_add_int(data_state, "oldmsg", oldmsg);
11568 
11569    if (zone) {
11570       data_zone = ast_data_add_node(data_user, "zone");
11571       ast_data_add_structure(vm_zone, data_zone, zone);
11572    }
11573 
11574    if (!ast_data_search_match(search, data_user)) {
11575       ast_data_remove_node(data_root, data_user);
11576    }
11577 
11578    return 0;
11579 }

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

Definition at line 11220 of file app_voicemail.c.

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

Referenced by load_module().

11221 {
11222    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11223    struct ast_vm_user vmus;
11224    char *options = NULL;
11225    int silent = 0, skipuser = 0;
11226    int res = -1;
11227    
11228    if (data) {
11229       s = ast_strdupa(data);
11230       user = strsep(&s, ",");
11231       options = strsep(&s, ",");
11232       if (user) {
11233          s = user;
11234          user = strsep(&s, "@");
11235          context = strsep(&s, "");
11236          if (!ast_strlen_zero(user))
11237             skipuser++;
11238          ast_copy_string(mailbox, user, sizeof(mailbox));
11239       }
11240    }
11241 
11242    if (options) {
11243       silent = (strchr(options, 's')) != NULL;
11244    }
11245 
11246    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11247       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11248       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11249       ast_play_and_wait(chan, "auth-thankyou");
11250       res = 0;
11251    } else if (mailbox[0] == '*') {
11252       /* user entered '*' */
11253       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11254          res = 0; /* prevent hangup */
11255       }
11256    }
11257 
11258    return res;
11259 }

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

Definition at line 12745 of file app_voicemail.c.

References ast_channel_language(), ast_debug, AST_DIGIT_ANY, ast_log(), ast_say_character_str(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), LOG_WARNING, and sayname().

Referenced by load_module().

12746 {
12747    char *context;
12748    char *args_copy;
12749    int res;
12750 
12751    if (ast_strlen_zero(data)) {
12752       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12753       return -1;
12754    }
12755 
12756    args_copy = ast_strdupa(data);
12757    if ((context = strchr(args_copy, '@'))) {
12758       *context++ = '\0';
12759    } else {
12760       context = "default";
12761    }
12762 
12763    if ((res = sayname(chan, args_copy, context)) < 0) {
12764       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12765       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12766       if (!res) {
12767          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, ast_channel_language(chan));
12768       }
12769    }
12770 
12771    return res;
12772 }

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

fill in *tm for current time according to the proper timezone, if any.

Returns:
tm so it can be used as a function argument.

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

04510 {
04511    const struct vm_zone *z = NULL;
04512    struct timeval t = ast_tvnow();
04513 
04514    /* Does this user have a timezone specified? */
04515    if (!ast_strlen_zero(vmu->zonetag)) {
04516       /* Find the zone in the list */
04517       AST_LIST_LOCK(&zones);
04518       AST_LIST_TRAVERSE(&zones, z, list) {
04519          if (!strcmp(z->name, vmu->zonetag))
04520             break;
04521       }
04522       AST_LIST_UNLOCK(&zones);
04523    }
04524    ast_localtime(&t, tm, z ? z->timezone : NULL);
04525    return tm;
04526 }

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

07540 {
07541    int res;
07542    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07543       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07544    return res;
07545 }

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

Definition at line 12719 of file app_voicemail.c.

References ast_category_append(), ast_category_new(), ast_config_new(), ast_config_text_file_save(), ast_log(), ast_variable_append(), ast_variable_new(), and LOG_ERROR.

Referenced by vm_change_password().

12719                                                                               {
12720    struct ast_config *conf;
12721    struct ast_category *cat;
12722    struct ast_variable *var;
12723 
12724    if (!(conf=ast_config_new())) {
12725       ast_log(LOG_ERROR, "Error creating new config structure\n");
12726       return -1;
12727    }
12728    if (!(cat=ast_category_new("general","",1))) {
12729       ast_log(LOG_ERROR, "Error creating new category structure\n");
12730       return -1;
12731    }
12732    if (!(var=ast_variable_new("password",password,""))) {
12733       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12734       return -1;
12735    }
12736    ast_category_append(conf,cat);
12737    ast_variable_append(cat,var);
12738    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12739       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12740       return -1;
12741    }
12742    return 0;
12743 }


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", } [static]

Definition at line 13910 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 844 of file app_voicemail.c.

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

Definition at line 971 of file app_voicemail.c.

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

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

Definition at line 972 of file app_voicemail.c.

Referenced by actual_load_config(), and adsi_load_vmail().

int adsiver = 1 [static]

Definition at line 973 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 847 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 850 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 852 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 853 of file app_voicemail.c.

Definition at line 13910 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 957 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

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

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 960 of file app_voicemail.c.

Referenced by actual_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 11457 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 956 of file app_voicemail.c.

Referenced by actual_load_config(), directory_exec(), and populate_defaults().

char* emailbody = NULL [static]

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

Definition at line 974 of file app_voicemail.c.

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

char* emailsubject = NULL [static]

Definition at line 964 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 958 of file app_voicemail.c.

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

char ext_pass_check_cmd[128] [static]

Definition at line 824 of file app_voicemail.c.

char ext_pass_cmd[128] [static]

Definition at line 823 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 867 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 967 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

struct ast_flags globalflags = {0} [static]

Definition at line 952 of file app_voicemail.c.

Definition at line 995 of file app_voicemail.c.

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

char listen_control_forward_key[12] [static]

Definition at line 922 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 927 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 928 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 926 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 929 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

char locale[20] [static]

Definition at line 860 of file app_voicemail.c.

Initial value:

 {
   .name = "MAILBOX_EXISTS",
   .read = acf_mailbox_exists,
}

Definition at line 11210 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

const char* const mailbox_folders[] [static]

Definition at line 1793 of file app_voicemail.c.

Referenced by get_folder_by_name(), and mbox().

char mailcmd[160] [static]

Definition at line 866 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 863 of file app_voicemail.c.

int maxgreet [static]

Definition at line 873 of file app_voicemail.c.

int maxlogins [static]

Definition at line 875 of file app_voicemail.c.

int maxmsg [static]

Definition at line 862 of file app_voicemail.c.

int maxsilence [static]

Definition at line 861 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 876 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 894 of file app_voicemail.c.

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

int my_umask [static]

Definition at line 826 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 965 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

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

Definition at line 975 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 968 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 966 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

int passwordlocation [static]

Definition at line 877 of file app_voicemail.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 889 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 884 of file app_voicemail.c.

ast_mutex_t poll_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 890 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 891 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 830 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 954 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

char* sayname_app = "VMSayName" [static]

Definition at line 855 of file app_voicemail.c.

char serveremail[80] [static]

Definition at line 865 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 864 of file app_voicemail.c.

Referenced by ast_record_review(), and setup_privacy_args().

int skipms [static]

Definition at line 874 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 868 of file app_voicemail.c.

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

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

Referenced by vm_exec(), and vm_execmain().

struct ast_data_entry vm_data_providers[] [static]

Initial value:

 {

}

Definition at line 11600 of file app_voicemail.c.

Referenced by load_module().

Initial value:

 {
   .name = "VM_INFO",
   .read = acf_vm_info,
}

Definition at line 11215 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

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

Definition at line 937 of file app_voicemail.c.

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

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

Definition at line 936 of file app_voicemail.c.

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

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

Definition at line 933 of file app_voicemail.c.

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

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

Definition at line 934 of file app_voicemail.c.

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

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

Definition at line 932 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_authenticate().

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

Definition at line 938 of file app_voicemail.c.

Referenced by actual_load_config(), vm_forwardoptions(), vm_newuser(), and vm_options().

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

Definition at line 950 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_forwardoptions().

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

Definition at line 935 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 821 of file app_voicemail.c.

Initial value:

Definition at line 11595 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 869 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 872 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 871 of file app_voicemail.c.

double volgain [static]

Definition at line 870 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 859 of file app_voicemail.c.

Referenced by build_peer().


Generated on Sat Feb 11 06:34:07 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6