Wed Apr 6 11:29:51 2011

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"

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 int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int add_email_attachment (FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
static void adsi_begin (struct ast_channel *chan, int *useadsi)
static void adsi_delete (struct ast_channel *chan, struct vm_state *vms)
static void adsi_folders (struct ast_channel *chan, int start, char *label)
static void adsi_goodbye (struct ast_channel *chan)
static int adsi_load_vmail (struct ast_channel *chan, int *useadsi)
static void adsi_login (struct ast_channel *chan)
static int adsi_logo (unsigned char *buf)
static void adsi_message (struct ast_channel *chan, struct vm_state *vms)
static void adsi_password (struct ast_channel *chan)
static void adsi_status (struct ast_channel *chan, struct vm_state *vms)
static void adsi_status2 (struct ast_channel *chan, struct vm_state *vms)
static int advanced_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
 The advanced options within a message.
static int append_mailbox (const char *context, const char *box, const char *data)
static void apply_option (struct ast_vm_user *vmu, const char *var, const char *value)
 Sets a a specific property value.
static void apply_options (struct ast_vm_user *vmu, const char *options)
 Destructively Parse options and apply.
static void apply_options_full (struct ast_vm_user *retval, struct ast_variable *var)
 Loads the options specific to a voicemail user.
 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)
static int play_message_category (struct ast_channel *chan, const char *category)
static int play_message_datetime (struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static int play_message_duration (struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static void poll_subscribed_mailbox (struct mwi_sub *mwi_sub)
static void poll_subscribed_mailboxes (void)
static void populate_defaults (struct ast_vm_user *vmu)
 Sets default voicemail system options to a voicemail user.
static void prep_email_sub_vars (struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, 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 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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}
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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char * 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 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_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, read doc/imapstorage.txt

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

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

Definition in file app_voicemail.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 421 of file app_voicemail.c.

#define BASELINELEN   72

Definition at line 444 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 445 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 418 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 414 of file app_voicemail.c.

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

Definition at line 728 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS ( USER   ) 

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

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 426 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 428 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 429 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 427 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 430 of file app_voicemail.c.

Referenced by load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 798 of file app_voicemail.c.

Referenced by load_config().

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

Definition at line 729 of file app_voicemail.c.

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

#define DISPOSE ( a,
 ) 

Definition at line 724 of file app_voicemail.c.

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

#define ENDL   "\n"

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

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

Definition at line 726 of file app_voicemail.c.

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

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

Referenced by handle_voicemail_show_users().

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

Referenced by handle_voicemail_show_zones().

#define INTRO   "vm-intro"

Definition at line 437 of file app_voicemail.c.

Referenced by play_record_review(), and vm_forwardoptions().

#define MAX_DATETIME_FORMAT   512

Definition at line 452 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 453 of file app_voicemail.c.

#define MAXMSG   100

Definition at line 439 of file app_voicemail.c.

Referenced by apply_option(), and load_config().

#define MAXMSGLIMIT   9999

Definition at line 440 of file app_voicemail.c.

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

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 442 of file app_voicemail.c.

Referenced by load_config().

#define OPERATOR_EXIT   300

Definition at line 475 of file app_voicemail.c.

Referenced by vm_exec(), and vm_execmain().

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 741 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 740 of file app_voicemail.c.

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

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

Definition at line 727 of file app_voicemail.c.

Referenced by close_mailbox(), and save_to_folder().

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 723 of file app_voicemail.c.

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

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

Definition at line 435 of file app_voicemail.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 412 of file app_voicemail.c.

Referenced by run_externnotify().

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

Definition at line 725 of file app_voicemail.c.

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

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 750 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 431 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 468 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)

Attach message to voicemail notifications?

Definition at line 466 of file app_voicemail.c.

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

#define VM_DELETE   (1 << 12)

Delete message after sending notification

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

Referenced by forward_message(), and load_config().

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 459 of file app_voicemail.c.

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

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 463 of file app_voicemail.c.

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

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 462 of file app_voicemail.c.

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

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 473 of file app_voicemail.c.

Referenced by forward_message(), and load_config().

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 472 of file app_voicemail.c.

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

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 471 of file app_voicemail.c.

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

#define VM_OPERATOR   (1 << 1)

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

Definition at line 456 of file app_voicemail.c.

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

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 464 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

#define VM_REVIEW   (1 << 0)

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

Definition at line 455 of file app_voicemail.c.

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

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 457 of file app_voicemail.c.

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

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 460 of file app_voicemail.c.

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

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 469 of file app_voicemail.c.

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

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 461 of file app_voicemail.c.

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

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 458 of file app_voicemail.c.

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

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 470 of file app_voicemail.c.

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

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 665 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 420 of file app_voicemail.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 416 of file app_voicemail.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 417 of file app_voicemail.c.

Referenced by add_email_attachment(), copy(), 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 478 of file app_voicemail.c.

00478             {
00479    NEW_FOLDER,
00480    OLD_FOLDER,
00481    WORK_FOLDER,
00482    FAMILY_FOLDER,
00483    FRIENDS_FOLDER,
00484    GREETINGS_FOLDER
00485 };

enum vm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 499 of file app_voicemail.c.

00499                     {
00500    OPT_ARG_RECORDGAIN = 0,
00501    OPT_ARG_PLAYFOLDER = 1,
00502    OPT_ARG_DTMFEXIT   = 2,
00503    /* This *must* be the last value in this enum! */
00504    OPT_ARG_ARRAY_SIZE = 3,
00505 };

enum vm_option_flags

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

00487                      {
00488    OPT_SILENT =           (1 << 0),
00489    OPT_BUSY_GREETING =    (1 << 1),
00490    OPT_UNAVAIL_GREETING = (1 << 2),
00491    OPT_RECORDGAIN =       (1 << 3),
00492    OPT_PREPEND_MAILBOX =  (1 << 4),
00493    OPT_AUTOPLAY =         (1 << 6),
00494    OPT_DTMFEXIT =         (1 << 7),
00495    OPT_MESSAGE_Urgent =   (1 << 8),
00496    OPT_MESSAGE_PRIORITY = (1 << 9)
00497 };

enum vm_passwordlocation

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 507 of file app_voicemail.c.

00507                          {
00508    OPT_PWLOC_VOICEMAILCONF = 0,
00509    OPT_PWLOC_SPOOLDIR      = 1,
00510    OPT_PWLOC_USERSCONF     = 2,
00511 };


Function Documentation

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

Definition at line 5254 of file app_voicemail.c.

References ast_strlen_zero().

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

05255 {
05256    DIR *dir;
05257    struct dirent *de;
05258    char fn[256];
05259    int ret = 0;
05260 
05261    /* If no mailbox, return immediately */
05262    if (ast_strlen_zero(mailbox))
05263       return 0;
05264 
05265    if (ast_strlen_zero(folder))
05266       folder = "INBOX";
05267    if (ast_strlen_zero(context))
05268       context = "default";
05269 
05270    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05271 
05272    if (!(dir = opendir(fn)))
05273       return 0;
05274 
05275    while ((de = readdir(dir))) {
05276       if (!strncasecmp(de->d_name, "msg", 3)) {
05277          if (shortcircuit) {
05278             ret = 1;
05279             break;
05280          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05281             ret++;
05282          }
05283       }
05284    }
05285 
05286    closedir(dir);
05287 
05288    return ret;
05289 }

static void __reg_module ( void   )  [static]

Definition at line 13214 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

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

10719 {
10720    struct ast_vm_user svm;
10721    AST_DECLARE_APP_ARGS(arg,
10722       AST_APP_ARG(mbox);
10723       AST_APP_ARG(context);
10724    );
10725 
10726    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
10727 
10728    if (ast_strlen_zero(arg.mbox)) {
10729       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
10730       return -1;
10731    }
10732 
10733    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
10734    return 0;
10735 }

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

04673 {
04674    char tmpdir[256], newtmp[256];
04675    char fname[256];
04676    char tmpcmd[256];
04677    int tmpfd = -1;
04678 
04679    /* Eww. We want formats to tell us their own MIME type */
04680    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04681 
04682    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04683       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04684       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04685       tmpfd = mkstemp(newtmp);
04686       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04687       ast_debug(3, "newtmp: %s\n", newtmp);
04688       if (tmpfd > -1) {
04689          int soxstatus;
04690          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04691          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04692             attach = newtmp;
04693             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04694          } else {
04695             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04696                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04697             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04698          }
04699       }
04700    }
04701    fprintf(p, "--%s" ENDL, bound);
04702    if (msgnum > -1)
04703       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04704    else
04705       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04706    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04707    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04708    if (msgnum > -1)
04709       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04710    else
04711       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04712    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04713    base_encode(fname, p);
04714    if (last)
04715       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04716    if (tmpfd > -1) {
04717       unlink(fname);
04718       close(tmpfd);
04719       unlink(newtmp);
04720    }
04721    return 0;
04722 }

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

Definition at line 6240 of file app_voicemail.c.

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

Referenced by vm_authenticate(), and vm_execmain().

06241 {
06242    int x;
06243    if (!ast_adsi_available(chan))
06244       return;
06245    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06246    if (x < 0)
06247       return;
06248    if (!x) {
06249       if (adsi_load_vmail(chan, useadsi)) {
06250          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06251          return;
06252       }
06253    } else
06254       *useadsi = 1;
06255 }

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

Definition at line 6429 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available(), and vm_state::curmsg.

Referenced by vm_execmain().

06430 {
06431    int bytes = 0;
06432    unsigned char buf[256];
06433    unsigned char keys[8];
06434 
06435    int x;
06436 
06437    if (!ast_adsi_available(chan))
06438       return;
06439 
06440    /* New meaning for keys */
06441    for (x = 0; x < 5; x++)
06442       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06443 
06444    keys[6] = 0x0;
06445    keys[7] = 0x0;
06446 
06447    if (!vms->curmsg) {
06448       /* No prev key, provide "Folder" instead */
06449       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06450    }
06451    if (vms->curmsg >= vms->lastmsg) {
06452       /* If last message ... */
06453       if (vms->curmsg) {
06454          /* but not only message, provide "Folder" instead */
06455          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06456       } else {
06457          /* Otherwise if only message, leave blank */
06458          keys[3] = 1;
06459       }
06460    }
06461 
06462    /* If deleted, show "undeleted" */
06463    if (vms->deleted[vms->curmsg]) 
06464       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06465 
06466    /* Except "Exit" */
06467    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06468    bytes += ast_adsi_set_keys(buf + bytes, keys);
06469    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06470 
06471    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06472 }

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

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

06306 {
06307    unsigned char buf[256];
06308    int bytes = 0;
06309    unsigned char keys[8];
06310    int x, y;
06311 
06312    if (!ast_adsi_available(chan))
06313       return;
06314 
06315    for (x = 0; x < 5; x++) {
06316       y = ADSI_KEY_APPS + 12 + start + x;
06317       if (y > ADSI_KEY_APPS + 12 + 4)
06318          y = 0;
06319       keys[x] = ADSI_KEY_SKT | y;
06320    }
06321    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06322    keys[6] = 0;
06323    keys[7] = 0;
06324 
06325    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06326    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06327    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06328    bytes += ast_adsi_set_keys(buf + bytes, keys);
06329    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06330 
06331    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06332 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06578 {
06579    unsigned char buf[256];
06580    int bytes = 0;
06581 
06582    if (!ast_adsi_available(chan))
06583       return;
06584    bytes += adsi_logo(buf + bytes);
06585    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06586    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06587    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06588    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06589 
06590    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06591 }

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

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

06112 {
06113    unsigned char buf[256];
06114    int bytes = 0;
06115    int x;
06116    char num[5];
06117 
06118    *useadsi = 0;
06119    bytes += ast_adsi_data_mode(buf + bytes);
06120    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06121 
06122    bytes = 0;
06123    bytes += adsi_logo(buf);
06124    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06125 #ifdef DISPLAY
06126    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06127 #endif
06128    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06129    bytes += ast_adsi_data_mode(buf + bytes);
06130    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06131 
06132    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06133       bytes = 0;
06134       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06135       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06136       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06137       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06138       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06139       return 0;
06140    }
06141 
06142 #ifdef DISPLAY
06143    /* Add a dot */
06144    bytes = 0;
06145    bytes += ast_adsi_logo(buf);
06146    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06147    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06148    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06149    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06150 #endif
06151    bytes = 0;
06152    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06153    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06154    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06155    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06156    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06157    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06158    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06159 
06160 #ifdef DISPLAY
06161    /* Add another dot */
06162    bytes = 0;
06163    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06164    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06165 
06166    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06167    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06168 #endif
06169 
06170    bytes = 0;
06171    /* These buttons we load but don't use yet */
06172    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06173    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06174    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06175    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06176    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06177    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06178    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06179 
06180 #ifdef DISPLAY
06181    /* Add another dot */
06182    bytes = 0;
06183    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06184    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06185    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06186 #endif
06187 
06188    bytes = 0;
06189    for (x = 0; x < 5; x++) {
06190       snprintf(num, sizeof(num), "%d", x);
06191       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06192    }
06193    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06194    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06195 
06196 #ifdef DISPLAY
06197    /* Add another dot */
06198    bytes = 0;
06199    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06200    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06201    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06202 #endif
06203 
06204    if (ast_adsi_end_download(chan)) {
06205       bytes = 0;
06206       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06207       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06208       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06209       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06210       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06211       return 0;
06212    }
06213    bytes = 0;
06214    bytes += ast_adsi_download_disconnect(buf + bytes);
06215    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06216    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06217 
06218    ast_debug(1, "Done downloading scripts...\n");
06219 
06220 #ifdef DISPLAY
06221    /* Add last dot */
06222    bytes = 0;
06223    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06224    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06225 #endif
06226    ast_debug(1, "Restarting session...\n");
06227 
06228    bytes = 0;
06229    /* Load the session now */
06230    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06231       *useadsi = 1;
06232       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06233    } else
06234       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06235 
06236    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06237    return 0;
06238 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06258 {
06259    unsigned char buf[256];
06260    int bytes = 0;
06261    unsigned char keys[8];
06262    int x;
06263    if (!ast_adsi_available(chan))
06264       return;
06265 
06266    for (x = 0; x < 8; x++)
06267       keys[x] = 0;
06268    /* Set one key for next */
06269    keys[3] = ADSI_KEY_APPS + 3;
06270 
06271    bytes += adsi_logo(buf + bytes);
06272    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06273    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06274    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06275    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06276    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06277    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06278    bytes += ast_adsi_set_keys(buf + bytes, keys);
06279    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06280    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06281 }

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

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

06104 {
06105    int bytes = 0;
06106    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06107    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06108    return bytes;
06109 }

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

Definition at line 6334 of file app_voicemail.c.

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

Referenced by play_message(), and vm_execmain().

06335 {
06336    int bytes = 0;
06337    unsigned char buf[256]; 
06338    char buf1[256], buf2[256];
06339    char fn2[PATH_MAX];
06340 
06341    char cid[256] = "";
06342    char *val;
06343    char *name, *num;
06344    char datetime[21] = "";
06345    FILE *f;
06346 
06347    unsigned char keys[8];
06348 
06349    int x;
06350 
06351    if (!ast_adsi_available(chan))
06352       return;
06353 
06354    /* Retrieve important info */
06355    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06356    f = fopen(fn2, "r");
06357    if (f) {
06358       while (!feof(f)) {   
06359          if (!fgets((char *) buf, sizeof(buf), f)) {
06360             continue;
06361          }
06362          if (!feof(f)) {
06363             char *stringp = NULL;
06364             stringp = (char *) buf;
06365             strsep(&stringp, "=");
06366             val = strsep(&stringp, "=");
06367             if (!ast_strlen_zero(val)) {
06368                if (!strcmp((char *) buf, "callerid"))
06369                   ast_copy_string(cid, val, sizeof(cid));
06370                if (!strcmp((char *) buf, "origdate"))
06371                   ast_copy_string(datetime, val, sizeof(datetime));
06372             }
06373          }
06374       }
06375       fclose(f);
06376    }
06377    /* New meaning for keys */
06378    for (x = 0; x < 5; x++)
06379       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06380    keys[6] = 0x0;
06381    keys[7] = 0x0;
06382 
06383    if (!vms->curmsg) {
06384       /* No prev key, provide "Folder" instead */
06385       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06386    }
06387    if (vms->curmsg >= vms->lastmsg) {
06388       /* If last message ... */
06389       if (vms->curmsg) {
06390          /* but not only message, provide "Folder" instead */
06391          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06392          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06393 
06394       } else {
06395          /* Otherwise if only message, leave blank */
06396          keys[3] = 1;
06397       }
06398    }
06399 
06400    if (!ast_strlen_zero(cid)) {
06401       ast_callerid_parse(cid, &name, &num);
06402       if (!name)
06403          name = num;
06404    } else
06405       name = "Unknown Caller";
06406 
06407    /* If deleted, show "undeleted" */
06408 
06409    if (vms->deleted[vms->curmsg])
06410       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06411 
06412    /* Except "Exit" */
06413    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06414    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06415       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06416    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06417 
06418    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06419    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06420    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06421    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06422    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06423    bytes += ast_adsi_set_keys(buf + bytes, keys);
06424    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06425 
06426    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06427 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06284 {
06285    unsigned char buf[256];
06286    int bytes = 0;
06287    unsigned char keys[8];
06288    int x;
06289    if (!ast_adsi_available(chan))
06290       return;
06291 
06292    for (x = 0; x < 8; x++)
06293       keys[x] = 0;
06294    /* Set one key for next */
06295    keys[3] = ADSI_KEY_APPS + 3;
06296 
06297    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06298    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06299    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06300    bytes += ast_adsi_set_keys(buf + bytes, keys);
06301    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06302    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06303 }

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

Definition at line 6474 of file app_voicemail.c.

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

Referenced by vm_execmain().

06475 {
06476    unsigned char buf[256] = "";
06477    char buf1[256] = "", buf2[256] = "";
06478    int bytes = 0;
06479    unsigned char keys[8];
06480    int x;
06481 
06482    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06483    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06484    if (!ast_adsi_available(chan))
06485       return;
06486    if (vms->newmessages) {
06487       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06488       if (vms->oldmessages) {
06489          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06490          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06491       } else {
06492          snprintf(buf2, sizeof(buf2), "%s.", newm);
06493       }
06494    } else if (vms->oldmessages) {
06495       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06496       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06497    } else {
06498       strcpy(buf1, "You have no messages.");
06499       buf2[0] = ' ';
06500       buf2[1] = '\0';
06501    }
06502    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06503    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06504    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06505 
06506    for (x = 0; x < 6; x++)
06507       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06508    keys[6] = 0;
06509    keys[7] = 0;
06510 
06511    /* Don't let them listen if there are none */
06512    if (vms->lastmsg < 0)
06513       keys[0] = 1;
06514    bytes += ast_adsi_set_keys(buf + bytes, keys);
06515 
06516    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06517 
06518    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06519 }

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

Definition at line 6521 of file app_voicemail.c.

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

Referenced by vm_execmain().

06522 {
06523    unsigned char buf[256] = "";
06524    char buf1[256] = "", buf2[256] = "";
06525    int bytes = 0;
06526    unsigned char keys[8];
06527    int x;
06528 
06529    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06530 
06531    if (!ast_adsi_available(chan))
06532       return;
06533 
06534    /* Original command keys */
06535    for (x = 0; x < 6; x++)
06536       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06537 
06538    keys[6] = 0;
06539    keys[7] = 0;
06540 
06541    if ((vms->lastmsg + 1) < 1)
06542       keys[0] = 0;
06543 
06544    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06545       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06546 
06547    if (vms->lastmsg + 1)
06548       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06549    else
06550       strcpy(buf2, "no messages.");
06551    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06552    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06553    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06554    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06555    bytes += ast_adsi_set_keys(buf + bytes, keys);
06556 
06557    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06558 
06559    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06560    
06561 }

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

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

Referenced by vm_execmain().

12781 {
12782    int res = 0;
12783    char filename[PATH_MAX];
12784    struct ast_config *msg_cfg = NULL;
12785    const char *origtime, *context;
12786    char *name, *num;
12787    int retries = 0;
12788    char *cid;
12789    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
12790 
12791    vms->starting = 0; 
12792 
12793    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12794 
12795    /* Retrieve info from VM attribute file */
12796    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
12797    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
12798    msg_cfg = ast_config_load(filename, config_flags);
12799    DISPOSE(vms->curdir, vms->curmsg);
12800    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
12801       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
12802       return 0;
12803    }
12804 
12805    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
12806       ast_config_destroy(msg_cfg);
12807       return 0;
12808    }
12809 
12810    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
12811 
12812    context = ast_variable_retrieve(msg_cfg, "message", "context");
12813    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
12814       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
12815    switch (option) {
12816    case 3: /* Play message envelope */
12817       if (!res)
12818          res = play_message_datetime(chan, vmu, origtime, filename);
12819       if (!res)
12820          res = play_message_callerid(chan, vms, cid, context, 0);
12821 
12822       res = 't';
12823       break;
12824 
12825    case 2:  /* Call back */
12826 
12827       if (ast_strlen_zero(cid))
12828          break;
12829 
12830       ast_callerid_parse(cid, &name, &num);
12831       while ((res > -1) && (res != 't')) {
12832          switch (res) {
12833          case '1':
12834             if (num) {
12835                /* Dial the CID number */
12836                res = dialout(chan, vmu, num, vmu->callback);
12837                if (res) {
12838                   ast_config_destroy(msg_cfg);
12839                   return 9;
12840                }
12841             } else {
12842                res = '2';
12843             }
12844             break;
12845 
12846          case '2':
12847             /* Want to enter a different number, can only do this if there's a dialout context for this user */
12848             if (!ast_strlen_zero(vmu->dialout)) {
12849                res = dialout(chan, vmu, NULL, vmu->dialout);
12850                if (res) {
12851                   ast_config_destroy(msg_cfg);
12852                   return 9;
12853                }
12854             } else {
12855                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
12856                res = ast_play_and_wait(chan, "vm-sorry");
12857             }
12858             ast_config_destroy(msg_cfg);
12859             return res;
12860          case '*':
12861             res = 't';
12862             break;
12863          case '3':
12864          case '4':
12865          case '5':
12866          case '6':
12867          case '7':
12868          case '8':
12869          case '9':
12870          case '0':
12871 
12872             res = ast_play_and_wait(chan, "vm-sorry");
12873             retries++;
12874             break;
12875          default:
12876             if (num) {
12877                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
12878                res = ast_play_and_wait(chan, "vm-num-i-have");
12879                if (!res)
12880                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
12881                if (!res)
12882                   res = ast_play_and_wait(chan, "vm-tocallnum");
12883                /* Only prompt for a caller-specified number if there is a dialout context specified */
12884                if (!ast_strlen_zero(vmu->dialout)) {
12885                   if (!res)
12886                      res = ast_play_and_wait(chan, "vm-calldiffnum");
12887                }
12888             } else {
12889                res = ast_play_and_wait(chan, "vm-nonumber");
12890                if (!ast_strlen_zero(vmu->dialout)) {
12891                   if (!res)
12892                      res = ast_play_and_wait(chan, "vm-toenternumber");
12893                }
12894             }
12895             if (!res)
12896                res = ast_play_and_wait(chan, "vm-star-cancel");
12897             if (!res)
12898                res = ast_waitfordigit(chan, 6000);
12899             if (!res) {
12900                retries++;
12901                if (retries > 3)
12902                   res = 't';
12903             }
12904             break; 
12905             
12906          }
12907          if (res == 't')
12908             res = 0;
12909          else if (res == '*')
12910             res = -1;
12911       }
12912       break;
12913       
12914    case 1:  /* Reply */
12915       /* Send reply directly to sender */
12916       if (ast_strlen_zero(cid))
12917          break;
12918 
12919       ast_callerid_parse(cid, &name, &num);
12920       if (!num) {
12921          ast_verb(3, "No CID number available, no reply sent\n");
12922          if (!res)
12923             res = ast_play_and_wait(chan, "vm-nonumber");
12924          ast_config_destroy(msg_cfg);
12925          return res;
12926       } else {
12927          struct ast_vm_user vmu2;
12928          if (find_user(&vmu2, vmu->context, num)) {
12929             struct leave_vm_options leave_options;
12930             char mailbox[AST_MAX_EXTENSION * 2 + 2];
12931             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
12932 
12933             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
12934             
12935             memset(&leave_options, 0, sizeof(leave_options));
12936             leave_options.record_gain = record_gain;
12937             res = leave_voicemail(chan, mailbox, &leave_options);
12938             if (!res)
12939                res = 't';
12940             ast_config_destroy(msg_cfg);
12941             return res;
12942          } else {
12943             /* Sender has no mailbox, can't reply */
12944             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
12945             ast_play_and_wait(chan, "vm-nobox");
12946             res = 't';
12947             ast_config_destroy(msg_cfg);
12948             return res;
12949          }
12950       } 
12951       res = 0;
12952 
12953       break;
12954    }
12955 
12956 #ifndef IMAP_STORAGE
12957    ast_config_destroy(msg_cfg);
12958 
12959    if (!res) {
12960       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12961       vms->heard[msg] = 1;
12962       res = wait_file(chan, vms, vms->fn);
12963    }
12964 #endif
12965    return res;
12966 }

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

Definition at line 10461 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_strdupa, ast_vm_user::context, ast_vm_user::email, find_or_create(), ast_vm_user::fullname, inboxcount2(), 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 load_config().

10462 {
10463    /* Assumes lock is already held */
10464    char *tmp;
10465    char *stringp;
10466    char *s;
10467    struct ast_vm_user *vmu;
10468    char *mailbox_full;
10469    int new = 0, old = 0, urgent = 0;
10470    char secretfn[PATH_MAX] = "";
10471 
10472    tmp = ast_strdupa(data);
10473 
10474    if (!(vmu = find_or_create(context, box)))
10475       return -1;
10476 
10477    populate_defaults(vmu);
10478 
10479    stringp = tmp;
10480    if ((s = strsep(&stringp, ","))) {
10481       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10482    }
10483    if (stringp && (s = strsep(&stringp, ","))) {
10484       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10485    }
10486    if (stringp && (s = strsep(&stringp, ","))) {
10487       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10488    }
10489    if (stringp && (s = strsep(&stringp, ","))) {
10490       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10491    }
10492    if (stringp && (s = strsep(&stringp, ","))) {
10493       apply_options(vmu, s);
10494    }
10495 
10496    switch (vmu->passwordlocation) {
10497    case OPT_PWLOC_SPOOLDIR:
10498       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10499       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10500    }
10501 
10502    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10503    strcpy(mailbox_full, box);
10504    strcat(mailbox_full, "@");
10505    strcat(mailbox_full, context);
10506 
10507    inboxcount2(mailbox_full, &urgent, &new, &old);
10508    queue_mwi_event(mailbox_full, urgent, new, old);
10509 
10510    return 0;
10511 }

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

References apply_options(), ast_copy_string(), ast_log(), AST_LOG_WARNING, ast_set2_flag, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::exit, ast_vm_user::language, ast_vm_user::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, 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().

01027 {
01028    int x;
01029    if (!strcasecmp(var, "attach")) {
01030       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01031    } else if (!strcasecmp(var, "attachfmt")) {
01032       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01033    } else if (!strcasecmp(var, "serveremail")) {
01034       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01035    } else if (!strcasecmp(var, "language")) {
01036       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01037    } else if (!strcasecmp(var, "tz")) {
01038       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01039    } else if (!strcasecmp(var, "locale")) {
01040       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01041 #ifdef IMAP_STORAGE
01042    } else if (!strcasecmp(var, "imapuser")) {
01043       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01044       vmu->imapversion = imapversion;
01045    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01046       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01047       vmu->imapversion = imapversion;
01048    } else if (!strcasecmp(var, "imapfolder")) {
01049       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01050    } else if (!strcasecmp(var, "imapvmshareid")) {
01051       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01052       vmu->imapversion = imapversion;
01053 #endif
01054    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01055       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01056    } else if (!strcasecmp(var, "saycid")){
01057       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01058    } else if (!strcasecmp(var, "sendvoicemail")){
01059       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01060    } else if (!strcasecmp(var, "review")){
01061       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01062    } else if (!strcasecmp(var, "tempgreetwarn")){
01063       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01064    } else if (!strcasecmp(var, "messagewrap")){
01065       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01066    } else if (!strcasecmp(var, "operator")) {
01067       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01068    } else if (!strcasecmp(var, "envelope")){
01069       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01070    } else if (!strcasecmp(var, "moveheard")){
01071       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01072    } else if (!strcasecmp(var, "sayduration")){
01073       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01074    } else if (!strcasecmp(var, "saydurationm")){
01075       if (sscanf(value, "%30d", &x) == 1) {
01076          vmu->saydurationm = x;
01077       } else {
01078          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01079       }
01080    } else if (!strcasecmp(var, "forcename")){
01081       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01082    } else if (!strcasecmp(var, "forcegreetings")){
01083       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01084    } else if (!strcasecmp(var, "callback")) {
01085       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01086    } else if (!strcasecmp(var, "dialout")) {
01087       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01088    } else if (!strcasecmp(var, "exitcontext")) {
01089       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01090    } else if (!strcasecmp(var, "minsecs")) {
01091       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01092          vmu->minsecs = x;
01093       } else {
01094          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01095          vmu->minsecs = vmminsecs;
01096       }
01097    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01098       vmu->maxsecs = atoi(value);
01099       if (vmu->maxsecs <= 0) {
01100          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01101          vmu->maxsecs = vmmaxsecs;
01102       } else {
01103          vmu->maxsecs = atoi(value);
01104       }
01105       if (!strcasecmp(var, "maxmessage"))
01106          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01107    } else if (!strcasecmp(var, "maxmsg")) {
01108       vmu->maxmsg = atoi(value);
01109       /* Accept maxmsg=0 (Greetings only voicemail) */
01110       if (vmu->maxmsg < 0) {
01111          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01112          vmu->maxmsg = MAXMSG;
01113       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01114          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01115          vmu->maxmsg = MAXMSGLIMIT;
01116       }
01117    } else if (!strcasecmp(var, "nextaftercmd")) {
01118       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01119    } else if (!strcasecmp(var, "backupdeleted")) {
01120       if (sscanf(value, "%30d", &x) == 1)
01121          vmu->maxdeletedmsg = x;
01122       else if (ast_true(value))
01123          vmu->maxdeletedmsg = MAXMSG;
01124       else
01125          vmu->maxdeletedmsg = 0;
01126 
01127       if (vmu->maxdeletedmsg < 0) {
01128          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01129          vmu->maxdeletedmsg = MAXMSG;
01130       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01131          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01132          vmu->maxdeletedmsg = MAXMSGLIMIT;
01133       }
01134    } else if (!strcasecmp(var, "volgain")) {
01135       sscanf(value, "%30lf", &vmu->volgain);
01136    } else if (!strcasecmp(var, "passwordlocation")) {
01137       if (!strcasecmp(value, "spooldir")) {
01138          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01139       } else {
01140          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01141       }
01142    } else if (!strcasecmp(var, "options")) {
01143       apply_options(vmu, value);
01144    }
01145 }

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

Destructively Parse options and apply.

Definition at line 1259 of file app_voicemail.c.

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

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

01260 {  
01261    char *stringp;
01262    char *s;
01263    char *var, *value;
01264    stringp = ast_strdupa(options);
01265    while ((s = strsep(&stringp, "|"))) {
01266       value = s;
01267       if ((var = strsep(&value, "=")) && value) {
01268          apply_option(vmu, var, value);
01269       }
01270    }  
01271 }

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

References ast_copy_string(), ast_strlen_zero(), ast_vm_user::password, and var.

Referenced by find_user_realtime(), and load_config().

01279 {
01280    for (; var; var = var->next) {
01281       if (!strcasecmp(var->name, "vmsecret")) {
01282          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01283       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01284          if (ast_strlen_zero(retval->password))
01285             ast_copy_string(retval->password, var->value, sizeof(retval->password));
01286       } else if (!strcasecmp(var->name, "uniqueid")) {
01287          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01288       } else if (!strcasecmp(var->name, "pager")) {
01289          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01290       } else if (!strcasecmp(var->name, "email")) {
01291          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01292       } else if (!strcasecmp(var->name, "fullname")) {
01293          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01294       } else if (!strcasecmp(var->name, "context")) {
01295          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01296       } else if (!strcasecmp(var->name, "emailsubject")) {
01297          retval->emailsubject = ast_strdup(var->value);
01298       } else if (!strcasecmp(var->name, "emailbody")) {
01299          retval->emailbody = ast_strdup(var->value);
01300 #ifdef IMAP_STORAGE
01301       } else if (!strcasecmp(var->name, "imapuser")) {
01302          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01303          retval->imapversion = imapversion;
01304       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01305          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01306          retval->imapversion = imapversion;
01307       } else if (!strcasecmp(var->name, "imapfolder")) {
01308          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01309       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01310          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01311          retval->imapversion = imapversion;
01312 #endif
01313       } else
01314          apply_option(retval, var->name, var->value);
01315    }
01316 }

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

04348 {
04349    struct ast_str *tmp = ast_str_alloca(80);
04350    int first_section = 1;
04351 
04352    ast_str_reset(*end);
04353    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04354    for (; *start; start++) {
04355       int need_encoding = 0;
04356       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04357          need_encoding = 1;
04358       }
04359       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04360          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04361          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04362          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04363          /* Start new line */
04364          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04365          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04366          first_section = 0;
04367       }
04368       if (need_encoding && *start == ' ') {
04369          ast_str_append(&tmp, -1, "_");
04370       } else if (need_encoding) {
04371          ast_str_append(&tmp, -1, "=%hhX", *start);
04372       } else {
04373          ast_str_append(&tmp, -1, "%c", *start);
04374       }
04375    }
04376    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04377    return ast_str_buffer(*end);
04378 }

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

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

04276 {
04277    const char *ptr;
04278 
04279    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04280    ast_str_set(buf, maxlen, "\"");
04281    for (ptr = from; *ptr; ptr++) {
04282       if (*ptr == '"' || *ptr == '\\') {
04283          ast_str_append(buf, maxlen, "\\%c", *ptr);
04284       } else {
04285          ast_str_append(buf, maxlen, "%c", *ptr);
04286       }
04287    }
04288    ast_str_append(buf, maxlen, "\"");
04289 
04290    return ast_str_buffer(*buf);
04291 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10513 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, free_user(), OPT_PWLOC_SPOOLDIR, 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, and VM_TEMPGREETWARN.

10514 {
10515    int res = 0;
10516    struct ast_vm_user *vmu;
10517    /* language parameter seems to only be used for display in manager action */
10518    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10519       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10520       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10521       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10522       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10523       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10524       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir";
10525 #ifdef IMAP_STORAGE
10526    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10527       "imapfolder=INBOX|imapvmshareid=6000";
10528 #endif
10529 
10530    switch (cmd) {
10531    case TEST_INIT:
10532       info->name = "vmuser";
10533       info->category = "/apps/app_voicemail/";
10534       info->summary = "Vmuser unit test";
10535       info->description =
10536          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10537       return AST_TEST_NOT_RUN;
10538    case TEST_EXECUTE:
10539       break;
10540    }
10541 
10542    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10543       return AST_TEST_NOT_RUN;
10544    }
10545    ast_set_flag(vmu, VM_ALLOCED);
10546 
10547    apply_options(vmu, options_string);
10548 
10549    if (!ast_test_flag(vmu, VM_ATTACH)) {
10550       ast_test_status_update(test, "Parse failure for attach option\n");
10551       res = 1;
10552    }
10553    if (strcasecmp(vmu->attachfmt, "wav49")) {
10554       ast_test_status_update(test, "Parse failure for attachftm option\n");
10555       res = 1;
10556    }
10557    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10558       ast_test_status_update(test, "Parse failure for serveremail option\n");
10559       res = 1;
10560    }
10561    if (strcasecmp(vmu->zonetag, "central")) {
10562       ast_test_status_update(test, "Parse failure for tz option\n");
10563       res = 1;
10564    }
10565    if (!ast_test_flag(vmu, VM_DELETE)) {
10566       ast_test_status_update(test, "Parse failure for delete option\n");
10567       res = 1;
10568    }
10569    if (!ast_test_flag(vmu, VM_SAYCID)) {
10570       ast_test_status_update(test, "Parse failure for saycid option\n");
10571       res = 1;
10572    }
10573    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10574       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10575       res = 1;
10576    }
10577    if (!ast_test_flag(vmu, VM_REVIEW)) {
10578       ast_test_status_update(test, "Parse failure for review option\n");
10579       res = 1;
10580    }
10581    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10582       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10583       res = 1;
10584    }
10585    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10586       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10587       res = 1;
10588    }
10589    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10590       ast_test_status_update(test, "Parse failure for operator option\n");
10591       res = 1;
10592    }
10593    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10594       ast_test_status_update(test, "Parse failure for envelope option\n");
10595       res = 1;
10596    }
10597    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10598       ast_test_status_update(test, "Parse failure for moveheard option\n");
10599       res = 1;
10600    }
10601    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10602       ast_test_status_update(test, "Parse failure for sayduration option\n");
10603       res = 1;
10604    }
10605    if (vmu->saydurationm != 5) {
10606       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10607       res = 1;
10608    }
10609    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10610       ast_test_status_update(test, "Parse failure for forcename option\n");
10611       res = 1;
10612    }
10613    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10614       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10615       res = 1;
10616    }
10617    if (strcasecmp(vmu->callback, "somecontext")) {
10618       ast_test_status_update(test, "Parse failure for callbacks option\n");
10619       res = 1;
10620    }
10621    if (strcasecmp(vmu->dialout, "somecontext2")) {
10622       ast_test_status_update(test, "Parse failure for dialout option\n");
10623       res = 1;
10624    }
10625    if (strcasecmp(vmu->exit, "somecontext3")) {
10626       ast_test_status_update(test, "Parse failure for exitcontext option\n");
10627       res = 1;
10628    }
10629    if (vmu->minsecs != 10) {
10630       ast_test_status_update(test, "Parse failure for minsecs option\n");
10631       res = 1;
10632    }
10633    if (vmu->maxsecs != 100) {
10634       ast_test_status_update(test, "Parse failure for maxsecs option\n");
10635       res = 1;
10636    }
10637    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10638       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10639       res = 1;
10640    }
10641    if (vmu->maxdeletedmsg != 50) {
10642       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10643       res = 1;
10644    }
10645    if (vmu->volgain != 1.3) {
10646       ast_test_status_update(test, "Parse failure for volgain option\n");
10647       res = 1;
10648    }
10649    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10650       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10651       res = 1;
10652    }
10653 #ifdef IMAP_STORAGE
10654    apply_options(vmu, option_string2);
10655 
10656    if (strcasecmp(vmu->imapuser, "imapuser")) {
10657       ast_test_status_update(test, "Parse failure for imapuser option\n");
10658       res = 1;
10659    }
10660    if (strcasecmp(vmu->imappassword, "imappasswd")) {
10661       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10662       res = 1;
10663    }
10664    if (strcasecmp(vmu->imapfolder, "INBOX")) {
10665       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10666       res = 1;
10667    }
10668    if (strcasecmp(vmu->imapvmshareid, "6000")) {
10669       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
10670       res = 1;
10671    }
10672 #endif
10673 
10674    free_user(vmu);
10675    return res ? AST_TEST_FAIL : AST_TEST_PASS;
10676 }

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

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

04152 {
04153    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04154       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04155       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04156       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04157    int i, hiteof = 0;
04158    FILE *fi;
04159    struct baseio bio;
04160 
04161    memset(&bio, 0, sizeof(bio));
04162    bio.iocp = BASEMAXINLINE;
04163 
04164    if (!(fi = fopen(filename, "rb"))) {
04165       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04166       return -1;
04167    }
04168 
04169    while (!hiteof){
04170       unsigned char igroup[3], ogroup[4];
04171       int c, n;
04172 
04173       memset(igroup, 0, sizeof(igroup));
04174 
04175       for (n = 0; n < 3; n++) {
04176          if ((c = inchar(&bio, fi)) == EOF) {
04177             hiteof = 1;
04178             break;
04179          }
04180 
04181          igroup[n] = (unsigned char) c;
04182       }
04183 
04184       if (n > 0) {
04185          ogroup[0]= dtable[igroup[0] >> 2];
04186          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04187          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04188          ogroup[3]= dtable[igroup[2] & 0x3F];
04189 
04190          if (n < 3) {
04191             ogroup[3] = '=';
04192 
04193             if (n < 2)
04194                ogroup[2] = '=';
04195          }
04196 
04197          for (i = 0; i < 4; i++)
04198             ochar(&bio, ogroup[i], so);
04199       }
04200    }
04201 
04202    fclose(fi);
04203    
04204    if (fputs(ENDL, so) == EOF) {
04205       return 0;
04206    }
04207 
04208    return 1;
04209 }

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

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

Referenced by vm_change_password().

01239 {
01240    int res = -1;
01241    if (!strcmp(vmu->password, password)) {
01242       /* No change (but an update would return 0 rows updated, so we opt out here) */
01243       return 0;
01244    }
01245 
01246    if (strlen(password) > 10) {
01247       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01248    }
01249    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01250       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01251       res = 0;
01252    }
01253    return res;
01254 }

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

04321 {
04322    for (; *str; str++) {
04323       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04324          return 1;
04325       }
04326    }
04327    return 0;
04328 }

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

References ast_debug, ast_log(), AST_LOG_DEBUG, 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().

01201 {
01202    /* check minimum length */
01203    if (strlen(password) < minpassword)
01204       return 1;
01205    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01206       char cmd[255], buf[255];
01207 
01208       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01209 
01210       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01211       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01212          ast_debug(5, "Result: %s\n", buf);
01213          if (!strncasecmp(buf, "VALID", 5)) {
01214             ast_debug(3, "Passed password check: '%s'\n", buf);
01215             return 0;
01216          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01217             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01218             return 0;
01219          } else {
01220             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01221             return 1;
01222          }
01223       }
01224    }
01225    return 0;
01226 }

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

Definition at line 7739 of file app_voicemail.c.

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

Referenced by vm_execmain().

07740 {
07741    int x = 0;
07742 #ifndef IMAP_STORAGE
07743    int res = 0, nummsg;
07744    char fn2[PATH_MAX];
07745 #endif
07746 
07747    if (vms->lastmsg <= -1) {
07748       goto done;
07749    }
07750 
07751    vms->curmsg = -1;
07752 #ifndef IMAP_STORAGE
07753    /* Get the deleted messages fixed */
07754    if (vm_lock_path(vms->curdir)) {
07755       return ERROR_LOCK_PATH;
07756    }
07757 
07758    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07759    for (x = 0; x < vms->lastmsg + 1; x++) {
07760       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07761          /* Save this message.  It's not in INBOX or hasn't been heard */
07762          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07763          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07764             break;
07765          }
07766          vms->curmsg++;
07767          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07768          if (strcmp(vms->fn, fn2)) {
07769             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07770          }
07771       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07772          /* Move to old folder before deleting */
07773          res = save_to_folder(vmu, vms, x, 1);
07774          if (res == ERROR_LOCK_PATH) {
07775             /* If save failed do not delete the message */
07776             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07777             vms->deleted[x] = 0;
07778             vms->heard[x] = 0;
07779             --x;
07780          }
07781       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07782          /* Move to deleted folder */
07783          res = save_to_folder(vmu, vms, x, 10);
07784          if (res == ERROR_LOCK_PATH) {
07785             /* If save failed do not delete the message */
07786             vms->deleted[x] = 0;
07787             vms->heard[x] = 0;
07788             --x;
07789          }
07790       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07791          /* If realtime storage enabled - we should explicitly delete this message,
07792          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07793          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07794          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07795             DELETE(vms->curdir, x, vms->fn, vmu);
07796          }
07797       }
07798    }
07799 
07800    /* Delete ALL remaining messages */
07801    nummsg = x - 1;
07802    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07803       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07804       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07805          DELETE(vms->curdir, x, vms->fn, vmu);
07806       }
07807    }
07808    ast_unlock_path(vms->curdir);
07809 #else /* defined(IMAP_STORAGE) */
07810    if (vms->deleted) {
07811       /* Since we now expunge after each delete, deleting in reverse order
07812        * ensures that no reordering occurs between each step. */
07813       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
07814          if (vms->deleted[x]) {
07815             ast_debug(3, "IMAP delete of %d\n", x);
07816             DELETE(vms->curdir, x, vms->fn, vmu);
07817          }
07818       }
07819    }
07820 #endif
07821 
07822 done:
07823    if (vms->deleted && vmu->maxmsg) {
07824       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
07825    }
07826    if (vms->heard && vmu->maxmsg) {
07827       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
07828    }
07829 
07830    return 0;
07831 }

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

Definition at line 10822 of file app_voicemail.c.

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

Referenced by handle_voicemail_show_users().

10823 {
10824    int which = 0;
10825    int wordlen;
10826    struct ast_vm_user *vmu;
10827    const char *context = "";
10828 
10829    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
10830    if (pos > 4)
10831       return NULL;
10832    if (pos == 3)
10833       return (state == 0) ? ast_strdup("for") : NULL;
10834    wordlen = strlen(word);
10835    AST_LIST_TRAVERSE(&users, vmu, list) {
10836       if (!strncasecmp(word, vmu->context, wordlen)) {
10837          if (context && strcmp(context, vmu->context) && ++which > state)
10838             return ast_strdup(vmu->context);
10839          /* ignore repeated contexts ? */
10840          context = vmu->context;
10841       }
10842    }
10843    return NULL;
10844 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

Referenced by ast_filehelper(), ast_func_read(), ast_func_read2(), ast_func_write(), handle_cli_transcoder_show(), iax2_register(), and vm_forwardoptions().

03956 {
03957    int ifd;
03958    int ofd;
03959    int res;
03960    int len;
03961    char buf[4096];
03962 
03963 #ifdef HARDLINK_WHEN_POSSIBLE
03964    /* Hard link if possible; saves disk space & is faster */
03965    if (link(infile, outfile)) {
03966 #endif
03967       if ((ifd = open(infile, O_RDONLY)) < 0) {
03968          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03969          return -1;
03970       }
03971       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03972          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03973          close(ifd);
03974          return -1;
03975       }
03976       do {
03977          len = read(ifd, buf, sizeof(buf));
03978          if (len < 0) {
03979             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03980             close(ifd);
03981             close(ofd);
03982             unlink(outfile);
03983          }
03984          if (len) {
03985             res = write(ofd, buf, len);
03986             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03987                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03988                close(ifd);
03989                close(ofd);
03990                unlink(outfile);
03991             }
03992          }
03993       } while (len);
03994       close(ifd);
03995       close(ofd);
03996       return 0;
03997 #ifdef HARDLINK_WHEN_POSSIBLE
03998    } else {
03999       /* Hard link succeeded */
04000       return 0;
04001    }
04002 #endif
04003 }

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

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), ast_channel::caller, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), ast_channel::language, 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().

05192 {
05193    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05194    const char *frombox = mbox(vmu, imbox);
05195    int recipmsgnum;
05196    int res = 0;
05197 
05198    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05199 
05200    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05201       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
05202    } else {
05203       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
05204    }
05205    
05206    if (!dir)
05207       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05208    else
05209       ast_copy_string(fromdir, dir, sizeof(fromdir));
05210 
05211    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05212    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
05213 
05214    if (vm_lock_path(todir))
05215       return ERROR_LOCK_PATH;
05216 
05217    recipmsgnum = last_message_index(recip, todir) + 1;
05218    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05219       make_file(topath, sizeof(topath), todir, recipmsgnum);
05220 #ifndef ODBC_STORAGE
05221       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05222          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05223       } else {
05224 #endif
05225          /* If we are prepending a message for ODBC, then the message already
05226           * exists in the database, but we want to force copying from the
05227           * filesystem (since only the FS contains the prepend). */
05228          copy_plain_file(frompath, topath);
05229          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05230          vm_delete(topath);
05231 #ifndef ODBC_STORAGE
05232       }
05233 #endif
05234    } else {
05235       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05236       res = -1;
05237    }
05238    ast_unlock_path(todir);
05239    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05240       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05241       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05242       flag);
05243    
05244    return res;
05245 }

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

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

Referenced by copy_message().

04015 {
04016    char frompath2[PATH_MAX], topath2[PATH_MAX];
04017    struct ast_variable *tmp,*var = NULL;
04018    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04019    ast_filecopy(frompath, topath, NULL);
04020    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04021    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04022    if (ast_check_realtime("voicemail_data")) {
04023       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04024       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04025       for (tmp = var; tmp; tmp = tmp->next) {
04026          if (!strcasecmp(tmp->name, "origmailbox")) {
04027             origmailbox = tmp->value;
04028          } else if (!strcasecmp(tmp->name, "context")) {
04029             context = tmp->value;
04030          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04031             macrocontext = tmp->value;
04032          } else if (!strcasecmp(tmp->name, "exten")) {
04033             exten = tmp->value;
04034          } else if (!strcasecmp(tmp->name, "priority")) {
04035             priority = tmp->value;
04036          } else if (!strcasecmp(tmp->name, "callerchan")) {
04037             callerchan = tmp->value;
04038          } else if (!strcasecmp(tmp->name, "callerid")) {
04039             callerid = tmp->value;
04040          } else if (!strcasecmp(tmp->name, "origdate")) {
04041             origdate = tmp->value;
04042          } else if (!strcasecmp(tmp->name, "origtime")) {
04043             origtime = tmp->value;
04044          } else if (!strcasecmp(tmp->name, "category")) {
04045             category = tmp->value;
04046          } else if (!strcasecmp(tmp->name, "duration")) {
04047             duration = tmp->value;
04048          }
04049       }
04050       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);
04051    }
04052    copy(frompath2, topath2);
04053    ast_variables_destroy(var);
04054 }

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

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

Referenced by manager_list_voicemail_users(), and open_mailbox().

03859 {
03860 
03861    int vmcount = 0;
03862    DIR *vmdir = NULL;
03863    struct dirent *vment = NULL;
03864 
03865    if (vm_lock_path(dir))
03866       return ERROR_LOCK_PATH;
03867 
03868    if ((vmdir = opendir(dir))) {
03869       while ((vment = readdir(vmdir))) {
03870          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03871             vmcount++;
03872          }
03873       }
03874       closedir(vmdir);
03875    }
03876    ast_unlock_path(dir);
03877    
03878    return vmcount;
03879 }

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

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

01627 {
01628    mode_t   mode = VOICEMAIL_DIR_MODE;
01629    int res;
01630 
01631    make_dir(dest, len, context, ext, folder);
01632    if ((res = ast_mkdir(dest, mode))) {
01633       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01634       return -1;
01635    }
01636    return 0;
01637 }

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

Definition at line 12708 of file app_voicemail.c.

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

Referenced by advanced_options(), and vm_execmain().

12709 {
12710    int cmd = 0;
12711    char destination[80] = "";
12712    int retries = 0;
12713 
12714    if (!num) {
12715       ast_verb(3, "Destination number will be entered manually\n");
12716       while (retries < 3 && cmd != 't') {
12717          destination[1] = '\0';
12718          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
12719          if (!cmd)
12720             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
12721          if (!cmd)
12722             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
12723          if (!cmd) {
12724             cmd = ast_waitfordigit(chan, 6000);
12725             if (cmd)
12726                destination[0] = cmd;
12727          }
12728          if (!cmd) {
12729             retries++;
12730          } else {
12731 
12732             if (cmd < 0)
12733                return 0;
12734             if (cmd == '*') {
12735                ast_verb(3, "User hit '*' to cancel outgoing call\n");
12736                return 0;
12737             }
12738             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
12739                retries++;
12740             else
12741                cmd = 't';
12742          }
12743       }
12744       if (retries >= 3) {
12745          return 0;
12746       }
12747       
12748    } else {
12749       if (option_verbose > 2)
12750          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
12751       ast_copy_string(destination, num, sizeof(destination));
12752    }
12753 
12754    if (!ast_strlen_zero(destination)) {
12755       if (destination[strlen(destination) -1 ] == '*')
12756          return 0; 
12757       if (option_verbose > 2)
12758          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
12759       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
12760       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
12761       chan->priority = 0;
12762       return 9;
12763    }
12764    return 0;
12765 }

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

Definition at line 10429 of file app_voicemail.c.

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

Referenced by append_mailbox(), and load_config().

10430 {
10431    struct ast_vm_user *vmu;
10432 
10433    AST_LIST_TRAVERSE(&users, vmu, list) {
10434       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10435          if (strcasecmp(vmu->context, context)) {
10436             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10437                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10438                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10439                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10440          }
10441          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10442          return NULL;
10443       }
10444       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10445          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10446          return NULL;
10447       }
10448    }
10449    
10450    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10451       return NULL;
10452    
10453    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10454    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10455 
10456    AST_LIST_INSERT_TAIL(&users, vmu, list);
10457    
10458    return vmu;
10459 }

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

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

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

Definition at line 1387 of file app_voicemail.c.

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

01388 {
01389    /* This function could be made to generate one from a database, too */
01390    struct ast_vm_user *vmu = NULL, *cur;
01391    AST_LIST_LOCK(&users);
01392 
01393    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01394       context = "default";
01395 
01396    AST_LIST_TRAVERSE(&users, cur, list) {
01397 #ifdef IMAP_STORAGE
01398       if (cur->imapversion != imapversion) {
01399          continue;
01400       }
01401 #endif
01402       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01403          break;
01404       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01405          break;
01406    }
01407    if (cur) {
01408       /* Make a copy, so that on a reload, we have no race */
01409       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01410          memcpy(vmu, cur, sizeof(*vmu));
01411          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01412          AST_LIST_NEXT(vmu, list) = NULL;
01413       }
01414    } else
01415       vmu = find_user_realtime(ivm, context, mailbox);
01416    AST_LIST_UNLOCK(&users);
01417    return vmu;
01418 }

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

Finds a voicemail user from the realtime engine.

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

Definition at line 1350 of file app_voicemail.c.

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

01351 {
01352    struct ast_variable *var;
01353    struct ast_vm_user *retval;
01354 
01355    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01356       if (!ivm)
01357          ast_set_flag(retval, VM_ALLOCED);   
01358       else
01359          memset(retval, 0, sizeof(*retval));
01360       if (mailbox) 
01361          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01362       populate_defaults(retval);
01363       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01364          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01365       else
01366          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01367       if (var) {
01368          apply_options_full(retval, var);
01369          ast_variables_destroy(var);
01370       } else { 
01371          if (!ivm) 
01372             ast_free(retval);
01373          retval = NULL;
01374       }  
01375    } 
01376    return retval;
01377 }

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

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

Returns:
zero on success, -1 on error.

Definition at line 6956 of file app_voicemail.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), 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(), free_user(), globalflags, ast_party_caller::id, inboxcount(), inprocess_count(), ast_channel::language, leave_voicemail(), ast_app::list, 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, 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().

06957 {
06958 #ifdef IMAP_STORAGE
06959    int todircount = 0;
06960    struct vm_state *dstvms;
06961 #endif
06962    char username[70]="";
06963    char fn[PATH_MAX]; /* for playback of name greeting */
06964    char ecodes[16] = "#";
06965    int res = 0, cmd = 0;
06966    struct ast_vm_user *receiver = NULL, *vmtmp;
06967    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06968    char *stringp;
06969    const char *s;
06970    int saved_messages = 0;
06971    int valid_extensions = 0;
06972    char *dir;
06973    int curmsg;
06974    char urgent_str[7] = "";
06975    char tmptxtfile[PATH_MAX];
06976    int prompt_played = 0;
06977 #ifndef IMAP_STORAGE
06978    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06979 #endif
06980    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
06981       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
06982    }
06983 
06984    if (vms == NULL) return -1;
06985    dir = vms->curdir;
06986    curmsg = vms->curmsg;
06987 
06988    tmptxtfile[0] = '\0';
06989    while (!res && !valid_extensions) {
06990       int use_directory = 0;
06991       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
06992          int done = 0;
06993          int retries = 0;
06994          cmd = 0;
06995          while ((cmd >= 0) && !done ){
06996             if (cmd)
06997                retries = 0;
06998             switch (cmd) {
06999             case '1': 
07000                use_directory = 0;
07001                done = 1;
07002                break;
07003             case '2': 
07004                use_directory = 1;
07005                done = 1;
07006                break;
07007             case '*': 
07008                cmd = 't';
07009                done = 1;
07010                break;
07011             default: 
07012                /* Press 1 to enter an extension press 2 to use the directory */
07013                cmd = ast_play_and_wait(chan, "vm-forward");
07014                if (!cmd)
07015                   cmd = ast_waitfordigit(chan, 3000);
07016                if (!cmd)
07017                   retries++;
07018                if (retries > 3) {
07019                   cmd = 't';
07020                   done = 1;
07021                }
07022                
07023             }
07024          }
07025          if (cmd < 0 || cmd == 't')
07026             break;
07027       }
07028       
07029       if (use_directory) {
07030          /* use app_directory */
07031          
07032          char old_context[sizeof(chan->context)];
07033          char old_exten[sizeof(chan->exten)];
07034          int old_priority;
07035          struct ast_app* directory_app;
07036 
07037          directory_app = pbx_findapp("Directory");
07038          if (directory_app) {
07039             char vmcontext[256];
07040             /* make backup copies */
07041             memcpy(old_context, chan->context, sizeof(chan->context));
07042             memcpy(old_exten, chan->exten, sizeof(chan->exten));
07043             old_priority = chan->priority;
07044             
07045             /* call the the Directory, changes the channel */
07046             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
07047             res = pbx_exec(chan, directory_app, vmcontext);
07048             
07049             ast_copy_string(username, chan->exten, sizeof(username));
07050             
07051             /* restore the old context, exten, and priority */
07052             memcpy(chan->context, old_context, sizeof(chan->context));
07053             memcpy(chan->exten, old_exten, sizeof(chan->exten));
07054             chan->priority = old_priority;
07055          } else {
07056             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
07057             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
07058          }
07059       } else {
07060          /* Ask for an extension */
07061          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
07062          prompt_played++;
07063          if (res || prompt_played > 4)
07064             break;
07065          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
07066             break;
07067       }
07068       
07069       /* start all over if no username */
07070       if (ast_strlen_zero(username))
07071          continue;
07072       stringp = username;
07073       s = strsep(&stringp, "*");
07074       /* start optimistic */
07075       valid_extensions = 1;
07076       while (s) {
07077          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
07078             int oldmsgs;
07079             int newmsgs;
07080             int capacity;
07081             if (inboxcount(s, &newmsgs, &oldmsgs)) {
07082                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
07083                /* Shouldn't happen, but allow trying another extension if it does */
07084                res = ast_play_and_wait(chan, "pbx-invalid");
07085                valid_extensions = 0;
07086                break;
07087             }
07088             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
07089             if ((newmsgs + oldmsgs) >= capacity) {
07090                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
07091                res = ast_play_and_wait(chan, "vm-mailboxfull");
07092                valid_extensions = 0;
07093                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07094                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07095                   free_user(vmtmp);
07096                }
07097                inprocess_count(receiver->mailbox, receiver->context, -1);
07098                break;
07099             }
07100             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
07101          } else {
07102             /* XXX Optimization for the future.  When we encounter a single bad extension,
07103              * bailing out on all of the extensions may not be the way to go.  We should
07104              * probably just bail on that single extension, then allow the user to enter
07105              * several more. XXX
07106              */
07107             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07108                free_user(receiver);
07109             }
07110             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
07111             /* "I am sorry, that's not a valid extension.  Please try again." */
07112             res = ast_play_and_wait(chan, "pbx-invalid");
07113             valid_extensions = 0;
07114             break;
07115          }
07116 
07117          /* play name if available, else play extension number */
07118          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
07119          RETRIEVE(fn, -1, s, receiver->context);
07120          if (ast_fileexists(fn, NULL, NULL) > 0) {
07121             res = ast_stream_and_wait(chan, fn, ecodes);
07122             if (res) {
07123                DISPOSE(fn, -1);
07124                return res;
07125             }
07126          } else {
07127             res = ast_say_digit_str(chan, s, ecodes, chan->language);
07128          }
07129          DISPOSE(fn, -1);
07130 
07131          s = strsep(&stringp, "*");
07132       }
07133       /* break from the loop of reading the extensions */
07134       if (valid_extensions)
07135          break;
07136    }
07137    /* check if we're clear to proceed */
07138    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
07139       return res;
07140    if (is_new_message == 1) {
07141       struct leave_vm_options leave_options;
07142       char mailbox[AST_MAX_EXTENSION * 2 + 2];
07143       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
07144 
07145       /* Send VoiceMail */
07146       memset(&leave_options, 0, sizeof(leave_options));
07147       leave_options.record_gain = record_gain;
07148       cmd = leave_voicemail(chan, mailbox, &leave_options);
07149    } else {
07150       /* Forward VoiceMail */
07151       long duration = 0;
07152       struct vm_state vmstmp;
07153       int copy_msg_result = 0;
07154       memcpy(&vmstmp, vms, sizeof(vmstmp));
07155 
07156       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
07157 
07158       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
07159       if (!cmd) {
07160          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
07161 #ifdef IMAP_STORAGE
07162             int attach_user_voicemail;
07163             char *myserveremail = serveremail;
07164             
07165             /* get destination mailbox */
07166             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
07167             if (!dstvms) {
07168                dstvms = create_vm_state_from_user(vmtmp);
07169             }
07170             if (dstvms) {
07171                init_mailstream(dstvms, 0);
07172                if (!dstvms->mailstream) {
07173                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
07174                } else {
07175                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
07176                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
07177                }
07178             } else {
07179                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
07180             }
07181             if (!ast_strlen_zero(vmtmp->serveremail))
07182                myserveremail = vmtmp->serveremail;
07183             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
07184             /* NULL category for IMAP storage */
07185             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
07186                dstvms->curbox,
07187                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
07188                S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
07189                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
07190                NULL, urgent_str);
07191 #else
07192             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
07193 #endif
07194             saved_messages++;
07195             AST_LIST_REMOVE_CURRENT(list);
07196             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07197             free_user(vmtmp);
07198             if (res)
07199                break;
07200          }
07201          AST_LIST_TRAVERSE_SAFE_END;
07202          if (saved_messages > 0 && !copy_msg_result) {
07203             /* give confirmation that the message was saved */
07204             /* commented out since we can't forward batches yet
07205             if (saved_messages == 1)
07206                res = ast_play_and_wait(chan, "vm-message");
07207             else
07208                res = ast_play_and_wait(chan, "vm-messages");
07209             if (!res)
07210                res = ast_play_and_wait(chan, "vm-saved"); */
07211 #ifdef IMAP_STORAGE
07212             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
07213             if (ast_strlen_zero(vmstmp.introfn))
07214 #endif
07215             res = ast_play_and_wait(chan, "vm-msgsaved");
07216          }
07217 #ifndef IMAP_STORAGE
07218          else {
07219             /* with IMAP, mailbox full warning played by imap_check_limits */
07220             res = ast_play_and_wait(chan, "vm-mailboxfull");
07221          }
07222          /* Restore original message without prepended message if backup exists */
07223          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07224          strcpy(textfile, msgfile);
07225          strcpy(backup, msgfile);
07226          strcpy(backup_textfile, msgfile);
07227          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07228          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
07229          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07230          if (ast_fileexists(backup, NULL, NULL) > 0) {
07231             ast_filerename(backup, msgfile, NULL);
07232             rename(backup_textfile, textfile);
07233          }
07234 #endif
07235       }
07236       DISPOSE(dir, curmsg);
07237 #ifndef IMAP_STORAGE
07238       if (cmd) { /* assuming hangup, cleanup backup file */
07239          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07240          strcpy(textfile, msgfile);
07241          strcpy(backup_textfile, msgfile);
07242          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07243          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07244          rename(backup_textfile, textfile);
07245       }
07246 #endif
07247    }
07248 
07249    /* If anything failed above, we still have this list to free */
07250    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07251       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07252       free_user(vmtmp);
07253    }
07254    return res ? res : cmd;
07255 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1681 of file app_voicemail.c.

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

01682 {
01683    if (ast_test_flag(vmu, VM_ALLOCED)) {
01684       if (vmu->emailbody != NULL) {
01685          ast_free(vmu->emailbody);
01686          vmu->emailbody = NULL;
01687       }
01688       if (vmu->emailsubject != NULL) {
01689          ast_free(vmu->emailsubject);
01690          vmu->emailsubject = NULL;
01691       }
01692       ast_free(vmu);
01693    }
01694 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11421 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

11422 {
11423    struct ast_vm_user *current;
11424    AST_LIST_LOCK(&users);
11425    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11426       ast_set_flag(current, VM_ALLOCED);
11427       free_user(current);
11428    }
11429    AST_LIST_UNLOCK(&users);
11430 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11433 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

11434 {
11435    struct vm_zone *zcur;
11436    AST_LIST_LOCK(&zones);
11437    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11438       free_zone(zcur);
11439    AST_LIST_UNLOCK(&zones);
11440 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4958 of file app_voicemail.c.

References ast_free.

04959 {
04960    ast_free(z);
04961 }

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

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

04915 {
04916    struct ast_tm tm;
04917    struct timeval t = ast_tvnow();
04918    
04919    ast_localtime(&t, &tm, "UTC");
04920 
04921    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04922 }

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

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

Referenced by get_folder2().

06598 {
06599    int x;
06600    int d;
06601    char fn[PATH_MAX];
06602    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06603    if (d)
06604       return d;
06605    for (x = start; x < 5; x++) { /* For all folders */
06606       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06607          return d;
06608       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06609       if (d)
06610          return d;
06611       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06612       d = vm_play_folder_name(chan, fn);
06613       if (d)
06614          return d;
06615       d = ast_waitfordigit(chan, 500);
06616       if (d)
06617          return d;
06618    }
06619    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06620    if (d)
06621       return d;
06622    d = ast_waitfordigit(chan, 4000);
06623    return d;
06624 }

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

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

06639 {
06640    int res = 0;
06641    int loops = 0;
06642    res = ast_play_and_wait(chan, fn);  /* Folder name */
06643    while (((res < '0') || (res > '9')) &&
06644          (res != '#') && (res >= 0) &&
06645          loops < 4) {
06646       res = get_folder(chan, 0);
06647       loops++;
06648    }
06649    if (loops == 4) { /* give up */
06650       return '#';
06651    }
06652    return res;
06653 }

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

Definition at line 1668 of file app_voicemail.c.

References ARRAY_LEN.

Referenced by vm_execmain().

01669 {
01670    size_t i;
01671 
01672    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01673       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01674          return i;
01675       }
01676    }
01677 
01678    return -1;
01679 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11204 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_task::mailbox, mwi_sub, poll_subscribed_mailbox(), mwi_sub_task::uniqueid, and ast_event_sub::uniqueid.

Referenced by mwi_sub_event_cb().

11205 {
11206    unsigned int len;
11207    struct mwi_sub *mwi_sub;
11208    struct mwi_sub_task *p = datap;
11209 
11210    len = sizeof(*mwi_sub);
11211    if (!ast_strlen_zero(p->mailbox))
11212       len += strlen(p->mailbox);
11213 
11214    if (!ast_strlen_zero(p->context))
11215       len += strlen(p->context) + 1; /* Allow for seperator */
11216 
11217    if (!(mwi_sub = ast_calloc(1, len)))
11218       return -1;
11219 
11220    mwi_sub->uniqueid = p->uniqueid;
11221    if (!ast_strlen_zero(p->mailbox))
11222       strcpy(mwi_sub->mailbox, p->mailbox);
11223 
11224    if (!ast_strlen_zero(p->context)) {
11225       strcat(mwi_sub->mailbox, "@");
11226       strcat(mwi_sub->mailbox, p->context);
11227    }
11228 
11229    AST_RWLIST_WRLOCK(&mwi_subs);
11230    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11231    AST_RWLIST_UNLOCK(&mwi_subs);
11232    ast_free((void *) p->mailbox);
11233    ast_free((void *) p->context);
11234    ast_free(p);
11235    poll_subscribed_mailbox(mwi_sub);
11236    return 0;
11237 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11182 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, mwi_sub_destroy(), ast_event_sub::uniqueid, and mwi_sub::uniqueid.

Referenced by mwi_unsub_event_cb().

11183 {
11184    struct mwi_sub *mwi_sub;
11185    uint32_t *uniqueid = datap;
11186    
11187    AST_RWLIST_WRLOCK(&mwi_subs);
11188    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11189       if (mwi_sub->uniqueid == *uniqueid) {
11190          AST_LIST_REMOVE_CURRENT(entry);
11191          break;
11192       }
11193    }
11194    AST_RWLIST_TRAVERSE_SAFE_END
11195    AST_RWLIST_UNLOCK(&mwi_subs);
11196 
11197    if (mwi_sub)
11198       mwi_sub_destroy(mwi_sub);
11199 
11200    ast_free(uniqueid);  
11201    return 0;
11202 }

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

10958 {
10959    switch (cmd) {
10960    case CLI_INIT:
10961       e->command = "voicemail reload";
10962       e->usage =
10963          "Usage: voicemail reload\n"
10964          "       Reload voicemail configuration\n";
10965       return NULL;
10966    case CLI_GENERATE:
10967       return NULL;
10968    }
10969 
10970    if (a->argc != 2)
10971       return CLI_SHOWUSAGE;
10972 
10973    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
10974    load_config(1);
10975    
10976    return CLI_SUCCESS;
10977 }

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

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

10848 {
10849    struct ast_vm_user *vmu;
10850 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
10851    const char *context = NULL;
10852    int users_counter = 0;
10853 
10854    switch (cmd) {
10855    case CLI_INIT:
10856       e->command = "voicemail show users";
10857       e->usage =
10858          "Usage: voicemail show users [for <context>]\n"
10859          "       Lists all mailboxes currently set up\n";
10860       return NULL;
10861    case CLI_GENERATE:
10862       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10863    }  
10864 
10865    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10866       return CLI_SHOWUSAGE;
10867    if (a->argc == 5) {
10868       if (strcmp(a->argv[3],"for"))
10869          return CLI_SHOWUSAGE;
10870       context = a->argv[4];
10871    }
10872 
10873    if (ast_check_realtime("voicemail")) {
10874       if (!context) {
10875          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10876          return CLI_SHOWUSAGE;
10877       }
10878       return show_users_realtime(a->fd, context);
10879    }
10880 
10881    AST_LIST_LOCK(&users);
10882    if (AST_LIST_EMPTY(&users)) {
10883       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10884       AST_LIST_UNLOCK(&users);
10885       return CLI_FAILURE;
10886    }
10887    if (a->argc == 3)
10888       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10889    else {
10890       int count = 0;
10891       AST_LIST_TRAVERSE(&users, vmu, list) {
10892          if (!strcmp(context, vmu->context))
10893             count++;
10894       }
10895       if (count) {
10896          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10897       } else {
10898          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10899          AST_LIST_UNLOCK(&users);
10900          return CLI_FAILURE;
10901       }
10902    }
10903    AST_LIST_TRAVERSE(&users, vmu, list) {
10904       int newmsgs = 0, oldmsgs = 0;
10905       char count[12], tmp[256] = "";
10906 
10907       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10908          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10909          inboxcount(tmp, &newmsgs, &oldmsgs);
10910          snprintf(count, sizeof(count), "%d", newmsgs);
10911          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10912          users_counter++;
10913       }
10914    }
10915    AST_LIST_UNLOCK(&users);
10916    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10917    return CLI_SUCCESS;
10918 }

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

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

10922 {
10923    struct vm_zone *zone;
10924 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10925    char *res = CLI_SUCCESS;
10926 
10927    switch (cmd) {
10928    case CLI_INIT:
10929       e->command = "voicemail show zones";
10930       e->usage =
10931          "Usage: voicemail show zones\n"
10932          "       Lists zone message formats\n";
10933       return NULL;
10934    case CLI_GENERATE:
10935       return NULL;
10936    }
10937 
10938    if (a->argc != 3)
10939       return CLI_SHOWUSAGE;
10940 
10941    AST_LIST_LOCK(&zones);
10942    if (!AST_LIST_EMPTY(&zones)) {
10943       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10944       AST_LIST_TRAVERSE(&zones, zone, list) {
10945          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10946       }
10947    } else {
10948       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10949       res = CLI_FAILURE;
10950    }
10951    AST_LIST_UNLOCK(&zones);
10952 
10953    return res;
10954 }

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

05301 {
05302    char tmp[256], *tmp2 = tmp, *box, *context;
05303    ast_copy_string(tmp, mailbox, sizeof(tmp));
05304    if (ast_strlen_zero(folder)) {
05305       folder = "INBOX";
05306    }
05307    while ((box = strsep(&tmp2, ",&"))) {
05308       if ((context = strchr(box, '@')))
05309          *context++ = '\0';
05310       else
05311          context = "default";
05312       if (__has_voicemail(context, box, folder, 1))
05313          return 1;
05314       /* If we are checking INBOX, we should check Urgent as well */
05315       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05316          return 1;
05317       }
05318    }
05319    return 0;
05320 }

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

Definition at line 5382 of file app_voicemail.c.

References inboxcount2().

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

05383 {
05384    int urgentmsgs = 0;
05385    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05386    if (newmsgs) {
05387       *newmsgs += urgentmsgs;
05388    }
05389    return res;
05390 }

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

Definition at line 5323 of file app_voicemail.c.

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

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

05324 {
05325    char tmp[256];
05326    char *context;
05327 
05328    /* If no mailbox, return immediately */
05329    if (ast_strlen_zero(mailbox))
05330       return 0;
05331 
05332    if (newmsgs)
05333       *newmsgs = 0;
05334    if (oldmsgs)
05335       *oldmsgs = 0;
05336    if (urgentmsgs)
05337       *urgentmsgs = 0;
05338 
05339    if (strchr(mailbox, ',')) {
05340       int tmpnew, tmpold, tmpurgent;
05341       char *mb, *cur;
05342 
05343       ast_copy_string(tmp, mailbox, sizeof(tmp));
05344       mb = tmp;
05345       while ((cur = strsep(&mb, ", "))) {
05346          if (!ast_strlen_zero(cur)) {
05347             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05348                return -1;
05349             else {
05350                if (newmsgs)
05351                   *newmsgs += tmpnew; 
05352                if (oldmsgs)
05353                   *oldmsgs += tmpold;
05354                if (urgentmsgs)
05355                   *urgentmsgs += tmpurgent;
05356             }
05357          }
05358       }
05359       return 0;
05360    }
05361 
05362    ast_copy_string(tmp, mailbox, sizeof(tmp));
05363    
05364    if ((context = strchr(tmp, '@')))
05365       *context++ = '\0';
05366    else
05367       context = "default";
05368 
05369    if (newmsgs)
05370       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05371    if (oldmsgs)
05372       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05373    if (urgentmsgs)
05374       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05375 
05376    return 0;
05377 }

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

utility used by inchar(), for base_encode()

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

04087 {
04088    int l;
04089 
04090    if (bio->ateof)
04091       return 0;
04092 
04093    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04094       if (ferror(fi))
04095          return -1;
04096 
04097       bio->ateof = 1;
04098       return 0;
04099    }
04100 
04101    bio->iolen = l;
04102    bio->iocp = 0;
04103 
04104    return 1;
04105 }

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

utility used by base_encode()

Definition at line 4110 of file app_voicemail.c.

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

Referenced by base_encode().

04111 {
04112    if (bio->iocp>=bio->iolen) {
04113       if (!inbuf(bio, fi))
04114          return EOF;
04115    }
04116 
04117    return bio->iobuf[bio->iocp++];
04118 }

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

Definition at line 908 of file app_voicemail.c.

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

Referenced by load_module().

00909 {
00910    struct inprocess *i = obj, *j = arg;
00911    if (strcmp(i->mailbox, j->mailbox)) {
00912       return 0;
00913    }
00914    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00915 }

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

Definition at line 917 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::count, inprocess_container, and LOG_WARNING.

Referenced by copy_message(), and forward_message().

00918 {
00919    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00920    arg->context = arg->mailbox + strlen(mailbox) + 1;
00921    strcpy(arg->mailbox, mailbox); /* SAFE */
00922    strcpy(arg->context, context); /* SAFE */
00923    ao2_lock(inprocess_container);
00924    if ((i = ao2_find(inprocess_container, arg, 0))) {
00925       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00926       ao2_unlock(inprocess_container);
00927       ao2_ref(i, -1);
00928       return ret;
00929    }
00930    if (delta < 0) {
00931       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00932    }
00933    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00934       ao2_unlock(inprocess_container);
00935       return 0;
00936    }
00937    i->context = i->mailbox + strlen(mailbox) + 1;
00938    strcpy(i->mailbox, mailbox); /* SAFE */
00939    strcpy(i->context, context); /* SAFE */
00940    i->count = delta;
00941    ao2_link(inprocess_container, i);
00942    ao2_unlock(inprocess_container);
00943    ao2_ref(i, -1);
00944    return 0;
00945 }

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

Definition at line 902 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

00903 {
00904    const struct inprocess *i = obj;
00905    return atoi(i->mailbox);
00906 }

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

Definition at line 4924 of file app_voicemail.c.

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

04925 {
04926    int res;
04927    char fn[PATH_MAX];
04928    char dest[PATH_MAX];
04929 
04930    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04931 
04932    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04933       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04934       return -1;
04935    }
04936 
04937    RETRIEVE(fn, -1, ext, context);
04938    if (ast_fileexists(fn, NULL, NULL) > 0) {
04939       res = ast_stream_and_wait(chan, fn, ecodes);
04940       if (res) {
04941          DISPOSE(fn, -1);
04942          return res;
04943       }
04944    } else {
04945       /* Dispose just in case */
04946       DISPOSE(fn, -1);
04947       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04948       if (res)
04949          return res;
04950       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04951       if (res)
04952          return res;
04953    }
04954    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04955    return res;
04956 }

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

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

Referenced by load_config().

01326 {
01327    int i;
01328    char *local_key = ast_strdupa(key);
01329 
01330    for (i = 0; i < strlen(key); ++i) {
01331       if (!strchr(VALID_DTMF, *local_key)) {
01332          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01333          return 0;
01334       }
01335       local_key++;
01336    }
01337    return 1;
01338 }

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

References map, ast_vm_user::maxmsg, and MAXMSGLIMIT.

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

03913 {
03914    int x;
03915    unsigned char map[MAXMSGLIMIT] = "";
03916    DIR *msgdir;
03917    struct dirent *msgdirent;
03918    int msgdirint;
03919 
03920    /* Reading the entire directory into a file map scales better than
03921     * doing a stat repeatedly on a predicted sequence.  I suspect this
03922     * is partially due to stat(2) internally doing a readdir(2) itself to
03923     * find each file. */
03924    if (!(msgdir = opendir(dir))) {
03925       return -1;
03926    }
03927 
03928    while ((msgdirent = readdir(msgdir))) {
03929       if (sscanf(msgdirent->d_name, "msg%30d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
03930          map[msgdirint] = 1;
03931    }
03932    closedir(msgdir);
03933 
03934    for (x = 0; x < vmu->maxmsg; x++) {
03935       if (map[x] == 0)
03936          break;
03937    }
03938 
03939    return x - 1;
03940 }

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

References ast_canmatch_extension(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_exists_extension(), ast_fileexists(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::caller, ast_channel::context, ast_vm_user::context, create_dirpath(), DISPOSE, errno, ast_vm_user::exit, find_user(), ast_party_caller::id, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, ast_party_id::number, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), RETRIEVE, S_COR, ast_party_number::str, ast_party_number::valid, VM_OPERATOR, and VOICEMAIL_DIR_MODE.

05456 {
05457 #ifdef IMAP_STORAGE
05458    int newmsgs, oldmsgs;
05459 #else
05460    char urgdir[PATH_MAX];
05461 #endif
05462    char txtfile[PATH_MAX];
05463    char tmptxtfile[PATH_MAX];
05464    struct vm_state *vms = NULL;
05465    char callerid[256];
05466    FILE *txt;
05467    char date[256];
05468    int txtdes;
05469    int res = 0;
05470    int msgnum;
05471    int duration = 0;
05472    int ausemacro = 0;
05473    int ousemacro = 0;
05474    int ouseexten = 0;
05475    char tmpdur[16];
05476    char priority[16];
05477    char origtime[16];
05478    char dir[PATH_MAX];
05479    char tmpdir[PATH_MAX];
05480    char fn[PATH_MAX];
05481    char prefile[PATH_MAX] = "";
05482    char tempfile[PATH_MAX] = "";
05483    char ext_context[256] = "";
05484    char fmt[80];
05485    char *context;
05486    char ecodes[17] = "#";
05487    struct ast_str *tmp = ast_str_create(16);
05488    char *tmpptr;
05489    struct ast_vm_user *vmu;
05490    struct ast_vm_user svm;
05491    const char *category = NULL;
05492    const char *code;
05493    const char *alldtmf = "0123456789ABCD*#";
05494    char flag[80];
05495 
05496    if (!tmp) {
05497       return -1;
05498    }
05499 
05500    ast_str_set(&tmp, 0, "%s", ext);
05501    ext = ast_str_buffer(tmp);
05502    if ((context = strchr(ext, '@'))) {
05503       *context++ = '\0';
05504       tmpptr = strchr(context, '&');
05505    } else {
05506       tmpptr = strchr(ext, '&');
05507    }
05508 
05509    if (tmpptr)
05510       *tmpptr++ = '\0';
05511 
05512    ast_channel_lock(chan);
05513    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
05514       category = ast_strdupa(category);
05515    }
05516    ast_channel_unlock(chan);
05517 
05518    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
05519       ast_copy_string(flag, "Urgent", sizeof(flag));
05520    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
05521       ast_copy_string(flag, "PRIORITY", sizeof(flag));
05522    } else {
05523       flag[0] = '\0';
05524    }
05525 
05526    ast_debug(3, "Before find_user\n");
05527    if (!(vmu = find_user(&svm, context, ext))) {
05528       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
05529       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05530       ast_free(tmp);
05531       return res;
05532    }
05533    /* Setup pre-file if appropriate */
05534    if (strcmp(vmu->context, "default"))
05535       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
05536    else
05537       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
05538 
05539    /* Set the path to the prefile. Will be one of 
05540       VM_SPOOL_DIRcontext/ext/busy
05541       VM_SPOOL_DIRcontext/ext/unavail
05542       Depending on the flag set in options.
05543    */
05544    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
05545       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
05546    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
05547       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
05548    }
05549    /* Set the path to the tmpfile as
05550       VM_SPOOL_DIR/context/ext/temp
05551       and attempt to create the folder structure.
05552    */
05553    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
05554    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
05555       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
05556       ast_free(tmp);
05557       return -1;
05558    }
05559    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
05560    if (ast_fileexists(tempfile, NULL, NULL) > 0)
05561       ast_copy_string(prefile, tempfile, sizeof(prefile));
05562 
05563    DISPOSE(tempfile, -1);
05564    /* It's easier just to try to make it than to check for its existence */
05565 #ifndef IMAP_STORAGE
05566    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
05567 #else
05568    snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
05569    if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
05570       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
05571    }
05572 #endif
05573 
05574    /* Check current or macro-calling context for special extensions */
05575    if (ast_test_flag(vmu, VM_OPERATOR)) {
05576       if (!ast_strlen_zero(vmu->exit)) {
05577          if (ast_exists_extension(chan, vmu->exit, "o", 1,
05578             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05579             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05580             ouseexten = 1;
05581          }
05582       } else if (ast_exists_extension(chan, chan->context, "o", 1,
05583          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05584          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05585          ouseexten = 1;
05586       } else if (!ast_strlen_zero(chan->macrocontext)
05587          && ast_exists_extension(chan, chan->macrocontext, "o", 1,
05588             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05589          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05590          ousemacro = 1;
05591       }
05592    }
05593 
05594    if (!ast_strlen_zero(vmu->exit)) {
05595       if (ast_exists_extension(chan, vmu->exit, "a", 1,
05596          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05597          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05598       }
05599    } else if (ast_exists_extension(chan, chan->context, "a", 1,
05600       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05601       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05602    } else if (!ast_strlen_zero(chan->macrocontext)
05603       && ast_exists_extension(chan, chan->macrocontext, "a", 1,
05604          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05605       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05606       ausemacro = 1;
05607    }
05608 
05609    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05610       for (code = alldtmf; *code; code++) {
05611          char e[2] = "";
05612          e[0] = *code;
05613          if (strchr(ecodes, e[0]) == NULL
05614             && ast_canmatch_extension(chan, chan->context, e, 1,
05615                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05616             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05617          }
05618       }
05619    }
05620 
05621    /* Play the beginning intro if desired */
05622    if (!ast_strlen_zero(prefile)) {
05623 #ifdef ODBC_STORAGE
05624       int success = 
05625 #endif
05626          RETRIEVE(prefile, -1, ext, context);
05627       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05628          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05629             res = ast_waitstream(chan, ecodes);
05630 #ifdef ODBC_STORAGE
05631          if (success == -1) {
05632             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05633             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05634             store_file(prefile, vmu->mailbox, vmu->context, -1);
05635          }
05636 #endif
05637       } else {
05638          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05639          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05640       }
05641       DISPOSE(prefile, -1);
05642       if (res < 0) {
05643          ast_debug(1, "Hang up during prefile playback\n");
05644          free_user(vmu);
05645          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05646          ast_free(tmp);
05647          return -1;
05648       }
05649    }
05650    if (res == '#') {
05651       /* On a '#' we skip the instructions */
05652       ast_set_flag(options, OPT_SILENT);
05653       res = 0;
05654    }
05655    /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
05656    if (vmu->maxmsg == 0) {
05657       if (option_debug > 2)
05658          ast_log(LOG_DEBUG, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
05659       pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05660       goto leave_vm_out;
05661    }
05662    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05663       res = ast_stream_and_wait(chan, INTRO, ecodes);
05664       if (res == '#') {
05665          ast_set_flag(options, OPT_SILENT);
05666          res = 0;
05667       }
05668    }
05669    if (res > 0)
05670       ast_stopstream(chan);
05671    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05672     other than the operator -- an automated attendant or mailbox login for example */
05673    if (res == '*') {
05674       chan->exten[0] = 'a';
05675       chan->exten[1] = '\0';
05676       if (!ast_strlen_zero(vmu->exit)) {
05677          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05678       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05679          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05680       }
05681       chan->priority = 0;
05682       free_user(vmu);
05683       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05684       ast_free(tmp);
05685       return 0;
05686    }
05687 
05688    /* Check for a '0' here */
05689    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05690    transfer:
05691       if (ouseexten || ousemacro) {
05692          chan->exten[0] = 'o';
05693          chan->exten[1] = '\0';
05694          if (!ast_strlen_zero(vmu->exit)) {
05695             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05696          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05697             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05698          }
05699          ast_play_and_wait(chan, "transfer");
05700          chan->priority = 0;
05701          free_user(vmu);
05702          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05703       }
05704       ast_free(tmp);
05705       return OPERATOR_EXIT;
05706    }
05707 
05708    /* Allow all other digits to exit Voicemail and return to the dialplan */
05709    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05710       if (!ast_strlen_zero(options->exitcontext))
05711          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05712       free_user(vmu);
05713       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05714       ast_free(tmp);
05715       return res;
05716    }
05717 
05718    if (res < 0) {
05719       free_user(vmu);
05720       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05721       ast_free(tmp);
05722       return -1;
05723    }
05724    /* The meat of recording the message...  All the announcements and beeps have been played*/
05725    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05726    if (!ast_strlen_zero(fmt)) {
05727       msgnum = 0;
05728 
05729 #ifdef IMAP_STORAGE
05730       /* Is ext a mailbox? */
05731       /* must open stream for this user to get info! */
05732       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05733       if (res < 0) {
05734          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05735          ast_free(tmp);
05736          return -1;
05737       }
05738       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05739       /* It is possible under certain circumstances that inboxcount did not
05740        * create a vm_state when it was needed. This is a catchall which will
05741        * rarely be used.
05742        */
05743          if (!(vms = create_vm_state_from_user(vmu))) {
05744             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05745             ast_free(tmp);
05746             return -1;
05747          }
05748       }
05749       vms->newmessages++;
05750       
05751       /* here is a big difference! We add one to it later */
05752       msgnum = newmsgs + oldmsgs;
05753       ast_debug(3, "Messagecount set to %d\n", msgnum);
05754       snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05755       /* set variable for compatibility */
05756       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05757 
05758       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
05759          goto leave_vm_out;
05760       }
05761 #else
05762       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
05763          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05764          if (!res)
05765             res = ast_waitstream(chan, "");
05766          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05767          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05768          inprocess_count(vmu->mailbox, vmu->context, -1);
05769          goto leave_vm_out;
05770       }
05771 
05772 #endif
05773       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05774       txtdes = mkstemp(tmptxtfile);
05775       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05776       if (txtdes < 0) {
05777          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05778          if (!res)
05779             res = ast_waitstream(chan, "");
05780          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05781          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05782          inprocess_count(vmu->mailbox, vmu->context, -1);
05783          goto leave_vm_out;
05784       }
05785 
05786       /* Now play the beep once we have the message number for our next message. */
05787       if (res >= 0) {
05788          /* Unless we're *really* silent, try to send the beep */
05789          res = ast_stream_and_wait(chan, "beep", "");
05790       }
05791             
05792       /* Store information in real-time storage */
05793       if (ast_check_realtime("voicemail_data")) {
05794          snprintf(priority, sizeof(priority), "%d", chan->priority);
05795          snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
05796          get_date(date, sizeof(date));
05797          ast_callerid_merge(callerid, sizeof(callerid),
05798             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05799             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05800             "Unknown");
05801          ast_store_realtime("voicemail_data",
05802             "origmailbox", ext,
05803             "context", chan->context,
05804             "macrocontext", chan->macrocontext,
05805             "exten", chan->exten,
05806             "priority", priority,
05807             "callerchan", chan->name,
05808             "callerid", callerid,
05809             "origdate", date,
05810             "origtime", origtime,
05811             "category", S_OR(category, ""),
05812             "filename", tmptxtfile,
05813             SENTINEL);
05814       }
05815 
05816       /* Store information */
05817       txt = fdopen(txtdes, "w+");
05818       if (txt) {
05819          get_date(date, sizeof(date));
05820          ast_callerid_merge(callerid, sizeof(callerid),
05821             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05822             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05823             "Unknown");
05824          fprintf(txt, 
05825             ";\n"
05826             "; Message Information file\n"
05827             ";\n"
05828             "[message]\n"
05829             "origmailbox=%s\n"
05830             "context=%s\n"
05831             "macrocontext=%s\n"
05832             "exten=%s\n"
05833             "rdnis=%s\n"
05834             "priority=%d\n"
05835             "callerchan=%s\n"
05836             "callerid=%s\n"
05837             "origdate=%s\n"
05838             "origtime=%ld\n"
05839             "category=%s\n",
05840             ext,
05841             chan->context,
05842             chan->macrocontext, 
05843             chan->exten,
05844             S_COR(chan->redirecting.from.number.valid,
05845                chan->redirecting.from.number.str, "unknown"),
05846             chan->priority,
05847             chan->name,
05848             callerid,
05849             date, (long) time(NULL),
05850             category ? category : "");
05851       } else {
05852          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
05853          inprocess_count(vmu->mailbox, vmu->context, -1);
05854          if (ast_check_realtime("voicemail_data")) {
05855             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05856          }
05857          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05858          goto leave_vm_out;
05859       }
05860       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms, flag);
05861 
05862       if (txt) {
05863          fprintf(txt, "flag=%s\n", flag);
05864          if (duration < vmu->minsecs) {
05865             fclose(txt);
05866             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmu->minsecs);
05867             ast_filedelete(tmptxtfile, NULL);
05868             unlink(tmptxtfile);
05869             if (ast_check_realtime("voicemail_data")) {
05870                ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05871             }
05872             inprocess_count(vmu->mailbox, vmu->context, -1);
05873          } else {
05874             fprintf(txt, "duration=%d\n", duration);
05875             fclose(txt);
05876             if (vm_lock_path(dir)) {
05877                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
05878                /* Delete files */
05879                ast_filedelete(tmptxtfile, NULL);
05880                unlink(tmptxtfile);
05881                inprocess_count(vmu->mailbox, vmu->context, -1);
05882             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
05883                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
05884                unlink(tmptxtfile);
05885                ast_unlock_path(dir);
05886                inprocess_count(vmu->mailbox, vmu->context, -1);
05887                if (ast_check_realtime("voicemail_data")) {
05888                   ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05889                }
05890             } else {
05891 #ifndef IMAP_STORAGE
05892                msgnum = last_message_index(vmu, dir) + 1;
05893 #endif
05894                make_file(fn, sizeof(fn), dir, msgnum);
05895 
05896                /* assign a variable with the name of the voicemail file */ 
05897 #ifndef IMAP_STORAGE
05898                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
05899 #else
05900                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05901 #endif
05902 
05903                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
05904                ast_filerename(tmptxtfile, fn, NULL);
05905                rename(tmptxtfile, txtfile);
05906                inprocess_count(vmu->mailbox, vmu->context, -1);
05907 
05908                /* Properly set permissions on voicemail text descriptor file.
05909                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
05910                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
05911                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
05912 
05913                ast_unlock_path(dir);
05914                if (ast_check_realtime("voicemail_data")) {
05915                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
05916                   ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
05917                }
05918                /* We must store the file first, before copying the message, because
05919                 * ODBC storage does the entire copy with SQL.
05920                 */
05921                if (ast_fileexists(fn, NULL, NULL) > 0) {
05922                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
05923                }
05924 
05925                /* Are there to be more recipients of this message? */
05926                while (tmpptr) {
05927                   struct ast_vm_user recipu, *recip;
05928                   char *exten, *cntx;
05929                
05930                   exten = strsep(&tmpptr, "&");
05931                   cntx = strchr(exten, '@');
05932                   if (cntx) {
05933                      *cntx = '\0';
05934                      cntx++;
05935                   }
05936                   if ((recip = find_user(&recipu, cntx, exten))) {
05937                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
05938                      free_user(recip);
05939                   }
05940                }
05941 #ifndef IMAP_STORAGE
05942                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
05943                   /* Move the message from INBOX to Urgent folder if this is urgent! */
05944                   char sfn[PATH_MAX];
05945                   char dfn[PATH_MAX];
05946                   int x;
05947                   /* It's easier just to try to make it than to check for its existence */
05948                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
05949                   x = last_message_index(vmu, urgdir) + 1;
05950                   make_file(sfn, sizeof(sfn), dir, msgnum);
05951                   make_file(dfn, sizeof(dfn), urgdir, x);
05952                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
05953                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
05954                   /* Notification must happen for this new message in Urgent folder, not INBOX */
05955                   ast_copy_string(fn, dfn, sizeof(fn));
05956                   msgnum = x;
05957                }
05958 #endif
05959                /* Notification needs to happen after the copy, though. */
05960                if (ast_fileexists(fn, NULL, NULL)) {
05961 #ifdef IMAP_STORAGE
05962                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
05963                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05964                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05965                      flag);
05966 #else
05967                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
05968                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05969                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05970                      flag);
05971 #endif
05972                }
05973 
05974                /* Disposal needs to happen after the optional move and copy */
05975                if (ast_fileexists(fn, NULL, NULL)) {
05976                   DISPOSE(dir, msgnum);
05977                }
05978             }
05979          }
05980       } else {
05981          inprocess_count(vmu->mailbox, vmu->context, -1);
05982       }
05983       if (res == '0') {
05984          goto transfer;
05985       } else if (res > 0 && res != 't')
05986          res = 0;
05987 
05988       if (duration < vmu->minsecs)
05989          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
05990          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05991       else
05992          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05993    } else
05994       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
05995 leave_vm_out:
05996    free_user(vmu);
05997 
05998 #ifdef IMAP_STORAGE
05999    /* expunge message - use UID Expunge if supported on IMAP server*/
06000    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
06001    if (expungeonhangup == 1) {
06002       ast_mutex_lock(&vms->lock);
06003 #ifdef HAVE_IMAP_TK2006
06004       if (LEVELUIDPLUS (vms->mailstream)) {
06005          mail_expunge_full(vms->mailstream, NIL, EX_UID);
06006       } else 
06007 #endif
06008          mail_expunge(vms->mailstream);
06009       ast_mutex_unlock(&vms->lock);
06010    }
06011 #endif
06012 
06013    ast_free(tmp);
06014    return res;
06015 }

static int load_config ( int  reload  )  [static]

Definition at line 11486 of file app_voicemail.c.

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

11487 {
11488    struct ast_vm_user *current;
11489    struct ast_config *cfg, *ucfg;
11490    char *cat;
11491    struct ast_variable *var;
11492    const char *val;
11493    char *q, *stringp, *tmp;
11494    int x;
11495    int tmpadsi[4];
11496    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11497    char secretfn[PATH_MAX] = "";
11498 
11499    ast_unload_realtime("voicemail");
11500    ast_unload_realtime("voicemail_data");
11501 
11502    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11503       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11504          return 0;
11505       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11506          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11507          ucfg = NULL;
11508       }
11509       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11510       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11511          ast_config_destroy(ucfg);
11512          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11513          return 0;
11514       }
11515    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11516       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11517       return 0;
11518    } else {
11519       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11520       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11521          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11522          ucfg = NULL;
11523       }
11524    }
11525 #ifdef IMAP_STORAGE
11526    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
11527 #endif
11528    /* set audio control prompts */
11529    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
11530    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
11531    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
11532    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
11533    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
11534 
11535    /* Free all the users structure */  
11536    free_vm_users();
11537 
11538    /* Free all the zones structure */
11539    free_vm_zones();
11540 
11541    AST_LIST_LOCK(&users);  
11542 
11543    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
11544    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
11545 
11546    if (cfg) {
11547       /* General settings */
11548 
11549       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
11550          val = "default";
11551       ast_copy_string(userscontext, val, sizeof(userscontext));
11552       /* Attach voice message to mail message ? */
11553       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
11554          val = "yes";
11555       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
11556 
11557       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
11558          val = "no";
11559       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
11560 
11561       volgain = 0.0;
11562       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
11563          sscanf(val, "%30lf", &volgain);
11564 
11565 #ifdef ODBC_STORAGE
11566       strcpy(odbc_database, "asterisk");
11567       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
11568          ast_copy_string(odbc_database, val, sizeof(odbc_database));
11569       }
11570       strcpy(odbc_table, "voicemessages");
11571       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
11572          ast_copy_string(odbc_table, val, sizeof(odbc_table));
11573       }
11574 #endif      
11575       /* Mail command */
11576       strcpy(mailcmd, SENDMAIL);
11577       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
11578          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
11579 
11580       maxsilence = 0;
11581       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
11582          maxsilence = atoi(val);
11583          if (maxsilence > 0)
11584             maxsilence *= 1000;
11585       }
11586       
11587       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
11588          maxmsg = MAXMSG;
11589       } else {
11590          maxmsg = atoi(val);
11591          if (maxmsg < 0) {
11592             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
11593             maxmsg = MAXMSG;
11594          } else if (maxmsg > MAXMSGLIMIT) {
11595             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11596             maxmsg = MAXMSGLIMIT;
11597          }
11598       }
11599 
11600       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
11601          maxdeletedmsg = 0;
11602       } else {
11603          if (sscanf(val, "%30d", &x) == 1)
11604             maxdeletedmsg = x;
11605          else if (ast_true(val))
11606             maxdeletedmsg = MAXMSG;
11607          else
11608             maxdeletedmsg = 0;
11609 
11610          if (maxdeletedmsg < 0) {
11611             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
11612             maxdeletedmsg = MAXMSG;
11613          } else if (maxdeletedmsg > MAXMSGLIMIT) {
11614             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11615             maxdeletedmsg = MAXMSGLIMIT;
11616          }
11617       }
11618 
11619       /* Load date format config for voicemail mail */
11620       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
11621          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
11622       }
11623 
11624       /* Load date format config for voicemail pager mail */
11625       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
11626          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
11627       }
11628 
11629       /* External password changing command */
11630       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
11631          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11632          pwdchange = PWDCHANGE_EXTERNAL;
11633       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
11634          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11635          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
11636       }
11637  
11638       /* External password validation command */
11639       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
11640          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
11641          ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
11642       }
11643 
11644 #ifdef IMAP_STORAGE
11645       /* IMAP server address */
11646       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
11647          ast_copy_string(imapserver, val, sizeof(imapserver));
11648       } else {
11649          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
11650       }
11651       /* IMAP server port */
11652       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
11653          ast_copy_string(imapport, val, sizeof(imapport));
11654       } else {
11655          ast_copy_string(imapport, "143", sizeof(imapport));
11656       }
11657       /* IMAP server flags */
11658       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
11659          ast_copy_string(imapflags, val, sizeof(imapflags));
11660       }
11661       /* IMAP server master username */
11662       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
11663          ast_copy_string(authuser, val, sizeof(authuser));
11664       }
11665       /* IMAP server master password */
11666       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
11667          ast_copy_string(authpassword, val, sizeof(authpassword));
11668       }
11669       /* Expunge on exit */
11670       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
11671          if (ast_false(val))
11672             expungeonhangup = 0;
11673          else
11674             expungeonhangup = 1;
11675       } else {
11676          expungeonhangup = 1;
11677       }
11678       /* IMAP voicemail folder */
11679       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
11680          ast_copy_string(imapfolder, val, sizeof(imapfolder));
11681       } else {
11682          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
11683       }
11684       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
11685          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
11686       }
11687       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
11688          imapgreetings = ast_true(val);
11689       } else {
11690          imapgreetings = 0;
11691       }
11692       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
11693          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
11694       } else {
11695          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
11696       }
11697 
11698       /* There is some very unorthodox casting done here. This is due
11699        * to the way c-client handles the argument passed in. It expects a 
11700        * void pointer and casts the pointer directly to a long without
11701        * first dereferencing it. */
11702       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
11703          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
11704       } else {
11705          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
11706       }
11707 
11708       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
11709          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
11710       } else {
11711          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
11712       }
11713 
11714       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
11715          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
11716       } else {
11717          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
11718       }
11719 
11720       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
11721          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
11722       } else {
11723          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
11724       }
11725 
11726       /* Increment configuration version */
11727       imapversion++;
11728 #endif
11729       /* External voicemail notify application */
11730       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
11731          ast_copy_string(externnotify, val, sizeof(externnotify));
11732          ast_debug(1, "found externnotify: %s\n", externnotify);
11733       } else {
11734          externnotify[0] = '\0';
11735       }
11736 
11737       /* SMDI voicemail notification */
11738       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
11739          ast_debug(1, "Enabled SMDI voicemail notification\n");
11740          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
11741             smdi_iface = ast_smdi_interface_find(val);
11742          } else {
11743             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
11744             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
11745          }
11746          if (!smdi_iface) {
11747             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
11748          } 
11749       }
11750 
11751       /* Silence treshold */
11752       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
11753       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
11754          silencethreshold = atoi(val);
11755       
11756       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
11757          val = ASTERISK_USERNAME;
11758       ast_copy_string(serveremail, val, sizeof(serveremail));
11759       
11760       vmmaxsecs = 0;
11761       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
11762          if (sscanf(val, "%30d", &x) == 1) {
11763             vmmaxsecs = x;
11764          } else {
11765             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
11766          }
11767       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
11768          static int maxmessage_deprecate = 0;
11769          if (maxmessage_deprecate == 0) {
11770             maxmessage_deprecate = 1;
11771             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
11772          }
11773          if (sscanf(val, "%30d", &x) == 1) {
11774             vmmaxsecs = x;
11775          } else {
11776             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
11777          }
11778       }
11779 
11780       vmminsecs = 0;
11781       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
11782          if (sscanf(val, "%30d", &x) == 1) {
11783             vmminsecs = x;
11784             if (maxsilence / 1000 >= vmminsecs) {
11785                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
11786             }
11787          } else {
11788             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
11789          }
11790       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
11791          static int maxmessage_deprecate = 0;
11792          if (maxmessage_deprecate == 0) {
11793             maxmessage_deprecate = 1;
11794             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
11795          }
11796          if (sscanf(val, "%30d", &x) == 1) {
11797             vmminsecs = x;
11798             if (maxsilence / 1000 >= vmminsecs) {
11799                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
11800             }
11801          } else {
11802             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
11803          }
11804       }
11805 
11806       val = ast_variable_retrieve(cfg, "general", "format");
11807       if (!val) {
11808          val = "wav";   
11809       } else {
11810          tmp = ast_strdupa(val);
11811          val = ast_format_str_reduce(tmp);
11812          if (!val) {
11813             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
11814             val = "wav";
11815          }
11816       }
11817       ast_copy_string(vmfmts, val, sizeof(vmfmts));
11818 
11819       skipms = 3000;
11820       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
11821          if (sscanf(val, "%30d", &x) == 1) {
11822             maxgreet = x;
11823          } else {
11824             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
11825          }
11826       }
11827 
11828       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
11829          if (sscanf(val, "%30d", &x) == 1) {
11830             skipms = x;
11831          } else {
11832             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
11833          }
11834       }
11835 
11836       maxlogins = 3;
11837       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
11838          if (sscanf(val, "%30d", &x) == 1) {
11839             maxlogins = x;
11840          } else {
11841             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
11842          }
11843       }
11844 
11845       minpassword = MINPASSWORD;
11846       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
11847          if (sscanf(val, "%30d", &x) == 1) {
11848             minpassword = x;
11849          } else {
11850             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
11851          }
11852       }
11853 
11854       /* Force new user to record name ? */
11855       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
11856          val = "no";
11857       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
11858 
11859       /* Force new user to record greetings ? */
11860       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
11861          val = "no";
11862       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
11863 
11864       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
11865          ast_debug(1, "VM_CID Internal context string: %s\n", val);
11866          stringp = ast_strdupa(val);
11867          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
11868             if (!ast_strlen_zero(stringp)) {
11869                q = strsep(&stringp, ",");
11870                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
11871                   q++;
11872                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
11873                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
11874             } else {
11875                cidinternalcontexts[x][0] = '\0';
11876             }
11877          }
11878       }
11879       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
11880          ast_debug(1, "VM Review Option disabled globally\n");
11881          val = "no";
11882       }
11883       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
11884 
11885       /* Temporary greeting reminder */
11886       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
11887          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
11888          val = "no";
11889       } else {
11890          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
11891       }
11892       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
11893       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
11894          ast_debug(1, "VM next message wrap disabled globally\n");
11895          val = "no";
11896       }
11897       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);  
11898 
11899       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
11900          ast_debug(1, "VM Operator break disabled globally\n");
11901          val = "no";
11902       }
11903       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
11904 
11905       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
11906          ast_debug(1, "VM CID Info before msg disabled globally\n");
11907          val = "no";
11908       } 
11909       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
11910 
11911       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
11912          ast_debug(1, "Send Voicemail msg disabled globally\n");
11913          val = "no";
11914       }
11915       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
11916    
11917       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
11918          ast_debug(1, "ENVELOPE before msg enabled globally\n");
11919          val = "yes";
11920       }
11921       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
11922 
11923       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
11924          ast_debug(1, "Move Heard enabled globally\n");
11925          val = "yes";
11926       }
11927       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
11928 
11929       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
11930          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
11931          val = "no";
11932       }
11933       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);   
11934 
11935       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
11936          ast_debug(1, "Duration info before msg enabled globally\n");
11937          val = "yes";
11938       }
11939       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
11940 
11941       saydurationminfo = 2;
11942       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
11943          if (sscanf(val, "%30d", &x) == 1) {
11944             saydurationminfo = x;
11945          } else {
11946             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
11947          }
11948       }
11949 
11950       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
11951          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
11952          val = "no";
11953       }
11954       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
11955 
11956       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
11957          ast_copy_string(dialcontext, val, sizeof(dialcontext));
11958          ast_debug(1, "found dialout context: %s\n", dialcontext);
11959       } else {
11960          dialcontext[0] = '\0';  
11961       }
11962       
11963       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
11964          ast_copy_string(callcontext, val, sizeof(callcontext));
11965          ast_debug(1, "found callback context: %s\n", callcontext);
11966       } else {
11967          callcontext[0] = '\0';
11968       }
11969 
11970       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
11971          ast_copy_string(exitcontext, val, sizeof(exitcontext));
11972          ast_debug(1, "found operator context: %s\n", exitcontext);
11973       } else {
11974          exitcontext[0] = '\0';
11975       }
11976       
11977       /* load password sounds configuration */
11978       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
11979          ast_copy_string(vm_password, val, sizeof(vm_password));
11980       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
11981          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
11982       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
11983          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
11984       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
11985          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
11986       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
11987          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
11988       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
11989          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
11990       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
11991          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
11992       }
11993       /* load configurable audio prompts */
11994       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
11995          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
11996       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
11997          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
11998       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
11999          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
12000       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
12001          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
12002       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
12003          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
12004 
12005       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
12006          val = "no";
12007       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
12008 
12009       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
12010          val = "voicemail.conf";
12011       }
12012       if (!(strcmp(val, "spooldir"))) {
12013          passwordlocation = OPT_PWLOC_SPOOLDIR;
12014       } else {
12015          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
12016       }
12017 
12018       poll_freq = DEFAULT_POLL_FREQ;
12019       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
12020          if (sscanf(val, "%30u", &poll_freq) != 1) {
12021             poll_freq = DEFAULT_POLL_FREQ;
12022             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
12023          }
12024       }
12025 
12026       poll_mailboxes = 0;
12027       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
12028          poll_mailboxes = ast_true(val);
12029 
12030       if (ucfg) { 
12031          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
12032             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
12033                continue;
12034             if ((current = find_or_create(userscontext, cat))) {
12035                populate_defaults(current);
12036                apply_options_full(current, ast_variable_browse(ucfg, cat));
12037                ast_copy_string(current->context, userscontext, sizeof(current->context));
12038                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
12039                   current->passwordlocation = OPT_PWLOC_USERSCONF;
12040                }
12041 
12042                switch (current->passwordlocation) {
12043                case OPT_PWLOC_SPOOLDIR:
12044                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
12045                   read_password_from_file(secretfn, current->password, sizeof(current->password));
12046                }
12047             }
12048          }
12049          ast_config_destroy(ucfg);
12050       }
12051       cat = ast_category_browse(cfg, NULL);
12052       while (cat) {
12053          if (strcasecmp(cat, "general")) {
12054             var = ast_variable_browse(cfg, cat);
12055             if (strcasecmp(cat, "zonemessages")) {
12056                /* Process mailboxes in this context */
12057                while (var) {
12058                   append_mailbox(cat, var->name, var->value);
12059                   var = var->next;
12060                }
12061             } else {
12062                /* Timezones in this context */
12063                while (var) {
12064                   struct vm_zone *z;
12065                   if ((z = ast_malloc(sizeof(*z)))) {
12066                      char *msg_format, *tzone;
12067                      msg_format = ast_strdupa(var->value);
12068                      tzone = strsep(&msg_format, "|,");
12069                      if (msg_format) {
12070                         ast_copy_string(z->name, var->name, sizeof(z->name));
12071                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
12072                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
12073                         AST_LIST_LOCK(&zones);
12074                         AST_LIST_INSERT_HEAD(&zones, z, list);
12075                         AST_LIST_UNLOCK(&zones);
12076                      } else {
12077                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
12078                         ast_free(z);
12079                      }
12080                   } else {
12081                      AST_LIST_UNLOCK(&users);
12082                      ast_config_destroy(cfg);
12083                      return -1;
12084                   }
12085                   var = var->next;
12086                }
12087             }
12088          }
12089          cat = ast_category_browse(cfg, cat);
12090       }
12091       memset(fromstring, 0, sizeof(fromstring));
12092       memset(pagerfromstring, 0, sizeof(pagerfromstring));
12093       strcpy(charset, "ISO-8859-1");
12094       if (emailbody) {
12095          ast_free(emailbody);
12096          emailbody = NULL;
12097       }
12098       if (emailsubject) {
12099          ast_free(emailsubject);
12100          emailsubject = NULL;
12101       }
12102       if (pagerbody) {
12103          ast_free(pagerbody);
12104          pagerbody = NULL;
12105       }
12106       if (pagersubject) {
12107          ast_free(pagersubject);
12108          pagersubject = NULL;
12109       }
12110       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
12111          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
12112       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
12113          ast_copy_string(fromstring, val, sizeof(fromstring));
12114       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
12115          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
12116       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
12117          ast_copy_string(charset, val, sizeof(charset));
12118       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
12119          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12120          for (x = 0; x < 4; x++) {
12121             memcpy(&adsifdn[x], &tmpadsi[x], 1);
12122          }
12123       }
12124       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
12125          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12126          for (x = 0; x < 4; x++) {
12127             memcpy(&adsisec[x], &tmpadsi[x], 1);
12128          }
12129       }
12130       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
12131          if (atoi(val)) {
12132             adsiver = atoi(val);
12133          }
12134       }
12135       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
12136          ast_copy_string(zonetag, val, sizeof(zonetag));
12137       }
12138       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
12139          ast_copy_string(locale, val, sizeof(locale));
12140       }
12141       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
12142          emailsubject = ast_strdup(val);
12143       }
12144       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
12145          emailbody = ast_strdup(substitute_escapes(val));
12146       }
12147       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
12148          pagersubject = ast_strdup(val);
12149       }
12150       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
12151          pagerbody = ast_strdup(substitute_escapes(val));
12152       }
12153       AST_LIST_UNLOCK(&users);
12154       ast_config_destroy(cfg);
12155 
12156       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
12157          start_poll_thread();
12158       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
12159          stop_poll_thread();;
12160 
12161       return 0;
12162    } else {
12163       AST_LIST_UNLOCK(&users);
12164       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
12165       if (ucfg)
12166          ast_config_destroy(ucfg);
12167       return 0;
12168    }
12169 }

static int load_module ( void   )  [static]

Definition at line 12661 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_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(), vmauthenticate(), and vmsayname_exec().

12662 {
12663    int res;
12664    my_umask = umask(0);
12665    umask(my_umask);
12666 
12667    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
12668       return AST_MODULE_LOAD_DECLINE;
12669    }
12670 
12671    /* compute the location of the voicemail spool directory */
12672    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
12673    
12674    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
12675       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
12676    }
12677 
12678    if ((res = load_config(0)))
12679       return res;
12680 
12681    res = ast_register_application_xml(app, vm_exec);
12682    res |= ast_register_application_xml(app2, vm_execmain);
12683    res |= ast_register_application_xml(app3, vm_box_exists);
12684    res |= ast_register_application_xml(app4, vmauthenticate);
12685    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
12686    res |= ast_custom_function_register(&mailbox_exists_acf);
12687    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
12688 #ifdef TEST_FRAMEWORK
12689    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
12690    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
12691    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
12692    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
12693 #endif
12694 
12695    if (res)
12696       return res;
12697 
12698    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12699    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
12700 
12701    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
12702    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
12703    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
12704 
12705    return res;
12706 }

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

01581 {
01582    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01583 }

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

References add_email_attachment(), ast_channel_release(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_localtime(), ast_log(), 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, config_flags, 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, ast_channel::name, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

04404 {
04405    char date[256];
04406    char host[MAXHOSTNAMELEN] = "";
04407    char who[256];
04408    char bound[256];
04409    char dur[256];
04410    struct ast_tm tm;
04411    char enc_cidnum[256] = "", enc_cidname[256] = "";
04412    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04413    char *greeting_attachment; 
04414    char filename[256];
04415 
04416    if (!str1 || !str2) {
04417       ast_free(str1);
04418       ast_free(str2);
04419       return;
04420    }
04421 
04422    if (cidnum) {
04423       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04424    }
04425    if (cidname) {
04426       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04427    }
04428    gethostname(host, sizeof(host) - 1);
04429 
04430    if (strchr(srcemail, '@')) {
04431       ast_copy_string(who, srcemail, sizeof(who));
04432    } else {
04433       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04434    }
04435 
04436    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04437    if (greeting_attachment) {
04438       *greeting_attachment++ = '\0';
04439    }
04440 
04441    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04442    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04443    fprintf(p, "Date: %s" ENDL, date);
04444 
04445    /* Set date format for voicemail mail */
04446    ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04447 
04448    if (!ast_strlen_zero(fromstring)) {
04449       struct ast_channel *ast;
04450       if ((ast = ast_dummy_channel_alloc())) {
04451          char *ptr;
04452          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04453          ast_str_substitute_variables(&str1, 0, ast, fromstring);
04454 
04455          if (check_mime(ast_str_buffer(str1))) {
04456             int first_line = 1;
04457             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04458             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04459                *ptr = '\0';
04460                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04461                first_line = 0;
04462                /* Substring is smaller, so this will never grow */
04463                ast_str_set(&str2, 0, "%s", ptr + 1);
04464             }
04465             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04466          } else {
04467             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04468          }
04469          ast = ast_channel_release(ast);
04470       } else {
04471          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04472       }
04473    } else {
04474       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04475    }
04476 
04477    if (check_mime(vmu->fullname)) {
04478       int first_line = 1;
04479       char *ptr;
04480       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
04481       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04482          *ptr = '\0';
04483          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04484          first_line = 0;
04485          /* Substring is smaller, so this will never grow */
04486          ast_str_set(&str2, 0, "%s", ptr + 1);
04487       }
04488       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
04489    } else {
04490       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
04491    }
04492 
04493    if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
04494       char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
04495       struct ast_channel *ast;
04496       if ((ast = ast_dummy_channel_alloc())) {
04497          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04498          ast_str_substitute_variables(&str1, 0, ast, e_subj);
04499          if (check_mime(ast_str_buffer(str1))) {
04500             int first_line = 1;
04501             char *ptr;
04502             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04503             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04504                *ptr = '\0';
04505                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04506                first_line = 0;
04507                /* Substring is smaller, so this will never grow */
04508                ast_str_set(&str2, 0, "%s", ptr + 1);
04509             }
04510             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04511          } else {
04512             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04513          }
04514          ast = ast_channel_release(ast);
04515       } else {
04516          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04517       }
04518    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04519       if (ast_strlen_zero(flag)) {
04520          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04521       } else {
04522          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04523       }
04524    } else {
04525       if (ast_strlen_zero(flag)) {
04526          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04527       } else {
04528          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04529       }
04530    }
04531 
04532    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1,
04533       (unsigned int) ast_random(), mailbox, (int) getpid(), host);
04534    if (imap) {
04535       /* additional information needed for IMAP searching */
04536       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04537       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04538       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04539       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04540 #ifdef IMAP_STORAGE
04541       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04542 #else
04543       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04544 #endif
04545       /* flag added for Urgent */
04546       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04547       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04548       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04549       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04550       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04551       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04552       if (!ast_strlen_zero(category)) {
04553          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04554       } else {
04555          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04556       }
04557       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04558       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04559       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
04560    }
04561    if (!ast_strlen_zero(cidnum)) {
04562       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04563    }
04564    if (!ast_strlen_zero(cidname)) {
04565       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04566    }
04567    fprintf(p, "MIME-Version: 1.0" ENDL);
04568    if (attach_user_voicemail) {
04569       /* Something unique. */
04570       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox,
04571          (int) getpid(), (unsigned int) ast_random());
04572 
04573       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04574       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04575       fprintf(p, "--%s" ENDL, bound);
04576    }
04577    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04578    if (emailbody || vmu->emailbody) {
04579       char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
04580       struct ast_channel *ast;
04581       if ((ast = ast_dummy_channel_alloc())) {
04582          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04583          ast_str_substitute_variables(&str1, 0, ast, e_body);
04584 #ifdef IMAP_STORAGE
04585             {
04586                /* Convert body to native line terminators for IMAP backend */
04587                char *line = ast_str_buffer(str1), *next;
04588                do {
04589                   /* Terminate line before outputting it to the file */
04590                   if ((next = strchr(line, '\n'))) {
04591                      *next++ = '\0';
04592                   }
04593                   fprintf(p, "%s" ENDL, line);
04594                   line = next;
04595                } while (!ast_strlen_zero(line));
04596             }
04597 #else
04598          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04599 #endif
04600          ast = ast_channel_release(ast);
04601       } else {
04602          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04603       }
04604    } else if (msgnum > -1) {
04605       if (strcmp(vmu->mailbox, mailbox)) {
04606          /* Forwarded type */
04607          struct ast_config *msg_cfg;
04608          const char *v;
04609          int inttime;
04610          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04611          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04612          /* Retrieve info from VM attribute file */
04613          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04614          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04615          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04616             strcat(fromfile, ".txt");
04617          }
04618          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04619             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04620                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04621             }
04622 
04623             /* You might be tempted to do origdate, except that a) it's in the wrong
04624              * format, and b) it's missing for IMAP recordings. */
04625             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04626                struct timeval tv = { inttime, };
04627                struct ast_tm tm;
04628                ast_localtime(&tv, &tm, NULL);
04629                ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04630             }
04631             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04632                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04633                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04634                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04635                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04636                date, origcallerid, origdate);
04637             ast_config_destroy(msg_cfg);
04638          } else {
04639             goto plain_message;
04640          }
04641       } else {
04642 plain_message:
04643          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04644             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04645             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04646             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04647             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04648       }
04649    } else {
04650       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04651             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04652    }
04653 
04654    if (imap || attach_user_voicemail) {
04655       if (!ast_strlen_zero(attach2)) {
04656          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04657          ast_debug(5, "creating second attachment filename %s\n", filename);
04658          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04659          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04660          ast_debug(5, "creating attachment filename %s\n", filename);
04661          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04662       } else {
04663          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04664          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04665          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04666       }
04667    }
04668    ast_free(str1);
04669    ast_free(str2);
04670 }

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

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

01598 {
01599    return snprintf(dest, len, "%s/msg%04d", dir, num);
01600 }

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

Manager list voicemail users command.

Definition at line 11320 of file app_voicemail.c.

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

11321 {
11322    struct ast_vm_user *vmu = NULL;
11323    const char *id = astman_get_header(m, "ActionID");
11324    char actionid[128] = "";
11325 
11326    if (!ast_strlen_zero(id))
11327       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11328 
11329    AST_LIST_LOCK(&users);
11330 
11331    if (AST_LIST_EMPTY(&users)) {
11332       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11333       AST_LIST_UNLOCK(&users);
11334       return RESULT_SUCCESS;
11335    }
11336    
11337    astman_send_ack(s, m, "Voicemail user list will follow");
11338    
11339    AST_LIST_TRAVERSE(&users, vmu, list) {
11340       char dirname[256];
11341 
11342 #ifdef IMAP_STORAGE
11343       int new, old;
11344       inboxcount(vmu->mailbox, &new, &old);
11345 #endif
11346       
11347       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11348       astman_append(s,
11349          "%s"
11350          "Event: VoicemailUserEntry\r\n"
11351          "VMContext: %s\r\n"
11352          "VoiceMailbox: %s\r\n"
11353          "Fullname: %s\r\n"
11354          "Email: %s\r\n"
11355          "Pager: %s\r\n"
11356          "ServerEmail: %s\r\n"
11357          "MailCommand: %s\r\n"
11358          "Language: %s\r\n"
11359          "TimeZone: %s\r\n"
11360          "Callback: %s\r\n"
11361          "Dialout: %s\r\n"
11362          "UniqueID: %s\r\n"
11363          "ExitContext: %s\r\n"
11364          "SayDurationMinimum: %d\r\n"
11365          "SayEnvelope: %s\r\n"
11366          "SayCID: %s\r\n"
11367          "AttachMessage: %s\r\n"
11368          "AttachmentFormat: %s\r\n"
11369          "DeleteMessage: %s\r\n"
11370          "VolumeGain: %.2f\r\n"
11371          "CanReview: %s\r\n"
11372          "CallOperator: %s\r\n"
11373          "MaxMessageCount: %d\r\n"
11374          "MaxMessageLength: %d\r\n"
11375          "NewMessageCount: %d\r\n"
11376 #ifdef IMAP_STORAGE
11377          "OldMessageCount: %d\r\n"
11378          "IMAPUser: %s\r\n"
11379 #endif
11380          "\r\n",
11381          actionid,
11382          vmu->context,
11383          vmu->mailbox,
11384          vmu->fullname,
11385          vmu->email,
11386          vmu->pager,
11387          vmu->serveremail,
11388          vmu->mailcmd,
11389          vmu->language,
11390          vmu->zonetag,
11391          vmu->callback,
11392          vmu->dialout,
11393          vmu->uniqueid,
11394          vmu->exit,
11395          vmu->saydurationm,
11396          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11397          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11398          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11399          vmu->attachfmt,
11400          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11401          vmu->volgain,
11402          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11403          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11404          vmu->maxmsg,
11405          vmu->maxsecs,
11406 #ifdef IMAP_STORAGE
11407          new, old, vmu->imapuser
11408 #else
11409          count_messages(vmu, dirname)
11410 #endif
11411          );
11412    }     
11413    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11414 
11415    AST_LIST_UNLOCK(&users);
11416 
11417    return RESULT_SUCCESS;
11418 }

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

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

11155 {
11156    while (poll_thread_run) {
11157       struct timespec ts = { 0, };
11158       struct timeval wait;
11159 
11160       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11161       ts.tv_sec = wait.tv_sec;
11162       ts.tv_nsec = wait.tv_usec * 1000;
11163 
11164       ast_mutex_lock(&poll_lock);
11165       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11166       ast_mutex_unlock(&poll_lock);
11167 
11168       if (!poll_thread_run)
11169          break;
11170 
11171       poll_subscribed_mailboxes();
11172    }
11173 
11174    return NULL;
11175 }

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

Definition at line 1658 of file app_voicemail.c.

References ARRAY_LEN.

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

01659 {
01660 #ifdef IMAP_STORAGE
01661    if (vmu && id == 0) {
01662       return vmu->imapfolder;
01663    }
01664 #endif
01665    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01666 }

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

Definition at line 5249 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

05250 {
05251    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05252 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11177 of file app_voicemail.c.

References ast_free, and mwi_sub.

Referenced by handle_unsubscribe().

11178 {
11179    ast_free(mwi_sub);
11180 }

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

Definition at line 11255 of file app_voicemail.c.

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

Referenced by start_poll_thread().

11256 {
11257    struct mwi_sub_task *mwist;
11258    
11259    if (ast_event_get_type(event) != AST_EVENT_SUB)
11260       return;
11261 
11262    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11263       return;
11264 
11265    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11266       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11267       return;
11268    }
11269    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11270    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11271    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11272    
11273    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11274       ast_free(mwist);
11275    }
11276 }

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

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

11240 {
11241    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11242    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11243       return;
11244 
11245    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11246       return;
11247 
11248    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11249    *uniqueid = u;
11250    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11251       ast_free(uniqueid);
11252    }
11253 }

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

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_unlock, ast_log(), 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.

06854 {
06855    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06856    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06857    const char *category;
06858    char *myserveremail = serveremail;
06859 
06860    ast_channel_lock(chan);
06861    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06862       category = ast_strdupa(category);
06863    }
06864    ast_channel_unlock(chan);
06865 
06866 #ifndef IMAP_STORAGE
06867    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06868 #else
06869    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
06870 #endif
06871    make_file(fn, sizeof(fn), todir, msgnum);
06872    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06873 
06874    if (!ast_strlen_zero(vmu->attachfmt)) {
06875       if (strstr(fmt, vmu->attachfmt))
06876          fmt = vmu->attachfmt;
06877       else
06878          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);
06879    }
06880 
06881    /* Attach only the first format */
06882    fmt = ast_strdupa(fmt);
06883    stringp = fmt;
06884    strsep(&stringp, "|");
06885 
06886    if (!ast_strlen_zero(vmu->serveremail))
06887       myserveremail = vmu->serveremail;
06888 
06889    if (!ast_strlen_zero(vmu->email)) {
06890       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06891 
06892       if (attach_user_voicemail)
06893          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06894 
06895       /* XXX possible imap issue, should category be NULL XXX */
06896       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06897 
06898       if (attach_user_voicemail)
06899          DISPOSE(todir, msgnum);
06900    }
06901 
06902    if (!ast_strlen_zero(vmu->pager)) {
06903       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
06904    }
06905 
06906    if (ast_test_flag(vmu, VM_DELETE))
06907       DELETE(todir, msgnum, fn, vmu);
06908 
06909    /* Leave voicemail for someone */
06910    if (ast_app_has_voicemail(ext_context, NULL)) 
06911       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06912 
06913    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06914 
06915    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);
06916    run_externnotify(vmu->context, vmu->mailbox, flag);
06917 
06918 #ifdef IMAP_STORAGE
06919    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06920    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06921       vm_imap_delete(NULL, vms->curmsg, vmu);
06922       vms->newmessages--;  /* Fix new message count */
06923    }
06924 #endif
06925 
06926    return 0;
06927 }

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

utility used by base_encode()

Definition at line 4123 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04124 {
04125    if (bio->linelength >= BASELINELEN) {
04126       if (fputs(ENDL, so) == EOF) {
04127          return -1;
04128       }
04129 
04130       bio->linelength = 0;
04131    }
04132 
04133    if (putc(((unsigned char) c), so) == EOF) {
04134       return -1;
04135    }
04136 
04137    bio->linelength++;
04138 
04139    return 1;
04140 }

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

Definition at line 7687 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(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

Referenced by vm_execmain().

07688 {
07689    int count_msg, last_msg;
07690 
07691    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07692 
07693    /* Rename the member vmbox HERE so that we don't try to return before
07694     * we know what's going on.
07695     */
07696    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07697 
07698    /* Faster to make the directory than to check if it exists. */
07699    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07700 
07701    /* traverses directory using readdir (or select query for ODBC) */
07702    count_msg = count_messages(vmu, vms->curdir);
07703    if (count_msg < 0) {
07704       return count_msg;
07705    } else {
07706       vms->lastmsg = count_msg - 1;
07707    }
07708 
07709    if (vm_allocate_dh(vms, vmu, count_msg)) {
07710       return -1;
07711    }
07712 
07713    /*
07714    The following test is needed in case sequencing gets messed up.
07715    There appears to be more than one way to mess up sequence, so
07716    we will not try to find all of the root causes--just fix it when
07717    detected.
07718    */
07719 
07720    if (vm_lock_path(vms->curdir)) {
07721       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07722       return ERROR_LOCK_PATH;
07723    }
07724 
07725    /* for local storage, checks directory for messages up to maxmsg limit */
07726    last_msg = last_message_index(vmu, vms->curdir);
07727    ast_unlock_path(vms->curdir);
07728 
07729    if (last_msg < -1) {
07730       return last_msg;
07731    } else if (vms->lastmsg != last_msg) {
07732       ast_log(LOG_NOTICE, "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);
07733    }
07734 
07735    return 0;
07736 }

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

Definition at line 7473 of file app_voicemail.c.

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

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

07474 {
07475    int res = 0;
07476    char filename[256], *cid;
07477    const char *origtime, *context, *category, *duration, *flag;
07478    struct ast_config *msg_cfg;
07479    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07480 
07481    vms->starting = 0;
07482    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07483    adsi_message(chan, vms);
07484    if (!vms->curmsg)
07485       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07486    else if (vms->curmsg == vms->lastmsg)
07487       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07488 
07489    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07490    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07491    msg_cfg = ast_config_load(filename, config_flags);
07492    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07493       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07494       return 0;
07495    }
07496    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07497 
07498    /* Play the word urgent if we are listening to urgent messages */
07499    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07500       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07501    }
07502 
07503    if (!res) {
07504       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07505       /* POLISH syntax */
07506       if (!strncasecmp(chan->language, "pl", 2)) {
07507          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07508             int ten, one;
07509             char nextmsg[256];
07510             ten = (vms->curmsg + 1) / 10;
07511             one = (vms->curmsg + 1) % 10;
07512 
07513             if (vms->curmsg < 20) {
07514                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07515                res = wait_file2(chan, vms, nextmsg);
07516             } else {
07517                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07518                res = wait_file2(chan, vms, nextmsg);
07519                if (one > 0) {
07520                   if (!res) {
07521                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07522                      res = wait_file2(chan, vms, nextmsg);
07523                   }
07524                }
07525             }
07526          }
07527          if (!res)
07528             res = wait_file2(chan, vms, "vm-message");
07529       /* HEBREW syntax */
07530       } else if (!strncasecmp(chan->language, "he", 2)) {
07531          if (!vms->curmsg) {
07532             res = wait_file2(chan, vms, "vm-message");
07533             res = wait_file2(chan, vms, "vm-first");
07534          } else if (vms->curmsg == vms->lastmsg) {
07535             res = wait_file2(chan, vms, "vm-message");
07536             res = wait_file2(chan, vms, "vm-last");
07537          } else {
07538             res = wait_file2(chan, vms, "vm-message");
07539             res = wait_file2(chan, vms, "vm-number");
07540             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07541          }
07542       /* VIETNAMESE syntax */
07543       } else if (!strncasecmp(chan->language, "vi", 2)) {
07544          if (!vms->curmsg) {
07545             res = wait_file2(chan, vms, "vm-message");
07546             res = wait_file2(chan, vms, "vm-first");
07547          } else if (vms->curmsg == vms->lastmsg) {
07548             res = wait_file2(chan, vms, "vm-message");
07549             res = wait_file2(chan, vms, "vm-last");
07550          } else {
07551             res = wait_file2(chan, vms, "vm-message");
07552             res = wait_file2(chan, vms, "vm-number");
07553             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07554          }
07555       } else {
07556          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07557             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07558          } else { /* DEFAULT syntax */
07559             res = wait_file2(chan, vms, "vm-message");
07560          }
07561          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07562             if (!res) {
07563                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07564             }
07565          }
07566       }
07567    }
07568 
07569    if (!msg_cfg) {
07570       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07571       return 0;
07572    }
07573 
07574    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07575       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07576       DISPOSE(vms->curdir, vms->curmsg);
07577       ast_config_destroy(msg_cfg);
07578       return 0;
07579    }
07580 
07581    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07582    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07583    category = ast_variable_retrieve(msg_cfg, "message", "category");
07584 
07585    context = ast_variable_retrieve(msg_cfg, "message", "context");
07586    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07587       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07588    if (!res) {
07589       res = play_message_category(chan, category);
07590    }
07591    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07592       res = play_message_datetime(chan, vmu, origtime, filename);
07593    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07594       res = play_message_callerid(chan, vms, cid, context, 0);
07595    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07596       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07597    /* Allow pressing '1' to skip envelope / callerid */
07598    if (res == '1')
07599       res = 0;
07600    ast_config_destroy(msg_cfg);
07601 
07602    if (!res) {
07603       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07604       vms->heard[vms->curmsg] = 1;
07605 #ifdef IMAP_STORAGE
07606       /*IMAP storage stores any prepended message from a forward
07607        * as a separate file from the rest of the message
07608        */
07609       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07610          wait_file(chan, vms, vms->introfn);
07611       }
07612 #endif
07613       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07614          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07615          res = 0;
07616       }
07617    }
07618    DISPOSE(vms->curdir, vms->curmsg);
07619    return res;
07620 }

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

Definition at line 7359 of file app_voicemail.c.

References ast_callerid_parse(), ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_say_digit_str(), ast_stream_and_wait(), ast_strlen_zero(), ast_verb, cidinternalcontexts, ast_channel::language, MAX_NUM_CID_CONTEXTS, and wait_file2().

Referenced by advanced_options(), and play_message().

07360 {
07361    int res = 0;
07362    int i;
07363    char *callerid, *name;
07364    char prefile[PATH_MAX] = "";
07365    
07366 
07367    /* If voicemail cid is not enabled, or we didn't get cid or context from
07368     * the attribute file, leave now.
07369     *
07370     * TODO Still need to change this so that if this function is called by the
07371     * message envelope (and someone is explicitly requesting to hear the CID),
07372     * it does not check to see if CID is enabled in the config file.
07373     */
07374    if ((cid == NULL)||(context == NULL))
07375       return res;
07376 
07377    /* Strip off caller ID number from name */
07378    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07379    ast_callerid_parse(cid, &name, &callerid);
07380    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07381       /* Check for internal contexts and only */
07382       /* say extension when the call didn't come from an internal context in the list */
07383       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07384          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07385          if ((strcmp(cidinternalcontexts[i], context) == 0))
07386             break;
07387       }
07388       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07389          if (!res) {
07390             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07391             if (!ast_strlen_zero(prefile)) {
07392             /* See if we can find a recorded name for this person instead of their extension number */
07393                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07394                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07395                   if (!callback)
07396                      res = wait_file2(chan, vms, "vm-from");
07397                   res = ast_stream_and_wait(chan, prefile, "");
07398                } else {
07399                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07400                   /* Say "from extension" as one saying to sound smoother */
07401                   if (!callback)
07402                      res = wait_file2(chan, vms, "vm-from-extension");
07403                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07404                }
07405             }
07406          }
07407       } else if (!res) {
07408          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07409          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07410          if (!callback)
07411             res = wait_file2(chan, vms, "vm-from-phonenumber");
07412          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07413       }
07414    } else {
07415       /* Number unknown */
07416       ast_debug(1, "VM-CID: From an unknown number\n");
07417       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07418       res = wait_file2(chan, vms, "vm-unknown-caller");
07419    }
07420    return res;
07421 }

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

Definition at line 7270 of file app_voicemail.c.

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

Referenced by play_message().

07271 {
07272    int res = 0;
07273 
07274    if (!ast_strlen_zero(category))
07275       res = ast_play_and_wait(chan, category);
07276 
07277    if (res) {
07278       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07279       res = 0;
07280    }
07281 
07282    return res;
07283 }

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

Definition at line 7285 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

07286 {
07287    int res = 0;
07288    struct vm_zone *the_zone = NULL;
07289    time_t t;
07290 
07291    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07292       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07293       return 0;
07294    }
07295 
07296    /* Does this user have a timezone specified? */
07297    if (!ast_strlen_zero(vmu->zonetag)) {
07298       /* Find the zone in the list */
07299       struct vm_zone *z;
07300       AST_LIST_LOCK(&zones);
07301       AST_LIST_TRAVERSE(&zones, z, list) {
07302          if (!strcmp(z->name, vmu->zonetag)) {
07303             the_zone = z;
07304             break;
07305          }
07306       }
07307       AST_LIST_UNLOCK(&zones);
07308    }
07309 
07310 /* No internal variable parsing for now, so we'll comment it out for the time being */
07311 #if 0
07312    /* Set the DIFF_* variables */
07313    ast_localtime(&t, &time_now, NULL);
07314    tv_now = ast_tvnow();
07315    ast_localtime(&tv_now, &time_then, NULL);
07316 
07317    /* Day difference */
07318    if (time_now.tm_year == time_then.tm_year)
07319       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07320    else
07321       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07322    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07323 
07324    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07325 #endif
07326    if (the_zone) {
07327       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07328    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07329       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07330    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07331       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07332    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07333       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
07334    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07335       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07336    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07337       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07338    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07339       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07340    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07341       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
07342    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07343       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07344    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07345       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07346    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07347       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL);
07348    } else {
07349       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07350    }
07351 #if 0
07352    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07353 #endif
07354    return res;
07355 }

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

Definition at line 7423 of file app_voicemail.c.

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

Referenced by play_message().

07424 {
07425    int res = 0;
07426    int durationm;
07427    int durations;
07428    /* Verify that we have a duration for the message */
07429    if (duration == NULL)
07430       return res;
07431 
07432    /* Convert from seconds to minutes */
07433    durations = atoi(duration);
07434    durationm = (durations / 60);
07435 
07436    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07437 
07438    if ((!res) && (durationm >= minduration)) {
07439       res = wait_file2(chan, vms, "vm-duration");
07440 
07441       /* POLISH syntax */
07442       if (!strncasecmp(chan->language, "pl", 2)) {
07443          div_t num = div(durationm, 10);
07444 
07445          if (durationm == 1) {
07446             res = ast_play_and_wait(chan, "digits/1z");
07447             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07448          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07449             if (num.rem == 2) {
07450                if (!num.quot) {
07451                   res = ast_play_and_wait(chan, "digits/2-ie");
07452                } else {
07453                   res = say_and_wait(chan, durationm - 2 , chan->language);
07454                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07455                }
07456             } else {
07457                res = say_and_wait(chan, durationm, chan->language);
07458             }
07459             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07460          } else {
07461             res = say_and_wait(chan, durationm, chan->language);
07462             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07463          }
07464       /* DEFAULT syntax */
07465       } else {
07466          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07467          res = wait_file2(chan, vms, "vm-minutes");
07468       }
07469    }
07470    return res;
07471 }

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

Definition at line 12968 of file app_voicemail.c.

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

12971 {
12972    /* Record message & let caller review or re-record it, or set options if applicable */
12973    int res = 0;
12974    int cmd = 0;
12975    int max_attempts = 3;
12976    int attempts = 0;
12977    int recorded = 0;
12978    int msg_exists = 0;
12979    signed char zero_gain = 0;
12980    char tempfile[PATH_MAX];
12981    char *acceptdtmf = "#";
12982    char *canceldtmf = "";
12983    int canceleddtmf = 0;
12984 
12985    /* Note that urgent and private are for flagging messages as such in the future */
12986 
12987    /* barf if no pointer passed to store duration in */
12988    if (duration == NULL) {
12989       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
12990       return -1;
12991    }
12992 
12993    if (!outsidecaller)
12994       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
12995    else
12996       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
12997 
12998    cmd = '3';  /* Want to start by recording */
12999 
13000    while ((cmd >= 0) && (cmd != 't')) {
13001       switch (cmd) {
13002       case '1':
13003          if (!msg_exists) {
13004             /* In this case, 1 is to record a message */
13005             cmd = '3';
13006             break;
13007          } else {
13008             /* Otherwise 1 is to save the existing message */
13009             ast_verb(3, "Saving message as is\n");
13010             if (!outsidecaller) 
13011                ast_filerename(tempfile, recordfile, NULL);
13012             ast_stream_and_wait(chan, "vm-msgsaved", "");
13013             if (!outsidecaller) {
13014                /* Saves to IMAP server only if imapgreeting=yes */
13015                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13016                DISPOSE(recordfile, -1);
13017             }
13018             cmd = 't';
13019             return res;
13020          }
13021       case '2':
13022          /* Review */
13023          ast_verb(3, "Reviewing the message\n");
13024          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13025          break;
13026       case '3':
13027          msg_exists = 0;
13028          /* Record */
13029          if (recorded == 1) 
13030             ast_verb(3, "Re-recording the message\n");
13031          else  
13032             ast_verb(3, "Recording the message\n");
13033          
13034          if (recorded && outsidecaller) {
13035             cmd = ast_play_and_wait(chan, INTRO);
13036             cmd = ast_play_and_wait(chan, "beep");
13037          }
13038          recorded = 1;
13039          /* 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 */
13040          if (record_gain)
13041             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13042          if (ast_test_flag(vmu, VM_OPERATOR))
13043             canceldtmf = "0";
13044          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13045          if (strchr(canceldtmf, cmd)) {
13046          /* need this flag here to distinguish between pressing '0' during message recording or after */
13047             canceleddtmf = 1;
13048          }
13049          if (record_gain)
13050             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13051          if (cmd == -1) {
13052             /* User has hung up, no options to give */
13053             if (!outsidecaller) {
13054                /* user was recording a greeting and they hung up, so let's delete the recording. */
13055                ast_filedelete(tempfile, NULL);
13056             }     
13057             return cmd;
13058          }
13059          if (cmd == '0') {
13060             break;
13061          } else if (cmd == '*') {
13062             break;
13063 #if 0
13064          } else if (vmu->review && (*duration < 5)) {
13065             /* Message is too short */
13066             ast_verb(3, "Message too short\n");
13067             cmd = ast_play_and_wait(chan, "vm-tooshort");
13068             cmd = ast_filedelete(tempfile, NULL);
13069             break;
13070          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
13071             /* Message is all silence */
13072             ast_verb(3, "Nothing recorded\n");
13073             cmd = ast_filedelete(tempfile, NULL);
13074             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13075             if (!cmd)
13076                cmd = ast_play_and_wait(chan, "vm-speakup");
13077             break;
13078 #endif
13079          } else {
13080             /* If all is well, a message exists */
13081             msg_exists = 1;
13082             cmd = 0;
13083          }
13084          break;
13085       case '4':
13086          if (outsidecaller) {  /* only mark vm messages */
13087             /* Mark Urgent */
13088             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13089                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13090                res = ast_play_and_wait(chan, "vm-marked-urgent");
13091                strcpy(flag, "Urgent");
13092             } else if (flag) {
13093                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13094                res = ast_play_and_wait(chan, "vm-urgent-removed");
13095                strcpy(flag, "");
13096             } else {
13097                ast_play_and_wait(chan, "vm-sorry");
13098             }
13099             cmd = 0;
13100          } else {
13101             cmd = ast_play_and_wait(chan, "vm-sorry");
13102          }
13103          break;
13104       case '5':
13105       case '6':
13106       case '7':
13107       case '8':
13108       case '9':
13109       case '*':
13110       case '#':
13111          cmd = ast_play_and_wait(chan, "vm-sorry");
13112          break;
13113 #if 0 
13114 /*  XXX Commented out for the moment because of the dangers of deleting
13115     a message while recording (can put the message numbers out of sync) */
13116       case '*':
13117          /* Cancel recording, delete message, offer to take another message*/
13118          cmd = ast_play_and_wait(chan, "vm-deleted");
13119          cmd = ast_filedelete(tempfile, NULL);
13120          if (outsidecaller) {
13121             res = vm_exec(chan, NULL);
13122             return res;
13123          }
13124          else
13125             return 1;
13126 #endif
13127       case '0':
13128          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13129             cmd = ast_play_and_wait(chan, "vm-sorry");
13130             break;
13131          }
13132          if (msg_exists || recorded) {
13133             cmd = ast_play_and_wait(chan, "vm-saveoper");
13134             if (!cmd)
13135                cmd = ast_waitfordigit(chan, 3000);
13136             if (cmd == '1') {
13137                ast_filerename(tempfile, recordfile, NULL);
13138                ast_play_and_wait(chan, "vm-msgsaved");
13139                cmd = '0';
13140             } else if (cmd == '4') {
13141                if (flag) {
13142                   ast_play_and_wait(chan, "vm-marked-urgent");
13143                   strcpy(flag, "Urgent");
13144                }
13145                ast_play_and_wait(chan, "vm-msgsaved");
13146                cmd = '0';
13147             } else {
13148                ast_play_and_wait(chan, "vm-deleted");
13149                DELETE(tempfile, -1, tempfile, vmu);
13150                cmd = '0';
13151             }
13152          }
13153          return cmd;
13154       default:
13155          /* If the caller is an ouside caller, and the review option is enabled,
13156             allow them to review the message, but let the owner of the box review
13157             their OGM's */
13158          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13159             return cmd;
13160          if (msg_exists) {
13161             cmd = ast_play_and_wait(chan, "vm-review");
13162             if (!cmd && outsidecaller) {
13163                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13164                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13165                } else if (flag) {
13166                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13167                }
13168             }
13169          } else {
13170             cmd = ast_play_and_wait(chan, "vm-torerecord");
13171             if (!cmd)
13172                cmd = ast_waitfordigit(chan, 600);
13173          }
13174          
13175          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13176             cmd = ast_play_and_wait(chan, "vm-reachoper");
13177             if (!cmd)
13178                cmd = ast_waitfordigit(chan, 600);
13179          }
13180 #if 0
13181          if (!cmd)
13182             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13183 #endif
13184          if (!cmd)
13185             cmd = ast_waitfordigit(chan, 6000);
13186          if (!cmd) {
13187             attempts++;
13188          }
13189          if (attempts > max_attempts) {
13190             cmd = 't';
13191          }
13192       }
13193    }
13194    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13195       /* Hang up or timeout, so delete the recording. */
13196       ast_filedelete(tempfile, NULL);
13197    }
13198 
13199    if (cmd != 't' && outsidecaller)
13200       ast_play_and_wait(chan, "vm-goodbye");
13201 
13202    return cmd;
13203 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11126 of file app_voicemail.c.

References inboxcount2(), mwi_sub, queue_mwi_event(), and run_externnotify().

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11127 {
11128    int new = 0, old = 0, urgent = 0;
11129 
11130    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11131 
11132    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11133       mwi_sub->old_urgent = urgent;
11134       mwi_sub->old_new = new;
11135       mwi_sub->old_old = old;
11136       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11137       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11138    }
11139 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11141 of file app_voicemail.c.

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

Referenced by mb_poll_thread().

11142 {
11143    struct mwi_sub *mwi_sub;
11144 
11145    AST_RWLIST_RDLOCK(&mwi_subs);
11146    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11147       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11148          poll_subscribed_mailbox(mwi_sub);
11149       }
11150    }
11151    AST_RWLIST_UNLOCK(&mwi_subs);
11152 }

static void populate_defaults ( struct ast_vm_user vmu  )  [static]

Sets default voicemail system options to a voicemail user.

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

Definition at line 986 of file app_voicemail.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_vm_user::callback, callcontext, dialcontext, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, exitcontext, globalflags, ast_vm_user::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.

00987 {
00988    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00989    vmu->passwordlocation = passwordlocation;
00990    if (saydurationminfo) {
00991       vmu->saydurationm = saydurationminfo;
00992    }
00993    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00994    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00995    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00996    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00997    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
00998    if (vmminsecs) {
00999       vmu->minsecs = vmminsecs;
01000    }
01001    if (vmmaxsecs) {
01002       vmu->maxsecs = vmmaxsecs;
01003    }
01004    if (maxmsg) {
01005       vmu->maxmsg = maxmsg;
01006    }
01007    if (maxdeletedmsg) {
01008       vmu->maxdeletedmsg = maxdeletedmsg;
01009    }
01010    vmu->volgain = volgain;
01011    vmu->emailsubject = NULL;
01012    vmu->emailbody = NULL;
01013 #ifdef IMAP_STORAGE
01014    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
01015 #endif
01016 }

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

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

04212 {
04213    char callerid[256];
04214    char num[12];
04215    char fromdir[256], fromfile[256];
04216    struct ast_config *msg_cfg;
04217    const char *origcallerid, *origtime;
04218    char origcidname[80], origcidnum[80], origdate[80];
04219    int inttime;
04220    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04221 
04222    /* Prepare variables for substitution in email body and subject */
04223    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04224    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04225    snprintf(num, sizeof(num), "%d", msgnum);
04226    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04227    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04228    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04229    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04230       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04231    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04232    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04233    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04234    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04235    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04236 
04237    /* Retrieve info from VM attribute file */
04238    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04239    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04240    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04241       strcat(fromfile, ".txt");
04242    }
04243    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04244       if (option_debug > 0) {
04245          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04246       }
04247       return;
04248    }
04249 
04250    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04251       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04252       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04253       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04254       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04255    }
04256 
04257    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04258       struct timeval tv = { inttime, };
04259       struct ast_tm tm;
04260       ast_localtime(&tv, &tm, NULL);
04261       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04262       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04263    }
04264    ast_config_destroy(msg_cfg);
04265 }

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

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

06817 {
06818    struct ast_event *event;
06819    char *mailbox, *context;
06820 
06821    /* Strip off @default */
06822    context = mailbox = ast_strdupa(box);
06823    strsep(&context, "@");
06824    if (ast_strlen_zero(context))
06825       context = "default";
06826 
06827    if (!(event = ast_event_new(AST_EVENT_MWI,
06828          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06829          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06830          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06831          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06832          AST_EVENT_IE_END))) {
06833       return;
06834    }
06835 
06836    ast_event_queue_and_cache(event);
06837 }

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

Definition at line 12185 of file app_voicemail.c.

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

Referenced by append_mailbox(), and load_config().

12185                                                                                            {
12186    struct ast_config *pwconf;
12187    struct ast_flags config_flags = { 0 };
12188 
12189    pwconf = ast_config_load(secretfn, config_flags);
12190    if (pwconf) {
12191       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12192       if (val) {
12193          ast_copy_string(password, val, passwordlen);
12194          return;
12195       }
12196    }
12197    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12198 }

static int reload ( void   )  [static]

Definition at line 12622 of file app_voicemail.c.

References load_config().

12623 {
12624    return load_config(1);
12625 }

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

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

03889 {
03890    char stxt[PATH_MAX];
03891    char dtxt[PATH_MAX];
03892    ast_filerename(sfn, dfn, NULL);
03893    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03894    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03895    if (ast_check_realtime("voicemail_data")) {
03896       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03897    }
03898    rename(stxt, dtxt);
03899 }

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

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

Referenced by vm_change_password(), and vm_change_password_shell().

01431 {
01432    /* This function could be made to generate one from a database, too */
01433    struct ast_vm_user *cur;
01434    int res = -1;
01435    AST_LIST_LOCK(&users);
01436    AST_LIST_TRAVERSE(&users, cur, list) {
01437       if ((!context || !strcasecmp(context, cur->context)) &&
01438          (!strcasecmp(mailbox, cur->mailbox)))
01439             break;
01440    }
01441    if (cur) {
01442       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01443       res = 0;
01444    }
01445    AST_LIST_UNLOCK(&users);
01446    return res;
01447 }

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

Definition at line 5392 of file app_voicemail.c.

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

05393 {
05394    char arguments[255];
05395    char ext_context[256] = "";
05396    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05397    struct ast_smdi_mwi_message *mwi_msg;
05398 
05399    if (!ast_strlen_zero(context))
05400       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05401    else
05402       ast_copy_string(ext_context, extension, sizeof(ext_context));
05403 
05404    if (smdi_iface) {
05405       if (ast_app_has_voicemail(ext_context, NULL)) 
05406          ast_smdi_mwi_set(smdi_iface, extension);
05407       else
05408          ast_smdi_mwi_unset(smdi_iface, extension);
05409 
05410       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05411          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05412          if (!strncmp(mwi_msg->cause, "INV", 3))
05413             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05414          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05415             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05416          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05417          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05418       } else {
05419          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05420       }
05421    }
05422 
05423    if (!ast_strlen_zero(externnotify)) {
05424       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05425          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05426       } else {
05427          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05428          ast_debug(1, "Executing %s\n", arguments);
05429          ast_safe_system(arguments);
05430       }
05431    }
05432 }

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

Definition at line 6024 of file app_voicemail.c.

References ast_debug, ast_log(), AST_LOG_NOTICE, ast_mutex_lock, ast_mutex_unlock, ast_unlock_path(), COPY, create_dirpath(), vm_state::curbox, vm_state::curdir, ERROR_LOCK_PATH, EXISTS, last_message_index(), make_file(), mbox(), NEW_FOLDER, OLD_FOLDER, RENAME, vm_state::username, and vm_lock_path().

Referenced by close_mailbox(), and vm_execmain().

06025 {
06026 #ifdef IMAP_STORAGE
06027    /* we must use mbox(x) folder names, and copy the message there */
06028    /* simple. huh? */
06029    char sequence[10];
06030    char mailbox[256];
06031    int res;
06032 
06033    /* get the real IMAP message number for this message */
06034    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06035    
06036    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06037    ast_mutex_lock(&vms->lock);
06038    /* if save to Old folder, put in INBOX as read */
06039    if (box == OLD_FOLDER) {
06040       mail_setflag(vms->mailstream, sequence, "\\Seen");
06041       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06042    } else if (box == NEW_FOLDER) {
06043       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06044       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06045    }
06046    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06047       ast_mutex_unlock(&vms->lock);
06048       return 0;
06049    }
06050    /* Create the folder if it don't exist */
06051    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06052    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06053    if (mail_create(vms->mailstream, mailbox) == NIL) 
06054       ast_debug(5, "Folder exists.\n");
06055    else
06056       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06057    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06058    ast_mutex_unlock(&vms->lock);
06059    return res;
06060 #else
06061    char *dir = vms->curdir;
06062    char *username = vms->username;
06063    char *context = vmu->context;
06064    char sfn[PATH_MAX];
06065    char dfn[PATH_MAX];
06066    char ddir[PATH_MAX];
06067    const char *dbox = mbox(vmu, box);
06068    int x, i;
06069    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06070 
06071    if (vm_lock_path(ddir))
06072       return ERROR_LOCK_PATH;
06073 
06074    x = last_message_index(vmu, ddir) + 1;
06075 
06076    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06077       x--;
06078       for (i = 1; i <= x; i++) {
06079          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06080          make_file(sfn, sizeof(sfn), ddir, i);
06081          make_file(dfn, sizeof(dfn), ddir, i - 1);
06082          if (EXISTS(ddir, i, sfn, NULL)) {
06083             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06084          } else
06085             break;
06086       }
06087    } else {
06088       if (x >= vmu->maxmsg) {
06089          ast_unlock_path(ddir);
06090          return -1;
06091       }
06092    }
06093    make_file(sfn, sizeof(sfn), dir, msg);
06094    make_file(dfn, sizeof(dfn), ddir, x);
06095    if (strcmp(sfn, dfn)) {
06096       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06097    }
06098    ast_unlock_path(ddir);
06099 #endif
06100    return 0;
06101 }

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

Definition at line 6017 of file app_voicemail.c.

References AST_DIGIT_ANY, and ast_say_number().

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

06018 {
06019    int d;
06020    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06021    return d;
06022 }

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

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

12172 {
12173    int res = -1;
12174    char dir[PATH_MAX];
12175    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12176    ast_debug(2, "About to try retrieving name file %s\n", dir);
12177    RETRIEVE(dir, -1, mailbox, context);
12178    if (ast_fileexists(dir, NULL, NULL)) {
12179       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12180    }
12181    DISPOSE(dir, -1);
12182    return res;
12183 }

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

References ast_debug, ast_log(), 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().

04725 {
04726    FILE *p = NULL;
04727    char tmp[80] = "/tmp/astmail-XXXXXX";
04728    char tmp2[256];
04729    char *stringp;
04730 
04731    if (vmu && ast_strlen_zero(vmu->email)) {
04732       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04733       return(0);
04734    }
04735 
04736    /* Mail only the first format */
04737    format = ast_strdupa(format);
04738    stringp = format;
04739    strsep(&stringp, "|");
04740 
04741    if (!strcmp(format, "wav49"))
04742       format = "WAV";
04743    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));
04744    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04745       command hangs */
04746    if ((p = vm_mkftemp(tmp)) == NULL) {
04747       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04748       return -1;
04749    } else {
04750       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04751       fclose(p);
04752       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04753       ast_safe_system(tmp2);
04754       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04755    }
04756    return 0;
04757 }

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

References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_log(), 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().

04760 {
04761    char enc_cidnum[256], enc_cidname[256];
04762    char date[256];
04763    char host[MAXHOSTNAMELEN] = "";
04764    char who[256];
04765    char dur[PATH_MAX];
04766    char tmp[80] = "/tmp/astmail-XXXXXX";
04767    char tmp2[PATH_MAX];
04768    struct ast_tm tm;
04769    FILE *p;
04770    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04771 
04772    if (!str1 || !str2) {
04773       ast_free(str1);
04774       ast_free(str2);
04775       return -1;
04776    }
04777 
04778    if (cidnum) {
04779       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04780    }
04781    if (cidname) {
04782       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04783    }
04784 
04785    if ((p = vm_mkftemp(tmp)) == NULL) {
04786       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04787       ast_free(str1);
04788       ast_free(str2);
04789       return -1;
04790    }
04791    gethostname(host, sizeof(host)-1);
04792    if (strchr(srcemail, '@')) {
04793       ast_copy_string(who, srcemail, sizeof(who));
04794    } else {
04795       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04796    }
04797    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04798    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04799    fprintf(p, "Date: %s\n", date);
04800 
04801    /* Reformat for custom pager format */
04802    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04803 
04804    if (!ast_strlen_zero(pagerfromstring)) {
04805       struct ast_channel *ast;
04806       if ((ast = ast_dummy_channel_alloc())) {
04807          char *ptr;
04808          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04809          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04810 
04811          if (check_mime(ast_str_buffer(str1))) {
04812             int first_line = 1;
04813             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04814             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04815                *ptr = '\0';
04816                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04817                first_line = 0;
04818                /* Substring is smaller, so this will never grow */
04819                ast_str_set(&str2, 0, "%s", ptr + 1);
04820             }
04821             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04822          } else {
04823             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04824          }
04825          ast = ast_channel_release(ast);
04826       } else {
04827          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04828       }
04829    } else {
04830       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04831    }
04832 
04833    if (check_mime(vmu->fullname)) {
04834       int first_line = 1;
04835       char *ptr;
04836       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04837       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04838          *ptr = '\0';
04839          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04840          first_line = 0;
04841          /* Substring is smaller, so this will never grow */
04842          ast_str_set(&str2, 0, "%s", ptr + 1);
04843       }
04844       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04845    } else {
04846       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
04847    }
04848 
04849    if (!ast_strlen_zero(pagersubject)) {
04850       struct ast_channel *ast;
04851       if ((ast = ast_dummy_channel_alloc())) {
04852          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04853          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
04854          if (check_mime(ast_str_buffer(str1))) {
04855             int first_line = 1;
04856             char *ptr;
04857             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04858             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04859                *ptr = '\0';
04860                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04861                first_line = 0;
04862                /* Substring is smaller, so this will never grow */
04863                ast_str_set(&str2, 0, "%s", ptr + 1);
04864             }
04865             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04866          } else {
04867             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04868          }
04869          ast = ast_channel_release(ast);
04870       } else {
04871          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04872       }
04873    } else {
04874       if (ast_strlen_zero(flag)) {
04875          fprintf(p, "Subject: New VM\n\n");
04876       } else {
04877          fprintf(p, "Subject: New %s VM\n\n", flag);
04878       }
04879    }
04880 
04881    if (pagerbody) {
04882       struct ast_channel *ast;
04883       if ((ast = ast_dummy_channel_alloc())) {
04884          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04885          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
04886          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04887          ast = ast_channel_release(ast);
04888       } else {
04889          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04890       }
04891    } else {
04892       fprintf(p, "New %s long %s msg in box %s\n"
04893             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04894    }
04895 
04896    fclose(p);
04897    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04898    ast_safe_system(tmp2);
04899    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04900    ast_free(str1);
04901    ast_free(str2);
04902    return 0;
04903 }

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

Definition at line 10783 of file app_voicemail.c.

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

Referenced by handle_voicemail_show_users().

10784 {
10785    struct ast_config *cfg;
10786    const char *cat = NULL;
10787 
10788    if (!(cfg = ast_load_realtime_multientry("voicemail", 
10789       "context", context, SENTINEL))) {
10790       return CLI_FAILURE;
10791    }
10792 
10793    ast_cli(fd,
10794       "\n"
10795       "=============================================================\n"
10796       "=== Configured Voicemail Users ==============================\n"
10797       "=============================================================\n"
10798       "===\n");
10799 
10800    while ((cat = ast_category_browse(cfg, cat))) {
10801       struct ast_variable *var = NULL;
10802       ast_cli(fd,
10803          "=== Mailbox ...\n"
10804          "===\n");
10805       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
10806          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
10807       ast_cli(fd,
10808          "===\n"
10809          "=== ---------------------------------------------------------\n"
10810          "===\n");
10811    }
10812 
10813    ast_cli(fd,
10814       "=============================================================\n"
10815       "\n");
10816 
10817    ast_config_destroy(cfg);
10818 
10819    return CLI_SUCCESS;
10820 }

static void start_poll_thread ( void   )  [static]

Definition at line 11278 of file app_voicemail.c.

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

Referenced by load_config().

static void stop_poll_thread ( void   )  [static]

Definition at line 11296 of file app_voicemail.c.

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

Referenced by load_config(), and unload_module().

11297 {
11298    poll_thread_run = 0;
11299 
11300    if (mwi_sub_sub) {
11301       ast_event_unsubscribe(mwi_sub_sub);
11302       mwi_sub_sub = NULL;
11303    }
11304 
11305    if (mwi_unsub_sub) {
11306       ast_event_unsubscribe(mwi_unsub_sub);
11307       mwi_unsub_sub = NULL;
11308    }
11309 
11310    ast_mutex_lock(&poll_lock);
11311    ast_cond_signal(&poll_cond);
11312    ast_mutex_unlock(&poll_lock);
11313 
11314    pthread_join(poll_thread, NULL);
11315 
11316    poll_thread = AST_PTHREADT_NULL;
11317 }

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

Referenced by make_email_file(), and sendpage().

00958 {
00959    char *bufptr = buf;
00960    for (; *input; input++) {
00961       if (*input < 32) {
00962          continue;
00963       }
00964       *bufptr++ = *input;
00965       if (bufptr == buf + buflen - 1) {
00966          break;
00967       }
00968    }
00969    *bufptr = '\0';
00970    return buf;
00971 }

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

Definition at line 11442 of file app_voicemail.c.

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

Referenced by load_config().

11443 {
11444    char *current;
11445 
11446    /* Add 16 for fudge factor */
11447    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11448 
11449    ast_str_reset(str);
11450    
11451    /* Substitute strings \r, \n, and \t into the appropriate characters */
11452    for (current = (char *) value; *current; current++) {
11453       if (*current == '\\') {
11454          current++;
11455          if (!*current) {
11456             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11457             break;
11458          }
11459          switch (*current) {
11460          case 'r':
11461             ast_str_append(&str, 0, "\r");
11462             break;
11463          case 'n':
11464 #ifdef IMAP_STORAGE
11465             if (!str->used || str->str[str->used - 1] != '\r') {
11466                ast_str_append(&str, 0, "\r");
11467             }
11468 #endif
11469             ast_str_append(&str, 0, "\n");
11470             break;
11471          case 't':
11472             ast_str_append(&str, 0, "\t");
11473             break;
11474          default:
11475             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11476             break;
11477          }
11478       } else {
11479          ast_str_append(&str, 0, "%c", *current);
11480       }
11481    }
11482 
11483    return ast_str_buffer(str);
11484 }

static int unload_module ( void   )  [static]

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

12628 {
12629    int res;
12630 
12631    res = ast_unregister_application(app);
12632    res |= ast_unregister_application(app2);
12633    res |= ast_unregister_application(app3);
12634    res |= ast_unregister_application(app4);
12635    res |= ast_unregister_application(sayname_app);
12636    res |= ast_custom_function_unregister(&mailbox_exists_acf);
12637    res |= ast_manager_unregister("VoicemailUsersList");
12638    res |= ast_data_unregister(NULL);
12639 #ifdef TEST_FRAMEWORK
12640    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
12641    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
12642    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
12643    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
12644 #endif
12645    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12646    ast_uninstall_vm_functions();
12647    ao2_ref(inprocess_container, -1);
12648 
12649    if (poll_thread != AST_PTHREADT_NULL)
12650       stop_poll_thread();
12651 
12652    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
12653    ast_unload_realtime("voicemail");
12654    ast_unload_realtime("voicemail_data");
12655 
12656    free_vm_users();
12657    free_vm_zones();
12658    return res;
12659 }

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

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

01696                                                                                         {
01697 
01698    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01699    if (!vms->dh_arraysize) {
01700       /* initial allocation */
01701       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01702          return -1;
01703       }
01704       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01705          return -1;
01706       }
01707       vms->dh_arraysize = arraysize;
01708    } else if (vms->dh_arraysize < arraysize) {
01709       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01710          return -1;
01711       }
01712       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01713          return -1;
01714       }
01715       memset(vms->deleted, 0, arraysize * sizeof(int));
01716       memset(vms->heard, 0, arraysize * sizeof(int));
01717       vms->dh_arraysize = arraysize;
01718    }
01719 
01720    return 0;
01721 }

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

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

Referenced by vm_execmain(), and vmauthenticate().

09518 {
09519    int useadsi = 0, valid = 0, logretries = 0;
09520    char password[AST_MAX_EXTENSION]="", *passptr;
09521    struct ast_vm_user vmus, *vmu = NULL;
09522 
09523    /* If ADSI is supported, setup login screen */
09524    adsi_begin(chan, &useadsi);
09525    if (!skipuser && useadsi)
09526       adsi_login(chan);
09527    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09528       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09529       return -1;
09530    }
09531    
09532    /* Authenticate them and get their mailbox/password */
09533    
09534    while (!valid && (logretries < max_logins)) {
09535       /* Prompt for, and read in the username */
09536       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09537          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09538          return -1;
09539       }
09540       if (ast_strlen_zero(mailbox)) {
09541          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09542             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09543          } else {
09544             ast_verb(3, "Username not entered\n"); 
09545             return -1;
09546          }
09547       } else if (mailbox[0] == '*') {
09548          /* user entered '*' */
09549          if (ast_exists_extension(chan, chan->context, "a", 1,
09550             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09551             return -1;
09552          }
09553          mailbox[0] = '\0';
09554       }
09555 
09556       if (useadsi)
09557          adsi_password(chan);
09558 
09559       if (!ast_strlen_zero(prefix)) {
09560          char fullusername[80] = "";
09561          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09562          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09563          ast_copy_string(mailbox, fullusername, mailbox_size);
09564       }
09565 
09566       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09567       vmu = find_user(&vmus, context, mailbox);
09568       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09569          /* saved password is blank, so don't bother asking */
09570          password[0] = '\0';
09571       } else {
09572          if (ast_streamfile(chan, vm_password, chan->language)) {
09573             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09574             return -1;
09575          }
09576          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09577             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09578             return -1;
09579          } else if (password[0] == '*') {
09580             /* user entered '*' */
09581             if (ast_exists_extension(chan, chan->context, "a", 1,
09582                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09583                mailbox[0] = '*';
09584                return -1;
09585             }
09586             mailbox[0] = '\0';
09587          }
09588       }
09589 
09590       if (vmu) {
09591          passptr = vmu->password;
09592          if (passptr[0] == '-') passptr++;
09593       }
09594       if (vmu && !strcmp(passptr, password))
09595          valid++;
09596       else {
09597          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09598          if (!ast_strlen_zero(prefix))
09599             mailbox[0] = '\0';
09600       }
09601       logretries++;
09602       if (!valid) {
09603          if (skipuser || logretries >= max_logins) {
09604             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09605                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09606                return -1;
09607             }
09608          } else {
09609             if (useadsi)
09610                adsi_login(chan);
09611             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09612                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09613                return -1;
09614             }
09615          }
09616          if (ast_waitstream(chan, "")) /* Channel is hung up */
09617             return -1;
09618       }
09619    }
09620    if (!valid && (logretries >= max_logins)) {
09621       ast_stopstream(chan);
09622       ast_play_and_wait(chan, "vm-goodbye");
09623       return -1;
09624    }
09625    if (vmu && !skipuser) {
09626       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09627    }
09628    return 0;
09629 }

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

Definition at line 10678 of file app_voicemail.c.

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

Referenced by load_module().

10679 {
10680    struct ast_vm_user svm;
10681    char *context, *box;
10682    AST_DECLARE_APP_ARGS(args,
10683       AST_APP_ARG(mbox);
10684       AST_APP_ARG(options);
10685    );
10686    static int dep_warning = 0;
10687 
10688    if (ast_strlen_zero(data)) {
10689       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10690       return -1;
10691    }
10692 
10693    if (!dep_warning) {
10694       dep_warning = 1;
10695       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10696    }
10697 
10698    box = ast_strdupa(data);
10699 
10700    AST_STANDARD_APP_ARGS(args, box);
10701 
10702    if (args.options) {
10703    }
10704 
10705    if ((context = strchr(args.mbox, '@'))) {
10706       *context = '\0';
10707       context++;
10708    }
10709 
10710    if (find_user(&svm, context, args.mbox)) {
10711       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10712    } else
10713       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10714 
10715    return 0;
10716 }

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

09495 {
09496    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09497       return vm_browse_messages_es(chan, vms, vmu);
09498    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09499       return vm_browse_messages_gr(chan, vms, vmu);
09500    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09501       return vm_browse_messages_he(chan, vms, vmu);
09502    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09503       return vm_browse_messages_it(chan, vms, vmu);
09504    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09505       return vm_browse_messages_pt(chan, vms, vmu);
09506    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09507       return vm_browse_messages_vi(chan, vms, vmu);
09508    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09509       return vm_browse_messages_zh(chan, vms, vmu);
09510    } else {                                             /* Default to English syntax */
09511       return vm_browse_messages_en(chan, vms, vmu);
09512    }
09513 }

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

09334 {
09335    int cmd = 0;
09336 
09337    if (vms->lastmsg > -1) {
09338       cmd = play_message(chan, vmu, vms);
09339    } else {
09340       cmd = ast_play_and_wait(chan, "vm-youhave");
09341       if (!cmd) 
09342          cmd = ast_play_and_wait(chan, "vm-no");
09343       if (!cmd) {
09344          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09345          cmd = ast_play_and_wait(chan, vms->fn);
09346       }
09347       if (!cmd)
09348          cmd = ast_play_and_wait(chan, "vm-messages");
09349    }
09350    return cmd;
09351 }

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

09388 {
09389    int cmd;
09390 
09391    if (vms->lastmsg > -1) {
09392       cmd = play_message(chan, vmu, vms);
09393    } else {
09394       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09395       if (!cmd)
09396          cmd = ast_play_and_wait(chan, "vm-messages");
09397       if (!cmd) {
09398          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09399          cmd = ast_play_and_wait(chan, vms->fn);
09400       }
09401    }
09402    return cmd;
09403 }

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

09282 {
09283    int cmd = 0;
09284 
09285    if (vms->lastmsg > -1) {
09286       cmd = play_message(chan, vmu, vms);
09287    } else {
09288       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09289       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09290          if (!cmd) {
09291             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09292             cmd = ast_play_and_wait(chan, vms->fn);
09293          }
09294          if (!cmd)
09295             cmd = ast_play_and_wait(chan, "vm-messages");
09296       } else {
09297          if (!cmd)
09298             cmd = ast_play_and_wait(chan, "vm-messages");
09299          if (!cmd) {
09300             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09301             cmd = ast_play_and_wait(chan, vms->fn);
09302          }
09303       }
09304    } 
09305    return cmd;
09306 }

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

Definition at line 9309 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09310 {
09311    int cmd = 0;
09312 
09313    if (vms->lastmsg > -1) {
09314       cmd = play_message(chan, vmu, vms);
09315    } else {
09316       if (!strcasecmp(vms->fn, "INBOX")) {
09317          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09318       } else {
09319          cmd = ast_play_and_wait(chan, "vm-nomessages");
09320       }
09321    }
09322    return cmd;
09323 }

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

09362 {
09363    int cmd;
09364 
09365    if (vms->lastmsg > -1) {
09366       cmd = play_message(chan, vmu, vms);
09367    } else {
09368       cmd = ast_play_and_wait(chan, "vm-no");
09369       if (!cmd)
09370          cmd = ast_play_and_wait(chan, "vm-message");
09371       if (!cmd) {
09372          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09373          cmd = ast_play_and_wait(chan, vms->fn);
09374       }
09375    }
09376    return cmd;
09377 }

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

09414 {
09415    int cmd;
09416 
09417    if (vms->lastmsg > -1) {
09418       cmd = play_message(chan, vmu, vms);
09419    } else {
09420       cmd = ast_play_and_wait(chan, "vm-no");
09421       if (!cmd) {
09422          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09423          cmd = ast_play_and_wait(chan, vms->fn);
09424       }
09425       if (!cmd)
09426          cmd = ast_play_and_wait(chan, "vm-messages");
09427    }
09428    return cmd;
09429 }

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

09468 {
09469    int cmd = 0;
09470 
09471    if (vms->lastmsg > -1) {
09472       cmd = play_message(chan, vmu, vms);
09473    } else {
09474       cmd = ast_play_and_wait(chan, "vm-no");
09475       if (!cmd) {
09476          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09477          cmd = ast_play_and_wait(chan, vms->fn);
09478       }
09479    }
09480    return cmd;
09481 }

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

09440 {
09441    int cmd;
09442 
09443    if (vms->lastmsg > -1) {
09444       cmd = play_message(chan, vmu, vms);
09445    } else {
09446       cmd = ast_play_and_wait(chan, "vm-you");
09447       if (!cmd) 
09448          cmd = ast_play_and_wait(chan, "vm-haveno");
09449       if (!cmd)
09450          cmd = ast_play_and_wait(chan, "vm-messages");
09451       if (!cmd) {
09452          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09453          cmd = ast_play_and_wait(chan, vms->fn);
09454       }
09455    }
09456    return cmd;
09457 }

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 1456 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_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, config_flags, 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().

01457 {
01458    struct ast_config   *cfg = NULL;
01459    struct ast_variable *var = NULL;
01460    struct ast_category *cat = NULL;
01461    char *category = NULL, *value = NULL, *new = NULL;
01462    const char *tmp = NULL;
01463    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01464    char secretfn[PATH_MAX] = "";
01465    int found = 0;
01466 
01467    if (!change_password_realtime(vmu, newpassword))
01468       return;
01469 
01470    /* check if we should store the secret in the spool directory next to the messages */
01471    switch (vmu->passwordlocation) {
01472    case OPT_PWLOC_SPOOLDIR:
01473       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01474       if (write_password_to_file(secretfn, newpassword) == 0) {
01475          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01476          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01477          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01478          break;
01479       } else {
01480          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01481       }
01482       /* Fall-through */
01483    case OPT_PWLOC_VOICEMAILCONF:
01484       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01485          while ((category = ast_category_browse(cfg, category))) {
01486             if (!strcasecmp(category, vmu->context)) {
01487                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01488                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01489                   break;
01490                }
01491                value = strstr(tmp, ",");
01492                if (!value) {
01493                   new = alloca(strlen(newpassword)+1);
01494                   sprintf(new, "%s", newpassword);
01495                } else {
01496                   new = alloca((strlen(value) + strlen(newpassword) + 1));
01497                   sprintf(new, "%s%s", newpassword, value);
01498                }
01499                if (!(cat = ast_category_get(cfg, category))) {
01500                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01501                   break;
01502                }
01503                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01504                found = 1;
01505             }
01506          }
01507          /* save the results */
01508          if (found) {
01509             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01510             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01511             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01512             break;
01513          }
01514       }
01515       /* Fall-through */
01516    case OPT_PWLOC_USERSCONF:
01517       /* check users.conf and update the password stored for the mailbox */
01518       /* if no vmsecret entry exists create one. */
01519       if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01520          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01521          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01522             ast_debug(4, "users.conf: %s\n", category);
01523             if (!strcasecmp(category, vmu->mailbox)) {
01524                if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01525                   ast_debug(3, "looks like we need to make vmsecret!\n");
01526                   var = ast_variable_new("vmsecret", newpassword, "");
01527                } else {
01528                   var = NULL;
01529                }
01530                new = alloca(strlen(newpassword) + 1);
01531                sprintf(new, "%s", newpassword);
01532                if (!(cat = ast_category_get(cfg, category))) {
01533                   ast_debug(4, "failed to get category!\n");
01534                   ast_free(var);
01535                   break;
01536                }
01537                if (!var) {
01538                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01539                } else {
01540                   ast_variable_append(cat, var);
01541                }
01542                found = 1;
01543                break;
01544             }
01545          }
01546          /* save the results and clean things up */
01547          if (found) {
01548             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01549             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01550             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01551          }
01552       }
01553    }
01554 }

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

Definition at line 1556 of file app_voicemail.c.

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

Referenced by vm_newuser(), and vm_options().

01557 {
01558    char buf[255];
01559    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01560    if (!ast_safe_system(buf)) {
01561       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01562       /* Reset the password in memory, too */
01563       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01564    }
01565 }

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

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

01148 {
01149    int fds[2], pid = 0;
01150 
01151    memset(buf, 0, len);
01152 
01153    if (pipe(fds)) {
01154       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01155    } else {
01156       /* good to go*/
01157       pid = ast_safe_fork(0);
01158 
01159       if (pid < 0) {
01160          /* ok maybe not */
01161          close(fds[0]);
01162          close(fds[1]);
01163          snprintf(buf, len, "FAILURE: Fork failed");
01164       } else if (pid) {
01165          /* parent */
01166          close(fds[1]);
01167          if (read(fds[0], buf, len) < 0) {
01168             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01169          }
01170          close(fds[0]);
01171       } else {
01172          /*  child */
01173          AST_DECLARE_APP_ARGS(arg,
01174             AST_APP_ARG(v)[20];
01175          );
01176          char *mycmd = ast_strdupa(command);
01177 
01178          close(fds[0]);
01179          dup2(fds[1], STDOUT_FILENO);
01180          close(fds[1]);
01181          ast_close_fds_above_n(STDOUT_FILENO);
01182 
01183          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01184 
01185          execv(arg.v[0], arg.v); 
01186          printf("FAILURE: %s", strerror(errno));
01187          _exit(0);
01188       }
01189    }
01190    return buf;
01191 }

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

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

04066 {
04067    char *txt;
04068    int txtsize = 0;
04069 
04070    txtsize = (strlen(file) + 5)*sizeof(char);
04071    txt = alloca(txtsize);
04072    /* Sprintf here would safe because we alloca'd exactly the right length,
04073     * but trying to eliminate all sprintf's anyhow
04074     */
04075    if (ast_check_realtime("voicemail_data")) {
04076       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04077    }
04078    snprintf(txt, txtsize, "%s.txt", file);
04079    unlink(txt);
04080    return ast_filedelete(file, NULL);
04081 }

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

Definition at line 10361 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_play_and_wait(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ERROR_LOCK_PATH, ast_flags::flags, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), and vm_app_options.

Referenced by load_module(), and play_record_review().

10362 {
10363    int res = 0;
10364    char *tmp;
10365    struct leave_vm_options leave_options;
10366    struct ast_flags flags = { 0 };
10367    char *opts[OPT_ARG_ARRAY_SIZE];
10368    AST_DECLARE_APP_ARGS(args,
10369       AST_APP_ARG(argv0);
10370       AST_APP_ARG(argv1);
10371    );
10372    
10373    memset(&leave_options, 0, sizeof(leave_options));
10374 
10375    if (chan->_state != AST_STATE_UP)
10376       ast_answer(chan);
10377 
10378    if (!ast_strlen_zero(data)) {
10379       tmp = ast_strdupa(data);
10380       AST_STANDARD_APP_ARGS(args, tmp);
10381       if (args.argc == 2) {
10382          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10383             return -1;
10384          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10385          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10386             int gain;
10387 
10388             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10389                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10390                return -1;
10391             } else {
10392                leave_options.record_gain = (signed char) gain;
10393             }
10394          }
10395          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10396             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10397                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10398          }
10399       }
10400    } else {
10401       char temp[256];
10402       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10403       if (res < 0)
10404          return res;
10405       if (ast_strlen_zero(temp))
10406          return 0;
10407       args.argv0 = ast_strdupa(temp);
10408    }
10409 
10410    res = leave_voicemail(chan, args.argv0, &leave_options);
10411    if (res == 't') {
10412       ast_play_and_wait(chan, "vm-goodbye");
10413       res = 0;
10414    }
10415 
10416    if (res == OPERATOR_EXIT) {
10417       res = 0;
10418    }
10419 
10420    if (res == ERROR_LOCK_PATH) {
10421       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10422       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10423       res = 0;
10424    }
10425 
10426    return res;
10427 }

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

Definition at line 9631 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_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_goto_if_exists(), ast_log(), AST_LOG_ERROR, 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_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, ast_channel::context, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), ast_flags::flags, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, has_voicemail(), language, ast_vm_user::language, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), run_externnotify(), save_to_folder(), say_and_wait(), vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, and VM_SVMAIL.

Referenced by load_module().

09632 {
09633    /* XXX This is, admittedly, some pretty horrendous code.  For some
09634       reason it just seemed a lot easier to do with GOTO's.  I feel
09635       like I'm back in my GWBASIC days. XXX */
09636    int res = -1;
09637    int cmd = 0;
09638    int valid = 0;
09639    char prefixstr[80] ="";
09640    char ext_context[256]="";
09641    int box;
09642    int useadsi = 0;
09643    int skipuser = 0;
09644    struct vm_state vms;
09645    struct ast_vm_user *vmu = NULL, vmus;
09646    char *context = NULL;
09647    int silentexit = 0;
09648    struct ast_flags flags = { 0 };
09649    signed char record_gain = 0;
09650    int play_auto = 0;
09651    int play_folder = 0;
09652    int in_urgent = 0;
09653 #ifdef IMAP_STORAGE
09654    int deleted = 0;
09655 #endif
09656 
09657    /* Add the vm_state to the active list and keep it active */
09658    memset(&vms, 0, sizeof(vms));
09659 
09660    vms.lastmsg = -1;
09661 
09662    memset(&vmus, 0, sizeof(vmus));
09663 
09664    if (chan->_state != AST_STATE_UP) {
09665       ast_debug(1, "Before ast_answer\n");
09666       ast_answer(chan);
09667    }
09668 
09669    if (!ast_strlen_zero(data)) {
09670       char *opts[OPT_ARG_ARRAY_SIZE];
09671       char *parse;
09672       AST_DECLARE_APP_ARGS(args,
09673          AST_APP_ARG(argv0);
09674          AST_APP_ARG(argv1);
09675       );
09676 
09677       parse = ast_strdupa(data);
09678 
09679       AST_STANDARD_APP_ARGS(args, parse);
09680 
09681       if (args.argc == 2) {
09682          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09683             return -1;
09684          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09685             int gain;
09686             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
09687                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09688                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09689                   return -1;
09690                } else {
09691                   record_gain = (signed char) gain;
09692                }
09693             } else {
09694                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
09695             }
09696          }
09697          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
09698             play_auto = 1;
09699             if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
09700                /* See if it is a folder name first */
09701                if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
09702                   if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
09703                      play_folder = -1;
09704                   }
09705                } else {
09706                   play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
09707                }
09708             } else {
09709                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
09710             }
09711             if (play_folder > 9 || play_folder < 0) {
09712                ast_log(AST_LOG_WARNING,
09713                   "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
09714                   opts[OPT_ARG_PLAYFOLDER]);
09715                play_folder = 0;
09716             }
09717          }
09718       } else {
09719          /* old style options parsing */
09720          while (*(args.argv0)) {
09721             if (*(args.argv0) == 's')
09722                ast_set_flag(&flags, OPT_SILENT);
09723             else if (*(args.argv0) == 'p')
09724                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
09725             else 
09726                break;
09727             (args.argv0)++;
09728          }
09729 
09730       }
09731 
09732       valid = ast_test_flag(&flags, OPT_SILENT);
09733 
09734       if ((context = strchr(args.argv0, '@')))
09735          *context++ = '\0';
09736 
09737       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
09738          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
09739       else
09740          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
09741 
09742       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
09743          skipuser++;
09744       else
09745          valid = 0;
09746    }
09747 
09748    if (!valid)
09749       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
09750 
09751    ast_debug(1, "After vm_authenticate\n");
09752 
09753    if (vms.username[0] == '*') {
09754       ast_debug(1, "user pressed * in context '%s'\n", chan->context);
09755 
09756       /* user entered '*' */
09757       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
09758          res = 0; /* prevent hangup */
09759          goto out;
09760       }
09761    }
09762 
09763    if (!res) {
09764       valid = 1;
09765       if (!skipuser)
09766          vmu = &vmus;
09767    } else {
09768       res = 0;
09769    }
09770 
09771    /* If ADSI is supported, setup login screen */
09772    adsi_begin(chan, &useadsi);
09773 
09774    if (!valid) {
09775       goto out;
09776    }
09777 
09778 #ifdef IMAP_STORAGE
09779    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
09780    pthread_setspecific(ts_vmstate.key, &vms);
09781 
09782    vms.interactive = 1;
09783    vms.updated = 1;
09784    if (vmu)
09785       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
09786    vmstate_insert(&vms);
09787    init_vm_state(&vms);
09788 #endif
09789    /* Avoid allocating a buffer of 0 bytes, because some platforms really don't like that. */
09790    if (!(vms.deleted = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
09791       ast_log(AST_LOG_ERROR, "Could not allocate memory for deleted message storage!\n");
09792       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09793       return -1;
09794    }
09795    if (!(vms.heard = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
09796       ast_log(AST_LOG_ERROR, "Could not allocate memory for heard message storage!\n");
09797       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09798       return -1;
09799    }
09800    
09801    /* Set language from config to override channel language */
09802    if (!ast_strlen_zero(vmu->language))
09803       ast_string_field_set(chan, language, vmu->language);
09804 
09805    /* Retrieve urgent, old and new message counts */
09806    ast_debug(1, "Before open_mailbox\n");
09807    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09808    if (res < 0)
09809       goto out;
09810    vms.oldmessages = vms.lastmsg + 1;
09811    ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
09812    /* check INBOX */
09813    res = open_mailbox(&vms, vmu, NEW_FOLDER);
09814    if (res < 0)
09815       goto out;
09816    vms.newmessages = vms.lastmsg + 1;
09817    ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
09818    /* Start in Urgent */
09819    in_urgent = 1;
09820    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
09821    if (res < 0)
09822       goto out;
09823    vms.urgentmessages = vms.lastmsg + 1;
09824    ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
09825 
09826    /* Select proper mailbox FIRST!! */
09827    if (play_auto) {
09828       if (vms.urgentmessages) {
09829          in_urgent = 1;
09830          res = open_mailbox(&vms, vmu, 11);
09831       } else {
09832          in_urgent = 0;
09833          res = open_mailbox(&vms, vmu, play_folder);
09834       }
09835       if (res < 0)
09836          goto out;
09837 
09838       /* If there are no new messages, inform the user and hangup */
09839       if (vms.lastmsg == -1) {
09840          in_urgent = 0;
09841          cmd = vm_browse_messages(chan, &vms, vmu);
09842          res = 0;
09843          goto out;
09844       }
09845    } else {
09846       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
09847          /* If we only have old messages start here */
09848          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09849          in_urgent = 0;
09850          play_folder = 1;
09851          if (res < 0)
09852             goto out;
09853       } else if (!vms.urgentmessages && vms.newmessages) {
09854          /* If we have new messages but none are urgent */
09855          in_urgent = 0;
09856          res = open_mailbox(&vms, vmu, NEW_FOLDER);
09857          if (res < 0)
09858             goto out;
09859       }
09860    }
09861 
09862    if (useadsi)
09863       adsi_status(chan, &vms);
09864    res = 0;
09865 
09866    /* Check to see if this is a new user */
09867    if (!strcasecmp(vmu->mailbox, vmu->password) && 
09868       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
09869       if (ast_play_and_wait(chan, "vm-newuser") == -1)
09870          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
09871       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
09872       if ((cmd == 't') || (cmd == '#')) {
09873          /* Timeout */
09874          res = 0;
09875          goto out;
09876       } else if (cmd < 0) {
09877          /* Hangup */
09878          res = -1;
09879          goto out;
09880       }
09881    }
09882 #ifdef IMAP_STORAGE
09883       ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
09884       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
09885          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
09886          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09887       }
09888       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09889       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
09890          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09891          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09892       }
09893 #endif
09894    if (play_auto) {
09895       cmd = '1';
09896    } else {
09897       cmd = vm_intro(chan, vmu, &vms);
09898    }
09899 
09900    vms.repeats = 0;
09901    vms.starting = 1;
09902    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09903       /* Run main menu */
09904       switch (cmd) {
09905       case '1': /* First message */
09906          vms.curmsg = 0;
09907          /* Fall through */
09908       case '5': /* Play current message */
09909          cmd = vm_browse_messages(chan, &vms, vmu);
09910          break;
09911       case '2': /* Change folders */
09912          if (useadsi)
09913             adsi_folders(chan, 0, "Change to folder...");
09914          cmd = get_folder2(chan, "vm-changeto", 0);
09915          if (cmd == '#') {
09916             cmd = 0;
09917          } else if (cmd > 0) {
09918             cmd = cmd - '0';
09919             res = close_mailbox(&vms, vmu);
09920             if (res == ERROR_LOCK_PATH)
09921                goto out;
09922             /* If folder is not urgent, set in_urgent to zero! */
09923             if (cmd != 11) in_urgent = 0;
09924             res = open_mailbox(&vms, vmu, cmd);
09925             if (res < 0)
09926                goto out;
09927             play_folder = cmd;
09928             cmd = 0;
09929          }
09930          if (useadsi)
09931             adsi_status2(chan, &vms);
09932             
09933          if (!cmd)
09934             cmd = vm_play_folder_name(chan, vms.vmbox);
09935 
09936          vms.starting = 1;
09937          break;
09938       case '3': /* Advanced options */
09939          cmd = 0;
09940          vms.repeats = 0;
09941          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09942             switch (cmd) {
09943             case '1': /* Reply */
09944                if (vms.lastmsg > -1 && !vms.starting) {
09945                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
09946                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09947                      res = cmd;
09948                      goto out;
09949                   }
09950                } else
09951                   cmd = ast_play_and_wait(chan, "vm-sorry");
09952                cmd = 't';
09953                break;
09954             case '2': /* Callback */
09955                if (!vms.starting)
09956                   ast_verb(3, "Callback Requested\n");
09957                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
09958                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
09959                   if (cmd == 9) {
09960                      silentexit = 1;
09961                      goto out;
09962                   } else if (cmd == ERROR_LOCK_PATH) {
09963                      res = cmd;
09964                      goto out;
09965                   }
09966                } else 
09967                   cmd = ast_play_and_wait(chan, "vm-sorry");
09968                cmd = 't';
09969                break;
09970             case '3': /* Envelope */
09971                if (vms.lastmsg > -1 && !vms.starting) {
09972                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
09973                   if (cmd == ERROR_LOCK_PATH) {
09974                      res = cmd;
09975                      goto out;
09976                   }
09977                } else
09978                   cmd = ast_play_and_wait(chan, "vm-sorry");
09979                cmd = 't';
09980                break;
09981             case '4': /* Dialout */
09982                if (!ast_strlen_zero(vmu->dialout)) {
09983                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
09984                   if (cmd == 9) {
09985                      silentexit = 1;
09986                      goto out;
09987                   }
09988                } else 
09989                   cmd = ast_play_and_wait(chan, "vm-sorry");
09990                cmd = 't';
09991                break;
09992 
09993             case '5': /* Leave VoiceMail */
09994                if (ast_test_flag(vmu, VM_SVMAIL)) {
09995                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
09996                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09997                      res = cmd;
09998                      goto out;
09999                   }
10000                } else
10001                   cmd = ast_play_and_wait(chan, "vm-sorry");
10002                cmd = 't';
10003                break;
10004                
10005             case '*': /* Return to main menu */
10006                cmd = 't';
10007                break;
10008 
10009             default:
10010                cmd = 0;
10011                if (!vms.starting) {
10012                   cmd = ast_play_and_wait(chan, "vm-toreply");
10013                }
10014                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
10015                   cmd = ast_play_and_wait(chan, "vm-tocallback");
10016                }
10017                if (!cmd && !vms.starting) {
10018                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
10019                }
10020                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
10021                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
10022                }
10023                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
10024                   cmd = ast_play_and_wait(chan, "vm-leavemsg");
10025                if (!cmd)
10026                   cmd = ast_play_and_wait(chan, "vm-starmain");
10027                if (!cmd)
10028                   cmd = ast_waitfordigit(chan, 6000);
10029                if (!cmd)
10030                   vms.repeats++;
10031                if (vms.repeats > 3)
10032                   cmd = 't';
10033             }
10034          }
10035          if (cmd == 't') {
10036             cmd = 0;
10037             vms.repeats = 0;
10038          }
10039          break;
10040       case '4': /* Go to the previous message */
10041          if (vms.curmsg > 0) {
10042             vms.curmsg--;
10043             cmd = play_message(chan, vmu, &vms);
10044          } else {
10045             /* Check if we were listening to new
10046                messages.  If so, go to Urgent messages
10047                instead of saying "no more messages"
10048             */
10049             if (in_urgent == 0 && vms.urgentmessages > 0) {
10050                /* Check for Urgent messages */
10051                in_urgent = 1;
10052                res = close_mailbox(&vms, vmu);
10053                if (res == ERROR_LOCK_PATH)
10054                   goto out;
10055                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
10056                if (res < 0)
10057                   goto out;
10058                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
10059                vms.curmsg = vms.lastmsg;
10060                if (vms.lastmsg < 0)
10061                   cmd = ast_play_and_wait(chan, "vm-nomore");
10062             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10063                vms.curmsg = vms.lastmsg;
10064                cmd = play_message(chan, vmu, &vms);
10065             } else {
10066                cmd = ast_play_and_wait(chan, "vm-nomore");
10067             }
10068          }
10069          break;
10070       case '6': /* Go to the next message */
10071          if (vms.curmsg < vms.lastmsg) {
10072             vms.curmsg++;
10073             cmd = play_message(chan, vmu, &vms);
10074          } else {
10075             if (in_urgent && vms.newmessages > 0) {
10076                /* Check if we were listening to urgent
10077                 * messages.  If so, go to regular new messages
10078                 * instead of saying "no more messages"
10079                 */
10080                in_urgent = 0;
10081                res = close_mailbox(&vms, vmu);
10082                if (res == ERROR_LOCK_PATH)
10083                   goto out;
10084                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10085                if (res < 0)
10086                   goto out;
10087                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10088                vms.curmsg = -1;
10089                if (vms.lastmsg < 0) {
10090                   cmd = ast_play_and_wait(chan, "vm-nomore");
10091                }
10092             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10093                vms.curmsg = 0;
10094                cmd = play_message(chan, vmu, &vms);
10095             } else {
10096                cmd = ast_play_and_wait(chan, "vm-nomore");
10097             }
10098          }
10099          break;
10100       case '7': /* Delete the current message */
10101          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
10102             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
10103             if (useadsi)
10104                adsi_delete(chan, &vms);
10105             if (vms.deleted[vms.curmsg]) {
10106                if (play_folder == 0) {
10107                   if (in_urgent) {
10108                      vms.urgentmessages--;
10109                   } else {
10110                      vms.newmessages--;
10111                   }
10112                }
10113                else if (play_folder == 1)
10114                   vms.oldmessages--;
10115                cmd = ast_play_and_wait(chan, "vm-deleted");
10116             } else {
10117                if (play_folder == 0) {
10118                   if (in_urgent) {
10119                      vms.urgentmessages++;
10120                   } else {
10121                      vms.newmessages++;
10122                   }
10123                }
10124                else if (play_folder == 1)
10125                   vms.oldmessages++;
10126                cmd = ast_play_and_wait(chan, "vm-undeleted");
10127             }
10128             if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10129                if (vms.curmsg < vms.lastmsg) {
10130                   vms.curmsg++;
10131                   cmd = play_message(chan, vmu, &vms);
10132                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10133                   vms.curmsg = 0;
10134                   cmd = play_message(chan, vmu, &vms);
10135                } else {
10136                   /* Check if we were listening to urgent
10137                      messages.  If so, go to regular new messages
10138                      instead of saying "no more messages"
10139                   */
10140                   if (in_urgent == 1) {
10141                      /* Check for new messages */
10142                      in_urgent = 0;
10143                      res = close_mailbox(&vms, vmu);
10144                      if (res == ERROR_LOCK_PATH)
10145                         goto out;
10146                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
10147                      if (res < 0)
10148                         goto out;
10149                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10150                      vms.curmsg = -1;
10151                      if (vms.lastmsg < 0)
10152                         cmd = ast_play_and_wait(chan, "vm-nomore");
10153                   } else {
10154                      cmd = ast_play_and_wait(chan, "vm-nomore");
10155                   }
10156                }
10157             }
10158          } else /* Delete not valid if we haven't selected a message */
10159             cmd = 0;
10160 #ifdef IMAP_STORAGE
10161          deleted = 1;
10162 #endif
10163          break;
10164    
10165       case '8': /* Forward the current messgae */
10166          if (vms.lastmsg > -1) {
10167             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10168             if (cmd == ERROR_LOCK_PATH) {
10169                res = cmd;
10170                goto out;
10171             }
10172          } else {
10173             /* Check if we were listening to urgent
10174                messages.  If so, go to regular new messages
10175                instead of saying "no more messages"
10176             */
10177             if (in_urgent == 1 && vms.newmessages > 0) {
10178                /* Check for new messages */
10179                in_urgent = 0;
10180                res = close_mailbox(&vms, vmu);
10181                if (res == ERROR_LOCK_PATH)
10182                   goto out;
10183                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10184                if (res < 0)
10185                   goto out;
10186                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10187                vms.curmsg = -1;
10188                if (vms.lastmsg < 0)
10189                   cmd = ast_play_and_wait(chan, "vm-nomore");
10190             } else {
10191                cmd = ast_play_and_wait(chan, "vm-nomore");
10192             }
10193          }
10194          break;
10195       case '9': /* Save message to folder */
10196          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
10197             /* No message selected */
10198             cmd = 0;
10199             break;
10200          }
10201          if (useadsi)
10202             adsi_folders(chan, 1, "Save to folder...");
10203          cmd = get_folder2(chan, "vm-savefolder", 1);
10204          box = 0; /* Shut up compiler */
10205          if (cmd == '#') {
10206             cmd = 0;
10207             break;
10208          } else if (cmd > 0) {
10209             box = cmd = cmd - '0';
10210             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
10211             if (cmd == ERROR_LOCK_PATH) {
10212                res = cmd;
10213                goto out;
10214 #ifndef IMAP_STORAGE
10215             } else if (!cmd) {
10216                vms.deleted[vms.curmsg] = 1;
10217 #endif
10218             } else {
10219                vms.deleted[vms.curmsg] = 0;
10220                vms.heard[vms.curmsg] = 0;
10221             }
10222          }
10223          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
10224          if (useadsi)
10225             adsi_message(chan, &vms);
10226          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
10227          if (!cmd) {
10228             cmd = ast_play_and_wait(chan, "vm-message");
10229             if (!cmd) 
10230                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
10231             if (!cmd)
10232                cmd = ast_play_and_wait(chan, "vm-savedto");
10233             if (!cmd)
10234                cmd = vm_play_folder_name(chan, vms.fn);
10235          } else {
10236             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10237          }
10238          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
10239             if (vms.curmsg < vms.lastmsg) {
10240                vms.curmsg++;
10241                cmd = play_message(chan, vmu, &vms);
10242             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10243                vms.curmsg = 0;
10244                cmd = play_message(chan, vmu, &vms);
10245             } else {
10246                /* Check if we were listening to urgent
10247                   messages.  If so, go to regular new messages
10248                   instead of saying "no more messages"
10249                */
10250                if (in_urgent == 1 && vms.newmessages > 0) {
10251                   /* Check for new messages */
10252                   in_urgent = 0;
10253                   res = close_mailbox(&vms, vmu);
10254                   if (res == ERROR_LOCK_PATH)
10255                      goto out;
10256                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
10257                   if (res < 0)
10258                      goto out;
10259                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10260                   vms.curmsg = -1;
10261                   if (vms.lastmsg < 0)
10262                      cmd = ast_play_and_wait(chan, "vm-nomore");
10263                } else {
10264                   cmd = ast_play_and_wait(chan, "vm-nomore");
10265                }
10266             }
10267          }
10268          break;
10269       case '*': /* Help */
10270          if (!vms.starting) {
10271             cmd = ast_play_and_wait(chan, "vm-onefor");
10272             if (!strncasecmp(chan->language, "he", 2)) {
10273                cmd = ast_play_and_wait(chan, "vm-for");
10274             }
10275             if (!cmd)
10276                cmd = vm_play_folder_name(chan, vms.vmbox);
10277             if (!cmd)
10278                cmd = ast_play_and_wait(chan, "vm-opts");
10279             if (!cmd)
10280                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
10281          } else
10282             cmd = 0;
10283          break;
10284       case '0': /* Mailbox options */
10285          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
10286          if (useadsi)
10287             adsi_status(chan, &vms);
10288          break;
10289       default: /* Nothing */
10290          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
10291          break;
10292       }
10293    }
10294    if ((cmd == 't') || (cmd == '#')) {
10295       /* Timeout */
10296       res = 0;
10297    } else {
10298       /* Hangup */
10299       res = -1;
10300    }
10301 
10302 out:
10303    if (res > -1) {
10304       ast_stopstream(chan);
10305       adsi_goodbye(chan);
10306       if (valid && res != OPERATOR_EXIT) {
10307          if (silentexit)
10308             res = ast_play_and_wait(chan, "vm-dialout");
10309          else 
10310             res = ast_play_and_wait(chan, "vm-goodbye");
10311       }
10312       if ((valid && res > 0) || res == OPERATOR_EXIT) {
10313          res = 0;
10314       }
10315       if (useadsi)
10316          ast_adsi_unload_session(chan);
10317    }
10318    if (vmu)
10319       close_mailbox(&vms, vmu);
10320    if (valid) {
10321       int new = 0, old = 0, urgent = 0;
10322       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
10323       ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
10324       /* Urgent flag not passwd to externnotify here */
10325       run_externnotify(vmu->context, vmu->mailbox, NULL);
10326       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
10327       queue_mwi_event(ext_context, urgent, new, old);
10328    }
10329 #ifdef IMAP_STORAGE
10330    /* expunge message - use UID Expunge if supported on IMAP server*/
10331    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10332    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10333       ast_mutex_lock(&vms.lock);
10334 #ifdef HAVE_IMAP_TK2006
10335       if (LEVELUIDPLUS (vms.mailstream)) {
10336          mail_expunge_full(vms.mailstream, NIL, EX_UID);
10337       } else 
10338 #endif
10339          mail_expunge(vms.mailstream);
10340       ast_mutex_unlock(&vms.lock);
10341    }
10342    /*  before we delete the state, we should copy pertinent info
10343     *  back to the persistent model */
10344    if (vmu) {
10345       vmstate_delete(&vms);
10346    }
10347 #endif
10348    if (vmu)
10349       free_user(vmu);
10350    if (vms.deleted)
10351       ast_free(vms.deleted);
10352    if (vms.heard)
10353       ast_free(vms.heard);
10354 
10355 #ifdef IMAP_STORAGE
10356    pthread_setspecific(ts_vmstate.key, NULL);
10357 #endif
10358    return res;
10359 }

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

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

Referenced by forward_message().

06675 {
06676 #ifdef IMAP_STORAGE
06677    int res;
06678 #endif
06679    int cmd = 0;
06680    int retries = 0, prepend_duration = 0, already_recorded = 0;
06681    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06682    char textfile[PATH_MAX];
06683    struct ast_config *msg_cfg;
06684    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06685 #ifndef IMAP_STORAGE
06686    signed char zero_gain = 0;
06687 #endif
06688    const char *duration_str;
06689 
06690    /* Must always populate duration correctly */
06691    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06692    strcpy(textfile, msgfile);
06693    strcpy(backup, msgfile);
06694    strcpy(backup_textfile, msgfile);
06695    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06696    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06697    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06698 
06699    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06700       *duration = atoi(duration_str);
06701    } else {
06702       *duration = 0;
06703    }
06704 
06705    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06706       if (cmd)
06707          retries = 0;
06708       switch (cmd) {
06709       case '1': 
06710 
06711 #ifdef IMAP_STORAGE
06712          /* Record new intro file */
06713          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06714          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06715          res = ast_play_and_wait(chan, INTRO);
06716          res = ast_play_and_wait(chan, "beep");
06717          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, record_gain, vms, flag);
06718          cmd = 't';
06719 #else
06720 
06721          /* prepend a message to the current message, update the metadata and return */
06722 
06723          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06724          strcpy(textfile, msgfile);
06725          strncat(textfile, ".txt", sizeof(textfile) - 1);
06726          *duration = 0;
06727 
06728          /* if we can't read the message metadata, stop now */
06729          if (!msg_cfg) {
06730             cmd = 0;
06731             break;
06732          }
06733          
06734          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06735          if (already_recorded) {
06736             ast_filecopy(backup, msgfile, NULL);
06737             copy(backup_textfile, textfile);
06738          }
06739          else {
06740             ast_filecopy(msgfile, backup, NULL);
06741             copy(textfile,backup_textfile);
06742          }
06743          already_recorded = 1;
06744 
06745          if (record_gain)
06746             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06747 
06748          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06749          if (cmd == 'S') {
06750             ast_filerename(backup, msgfile, NULL);
06751          }
06752 
06753          if (record_gain)
06754             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06755 
06756          
06757          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06758             *duration = atoi(duration_str);
06759 
06760          if (prepend_duration) {
06761             struct ast_category *msg_cat;
06762             /* need enough space for a maximum-length message duration */
06763             char duration_buf[12];
06764 
06765             *duration += prepend_duration;
06766             msg_cat = ast_category_get(msg_cfg, "message");
06767             snprintf(duration_buf, 11, "%ld", *duration);
06768             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06769                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06770             }
06771          }
06772 
06773 #endif
06774          break;
06775       case '2': 
06776          /* NULL out introfile so we know there is no intro! */
06777 #ifdef IMAP_STORAGE
06778          *vms->introfn = '\0';
06779 #endif
06780          cmd = 't';
06781          break;
06782       case '*':
06783          cmd = '*';
06784          break;
06785       default: 
06786          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
06787             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06788          if (!cmd)
06789             cmd = ast_play_and_wait(chan, "vm-starmain");
06790             /* "press star to return to the main menu" */
06791          if (!cmd)
06792             cmd = ast_waitfordigit(chan, 6000);
06793          if (!cmd)
06794             retries++;
06795          if (retries > 3)
06796             cmd = 't';
06797       }
06798    }
06799 
06800    if (msg_cfg)
06801       ast_config_destroy(msg_cfg);
06802    if (prepend_duration)
06803       *duration = prepend_duration;
06804 
06805    if (already_recorded && cmd == -1) {
06806       /* restore original message if prepention cancelled */
06807       ast_filerename(backup, msgfile, NULL);
06808       rename(backup_textfile, textfile);
06809    }
06810 
06811    if (cmd == 't' || cmd == 'S')
06812       cmd = 0;
06813    return cmd;
06814 }

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

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

Referenced by vm_execmain().

08973 {
08974    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08975       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
08976    } else {             /* Default to ENGLISH */
08977       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08978    }
08979 }

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

08872 {
08873    int res = 0;
08874    /* Play instructions and wait for new command */
08875    while (!res) {
08876       if (vms->starting) {
08877          if (vms->lastmsg > -1) {
08878             if (skipadvanced)
08879                res = ast_play_and_wait(chan, "vm-onefor-full");
08880             else
08881                res = ast_play_and_wait(chan, "vm-onefor");
08882             if (!res)
08883                res = vm_play_folder_name(chan, vms->vmbox);
08884          }
08885          if (!res) {
08886             if (skipadvanced)
08887                res = ast_play_and_wait(chan, "vm-opts-full");
08888             else
08889                res = ast_play_and_wait(chan, "vm-opts");
08890          }
08891       } else {
08892          /* Added for additional help */
08893          if (skipadvanced) {
08894             res = ast_play_and_wait(chan, "vm-onefor-full");
08895             if (!res)
08896                res = vm_play_folder_name(chan, vms->vmbox);
08897             res = ast_play_and_wait(chan, "vm-opts-full");
08898          }
08899          /* Logic:
08900           * If the current message is not the first OR
08901           * if we're listening to the first new message and there are
08902           * also urgent messages, then prompt for navigation to the
08903           * previous message
08904           */
08905          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08906             res = ast_play_and_wait(chan, "vm-prev");
08907          }
08908          if (!res && !skipadvanced)
08909             res = ast_play_and_wait(chan, "vm-advopts");
08910          if (!res)
08911             res = ast_play_and_wait(chan, "vm-repeat");
08912          /* Logic:
08913           * If we're not listening to the last message OR
08914           * we're listening to the last urgent message and there are
08915           * also new non-urgent messages, then prompt for navigation
08916           * to the next message
08917           */
08918          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08919             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08920             res = ast_play_and_wait(chan, "vm-next");
08921          }
08922          if (!res) {
08923             if (!vms->deleted[vms->curmsg])
08924                res = ast_play_and_wait(chan, "vm-delete");
08925             else
08926                res = ast_play_and_wait(chan, "vm-undelete");
08927             if (!res)
08928                res = ast_play_and_wait(chan, "vm-toforward");
08929             if (!res)
08930                res = ast_play_and_wait(chan, "vm-savemessage");
08931          }
08932       }
08933       if (!res) {
08934          res = ast_play_and_wait(chan, "vm-helpexit");
08935       }
08936       if (!res)
08937          res = ast_waitfordigit(chan, 6000);
08938       if (!res) {
08939          vms->repeats++;
08940          if (vms->repeats > 2) {
08941             res = 't';
08942          }
08943       }
08944    }
08945    return res;
08946 }

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

08949 {
08950    int res = 0;
08951    /* Play instructions and wait for new command */
08952    while (!res) {
08953       if (vms->lastmsg > -1) {
08954          res = ast_play_and_wait(chan, "vm-listen");
08955          if (!res)
08956             res = vm_play_folder_name(chan, vms->vmbox);
08957          if (!res)
08958             res = ast_play_and_wait(chan, "press");
08959          if (!res)
08960             res = ast_play_and_wait(chan, "digits/1");
08961       }
08962       if (!res)
08963          res = ast_play_and_wait(chan, "vm-opts");
08964       if (!res) {
08965          vms->starting = 0;
08966          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08967       }
08968    }
08969    return res;
08970 }

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

Definition at line 8809 of file app_voicemail.c.

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

Referenced by vm_execmain().

08810 {
08811    char prefile[256];
08812    
08813    /* Notify the user that the temp greeting is set and give them the option to remove it */
08814    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08815    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08816       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08817       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08818          ast_play_and_wait(chan, "vm-tempgreetactive");
08819       }
08820       DISPOSE(prefile, -1);
08821    }
08822 
08823    /* Play voicemail intro - syntax is different for different languages */
08824    if (0) {
08825       return 0;
08826    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08827       return vm_intro_cs(chan, vms);
08828    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08829       static int deprecation_warning = 0;
08830       if (deprecation_warning++ % 10 == 0) {
08831          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08832       }
08833       return vm_intro_cs(chan, vms);
08834    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08835       return vm_intro_de(chan, vms);
08836    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08837       return vm_intro_es(chan, vms);
08838    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08839       return vm_intro_fr(chan, vms);
08840    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08841       return vm_intro_gr(chan, vms);
08842    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08843       return vm_intro_he(chan, vms);
08844    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08845       return vm_intro_it(chan, vms);
08846    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08847       return vm_intro_nl(chan, vms);
08848    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08849       return vm_intro_no(chan, vms);
08850    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08851       return vm_intro_pl(chan, vms);
08852    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08853       return vm_intro_pt_BR(chan, vms);
08854    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08855       return vm_intro_pt(chan, vms);
08856    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08857       return vm_intro_multilang(chan, vms, "n");
08858    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08859       return vm_intro_se(chan, vms);
08860    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08861       return vm_intro_multilang(chan, vms, "n");
08862    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
08863       return vm_intro_vi(chan, vms);
08864    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08865       return vm_intro_zh(chan, vms);
08866    } else {                                             /* Default to ENGLISH */
08867       return vm_intro_en(chan, vms);
08868    }
08869 }

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

Definition at line 8679 of file app_voicemail.c.

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

Referenced by vm_intro().

08680 {
08681    int res;
08682    res = ast_play_and_wait(chan, "vm-youhave");
08683    if (!res) {
08684       if (vms->newmessages) {
08685          if (vms->newmessages == 1) {
08686             res = ast_play_and_wait(chan, "digits/jednu");
08687          } else {
08688             res = say_and_wait(chan, vms->newmessages, chan->language);
08689          }
08690          if (!res) {
08691             if ((vms->newmessages == 1))
08692                res = ast_play_and_wait(chan, "vm-novou");
08693             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08694                res = ast_play_and_wait(chan, "vm-nove");
08695             if (vms->newmessages > 4)
08696                res = ast_play_and_wait(chan, "vm-novych");
08697          }
08698          if (vms->oldmessages && !res)
08699             res = ast_play_and_wait(chan, "vm-and");
08700          else if (!res) {
08701             if ((vms->newmessages == 1))
08702                res = ast_play_and_wait(chan, "vm-zpravu");
08703             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08704                res = ast_play_and_wait(chan, "vm-zpravy");
08705             if (vms->newmessages > 4)
08706                res = ast_play_and_wait(chan, "vm-zprav");
08707          }
08708       }
08709       if (!res && vms->oldmessages) {
08710          res = say_and_wait(chan, vms->oldmessages, chan->language);
08711          if (!res) {
08712             if ((vms->oldmessages == 1))
08713                res = ast_play_and_wait(chan, "vm-starou");
08714             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08715                res = ast_play_and_wait(chan, "vm-stare");
08716             if (vms->oldmessages > 4)
08717                res = ast_play_and_wait(chan, "vm-starych");
08718          }
08719          if (!res) {
08720             if ((vms->oldmessages == 1))
08721                res = ast_play_and_wait(chan, "vm-zpravu");
08722             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08723                res = ast_play_and_wait(chan, "vm-zpravy");
08724             if (vms->oldmessages > 4)
08725                res = ast_play_and_wait(chan, "vm-zprav");
08726          }
08727       }
08728       if (!res) {
08729          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08730             res = ast_play_and_wait(chan, "vm-no");
08731             if (!res)
08732                res = ast_play_and_wait(chan, "vm-zpravy");
08733          }
08734       }
08735    }
08736    return res;
08737 }

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

Definition at line 8375 of file app_voicemail.c.

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

Referenced by vm_intro().

08376 {
08377    /* Introduce messages they have */
08378    int res;
08379    res = ast_play_and_wait(chan, "vm-youhave");
08380    if (!res) {
08381       if (vms->newmessages) {
08382          if ((vms->newmessages == 1))
08383             res = ast_play_and_wait(chan, "digits/1F");
08384          else
08385             res = say_and_wait(chan, vms->newmessages, chan->language);
08386          if (!res)
08387             res = ast_play_and_wait(chan, "vm-INBOX");
08388          if (vms->oldmessages && !res)
08389             res = ast_play_and_wait(chan, "vm-and");
08390          else if (!res) {
08391             if ((vms->newmessages == 1))
08392                res = ast_play_and_wait(chan, "vm-message");
08393             else
08394                res = ast_play_and_wait(chan, "vm-messages");
08395          }
08396             
08397       }
08398       if (!res && vms->oldmessages) {
08399          if (vms->oldmessages == 1)
08400             res = ast_play_and_wait(chan, "digits/1F");
08401          else
08402             res = say_and_wait(chan, vms->oldmessages, chan->language);
08403          if (!res)
08404             res = ast_play_and_wait(chan, "vm-Old");
08405          if (!res) {
08406             if (vms->oldmessages == 1)
08407                res = ast_play_and_wait(chan, "vm-message");
08408             else
08409                res = ast_play_and_wait(chan, "vm-messages");
08410          }
08411       }
08412       if (!res) {
08413          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08414             res = ast_play_and_wait(chan, "vm-no");
08415             if (!res)
08416                res = ast_play_and_wait(chan, "vm-messages");
08417          }
08418       }
08419    }
08420    return res;
08421 }

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

Definition at line 8124 of file app_voicemail.c.

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

Referenced by vm_intro().

08125 {
08126    int res;
08127 
08128    /* Introduce messages they have */
08129    res = ast_play_and_wait(chan, "vm-youhave");
08130    if (!res) {
08131       if (vms->urgentmessages) {
08132          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08133          if (!res)
08134             res = ast_play_and_wait(chan, "vm-Urgent");
08135          if ((vms->oldmessages || vms->newmessages) && !res) {
08136             res = ast_play_and_wait(chan, "vm-and");
08137          } else if (!res) {
08138             if ((vms->urgentmessages == 1))
08139                res = ast_play_and_wait(chan, "vm-message");
08140             else
08141                res = ast_play_and_wait(chan, "vm-messages");
08142          }
08143       }
08144       if (vms->newmessages) {
08145          res = say_and_wait(chan, vms->newmessages, chan->language);
08146          if (!res)
08147             res = ast_play_and_wait(chan, "vm-INBOX");
08148          if (vms->oldmessages && !res)
08149             res = ast_play_and_wait(chan, "vm-and");
08150          else if (!res) {
08151             if ((vms->newmessages == 1))
08152                res = ast_play_and_wait(chan, "vm-message");
08153             else
08154                res = ast_play_and_wait(chan, "vm-messages");
08155          }
08156             
08157       }
08158       if (!res && vms->oldmessages) {
08159          res = say_and_wait(chan, vms->oldmessages, chan->language);
08160          if (!res)
08161             res = ast_play_and_wait(chan, "vm-Old");
08162          if (!res) {
08163             if (vms->oldmessages == 1)
08164                res = ast_play_and_wait(chan, "vm-message");
08165             else
08166                res = ast_play_and_wait(chan, "vm-messages");
08167          }
08168       }
08169       if (!res) {
08170          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08171             res = ast_play_and_wait(chan, "vm-no");
08172             if (!res)
08173                res = ast_play_and_wait(chan, "vm-messages");
08174          }
08175       }
08176    }
08177    return res;
08178 }

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

Definition at line 8424 of file app_voicemail.c.

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

Referenced by vm_intro().

08425 {
08426    /* Introduce messages they have */
08427    int res;
08428    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08429       res = ast_play_and_wait(chan, "vm-youhaveno");
08430       if (!res)
08431          res = ast_play_and_wait(chan, "vm-messages");
08432    } else {
08433       res = ast_play_and_wait(chan, "vm-youhave");
08434    }
08435    if (!res) {
08436       if (vms->newmessages) {
08437          if (!res) {
08438             if ((vms->newmessages == 1)) {
08439                res = ast_play_and_wait(chan, "digits/1M");
08440                if (!res)
08441                   res = ast_play_and_wait(chan, "vm-message");
08442                if (!res)
08443                   res = ast_play_and_wait(chan, "vm-INBOXs");
08444             } else {
08445                res = say_and_wait(chan, vms->newmessages, chan->language);
08446                if (!res)
08447                   res = ast_play_and_wait(chan, "vm-messages");
08448                if (!res)
08449                   res = ast_play_and_wait(chan, "vm-INBOX");
08450             }
08451          }
08452          if (vms->oldmessages && !res)
08453             res = ast_play_and_wait(chan, "vm-and");
08454       }
08455       if (vms->oldmessages) {
08456          if (!res) {
08457             if (vms->oldmessages == 1) {
08458                res = ast_play_and_wait(chan, "digits/1M");
08459                if (!res)
08460                   res = ast_play_and_wait(chan, "vm-message");
08461                if (!res)
08462                   res = ast_play_and_wait(chan, "vm-Olds");
08463             } else {
08464                res = say_and_wait(chan, vms->oldmessages, chan->language);
08465                if (!res)
08466                   res = ast_play_and_wait(chan, "vm-messages");
08467                if (!res)
08468                   res = ast_play_and_wait(chan, "vm-Old");
08469             }
08470          }
08471       }
08472    }
08473 return res;
08474 }

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

Definition at line 8522 of file app_voicemail.c.

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

Referenced by vm_intro().

08523 {
08524    /* Introduce messages they have */
08525    int res;
08526    res = ast_play_and_wait(chan, "vm-youhave");
08527    if (!res) {
08528       if (vms->newmessages) {
08529          res = say_and_wait(chan, vms->newmessages, chan->language);
08530          if (!res)
08531             res = ast_play_and_wait(chan, "vm-INBOX");
08532          if (vms->oldmessages && !res)
08533             res = ast_play_and_wait(chan, "vm-and");
08534          else if (!res) {
08535             if ((vms->newmessages == 1))
08536                res = ast_play_and_wait(chan, "vm-message");
08537             else
08538                res = ast_play_and_wait(chan, "vm-messages");
08539          }
08540             
08541       }
08542       if (!res && vms->oldmessages) {
08543          res = say_and_wait(chan, vms->oldmessages, chan->language);
08544          if (!res)
08545             res = ast_play_and_wait(chan, "vm-Old");
08546          if (!res) {
08547             if (vms->oldmessages == 1)
08548                res = ast_play_and_wait(chan, "vm-message");
08549             else
08550                res = ast_play_and_wait(chan, "vm-messages");
08551          }
08552       }
08553       if (!res) {
08554          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08555             res = ast_play_and_wait(chan, "vm-no");
08556             if (!res)
08557                res = ast_play_and_wait(chan, "vm-messages");
08558          }
08559       }
08560    }
08561    return res;
08562 }

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

Definition at line 7923 of file app_voicemail.c.

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

Referenced by vm_intro().

07924 {
07925    int res = 0;
07926 
07927    if (vms->newmessages) {
07928       res = ast_play_and_wait(chan, "vm-youhave");
07929       if (!res) 
07930          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07931       if (!res) {
07932          if ((vms->newmessages == 1)) {
07933             res = ast_play_and_wait(chan, "vm-INBOX");
07934             if (!res)
07935                res = ast_play_and_wait(chan, "vm-message");
07936          } else {
07937             res = ast_play_and_wait(chan, "vm-INBOXs");
07938             if (!res)
07939                res = ast_play_and_wait(chan, "vm-messages");
07940          }
07941       }
07942    } else if (vms->oldmessages){
07943       res = ast_play_and_wait(chan, "vm-youhave");
07944       if (!res)
07945          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07946       if ((vms->oldmessages == 1)){
07947          res = ast_play_and_wait(chan, "vm-Old");
07948          if (!res)
07949             res = ast_play_and_wait(chan, "vm-message");
07950       } else {
07951          res = ast_play_and_wait(chan, "vm-Olds");
07952          if (!res)
07953             res = ast_play_and_wait(chan, "vm-messages");
07954       }
07955    } else if (!vms->oldmessages && !vms->newmessages) 
07956       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07957    return res;
07958 }

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

Definition at line 8057 of file app_voicemail.c.

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

Referenced by vm_intro().

08058 {
08059    int res = 0;
08060 
08061    /* Introduce messages they have */
08062    if (!res) {
08063       if ((vms->newmessages) || (vms->oldmessages)) {
08064          res = ast_play_and_wait(chan, "vm-youhave");
08065       }
08066       /*
08067        * The word "shtei" refers to the number 2 in hebrew when performing a count
08068        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08069        * an element, this is one of them.
08070        */
08071       if (vms->newmessages) {
08072          if (!res) {
08073             if (vms->newmessages == 1) {
08074                res = ast_play_and_wait(chan, "vm-INBOX1");
08075             } else {
08076                if (vms->newmessages == 2) {
08077                   res = ast_play_and_wait(chan, "vm-shtei");
08078                } else {
08079                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08080                }
08081                res = ast_play_and_wait(chan, "vm-INBOX");
08082             }
08083          }
08084          if (vms->oldmessages && !res) {
08085             res = ast_play_and_wait(chan, "vm-and");
08086             if (vms->oldmessages == 1) {
08087                res = ast_play_and_wait(chan, "vm-Old1");
08088             } else {
08089                if (vms->oldmessages == 2) {
08090                   res = ast_play_and_wait(chan, "vm-shtei");
08091                } else {
08092                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08093                }
08094                res = ast_play_and_wait(chan, "vm-Old");
08095             }
08096          }
08097       }
08098       if (!res && vms->oldmessages && !vms->newmessages) {
08099          if (!res) {
08100             if (vms->oldmessages == 1) {
08101                res = ast_play_and_wait(chan, "vm-Old1");
08102             } else {
08103                if (vms->oldmessages == 2) {
08104                   res = ast_play_and_wait(chan, "vm-shtei");
08105                } else {
08106                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08107                }
08108                res = ast_play_and_wait(chan, "vm-Old");
08109             }
08110          }
08111       }
08112       if (!res) {
08113          if (!vms->oldmessages && !vms->newmessages) {
08114             if (!res) {
08115                res = ast_play_and_wait(chan, "vm-nomessages");
08116             }
08117          }
08118       }
08119    }
08120    return res;
08121 }

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

Definition at line 8181 of file app_voicemail.c.

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

Referenced by vm_intro().

08182 {
08183    /* Introduce messages they have */
08184    int res;
08185    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08186       res = ast_play_and_wait(chan, "vm-no") ||
08187          ast_play_and_wait(chan, "vm-message");
08188    else
08189       res = ast_play_and_wait(chan, "vm-youhave");
08190    if (!res && vms->newmessages) {
08191       res = (vms->newmessages == 1) ?
08192          ast_play_and_wait(chan, "digits/un") ||
08193          ast_play_and_wait(chan, "vm-nuovo") ||
08194          ast_play_and_wait(chan, "vm-message") :
08195          /* 2 or more new messages */
08196          say_and_wait(chan, vms->newmessages, chan->language) ||
08197          ast_play_and_wait(chan, "vm-nuovi") ||
08198          ast_play_and_wait(chan, "vm-messages");
08199       if (!res && vms->oldmessages)
08200          res = ast_play_and_wait(chan, "vm-and");
08201    }
08202    if (!res && vms->oldmessages) {
08203       res = (vms->oldmessages == 1) ?
08204          ast_play_and_wait(chan, "digits/un") ||
08205          ast_play_and_wait(chan, "vm-vecchio") ||
08206          ast_play_and_wait(chan, "vm-message") :
08207          /* 2 or more old messages */
08208          say_and_wait(chan, vms->oldmessages, chan->language) ||
08209          ast_play_and_wait(chan, "vm-vecchi") ||
08210          ast_play_and_wait(chan, "vm-messages");
08211    }
08212    return res;
08213 }

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

Definition at line 8017 of file app_voicemail.c.

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

Referenced by vm_intro().

08018 {
08019    int res;
08020    int lastnum = 0;
08021 
08022    res = ast_play_and_wait(chan, "vm-youhave");
08023 
08024    if (!res && vms->newmessages) {
08025       lastnum = vms->newmessages;
08026 
08027       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08028          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08029       }
08030 
08031       if (!res && vms->oldmessages) {
08032          res = ast_play_and_wait(chan, "vm-and");
08033       }
08034    }
08035 
08036    if (!res && vms->oldmessages) {
08037       lastnum = vms->oldmessages;
08038 
08039       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08040          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08041       }
08042    }
08043 
08044    if (!res) {
08045       if (lastnum == 0) {
08046          res = ast_play_and_wait(chan, "vm-no");
08047       }
08048       if (!res) {
08049          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08050       }
08051    }
08052 
08053    return res;
08054 }

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

Definition at line 8565 of file app_voicemail.c.

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

Referenced by vm_intro().

08566 {
08567    /* Introduce messages they have */
08568    int res;
08569    res = ast_play_and_wait(chan, "vm-youhave");
08570    if (!res) {
08571       if (vms->newmessages) {
08572          res = say_and_wait(chan, vms->newmessages, chan->language);
08573          if (!res) {
08574             if (vms->newmessages == 1)
08575                res = ast_play_and_wait(chan, "vm-INBOXs");
08576             else
08577                res = ast_play_and_wait(chan, "vm-INBOX");
08578          }
08579          if (vms->oldmessages && !res)
08580             res = ast_play_and_wait(chan, "vm-and");
08581          else if (!res) {
08582             if ((vms->newmessages == 1))
08583                res = ast_play_and_wait(chan, "vm-message");
08584             else
08585                res = ast_play_and_wait(chan, "vm-messages");
08586          }
08587             
08588       }
08589       if (!res && vms->oldmessages) {
08590          res = say_and_wait(chan, vms->oldmessages, chan->language);
08591          if (!res) {
08592             if (vms->oldmessages == 1)
08593                res = ast_play_and_wait(chan, "vm-Olds");
08594             else
08595                res = ast_play_and_wait(chan, "vm-Old");
08596          }
08597          if (!res) {
08598             if (vms->oldmessages == 1)
08599                res = ast_play_and_wait(chan, "vm-message");
08600             else
08601                res = ast_play_and_wait(chan, "vm-messages");
08602          }
08603       }
08604       if (!res) {
08605          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08606             res = ast_play_and_wait(chan, "vm-no");
08607             if (!res)
08608                res = ast_play_and_wait(chan, "vm-messages");
08609          }
08610       }
08611    }
08612    return res;
08613 }

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

Definition at line 8331 of file app_voicemail.c.

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

Referenced by vm_intro().

08332 {
08333    /* Introduce messages they have */
08334    int res;
08335 
08336    res = ast_play_and_wait(chan, "vm-youhave");
08337    if (res)
08338       return res;
08339 
08340    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08341       res = ast_play_and_wait(chan, "vm-no");
08342       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08343       return res;
08344    }
08345 
08346    if (vms->newmessages) {
08347       if ((vms->newmessages == 1)) {
08348          res = ast_play_and_wait(chan, "digits/1");
08349          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08350          res = res ? res : ast_play_and_wait(chan, "vm-message");
08351       } else {
08352          res = say_and_wait(chan, vms->newmessages, chan->language);
08353          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08354          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08355       }
08356       if (!res && vms->oldmessages)
08357          res = ast_play_and_wait(chan, "vm-and");
08358    }
08359    if (!res && vms->oldmessages) {
08360       if (vms->oldmessages == 1) {
08361          res = ast_play_and_wait(chan, "digits/1");
08362          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08363          res = res ? res : ast_play_and_wait(chan, "vm-message");
08364       } else {
08365          res = say_and_wait(chan, vms->oldmessages, chan->language);
08366          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08367          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08368       }
08369    }
08370 
08371    return res;
08372 }

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

Definition at line 8216 of file app_voicemail.c.

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

Referenced by vm_intro().

08217 {
08218    /* Introduce messages they have */
08219    int res;
08220    div_t num;
08221 
08222    if (!vms->oldmessages && !vms->newmessages) {
08223       res = ast_play_and_wait(chan, "vm-no");
08224       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08225       return res;
08226    } else {
08227       res = ast_play_and_wait(chan, "vm-youhave");
08228    }
08229 
08230    if (vms->newmessages) {
08231       num = div(vms->newmessages, 10);
08232       if (vms->newmessages == 1) {
08233          res = ast_play_and_wait(chan, "digits/1-a");
08234          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08235          res = res ? res : ast_play_and_wait(chan, "vm-message");
08236       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08237          if (num.rem == 2) {
08238             if (!num.quot) {
08239                res = ast_play_and_wait(chan, "digits/2-ie");
08240             } else {
08241                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08242                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08243             }
08244          } else {
08245             res = say_and_wait(chan, vms->newmessages, chan->language);
08246          }
08247          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08248          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08249       } else {
08250          res = say_and_wait(chan, vms->newmessages, chan->language);
08251          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08252          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08253       }
08254       if (!res && vms->oldmessages)
08255          res = ast_play_and_wait(chan, "vm-and");
08256    }
08257    if (!res && vms->oldmessages) {
08258       num = div(vms->oldmessages, 10);
08259       if (vms->oldmessages == 1) {
08260          res = ast_play_and_wait(chan, "digits/1-a");
08261          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08262          res = res ? res : ast_play_and_wait(chan, "vm-message");
08263       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08264          if (num.rem == 2) {
08265             if (!num.quot) {
08266                res = ast_play_and_wait(chan, "digits/2-ie");
08267             } else {
08268                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08269                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08270             }
08271          } else {
08272             res = say_and_wait(chan, vms->oldmessages, chan->language);
08273          }
08274          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08275          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08276       } else {
08277          res = say_and_wait(chan, vms->oldmessages, chan->language);
08278          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08279          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08280       }
08281    }
08282 
08283    return res;
08284 }

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

Definition at line 8616 of file app_voicemail.c.

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

Referenced by vm_intro().

08617 {
08618    /* Introduce messages they have */
08619    int res;
08620    res = ast_play_and_wait(chan, "vm-youhave");
08621    if (!res) {
08622       if (vms->newmessages) {
08623          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08624          if (!res) {
08625             if ((vms->newmessages == 1)) {
08626                res = ast_play_and_wait(chan, "vm-message");
08627                if (!res)
08628                   res = ast_play_and_wait(chan, "vm-INBOXs");
08629             } else {
08630                res = ast_play_and_wait(chan, "vm-messages");
08631                if (!res)
08632                   res = ast_play_and_wait(chan, "vm-INBOX");
08633             }
08634          }
08635          if (vms->oldmessages && !res)
08636             res = ast_play_and_wait(chan, "vm-and");
08637       }
08638       if (!res && vms->oldmessages) {
08639          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08640          if (!res) {
08641             if (vms->oldmessages == 1) {
08642                res = ast_play_and_wait(chan, "vm-message");
08643                if (!res)
08644                   res = ast_play_and_wait(chan, "vm-Olds");
08645             } else {
08646                res = ast_play_and_wait(chan, "vm-messages");
08647                if (!res)
08648                   res = ast_play_and_wait(chan, "vm-Old");
08649             }
08650          }
08651       }
08652       if (!res) {
08653          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08654             res = ast_play_and_wait(chan, "vm-no");
08655             if (!res)
08656                res = ast_play_and_wait(chan, "vm-messages");
08657          }
08658       }
08659    }
08660    return res;
08661 }

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

Definition at line 8477 of file app_voicemail.c.

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

Referenced by vm_intro().

08477                                                                           {
08478    /* Introduce messages they have */
08479    int res;
08480    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08481       res = ast_play_and_wait(chan, "vm-nomessages");
08482       return res;
08483    } else {
08484       res = ast_play_and_wait(chan, "vm-youhave");
08485    }
08486    if (vms->newmessages) {
08487       if (!res)
08488          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08489       if ((vms->newmessages == 1)) {
08490          if (!res)
08491             res = ast_play_and_wait(chan, "vm-message");
08492          if (!res)
08493             res = ast_play_and_wait(chan, "vm-INBOXs");
08494       } else {
08495          if (!res)
08496             res = ast_play_and_wait(chan, "vm-messages");
08497          if (!res)
08498             res = ast_play_and_wait(chan, "vm-INBOX");
08499       }
08500       if (vms->oldmessages && !res)
08501          res = ast_play_and_wait(chan, "vm-and");
08502    }
08503    if (vms->oldmessages) {
08504       if (!res)
08505          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08506       if (vms->oldmessages == 1) {
08507          if (!res)
08508             res = ast_play_and_wait(chan, "vm-message");
08509          if (!res)
08510             res = ast_play_and_wait(chan, "vm-Olds");
08511       } else {
08512          if (!res)
08513             res = ast_play_and_wait(chan, "vm-messages");
08514          if (!res)
08515             res = ast_play_and_wait(chan, "vm-Old");
08516       }
08517    }
08518    return res;
08519 }

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

Definition at line 8287 of file app_voicemail.c.

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

Referenced by vm_intro().

08288 {
08289    /* Introduce messages they have */
08290    int res;
08291 
08292    res = ast_play_and_wait(chan, "vm-youhave");
08293    if (res)
08294       return res;
08295 
08296    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08297       res = ast_play_and_wait(chan, "vm-no");
08298       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08299       return res;
08300    }
08301 
08302    if (vms->newmessages) {
08303       if ((vms->newmessages == 1)) {
08304          res = ast_play_and_wait(chan, "digits/ett");
08305          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08306          res = res ? res : ast_play_and_wait(chan, "vm-message");
08307       } else {
08308          res = say_and_wait(chan, vms->newmessages, chan->language);
08309          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08310          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08311       }
08312       if (!res && vms->oldmessages)
08313          res = ast_play_and_wait(chan, "vm-and");
08314    }
08315    if (!res && vms->oldmessages) {
08316       if (vms->oldmessages == 1) {
08317          res = ast_play_and_wait(chan, "digits/ett");
08318          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08319          res = res ? res : ast_play_and_wait(chan, "vm-message");
08320       } else {
08321          res = say_and_wait(chan, vms->oldmessages, chan->language);
08322          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08323          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08324       }
08325    }
08326 
08327    return res;
08328 }

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

Definition at line 8779 of file app_voicemail.c.

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

Referenced by vm_intro().

08780 {
08781    int res;
08782 
08783    /* Introduce messages they have */
08784    res = ast_play_and_wait(chan, "vm-youhave");
08785    if (!res) {
08786       if (vms->newmessages) {
08787          res = say_and_wait(chan, vms->newmessages, chan->language);
08788          if (!res)
08789             res = ast_play_and_wait(chan, "vm-INBOX");
08790          if (vms->oldmessages && !res)
08791             res = ast_play_and_wait(chan, "vm-and");
08792       }
08793       if (!res && vms->oldmessages) {
08794          res = say_and_wait(chan, vms->oldmessages, chan->language);
08795          if (!res)
08796             res = ast_play_and_wait(chan, "vm-Old");        
08797       }
08798       if (!res) {
08799          if (!vms->oldmessages && !vms->newmessages) {
08800             res = ast_play_and_wait(chan, "vm-no");
08801             if (!res)
08802                res = ast_play_and_wait(chan, "vm-message");
08803          }
08804       }
08805    }
08806    return res;
08807 }

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

Definition at line 8740 of file app_voicemail.c.

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

Referenced by vm_intro().

08741 {
08742    int res;
08743    /* Introduce messages they have */
08744    res = ast_play_and_wait(chan, "vm-you");
08745 
08746    if (!res && vms->newmessages) {
08747       res = ast_play_and_wait(chan, "vm-have");
08748       if (!res)
08749          res = say_and_wait(chan, vms->newmessages, chan->language);
08750       if (!res)
08751          res = ast_play_and_wait(chan, "vm-tong");
08752       if (!res)
08753          res = ast_play_and_wait(chan, "vm-INBOX");
08754       if (vms->oldmessages && !res)
08755          res = ast_play_and_wait(chan, "vm-and");
08756       else if (!res) 
08757          res = ast_play_and_wait(chan, "vm-messages");
08758    }
08759    if (!res && vms->oldmessages) {
08760       res = ast_play_and_wait(chan, "vm-have");
08761       if (!res)
08762          res = say_and_wait(chan, vms->oldmessages, chan->language);
08763       if (!res)
08764          res = ast_play_and_wait(chan, "vm-tong");
08765       if (!res)
08766          res = ast_play_and_wait(chan, "vm-Old");
08767       if (!res)
08768          res = ast_play_and_wait(chan, "vm-messages");
08769    }
08770    if (!res && !vms->oldmessages && !vms->newmessages) {
08771       res = ast_play_and_wait(chan, "vm-haveno");
08772       if (!res)
08773          res = ast_play_and_wait(chan, "vm-messages");
08774    }
08775    return res;
08776 }

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03198 {
03199    switch (ast_lock_path(path)) {
03200    case AST_LOCK_TIMEOUT:
03201       return -1;
03202    default:
03203       return 0;
03204    }
03205 }

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

Definition at line 1603 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

01604 {
01605    FILE *p = NULL;
01606    int pfd = mkstemp(template);
01607    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01608    if (pfd > -1) {
01609       p = fdopen(pfd, "w+");
01610       if (!p) {
01611          close(pfd);
01612          pfd = -1;
01613       }
01614    }
01615    return p;
01616 }

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

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_flag, check_password(), 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().

08983 {
08984    int cmd = 0;
08985    int duration = 0;
08986    int tries = 0;
08987    char newpassword[80] = "";
08988    char newpassword2[80] = "";
08989    char prefile[PATH_MAX] = "";
08990    unsigned char buf[256];
08991    int bytes = 0;
08992 
08993    if (ast_adsi_available(chan)) {
08994       bytes += adsi_logo(buf + bytes);
08995       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
08996       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
08997       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
08998       bytes += ast_adsi_voice_mode(buf + bytes, 0);
08999       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09000    }
09001 
09002    /* First, have the user change their password 
09003       so they won't get here again */
09004    for (;;) {
09005       newpassword[1] = '\0';
09006       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09007       if (cmd == '#')
09008          newpassword[0] = '\0';
09009       if (cmd < 0 || cmd == 't' || cmd == '#')
09010          return cmd;
09011       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09012       if (cmd < 0 || cmd == 't' || cmd == '#')
09013          return cmd;
09014       cmd = check_password(vmu, newpassword); /* perform password validation */
09015       if (cmd != 0) {
09016          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09017          cmd = ast_play_and_wait(chan, vm_invalid_password);
09018       } else {
09019          newpassword2[1] = '\0';
09020          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09021          if (cmd == '#')
09022             newpassword2[0] = '\0';
09023          if (cmd < 0 || cmd == 't' || cmd == '#')
09024             return cmd;
09025          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09026          if (cmd < 0 || cmd == 't' || cmd == '#')
09027             return cmd;
09028          if (!strcmp(newpassword, newpassword2))
09029             break;
09030          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09031          cmd = ast_play_and_wait(chan, vm_mismatch);
09032       }
09033       if (++tries == 3)
09034          return -1;
09035       if (cmd != 0) {
09036          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09037       }
09038    }
09039    if (pwdchange & PWDCHANGE_INTERNAL)
09040       vm_change_password(vmu, newpassword);
09041    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09042       vm_change_password_shell(vmu, newpassword);
09043 
09044    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09045    cmd = ast_play_and_wait(chan, vm_passchanged);
09046 
09047    /* If forcename is set, have the user record their name */  
09048    if (ast_test_flag(vmu, VM_FORCENAME)) {
09049       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09050       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09051          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09052          if (cmd < 0 || cmd == 't' || cmd == '#')
09053             return cmd;
09054       }
09055    }
09056 
09057    /* If forcegreetings is set, have the user record their greetings */
09058    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09059       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09060       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09061          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09062          if (cmd < 0 || cmd == 't' || cmd == '#')
09063             return cmd;
09064       }
09065 
09066       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09067       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09068          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09069          if (cmd < 0 || cmd == 't' || cmd == '#')
09070             return cmd;
09071       }
09072    }
09073 
09074    return cmd;
09075 }

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

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_waitfordigit(), check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::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().

09078 {
09079    int cmd = 0;
09080    int retries = 0;
09081    int duration = 0;
09082    char newpassword[80] = "";
09083    char newpassword2[80] = "";
09084    char prefile[PATH_MAX] = "";
09085    unsigned char buf[256];
09086    int bytes = 0;
09087 
09088    if (ast_adsi_available(chan)) {
09089       bytes += adsi_logo(buf + bytes);
09090       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09091       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09092       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09093       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09094       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09095    }
09096    while ((cmd >= 0) && (cmd != 't')) {
09097       if (cmd)
09098          retries = 0;
09099       switch (cmd) {
09100       case '1': /* Record your unavailable message */
09101          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09102          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09103          break;
09104       case '2':  /* Record your busy message */
09105          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09106          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09107          break;
09108       case '3': /* Record greeting */
09109          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09110          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09111          break;
09112       case '4':  /* manage the temporary greeting */
09113          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09114          break;
09115       case '5': /* change password */
09116          if (vmu->password[0] == '-') {
09117             cmd = ast_play_and_wait(chan, "vm-no");
09118             break;
09119          }
09120          newpassword[1] = '\0';
09121          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09122          if (cmd == '#')
09123             newpassword[0] = '\0';
09124          else {
09125             if (cmd < 0)
09126                break;
09127             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09128                break;
09129             }
09130          }
09131          cmd = check_password(vmu, newpassword); /* perform password validation */
09132          if (cmd != 0) {
09133             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09134             cmd = ast_play_and_wait(chan, vm_invalid_password);
09135             if (!cmd) {
09136                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09137             }
09138             break;
09139          }
09140          newpassword2[1] = '\0';
09141          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09142          if (cmd == '#')
09143             newpassword2[0] = '\0';
09144          else {
09145             if (cmd < 0)
09146                break;
09147 
09148             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09149                break;
09150             }
09151          }
09152          if (strcmp(newpassword, newpassword2)) {
09153             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09154             cmd = ast_play_and_wait(chan, vm_mismatch);
09155             if (!cmd) {
09156                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09157             }
09158             break;
09159          }
09160          if (pwdchange & PWDCHANGE_INTERNAL)
09161             vm_change_password(vmu, newpassword);
09162          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09163             vm_change_password_shell(vmu, newpassword);
09164 
09165          ast_debug(1, "User %s set password to %s of length %d\n",
09166             vms->username, newpassword, (int) strlen(newpassword));
09167          cmd = ast_play_and_wait(chan, vm_passchanged);
09168          break;
09169       case '*': 
09170          cmd = 't';
09171          break;
09172       default: 
09173          cmd = 0;
09174          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09175          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09176          if (ast_fileexists(prefile, NULL, NULL)) {
09177             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09178          }
09179          DISPOSE(prefile, -1);
09180          if (!cmd) {
09181             cmd = ast_play_and_wait(chan, "vm-options");
09182          }
09183          if (!cmd) {
09184             cmd = ast_waitfordigit(chan, 6000);
09185          }
09186          if (!cmd) {
09187             retries++;
09188          }
09189          if (retries > 3) {
09190             cmd = 't';
09191          }
09192       }
09193    }
09194    if (cmd == 't')
09195       cmd = 0;
09196    return cmd;
09197 }

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

Definition at line 7886 of file app_voicemail.c.

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

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

07887 {
07888    int cmd;
07889 
07890    if (  !strncasecmp(chan->language, "it", 2) ||
07891         !strncasecmp(chan->language, "es", 2) ||
07892         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07893       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07894       return cmd ? cmd : ast_play_and_wait(chan, box);
07895    } else if (!strncasecmp(chan->language, "gr", 2)) {
07896       return vm_play_folder_name_gr(chan, box);
07897    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07898       return ast_play_and_wait(chan, box);
07899    } else if (!strncasecmp(chan->language, "pl", 2)) {
07900       return vm_play_folder_name_pl(chan, box);
07901    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07902       return vm_play_folder_name_ua(chan, box);
07903    } else if (!strncasecmp(chan->language, "vi", 2)) {
07904       return ast_play_and_wait(chan, box);
07905    } else {  /* Default English */
07906       cmd = ast_play_and_wait(chan, box);
07907       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07908    }
07909 }

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

Definition at line 7839 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07840 {
07841    int cmd;
07842    char *buf;
07843 
07844    buf = alloca(strlen(box) + 2);
07845    strcpy(buf, box);
07846    strcat(buf, "s");
07847 
07848    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07849       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07850       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07851    } else {
07852       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07853       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07854    }
07855 }

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

Definition at line 7857 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07858 {
07859    int cmd;
07860 
07861    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07862       if (!strcasecmp(box, "vm-INBOX"))
07863          cmd = ast_play_and_wait(chan, "vm-new-e");
07864       else
07865          cmd = ast_play_and_wait(chan, "vm-old-e");
07866       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07867    } else {
07868       cmd = ast_play_and_wait(chan, "vm-messages");
07869       return cmd ? cmd : ast_play_and_wait(chan, box);
07870    }
07871 }

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

Definition at line 7873 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07874 {
07875    int cmd;
07876 
07877    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07878       cmd = ast_play_and_wait(chan, "vm-messages");
07879       return cmd ? cmd : ast_play_and_wait(chan, box);
07880    } else {
07881       cmd = ast_play_and_wait(chan, box);
07882       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07883    }
07884 }

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

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_fileexists(), ast_play_and_wait(), ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

09216 {
09217    int cmd = 0;
09218    int retries = 0;
09219    int duration = 0;
09220    char prefile[PATH_MAX] = "";
09221    unsigned char buf[256];
09222    int bytes = 0;
09223 
09224    if (ast_adsi_available(chan)) {
09225       bytes += adsi_logo(buf + bytes);
09226       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09227       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09228       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09229       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09230       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09231    }
09232 
09233    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09234    while ((cmd >= 0) && (cmd != 't')) {
09235       if (cmd)
09236          retries = 0;
09237       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09238       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09239          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09240          cmd = 't';  
09241       } else {
09242          switch (cmd) {
09243          case '1':
09244             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09245             break;
09246          case '2':
09247             DELETE(prefile, -1, prefile, vmu);
09248             ast_play_and_wait(chan, "vm-tempremoved");
09249             cmd = 't';  
09250             break;
09251          case '*': 
09252             cmd = 't';
09253             break;
09254          default:
09255             cmd = ast_play_and_wait(chan,
09256                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09257                   "vm-tempgreeting2" : "vm-tempgreeting");
09258             if (!cmd)
09259                cmd = ast_waitfordigit(chan, 6000);
09260             if (!cmd)
09261                retries++;
09262             if (retries > 3)
09263                cmd = 't';
09264          }
09265       }
09266       DISPOSE(prefile, -1);
09267    }
09268    if (cmd == 't')
09269       cmd = 0;
09270    return cmd;
09271 }

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

Definition at line 11103 of file app_voicemail.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::list, user, and vm_users_data_provider_get_helper().

11105 {
11106    struct ast_vm_user *user;
11107 
11108    AST_LIST_LOCK(&users);
11109    AST_LIST_TRAVERSE(&users, user, list) {
11110       vm_users_data_provider_get_helper(search, data_root, user);
11111    }
11112    AST_LIST_UNLOCK(&users);
11113 
11114    return 0;
11115 }

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 11056 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, inboxcount2(), vm_zone::list, vm_zone::name, and user.

Referenced by vm_users_data_provider_get().

11058 {
11059    struct ast_data *data_user, *data_zone;
11060    struct ast_data *data_state;
11061    struct vm_zone *zone = NULL;
11062    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11063    char ext_context[256] = "";
11064 
11065    data_user = ast_data_add_node(data_root, "user");
11066    if (!data_user) {
11067       return -1;
11068    }
11069 
11070    ast_data_add_structure(ast_vm_user, data_user, user);
11071 
11072    AST_LIST_LOCK(&zones);
11073    AST_LIST_TRAVERSE(&zones, zone, list) {
11074       if (!strcmp(zone->name, user->zonetag)) {
11075          break;
11076       }
11077    }
11078    AST_LIST_UNLOCK(&zones);
11079 
11080    /* state */
11081    data_state = ast_data_add_node(data_user, "state");
11082    if (!data_state) {
11083       return -1;
11084    }
11085    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11086    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11087    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11088    ast_data_add_int(data_state, "newmsg", newmsg);
11089    ast_data_add_int(data_state, "oldmsg", oldmsg);
11090 
11091    if (zone) {
11092       data_zone = ast_data_add_node(data_user, "zone");
11093       ast_data_add_structure(vm_zone, data_zone, zone);
11094    }
11095 
11096    if (!ast_data_search_match(search, data_user)) {
11097       ast_data_remove_node(data_root, data_user);
11098    }
11099 
11100    return 0;
11101 }

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

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

10743 {
10744    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
10745    struct ast_vm_user vmus;
10746    char *options = NULL;
10747    int silent = 0, skipuser = 0;
10748    int res = -1;
10749    
10750    if (data) {
10751       s = ast_strdupa(data);
10752       user = strsep(&s, ",");
10753       options = strsep(&s, ",");
10754       if (user) {
10755          s = user;
10756          user = strsep(&s, "@");
10757          context = strsep(&s, "");
10758          if (!ast_strlen_zero(user))
10759             skipuser++;
10760          ast_copy_string(mailbox, user, sizeof(mailbox));
10761       }
10762    }
10763 
10764    if (options) {
10765       silent = (strchr(options, 's')) != NULL;
10766    }
10767 
10768    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
10769       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
10770       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
10771       ast_play_and_wait(chan, "auth-thankyou");
10772       res = 0;
10773    } else if (mailbox[0] == '*') {
10774       /* user entered '*' */
10775       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
10776          res = 0; /* prevent hangup */
10777       }
10778    }
10779 
10780    return res;
10781 }

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

Definition at line 12226 of file app_voicemail.c.

References ast_debug, AST_DIGIT_ANY, ast_log(), ast_say_character_str(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and sayname().

Referenced by load_module().

12227 {
12228    char *context;
12229    char *args_copy;
12230    int res;
12231 
12232    if (ast_strlen_zero(data)) {
12233       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12234       return -1;
12235    }
12236 
12237    args_copy = ast_strdupa(data);
12238    if ((context = strchr(args_copy, '@'))) {
12239       *context++ = '\0';
12240    } else {
12241       context = "default";
12242    }
12243 
12244    if ((res = sayname(chan, args_copy, context) < 0)) {
12245       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12246       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12247       if (!res) {
12248          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12249       }
12250    }
12251 
12252    return res;
12253 }

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

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

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

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

04298 {
04299    const struct vm_zone *z = NULL;
04300    struct timeval t = ast_tvnow();
04301 
04302    /* Does this user have a timezone specified? */
04303    if (!ast_strlen_zero(vmu->zonetag)) {
04304       /* Find the zone in the list */
04305       AST_LIST_LOCK(&zones);
04306       AST_LIST_TRAVERSE(&zones, z, list) {
04307          if (!strcmp(z->name, vmu->zonetag))
04308             break;
04309       }
04310       AST_LIST_UNLOCK(&zones);
04311    }
04312    ast_localtime(&t, tm, z ? z->timezone : NULL);
04313    return tm;
04314 }

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

Definition at line 7265 of file app_voicemail.c.

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

Referenced by advanced_options(), ast_say_date_da(), ast_say_date_de(), ast_say_date_pt(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_th(), ast_say_date_with_format_vi(), ast_say_date_with_format_zh(), ast_say_datetime_from_now_pt(), ast_say_number_full_pt(), ast_say_time_pt(), ast_say_time_pt_BR(), gr_say_number_female(), and play_message().

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

Definition at line 7257 of file app_voicemail.c.

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

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

07258 {
07259    int res;
07260    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07261       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07262    return res;
07263 }

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

Definition at line 12200 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(), LOG_ERROR, and var.

Referenced by vm_change_password().

12200                                                                               {
12201    struct ast_config *conf;
12202    struct ast_category *cat;
12203    struct ast_variable *var;
12204 
12205    if (!(conf=ast_config_new())) {
12206       ast_log(LOG_ERROR, "Error creating new config structure\n");
12207       return -1;
12208    }
12209    if (!(cat=ast_category_new("general","",1))) {
12210       ast_log(LOG_ERROR, "Error creating new category structure\n");
12211       return -1;
12212    }
12213    if (!(var=ast_variable_new("password",password,""))) {
12214       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12215       return -1;
12216    }
12217    ast_category_append(conf,cat);
12218    ast_variable_append(cat,var);
12219    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12220       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12221       return -1;
12222    }
12223    return 0;
12224 }


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

Definition at line 13214 of file app_voicemail.c.

char* addesc = "Comedian Mail" [static]

Definition at line 756 of file app_voicemail.c.

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

Definition at line 871 of file app_voicemail.c.

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

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

Definition at line 872 of file app_voicemail.c.

Referenced by adsi_load_vmail(), and load_config().

int adsiver = 1 [static]

Definition at line 873 of file app_voicemail.c.

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

char* app = "VoiceMail" [static]

Definition at line 759 of file app_voicemail.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 762 of file app_voicemail.c.

char* app3 = "MailboxExists" [static]

Definition at line 764 of file app_voicemail.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 765 of file app_voicemail.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 13214 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 857 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

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

Definition at line 869 of file app_voicemail.c.

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

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 860 of file app_voicemail.c.

Referenced by load_config(), and play_message_callerid().

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

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

Definition at line 10979 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 856 of file app_voicemail.c.

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

char* emailbody = NULL [static]

Definition at line 863 of file app_voicemail.c.

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

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

Definition at line 874 of file app_voicemail.c.

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

char* emailsubject = NULL [static]

Definition at line 864 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 858 of file app_voicemail.c.

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

char ext_pass_check_cmd[128] [static]

Definition at line 736 of file app_voicemail.c.

char ext_pass_cmd[128] [static]

Definition at line 735 of file app_voicemail.c.

char externnotify[160] [static]

Definition at line 779 of file app_voicemail.c.

char fromstring[100] [static]

Definition at line 867 of file app_voicemail.c.

Referenced by load_config(), and make_email_file().

struct ast_flags globalflags = {0} [static]

Definition at line 852 of file app_voicemail.c.

struct ao2_container* inprocess_container

Definition at line 894 of file app_voicemail.c.

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

char listen_control_forward_key[12] [static]

Definition at line 837 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_pause_key[12] [static]

Definition at line 839 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_restart_key[12] [static]

Definition at line 840 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_reverse_key[12] [static]

Definition at line 838 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char listen_control_stop_key[12] [static]

Definition at line 841 of file app_voicemail.c.

Referenced by load_config(), and wait_file().

char locale[20] [static]

Definition at line 772 of file app_voicemail.c.

struct ast_custom_function mailbox_exists_acf [static]

Initial value:

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

Definition at line 10737 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

const char* const mailbox_folders[] [static]

Definition at line 1639 of file app_voicemail.c.

char mailcmd[160] [static]

Definition at line 778 of file app_voicemail.c.

int maxdeletedmsg [static]

Definition at line 775 of file app_voicemail.c.

int maxgreet [static]

Definition at line 785 of file app_voicemail.c.

int maxlogins [static]

Definition at line 787 of file app_voicemail.c.

int maxmsg [static]

Definition at line 774 of file app_voicemail.c.

int maxsilence [static]

Definition at line 773 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword [static]

Definition at line 788 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 806 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

struct ast_taskprocessor* mwi_subscription_tps [static]

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

Referenced by start_poll_thread(), and stop_poll_thread().

int my_umask [static]

Definition at line 738 of file app_voicemail.c.

char* pagerbody = NULL [static]

Definition at line 865 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

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

Definition at line 875 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char pagerfromstring[100] [static]

Definition at line 868 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

char* pagersubject = NULL [static]

Definition at line 866 of file app_voicemail.c.

Referenced by load_config(), and sendpage().

int passwordlocation [static]

Definition at line 789 of file app_voicemail.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 801 of file app_voicemail.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 796 of file app_voicemail.c.

ast_mutex_t poll_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 802 of file app_voicemail.c.

unsigned char poll_thread_run [static]

Definition at line 803 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 742 of file app_voicemail.c.

int saydurationminfo [static]

Definition at line 854 of file app_voicemail.c.

Referenced by load_config(), and populate_defaults().

char* sayname_app = "VMSayName" [static]

Definition at line 767 of file app_voicemail.c.

char serveremail[80] [static]

Definition at line 777 of file app_voicemail.c.

int silencethreshold = 128 [static]

Definition at line 776 of file app_voicemail.c.

Referenced by ast_record_review(), and setup_privacy_args().

int skipms [static]

Definition at line 786 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 780 of file app_voicemail.c.

Referenced by load_config(), and run_externnotify().

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

Definition at line 754 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 523 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 11122 of file app_voicemail.c.

Referenced by load_module().

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

Definition at line 849 of file app_voicemail.c.

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

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

Definition at line 848 of file app_voicemail.c.

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

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

Definition at line 845 of file app_voicemail.c.

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

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

Definition at line 846 of file app_voicemail.c.

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

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

Definition at line 844 of file app_voicemail.c.

Referenced by load_config(), and vm_authenticate().

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

Definition at line 850 of file app_voicemail.c.

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

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

Definition at line 847 of file app_voicemail.c.

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

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 733 of file app_voicemail.c.

struct ast_data_handler vm_users_data_provider [static]

Initial value:

Definition at line 11117 of file app_voicemail.c.

char vmfmts[80] [static]

Definition at line 781 of file app_voicemail.c.

int vmmaxsecs [static]

Definition at line 784 of file app_voicemail.c.

int vmminsecs [static]

Definition at line 783 of file app_voicemail.c.

double volgain [static]

Definition at line 782 of file app_voicemail.c.

char zonetag[80] [static]

Definition at line 771 of file app_voicemail.c.

Referenced by build_peer().


Generated on Wed Apr 6 11:29:52 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7