Mon Jun 27 16:51:00 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 resequence_mailbox (struct ast_vm_user *vmu, char *dir, int stopcount)
static int reset_user_pw (const char *context, const char *mailbox, const char *newpass)
 Resets a user password to a specified password.
static void run_externnotify (char *context, char *extension, const char *flag)
static int save_to_folder (struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
static int say_and_wait (struct ast_channel *chan, int num, const char *language)
static int sayname (struct ast_channel *chan, const char *mailbox, const char *context)
static int sendmail (char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
static int sendpage (char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
static char * show_users_realtime (int fd, const char *context)
static void start_poll_thread (void)
static void stop_poll_thread (void)
static char * strip_control_and_high (const char *input, char *buf, size_t buflen)
 Strips control and non 7-bit clean characters from input string.
static const char * substitute_escapes (const char *value)
static int unload_module (void)
static int vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
static int vm_box_exists (struct ast_channel *chan, const char *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_browse_messages_en (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Spanish syntax for 'You have N messages' greeting.
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek syntax for 'You have N messages' greeting.
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_browse_messages_it (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Italian syntax for 'You have N messages' greeting.
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Portuguese syntax for 'You have N messages' greeting.
static int vm_browse_messages_vi (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Vietnamese syntax for 'You have N messages' greeting.
static int vm_browse_messages_zh (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Chinese (Taiwan)syntax for 'You have N messages' greeting.
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
 The handler for the change password option.
static void vm_change_password_shell (struct ast_vm_user *vmu, char *newpassword)
static char * vm_check_password_shell (char *command, char *buf, size_t len)
static int vm_delete (char *file)
 Removes the voicemail sound and information file.
static int vm_exec (struct ast_channel *chan, const char *data)
static int vm_execmain (struct ast_channel *chan, const char *data)
static int vm_forwardoptions (struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
 presents the option to prepend to an existing message when forwarding it.
static int vm_instructions (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_en (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_zh (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_intro (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_cs (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_de (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_en (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_es (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_fr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_gr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_he (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_it (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_multilang (struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_intro_nl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_no (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt_BR (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_se (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_vi (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_zh (struct ast_channel *chan, struct vm_state *vms)
static int vm_lock_path (const char *path)
 Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.
static FILE * vm_mkftemp (char *template)
static int vm_newuser (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_play_folder_name (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_gr (struct ast_channel *chan, char *box)
static int vm_play_folder_name_pl (struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua (struct ast_channel *chan, char *box)
static int vm_tempgreeting (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
 The handler for 'record a temporary greeting'.
static int vm_users_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int vm_users_data_provider_get_helper (const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
static int vmauthenticate (struct ast_channel *chan, const char *data)
static int vmsayname_exec (struct ast_channel *chan, const char *data)
static struct ast_tmvmu_tm (const struct ast_vm_user *vmu, struct ast_tm *tm)
 fill in *tm for current time according to the proper timezone, if any.
static int wait_file (struct ast_channel *chan, struct vm_state *vms, char *file)
static int wait_file2 (struct ast_channel *chan, struct vm_state *vms, char *file)
static int write_password_to_file (const char *secretfn, const char *password)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char * sayname_app = "VMSayName"
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_app_option vm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }}
static struct ast_data_entry vm_data_providers []
static 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, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage

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

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

Definition in file app_voicemail.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 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 11057 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 11085 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(), resequence_mailbox(), 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(), resequence_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 5262 of file app_voicemail.c.

References ast_strlen_zero().

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

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

static void __reg_module ( void   )  [static]

Definition at line 13260 of file app_voicemail.c.

static void __unreg_module ( void   )  [static]

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

10762 {
10763    struct ast_vm_user svm;
10764    AST_DECLARE_APP_ARGS(arg,
10765       AST_APP_ARG(mbox);
10766       AST_APP_ARG(context);
10767    );
10768 
10769    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
10770 
10771    if (ast_strlen_zero(arg.mbox)) {
10772       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
10773       return -1;
10774    }
10775 
10776    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
10777    return 0;
10778 }

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

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

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

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

06279 {
06280    int x;
06281    if (!ast_adsi_available(chan))
06282       return;
06283    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06284    if (x < 0)
06285       return;
06286    if (!x) {
06287       if (adsi_load_vmail(chan, useadsi)) {
06288          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06289          return;
06290       }
06291    } else
06292       *useadsi = 1;
06293 }

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

Definition at line 6467 of file app_voicemail.c.

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

Referenced by vm_execmain().

06468 {
06469    int bytes = 0;
06470    unsigned char buf[256];
06471    unsigned char keys[8];
06472 
06473    int x;
06474 
06475    if (!ast_adsi_available(chan))
06476       return;
06477 
06478    /* New meaning for keys */
06479    for (x = 0; x < 5; x++)
06480       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06481 
06482    keys[6] = 0x0;
06483    keys[7] = 0x0;
06484 
06485    if (!vms->curmsg) {
06486       /* No prev key, provide "Folder" instead */
06487       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06488    }
06489    if (vms->curmsg >= vms->lastmsg) {
06490       /* If last message ... */
06491       if (vms->curmsg) {
06492          /* but not only message, provide "Folder" instead */
06493          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06494       } else {
06495          /* Otherwise if only message, leave blank */
06496          keys[3] = 1;
06497       }
06498    }
06499 
06500    /* If deleted, show "undeleted" */
06501    if (vms->deleted[vms->curmsg]) 
06502       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06503 
06504    /* Except "Exit" */
06505    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06506    bytes += ast_adsi_set_keys(buf + bytes, keys);
06507    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06508 
06509    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06510 }

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

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

06344 {
06345    unsigned char buf[256];
06346    int bytes = 0;
06347    unsigned char keys[8];
06348    int x, y;
06349 
06350    if (!ast_adsi_available(chan))
06351       return;
06352 
06353    for (x = 0; x < 5; x++) {
06354       y = ADSI_KEY_APPS + 12 + start + x;
06355       if (y > ADSI_KEY_APPS + 12 + 4)
06356          y = 0;
06357       keys[x] = ADSI_KEY_SKT | y;
06358    }
06359    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06360    keys[6] = 0;
06361    keys[7] = 0;
06362 
06363    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06364    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06365    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06366    bytes += ast_adsi_set_keys(buf + bytes, keys);
06367    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06368 
06369    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06370 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06616 {
06617    unsigned char buf[256];
06618    int bytes = 0;
06619 
06620    if (!ast_adsi_available(chan))
06621       return;
06622    bytes += adsi_logo(buf + bytes);
06623    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06624    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06625    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06626    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06627 
06628    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06629 }

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

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

06150 {
06151    unsigned char buf[256];
06152    int bytes = 0;
06153    int x;
06154    char num[5];
06155 
06156    *useadsi = 0;
06157    bytes += ast_adsi_data_mode(buf + bytes);
06158    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06159 
06160    bytes = 0;
06161    bytes += adsi_logo(buf);
06162    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06163 #ifdef DISPLAY
06164    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06165 #endif
06166    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06167    bytes += ast_adsi_data_mode(buf + bytes);
06168    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06169 
06170    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06171       bytes = 0;
06172       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06173       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06174       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06175       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06176       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06177       return 0;
06178    }
06179 
06180 #ifdef DISPLAY
06181    /* Add a dot */
06182    bytes = 0;
06183    bytes += ast_adsi_logo(buf);
06184    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06185    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06186    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06187    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06188 #endif
06189    bytes = 0;
06190    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06191    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06192    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06193    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06194    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06195    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06196    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06197 
06198 #ifdef DISPLAY
06199    /* Add another dot */
06200    bytes = 0;
06201    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06202    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06203 
06204    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06205    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06206 #endif
06207 
06208    bytes = 0;
06209    /* These buttons we load but don't use yet */
06210    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06211    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06212    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06213    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06214    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06215    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06216    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06217 
06218 #ifdef DISPLAY
06219    /* Add another dot */
06220    bytes = 0;
06221    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06222    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06223    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06224 #endif
06225 
06226    bytes = 0;
06227    for (x = 0; x < 5; x++) {
06228       snprintf(num, sizeof(num), "%d", x);
06229       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06230    }
06231    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06232    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06233 
06234 #ifdef DISPLAY
06235    /* Add another dot */
06236    bytes = 0;
06237    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06238    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06239    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06240 #endif
06241 
06242    if (ast_adsi_end_download(chan)) {
06243       bytes = 0;
06244       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06245       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06246       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06247       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06248       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06249       return 0;
06250    }
06251    bytes = 0;
06252    bytes += ast_adsi_download_disconnect(buf + bytes);
06253    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06254    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06255 
06256    ast_debug(1, "Done downloading scripts...\n");
06257 
06258 #ifdef DISPLAY
06259    /* Add last dot */
06260    bytes = 0;
06261    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06262    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06263 #endif
06264    ast_debug(1, "Restarting session...\n");
06265 
06266    bytes = 0;
06267    /* Load the session now */
06268    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06269       *useadsi = 1;
06270       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06271    } else
06272       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06273 
06274    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06275    return 0;
06276 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06296 {
06297    unsigned char buf[256];
06298    int bytes = 0;
06299    unsigned char keys[8];
06300    int x;
06301    if (!ast_adsi_available(chan))
06302       return;
06303 
06304    for (x = 0; x < 8; x++)
06305       keys[x] = 0;
06306    /* Set one key for next */
06307    keys[3] = ADSI_KEY_APPS + 3;
06308 
06309    bytes += adsi_logo(buf + bytes);
06310    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06311    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06312    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06313    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06314    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06315    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06316    bytes += ast_adsi_set_keys(buf + bytes, keys);
06317    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06318    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06319 }

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

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

06142 {
06143    int bytes = 0;
06144    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06145    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06146    return bytes;
06147 }

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

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

06373 {
06374    int bytes = 0;
06375    unsigned char buf[256]; 
06376    char buf1[256], buf2[256];
06377    char fn2[PATH_MAX];
06378 
06379    char cid[256] = "";
06380    char *val;
06381    char *name, *num;
06382    char datetime[21] = "";
06383    FILE *f;
06384 
06385    unsigned char keys[8];
06386 
06387    int x;
06388 
06389    if (!ast_adsi_available(chan))
06390       return;
06391 
06392    /* Retrieve important info */
06393    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06394    f = fopen(fn2, "r");
06395    if (f) {
06396       while (!feof(f)) {   
06397          if (!fgets((char *) buf, sizeof(buf), f)) {
06398             continue;
06399          }
06400          if (!feof(f)) {
06401             char *stringp = NULL;
06402             stringp = (char *) buf;
06403             strsep(&stringp, "=");
06404             val = strsep(&stringp, "=");
06405             if (!ast_strlen_zero(val)) {
06406                if (!strcmp((char *) buf, "callerid"))
06407                   ast_copy_string(cid, val, sizeof(cid));
06408                if (!strcmp((char *) buf, "origdate"))
06409                   ast_copy_string(datetime, val, sizeof(datetime));
06410             }
06411          }
06412       }
06413       fclose(f);
06414    }
06415    /* New meaning for keys */
06416    for (x = 0; x < 5; x++)
06417       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06418    keys[6] = 0x0;
06419    keys[7] = 0x0;
06420 
06421    if (!vms->curmsg) {
06422       /* No prev key, provide "Folder" instead */
06423       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06424    }
06425    if (vms->curmsg >= vms->lastmsg) {
06426       /* If last message ... */
06427       if (vms->curmsg) {
06428          /* but not only message, provide "Folder" instead */
06429          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06430          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06431 
06432       } else {
06433          /* Otherwise if only message, leave blank */
06434          keys[3] = 1;
06435       }
06436    }
06437 
06438    if (!ast_strlen_zero(cid)) {
06439       ast_callerid_parse(cid, &name, &num);
06440       if (!name)
06441          name = num;
06442    } else
06443       name = "Unknown Caller";
06444 
06445    /* If deleted, show "undeleted" */
06446 
06447    if (vms->deleted[vms->curmsg])
06448       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06449 
06450    /* Except "Exit" */
06451    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06452    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06453       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06454    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06455 
06456    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06457    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06458    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06459    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06460    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06461    bytes += ast_adsi_set_keys(buf + bytes, keys);
06462    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06463 
06464    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06465 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06322 {
06323    unsigned char buf[256];
06324    int bytes = 0;
06325    unsigned char keys[8];
06326    int x;
06327    if (!ast_adsi_available(chan))
06328       return;
06329 
06330    for (x = 0; x < 8; x++)
06331       keys[x] = 0;
06332    /* Set one key for next */
06333    keys[3] = ADSI_KEY_APPS + 3;
06334 
06335    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06336    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06337    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06338    bytes += ast_adsi_set_keys(buf + bytes, keys);
06339    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06340    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06341 }

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

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

06513 {
06514    unsigned char buf[256] = "";
06515    char buf1[256] = "", buf2[256] = "";
06516    int bytes = 0;
06517    unsigned char keys[8];
06518    int x;
06519 
06520    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06521    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06522    if (!ast_adsi_available(chan))
06523       return;
06524    if (vms->newmessages) {
06525       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06526       if (vms->oldmessages) {
06527          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06528          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06529       } else {
06530          snprintf(buf2, sizeof(buf2), "%s.", newm);
06531       }
06532    } else if (vms->oldmessages) {
06533       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06534       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06535    } else {
06536       strcpy(buf1, "You have no messages.");
06537       buf2[0] = ' ';
06538       buf2[1] = '\0';
06539    }
06540    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06541    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06542    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06543 
06544    for (x = 0; x < 6; x++)
06545       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06546    keys[6] = 0;
06547    keys[7] = 0;
06548 
06549    /* Don't let them listen if there are none */
06550    if (vms->lastmsg < 0)
06551       keys[0] = 1;
06552    bytes += ast_adsi_set_keys(buf + bytes, keys);
06553 
06554    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06555 
06556    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06557 }

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

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

06560 {
06561    unsigned char buf[256] = "";
06562    char buf1[256] = "", buf2[256] = "";
06563    int bytes = 0;
06564    unsigned char keys[8];
06565    int x;
06566 
06567    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06568 
06569    if (!ast_adsi_available(chan))
06570       return;
06571 
06572    /* Original command keys */
06573    for (x = 0; x < 6; x++)
06574       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06575 
06576    keys[6] = 0;
06577    keys[7] = 0;
06578 
06579    if ((vms->lastmsg + 1) < 1)
06580       keys[0] = 0;
06581 
06582    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06583       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06584 
06585    if (vms->lastmsg + 1)
06586       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06587    else
06588       strcpy(buf2, "no messages.");
06589    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06590    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06591    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06592    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06593    bytes += ast_adsi_set_keys(buf + bytes, keys);
06594 
06595    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06596 
06597    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06598    
06599 }

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

12827 {
12828    int res = 0;
12829    char filename[PATH_MAX];
12830    struct ast_config *msg_cfg = NULL;
12831    const char *origtime, *context;
12832    char *name, *num;
12833    int retries = 0;
12834    char *cid;
12835    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
12836 
12837    vms->starting = 0; 
12838 
12839    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12840 
12841    /* Retrieve info from VM attribute file */
12842    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
12843    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
12844    msg_cfg = ast_config_load(filename, config_flags);
12845    DISPOSE(vms->curdir, vms->curmsg);
12846    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
12847       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
12848       return 0;
12849    }
12850 
12851    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
12852       ast_config_destroy(msg_cfg);
12853       return 0;
12854    }
12855 
12856    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
12857 
12858    context = ast_variable_retrieve(msg_cfg, "message", "context");
12859    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
12860       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
12861    switch (option) {
12862    case 3: /* Play message envelope */
12863       if (!res)
12864          res = play_message_datetime(chan, vmu, origtime, filename);
12865       if (!res)
12866          res = play_message_callerid(chan, vms, cid, context, 0);
12867 
12868       res = 't';
12869       break;
12870 
12871    case 2:  /* Call back */
12872 
12873       if (ast_strlen_zero(cid))
12874          break;
12875 
12876       ast_callerid_parse(cid, &name, &num);
12877       while ((res > -1) && (res != 't')) {
12878          switch (res) {
12879          case '1':
12880             if (num) {
12881                /* Dial the CID number */
12882                res = dialout(chan, vmu, num, vmu->callback);
12883                if (res) {
12884                   ast_config_destroy(msg_cfg);
12885                   return 9;
12886                }
12887             } else {
12888                res = '2';
12889             }
12890             break;
12891 
12892          case '2':
12893             /* Want to enter a different number, can only do this if there's a dialout context for this user */
12894             if (!ast_strlen_zero(vmu->dialout)) {
12895                res = dialout(chan, vmu, NULL, vmu->dialout);
12896                if (res) {
12897                   ast_config_destroy(msg_cfg);
12898                   return 9;
12899                }
12900             } else {
12901                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
12902                res = ast_play_and_wait(chan, "vm-sorry");
12903             }
12904             ast_config_destroy(msg_cfg);
12905             return res;
12906          case '*':
12907             res = 't';
12908             break;
12909          case '3':
12910          case '4':
12911          case '5':
12912          case '6':
12913          case '7':
12914          case '8':
12915          case '9':
12916          case '0':
12917 
12918             res = ast_play_and_wait(chan, "vm-sorry");
12919             retries++;
12920             break;
12921          default:
12922             if (num) {
12923                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
12924                res = ast_play_and_wait(chan, "vm-num-i-have");
12925                if (!res)
12926                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
12927                if (!res)
12928                   res = ast_play_and_wait(chan, "vm-tocallnum");
12929                /* Only prompt for a caller-specified number if there is a dialout context specified */
12930                if (!ast_strlen_zero(vmu->dialout)) {
12931                   if (!res)
12932                      res = ast_play_and_wait(chan, "vm-calldiffnum");
12933                }
12934             } else {
12935                res = ast_play_and_wait(chan, "vm-nonumber");
12936                if (!ast_strlen_zero(vmu->dialout)) {
12937                   if (!res)
12938                      res = ast_play_and_wait(chan, "vm-toenternumber");
12939                }
12940             }
12941             if (!res)
12942                res = ast_play_and_wait(chan, "vm-star-cancel");
12943             if (!res)
12944                res = ast_waitfordigit(chan, 6000);
12945             if (!res) {
12946                retries++;
12947                if (retries > 3)
12948                   res = 't';
12949             }
12950             break; 
12951             
12952          }
12953          if (res == 't')
12954             res = 0;
12955          else if (res == '*')
12956             res = -1;
12957       }
12958       break;
12959       
12960    case 1:  /* Reply */
12961       /* Send reply directly to sender */
12962       if (ast_strlen_zero(cid))
12963          break;
12964 
12965       ast_callerid_parse(cid, &name, &num);
12966       if (!num) {
12967          ast_verb(3, "No CID number available, no reply sent\n");
12968          if (!res)
12969             res = ast_play_and_wait(chan, "vm-nonumber");
12970          ast_config_destroy(msg_cfg);
12971          return res;
12972       } else {
12973          struct ast_vm_user vmu2;
12974          if (find_user(&vmu2, vmu->context, num)) {
12975             struct leave_vm_options leave_options;
12976             char mailbox[AST_MAX_EXTENSION * 2 + 2];
12977             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
12978 
12979             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
12980             
12981             memset(&leave_options, 0, sizeof(leave_options));
12982             leave_options.record_gain = record_gain;
12983             res = leave_voicemail(chan, mailbox, &leave_options);
12984             if (!res)
12985                res = 't';
12986             ast_config_destroy(msg_cfg);
12987             return res;
12988          } else {
12989             /* Sender has no mailbox, can't reply */
12990             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
12991             ast_play_and_wait(chan, "vm-nobox");
12992             res = 't';
12993             ast_config_destroy(msg_cfg);
12994             return res;
12995          }
12996       } 
12997       res = 0;
12998 
12999       break;
13000    }
13001 
13002 #ifndef IMAP_STORAGE
13003    ast_config_destroy(msg_cfg);
13004 
13005    if (!res) {
13006       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13007       vms->heard[msg] = 1;
13008       res = wait_file(chan, vms, vms->fn);
13009    }
13010 #endif
13011    return res;
13012 }

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

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

10505 {
10506    /* Assumes lock is already held */
10507    char *tmp;
10508    char *stringp;
10509    char *s;
10510    struct ast_vm_user *vmu;
10511    char *mailbox_full;
10512    int new = 0, old = 0, urgent = 0;
10513    char secretfn[PATH_MAX] = "";
10514 
10515    tmp = ast_strdupa(data);
10516 
10517    if (!(vmu = find_or_create(context, box)))
10518       return -1;
10519 
10520    populate_defaults(vmu);
10521 
10522    stringp = tmp;
10523    if ((s = strsep(&stringp, ","))) {
10524       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10525    }
10526    if (stringp && (s = strsep(&stringp, ","))) {
10527       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10528    }
10529    if (stringp && (s = strsep(&stringp, ","))) {
10530       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10531    }
10532    if (stringp && (s = strsep(&stringp, ","))) {
10533       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10534    }
10535    if (stringp && (s = strsep(&stringp, ","))) {
10536       apply_options(vmu, s);
10537    }
10538 
10539    switch (vmu->passwordlocation) {
10540    case OPT_PWLOC_SPOOLDIR:
10541       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10542       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10543    }
10544 
10545    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10546    strcpy(mailbox_full, box);
10547    strcat(mailbox_full, "@");
10548    strcat(mailbox_full, context);
10549 
10550    inboxcount2(mailbox_full, &urgent, &new, &old);
10551    queue_mwi_event(mailbox_full, urgent, new, old);
10552 
10553    return 0;
10554 }

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

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

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

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

04284 {
04285    const char *ptr;
04286 
04287    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04288    ast_str_set(buf, maxlen, "\"");
04289    for (ptr = from; *ptr; ptr++) {
04290       if (*ptr == '"' || *ptr == '\\') {
04291          ast_str_append(buf, maxlen, "\\%c", *ptr);
04292       } else {
04293          ast_str_append(buf, maxlen, "%c", *ptr);
04294       }
04295    }
04296    ast_str_append(buf, maxlen, "\"");
04297 
04298    return ast_str_buffer(*buf);
04299 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

10557 {
10558    int res = 0;
10559    struct ast_vm_user *vmu;
10560    /* language parameter seems to only be used for display in manager action */
10561    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10562       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10563       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10564       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10565       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10566       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10567       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir";
10568 #ifdef IMAP_STORAGE
10569    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10570       "imapfolder=INBOX|imapvmshareid=6000";
10571 #endif
10572 
10573    switch (cmd) {
10574    case TEST_INIT:
10575       info->name = "vmuser";
10576       info->category = "/apps/app_voicemail/";
10577       info->summary = "Vmuser unit test";
10578       info->description =
10579          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10580       return AST_TEST_NOT_RUN;
10581    case TEST_EXECUTE:
10582       break;
10583    }
10584 
10585    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10586       return AST_TEST_NOT_RUN;
10587    }
10588    ast_set_flag(vmu, VM_ALLOCED);
10589 
10590    apply_options(vmu, options_string);
10591 
10592    if (!ast_test_flag(vmu, VM_ATTACH)) {
10593       ast_test_status_update(test, "Parse failure for attach option\n");
10594       res = 1;
10595    }
10596    if (strcasecmp(vmu->attachfmt, "wav49")) {
10597       ast_test_status_update(test, "Parse failure for attachftm option\n");
10598       res = 1;
10599    }
10600    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10601       ast_test_status_update(test, "Parse failure for serveremail option\n");
10602       res = 1;
10603    }
10604    if (strcasecmp(vmu->zonetag, "central")) {
10605       ast_test_status_update(test, "Parse failure for tz option\n");
10606       res = 1;
10607    }
10608    if (!ast_test_flag(vmu, VM_DELETE)) {
10609       ast_test_status_update(test, "Parse failure for delete option\n");
10610       res = 1;
10611    }
10612    if (!ast_test_flag(vmu, VM_SAYCID)) {
10613       ast_test_status_update(test, "Parse failure for saycid option\n");
10614       res = 1;
10615    }
10616    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10617       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10618       res = 1;
10619    }
10620    if (!ast_test_flag(vmu, VM_REVIEW)) {
10621       ast_test_status_update(test, "Parse failure for review option\n");
10622       res = 1;
10623    }
10624    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10625       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10626       res = 1;
10627    }
10628    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10629       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10630       res = 1;
10631    }
10632    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10633       ast_test_status_update(test, "Parse failure for operator option\n");
10634       res = 1;
10635    }
10636    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10637       ast_test_status_update(test, "Parse failure for envelope option\n");
10638       res = 1;
10639    }
10640    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10641       ast_test_status_update(test, "Parse failure for moveheard option\n");
10642       res = 1;
10643    }
10644    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10645       ast_test_status_update(test, "Parse failure for sayduration option\n");
10646       res = 1;
10647    }
10648    if (vmu->saydurationm != 5) {
10649       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10650       res = 1;
10651    }
10652    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10653       ast_test_status_update(test, "Parse failure for forcename option\n");
10654       res = 1;
10655    }
10656    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10657       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10658       res = 1;
10659    }
10660    if (strcasecmp(vmu->callback, "somecontext")) {
10661       ast_test_status_update(test, "Parse failure for callbacks option\n");
10662       res = 1;
10663    }
10664    if (strcasecmp(vmu->dialout, "somecontext2")) {
10665       ast_test_status_update(test, "Parse failure for dialout option\n");
10666       res = 1;
10667    }
10668    if (strcasecmp(vmu->exit, "somecontext3")) {
10669       ast_test_status_update(test, "Parse failure for exitcontext option\n");
10670       res = 1;
10671    }
10672    if (vmu->minsecs != 10) {
10673       ast_test_status_update(test, "Parse failure for minsecs option\n");
10674       res = 1;
10675    }
10676    if (vmu->maxsecs != 100) {
10677       ast_test_status_update(test, "Parse failure for maxsecs option\n");
10678       res = 1;
10679    }
10680    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10681       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10682       res = 1;
10683    }
10684    if (vmu->maxdeletedmsg != 50) {
10685       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10686       res = 1;
10687    }
10688    if (vmu->volgain != 1.3) {
10689       ast_test_status_update(test, "Parse failure for volgain option\n");
10690       res = 1;
10691    }
10692    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10693       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10694       res = 1;
10695    }
10696 #ifdef IMAP_STORAGE
10697    apply_options(vmu, option_string2);
10698 
10699    if (strcasecmp(vmu->imapuser, "imapuser")) {
10700       ast_test_status_update(test, "Parse failure for imapuser option\n");
10701       res = 1;
10702    }
10703    if (strcasecmp(vmu->imappassword, "imappasswd")) {
10704       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10705       res = 1;
10706    }
10707    if (strcasecmp(vmu->imapfolder, "INBOX")) {
10708       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10709       res = 1;
10710    }
10711    if (strcasecmp(vmu->imapvmshareid, "6000")) {
10712       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
10713       res = 1;
10714    }
10715 #endif
10716 
10717    free_user(vmu);
10718    return res ? AST_TEST_FAIL : AST_TEST_PASS;
10719 }

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

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

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

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

04329 {
04330    for (; *str; str++) {
04331       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04332          return 1;
04333       }
04334    }
04335    return 0;
04336 }

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

07783 {
07784    int x = 0;
07785 #ifndef IMAP_STORAGE
07786    int res = 0, nummsg;
07787    char fn2[PATH_MAX];
07788 #endif
07789 
07790    if (vms->lastmsg <= -1) {
07791       goto done;
07792    }
07793 
07794    vms->curmsg = -1;
07795 #ifndef IMAP_STORAGE
07796    /* Get the deleted messages fixed */
07797    if (vm_lock_path(vms->curdir)) {
07798       return ERROR_LOCK_PATH;
07799    }
07800 
07801    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07802    for (x = 0; x < vms->lastmsg + 1; x++) {
07803       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07804          /* Save this message.  It's not in INBOX or hasn't been heard */
07805          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07806          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07807             break;
07808          }
07809          vms->curmsg++;
07810          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07811          if (strcmp(vms->fn, fn2)) {
07812             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07813          }
07814       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07815          /* Move to old folder before deleting */
07816          res = save_to_folder(vmu, vms, x, 1);
07817          if (res == ERROR_LOCK_PATH) {
07818             /* If save failed do not delete the message */
07819             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07820             vms->deleted[x] = 0;
07821             vms->heard[x] = 0;
07822             --x;
07823          }
07824       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07825          /* Move to deleted folder */
07826          res = save_to_folder(vmu, vms, x, 10);
07827          if (res == ERROR_LOCK_PATH) {
07828             /* If save failed do not delete the message */
07829             vms->deleted[x] = 0;
07830             vms->heard[x] = 0;
07831             --x;
07832          }
07833       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07834          /* If realtime storage enabled - we should explicitly delete this message,
07835          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07836          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07837          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07838             DELETE(vms->curdir, x, vms->fn, vmu);
07839          }
07840       }
07841    }
07842 
07843    /* Delete ALL remaining messages */
07844    nummsg = x - 1;
07845    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07846       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07847       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07848          DELETE(vms->curdir, x, vms->fn, vmu);
07849       }
07850    }
07851    ast_unlock_path(vms->curdir);
07852 #else /* defined(IMAP_STORAGE) */
07853    if (vms->deleted) {
07854       /* Since we now expunge after each delete, deleting in reverse order
07855        * ensures that no reordering occurs between each step. */
07856       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
07857          if (vms->deleted[x]) {
07858             ast_debug(3, "IMAP delete of %d\n", x);
07859             DELETE(vms->curdir, x, vms->fn, vmu);
07860          }
07861       }
07862    }
07863 #endif
07864 
07865 done:
07866    if (vms->deleted && vmu->maxmsg) {
07867       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
07868    }
07869    if (vms->heard && vmu->maxmsg) {
07870       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
07871    }
07872 
07873    return 0;
07874 }

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

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

10866 {
10867    int which = 0;
10868    int wordlen;
10869    struct ast_vm_user *vmu;
10870    const char *context = "";
10871 
10872    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
10873    if (pos > 4)
10874       return NULL;
10875    if (pos == 3)
10876       return (state == 0) ? ast_strdup("for") : NULL;
10877    wordlen = strlen(word);
10878    AST_LIST_TRAVERSE(&users, vmu, list) {
10879       if (!strncasecmp(word, vmu->context, wordlen)) {
10880          if (context && strcmp(context, vmu->context) && ++which > state)
10881             return ast_strdup(vmu->context);
10882          /* ignore repeated contexts ? */
10883          context = vmu->context;
10884       }
10885    }
10886    return NULL;
10887 }

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

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

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

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

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

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

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

12755 {
12756    int cmd = 0;
12757    char destination[80] = "";
12758    int retries = 0;
12759 
12760    if (!num) {
12761       ast_verb(3, "Destination number will be entered manually\n");
12762       while (retries < 3 && cmd != 't') {
12763          destination[1] = '\0';
12764          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
12765          if (!cmd)
12766             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
12767          if (!cmd)
12768             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
12769          if (!cmd) {
12770             cmd = ast_waitfordigit(chan, 6000);
12771             if (cmd)
12772                destination[0] = cmd;
12773          }
12774          if (!cmd) {
12775             retries++;
12776          } else {
12777 
12778             if (cmd < 0)
12779                return 0;
12780             if (cmd == '*') {
12781                ast_verb(3, "User hit '*' to cancel outgoing call\n");
12782                return 0;
12783             }
12784             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
12785                retries++;
12786             else
12787                cmd = 't';
12788          }
12789       }
12790       if (retries >= 3) {
12791          return 0;
12792       }
12793       
12794    } else {
12795       if (option_verbose > 2)
12796          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
12797       ast_copy_string(destination, num, sizeof(destination));
12798    }
12799 
12800    if (!ast_strlen_zero(destination)) {
12801       if (destination[strlen(destination) -1 ] == '*')
12802          return 0; 
12803       if (option_verbose > 2)
12804          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
12805       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
12806       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
12807       chan->priority = 0;
12808       return 9;
12809    }
12810    return 0;
12811 }

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

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

10473 {
10474    struct ast_vm_user *vmu;
10475 
10476    AST_LIST_TRAVERSE(&users, vmu, list) {
10477       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10478          if (strcasecmp(vmu->context, context)) {
10479             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10480                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10481                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10482                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10483          }
10484          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10485          return NULL;
10486       }
10487       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10488          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10489          return NULL;
10490       }
10491    }
10492    
10493    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10494       return NULL;
10495    
10496    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10497    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10498 
10499    AST_LIST_INSERT_TAIL(&users, vmu, list);
10500    
10501    return vmu;
10502 }

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

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

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

11465 {
11466    struct ast_vm_user *current;
11467    AST_LIST_LOCK(&users);
11468    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11469       ast_set_flag(current, VM_ALLOCED);
11470       free_user(current);
11471    }
11472    AST_LIST_UNLOCK(&users);
11473 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

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

11477 {
11478    struct vm_zone *zcur;
11479    AST_LIST_LOCK(&zones);
11480    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11481       free_zone(zcur);
11482    AST_LIST_UNLOCK(&zones);
11483 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4966 of file app_voicemail.c.

References ast_free.

04967 {
04968    ast_free(z);
04969 }

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

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

04923 {
04924    struct ast_tm tm;
04925    struct timeval t = ast_tvnow();
04926    
04927    ast_localtime(&t, &tm, "UTC");
04928 
04929    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04930 }

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

06636 {
06637    int x;
06638    int d;
06639    char fn[PATH_MAX];
06640    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06641    if (d)
06642       return d;
06643    for (x = start; x < 5; x++) { /* For all folders */
06644       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06645          return d;
06646       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06647       if (d)
06648          return d;
06649       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06650       d = vm_play_folder_name(chan, fn);
06651       if (d)
06652          return d;
06653       d = ast_waitfordigit(chan, 500);
06654       if (d)
06655          return d;
06656    }
06657    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06658    if (d)
06659       return d;
06660    d = ast_waitfordigit(chan, 4000);
06661    return d;
06662 }

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

References ast_play_and_wait(), and get_folder().

Referenced by vm_execmain().

06677 {
06678    int res = 0;
06679    int loops = 0;
06680    res = ast_play_and_wait(chan, fn);  /* Folder name */
06681    while (((res < '0') || (res > '9')) &&
06682          (res != '#') && (res >= 0) &&
06683          loops < 4) {
06684       res = get_folder(chan, 0);
06685       loops++;
06686    }
06687    if (loops == 4) { /* give up */
06688       return '#';
06689    }
06690    return res;
06691 }

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

11248 {
11249    unsigned int len;
11250    struct mwi_sub *mwi_sub;
11251    struct mwi_sub_task *p = datap;
11252 
11253    len = sizeof(*mwi_sub);
11254    if (!ast_strlen_zero(p->mailbox))
11255       len += strlen(p->mailbox);
11256 
11257    if (!ast_strlen_zero(p->context))
11258       len += strlen(p->context) + 1; /* Allow for seperator */
11259 
11260    if (!(mwi_sub = ast_calloc(1, len)))
11261       return -1;
11262 
11263    mwi_sub->uniqueid = p->uniqueid;
11264    if (!ast_strlen_zero(p->mailbox))
11265       strcpy(mwi_sub->mailbox, p->mailbox);
11266 
11267    if (!ast_strlen_zero(p->context)) {
11268       strcat(mwi_sub->mailbox, "@");
11269       strcat(mwi_sub->mailbox, p->context);
11270    }
11271 
11272    AST_RWLIST_WRLOCK(&mwi_subs);
11273    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11274    AST_RWLIST_UNLOCK(&mwi_subs);
11275    ast_free((void *) p->mailbox);
11276    ast_free((void *) p->context);
11277    ast_free(p);
11278    poll_subscribed_mailbox(mwi_sub);
11279    return 0;
11280 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

11226 {
11227    struct mwi_sub *mwi_sub;
11228    uint32_t *uniqueid = datap;
11229    
11230    AST_RWLIST_WRLOCK(&mwi_subs);
11231    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11232       if (mwi_sub->uniqueid == *uniqueid) {
11233          AST_LIST_REMOVE_CURRENT(entry);
11234          break;
11235       }
11236    }
11237    AST_RWLIST_TRAVERSE_SAFE_END
11238    AST_RWLIST_UNLOCK(&mwi_subs);
11239 
11240    if (mwi_sub)
11241       mwi_sub_destroy(mwi_sub);
11242 
11243    ast_free(uniqueid);  
11244    return 0;
11245 }

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

11001 {
11002    switch (cmd) {
11003    case CLI_INIT:
11004       e->command = "voicemail reload";
11005       e->usage =
11006          "Usage: voicemail reload\n"
11007          "       Reload voicemail configuration\n";
11008       return NULL;
11009    case CLI_GENERATE:
11010       return NULL;
11011    }
11012 
11013    if (a->argc != 2)
11014       return CLI_SHOWUSAGE;
11015 
11016    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11017    load_config(1);
11018    
11019    return CLI_SUCCESS;
11020 }

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

10891 {
10892    struct ast_vm_user *vmu;
10893 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
10894    const char *context = NULL;
10895    int users_counter = 0;
10896 
10897    switch (cmd) {
10898    case CLI_INIT:
10899       e->command = "voicemail show users";
10900       e->usage =
10901          "Usage: voicemail show users [for <context>]\n"
10902          "       Lists all mailboxes currently set up\n";
10903       return NULL;
10904    case CLI_GENERATE:
10905       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10906    }  
10907 
10908    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10909       return CLI_SHOWUSAGE;
10910    if (a->argc == 5) {
10911       if (strcmp(a->argv[3],"for"))
10912          return CLI_SHOWUSAGE;
10913       context = a->argv[4];
10914    }
10915 
10916    if (ast_check_realtime("voicemail")) {
10917       if (!context) {
10918          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10919          return CLI_SHOWUSAGE;
10920       }
10921       return show_users_realtime(a->fd, context);
10922    }
10923 
10924    AST_LIST_LOCK(&users);
10925    if (AST_LIST_EMPTY(&users)) {
10926       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10927       AST_LIST_UNLOCK(&users);
10928       return CLI_FAILURE;
10929    }
10930    if (a->argc == 3)
10931       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10932    else {
10933       int count = 0;
10934       AST_LIST_TRAVERSE(&users, vmu, list) {
10935          if (!strcmp(context, vmu->context))
10936             count++;
10937       }
10938       if (count) {
10939          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10940       } else {
10941          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10942          AST_LIST_UNLOCK(&users);
10943          return CLI_FAILURE;
10944       }
10945    }
10946    AST_LIST_TRAVERSE(&users, vmu, list) {
10947       int newmsgs = 0, oldmsgs = 0;
10948       char count[12], tmp[256] = "";
10949 
10950       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10951          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10952          inboxcount(tmp, &newmsgs, &oldmsgs);
10953          snprintf(count, sizeof(count), "%d", newmsgs);
10954          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10955          users_counter++;
10956       }
10957    }
10958    AST_LIST_UNLOCK(&users);
10959    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10960    return CLI_SUCCESS;
10961 }

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

10965 {
10966    struct vm_zone *zone;
10967 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10968    char *res = CLI_SUCCESS;
10969 
10970    switch (cmd) {
10971    case CLI_INIT:
10972       e->command = "voicemail show zones";
10973       e->usage =
10974          "Usage: voicemail show zones\n"
10975          "       Lists zone message formats\n";
10976       return NULL;
10977    case CLI_GENERATE:
10978       return NULL;
10979    }
10980 
10981    if (a->argc != 3)
10982       return CLI_SHOWUSAGE;
10983 
10984    AST_LIST_LOCK(&zones);
10985    if (!AST_LIST_EMPTY(&zones)) {
10986       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10987       AST_LIST_TRAVERSE(&zones, zone, list) {
10988          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10989       }
10990    } else {
10991       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10992       res = CLI_FAILURE;
10993    }
10994    AST_LIST_UNLOCK(&zones);
10995 
10996    return res;
10997 }

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

05309 {
05310    char tmp[256], *tmp2 = tmp, *box, *context;
05311    ast_copy_string(tmp, mailbox, sizeof(tmp));
05312    if (ast_strlen_zero(folder)) {
05313       folder = "INBOX";
05314    }
05315    while ((box = strsep(&tmp2, ",&"))) {
05316       if ((context = strchr(box, '@')))
05317          *context++ = '\0';
05318       else
05319          context = "default";
05320       if (__has_voicemail(context, box, folder, 1))
05321          return 1;
05322       /* If we are checking INBOX, we should check Urgent as well */
05323       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05324          return 1;
05325       }
05326    }
05327    return 0;
05328 }

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

Definition at line 5390 of file app_voicemail.c.

References inboxcount2().

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

05391 {
05392    int urgentmsgs = 0;
05393    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05394    if (newmsgs) {
05395       *newmsgs += urgentmsgs;
05396    }
05397    return res;
05398 }

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

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

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

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

utility used by inchar(), for base_encode()

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

04095 {
04096    int l;
04097 
04098    if (bio->ateof)
04099       return 0;
04100 
04101    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04102       if (ferror(fi))
04103          return -1;
04104 
04105       bio->ateof = 1;
04106       return 0;
04107    }
04108 
04109    bio->iolen = l;
04110    bio->iocp = 0;
04111 
04112    return 1;
04113 }

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

utility used by base_encode()

Definition at line 4118 of file app_voicemail.c.

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

Referenced by base_encode().

04119 {
04120    if (bio->iocp>=bio->iolen) {
04121       if (!inbuf(bio, fi))
04122          return EOF;
04123    }
04124 
04125    return bio->iobuf[bio->iocp++];
04126 }

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

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

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 ast_debug, 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    char extension[4];
03920    int stopcount = 0;
03921 
03922    /* Reading the entire directory into a file map scales better than
03923     * doing a stat repeatedly on a predicted sequence.  I suspect this
03924     * is partially due to stat(2) internally doing a readdir(2) itself to
03925     * find each file. */
03926    if (!(msgdir = opendir(dir))) {
03927       return -1;
03928    }
03929 
03930    while ((msgdirent = readdir(msgdir))) {
03931       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
03932          map[msgdirint] = 1;
03933          stopcount++;
03934          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
03935       }
03936    }
03937    closedir(msgdir);
03938 
03939    for (x = 0; x < vmu->maxmsg; x++) {
03940       if (map[x] == 1) {
03941          stopcount--;
03942       } else if (map[x] == 0 && !stopcount) {
03943          break;
03944       }
03945    }
03946 
03947    return x - 1;
03948 }

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

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

static int load_config ( int  reload  )  [static]

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

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

static int load_module ( void   )  [static]

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

12708 {
12709    int res;
12710    my_umask = umask(0);
12711    umask(my_umask);
12712 
12713    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
12714       return AST_MODULE_LOAD_DECLINE;
12715    }
12716 
12717    /* compute the location of the voicemail spool directory */
12718    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
12719    
12720    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
12721       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
12722    }
12723 
12724    if ((res = load_config(0)))
12725       return res;
12726 
12727    res = ast_register_application_xml(app, vm_exec);
12728    res |= ast_register_application_xml(app2, vm_execmain);
12729    res |= ast_register_application_xml(app3, vm_box_exists);
12730    res |= ast_register_application_xml(app4, vmauthenticate);
12731    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
12732    res |= ast_custom_function_register(&mailbox_exists_acf);
12733    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
12734 #ifdef TEST_FRAMEWORK
12735    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
12736    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
12737    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
12738    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
12739 #endif
12740 
12741    if (res)
12742       return res;
12743 
12744    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12745    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
12746 
12747    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
12748    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
12749    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
12750 
12751    return res;
12752 }

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

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

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

11364 {
11365    struct ast_vm_user *vmu = NULL;
11366    const char *id = astman_get_header(m, "ActionID");
11367    char actionid[128] = "";
11368 
11369    if (!ast_strlen_zero(id))
11370       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11371 
11372    AST_LIST_LOCK(&users);
11373 
11374    if (AST_LIST_EMPTY(&users)) {
11375       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11376       AST_LIST_UNLOCK(&users);
11377       return RESULT_SUCCESS;
11378    }
11379    
11380    astman_send_ack(s, m, "Voicemail user list will follow");
11381    
11382    AST_LIST_TRAVERSE(&users, vmu, list) {
11383       char dirname[256];
11384 
11385 #ifdef IMAP_STORAGE
11386       int new, old;
11387       inboxcount(vmu->mailbox, &new, &old);
11388 #endif
11389       
11390       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11391       astman_append(s,
11392          "%s"
11393          "Event: VoicemailUserEntry\r\n"
11394          "VMContext: %s\r\n"
11395          "VoiceMailbox: %s\r\n"
11396          "Fullname: %s\r\n"
11397          "Email: %s\r\n"
11398          "Pager: %s\r\n"
11399          "ServerEmail: %s\r\n"
11400          "MailCommand: %s\r\n"
11401          "Language: %s\r\n"
11402          "TimeZone: %s\r\n"
11403          "Callback: %s\r\n"
11404          "Dialout: %s\r\n"
11405          "UniqueID: %s\r\n"
11406          "ExitContext: %s\r\n"
11407          "SayDurationMinimum: %d\r\n"
11408          "SayEnvelope: %s\r\n"
11409          "SayCID: %s\r\n"
11410          "AttachMessage: %s\r\n"
11411          "AttachmentFormat: %s\r\n"
11412          "DeleteMessage: %s\r\n"
11413          "VolumeGain: %.2f\r\n"
11414          "CanReview: %s\r\n"
11415          "CallOperator: %s\r\n"
11416          "MaxMessageCount: %d\r\n"
11417          "MaxMessageLength: %d\r\n"
11418          "NewMessageCount: %d\r\n"
11419 #ifdef IMAP_STORAGE
11420          "OldMessageCount: %d\r\n"
11421          "IMAPUser: %s\r\n"
11422 #endif
11423          "\r\n",
11424          actionid,
11425          vmu->context,
11426          vmu->mailbox,
11427          vmu->fullname,
11428          vmu->email,
11429          vmu->pager,
11430          vmu->serveremail,
11431          vmu->mailcmd,
11432          vmu->language,
11433          vmu->zonetag,
11434          vmu->callback,
11435          vmu->dialout,
11436          vmu->uniqueid,
11437          vmu->exit,
11438          vmu->saydurationm,
11439          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11440          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11441          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11442          vmu->attachfmt,
11443          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11444          vmu->volgain,
11445          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11446          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11447          vmu->maxmsg,
11448          vmu->maxsecs,
11449 #ifdef IMAP_STORAGE
11450          new, old, vmu->imapuser
11451 #else
11452          count_messages(vmu, dirname)
11453 #endif
11454          );
11455    }     
11456    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11457 
11458    AST_LIST_UNLOCK(&users);
11459 
11460    return RESULT_SUCCESS;
11461 }

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

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

11198 {
11199    while (poll_thread_run) {
11200       struct timespec ts = { 0, };
11201       struct timeval wait;
11202 
11203       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11204       ts.tv_sec = wait.tv_sec;
11205       ts.tv_nsec = wait.tv_usec * 1000;
11206 
11207       ast_mutex_lock(&poll_lock);
11208       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11209       ast_mutex_unlock(&poll_lock);
11210 
11211       if (!poll_thread_run)
11212          break;
11213 
11214       poll_subscribed_mailboxes();
11215    }
11216 
11217    return NULL;
11218 }

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

References __has_voicemail().

Referenced by load_module().

05258 {
05259    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05260 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11220 of file app_voicemail.c.

References ast_free, and mwi_sub.

Referenced by handle_unsubscribe().

11221 {
11222    ast_free(mwi_sub);
11223 }

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

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

11299 {
11300    struct mwi_sub_task *mwist;
11301    
11302    if (ast_event_get_type(event) != AST_EVENT_SUB)
11303       return;
11304 
11305    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11306       return;
11307 
11308    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11309       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11310       return;
11311    }
11312    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11313    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11314    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11315    
11316    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11317       ast_free(mwist);
11318    }
11319 }

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

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

11283 {
11284    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11285    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11286       return;
11287 
11288    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11289       return;
11290 
11291    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11292    *uniqueid = u;
11293    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11294       ast_free(uniqueid);
11295    }
11296 }

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

06894 {
06895    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06896    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06897    const char *category;
06898    char *myserveremail = serveremail;
06899 
06900    ast_channel_lock(chan);
06901    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06902       category = ast_strdupa(category);
06903    }
06904    ast_channel_unlock(chan);
06905 
06906 #ifndef IMAP_STORAGE
06907    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06908 #else
06909    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
06910 #endif
06911    make_file(fn, sizeof(fn), todir, msgnum);
06912    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06913 
06914    if (!ast_strlen_zero(vmu->attachfmt)) {
06915       if (strstr(fmt, vmu->attachfmt))
06916          fmt = vmu->attachfmt;
06917       else
06918          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);
06919    }
06920 
06921    /* Attach only the first format */
06922    fmt = ast_strdupa(fmt);
06923    stringp = fmt;
06924    strsep(&stringp, "|");
06925 
06926    if (!ast_strlen_zero(vmu->serveremail))
06927       myserveremail = vmu->serveremail;
06928 
06929    if (!ast_strlen_zero(vmu->email)) {
06930       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06931 
06932       if (attach_user_voicemail)
06933          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06934 
06935       /* XXX possible imap issue, should category be NULL XXX */
06936       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06937 
06938       if (attach_user_voicemail)
06939          DISPOSE(todir, msgnum);
06940    }
06941 
06942    if (!ast_strlen_zero(vmu->pager)) {
06943       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
06944    }
06945 
06946    if (ast_test_flag(vmu, VM_DELETE))
06947       DELETE(todir, msgnum, fn, vmu);
06948 
06949    /* Leave voicemail for someone */
06950    if (ast_app_has_voicemail(ext_context, NULL)) 
06951       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06952 
06953    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06954 
06955    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);
06956    run_externnotify(vmu->context, vmu->mailbox, flag);
06957 
06958 #ifdef IMAP_STORAGE
06959    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06960    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06961       vm_imap_delete(NULL, vms->curmsg, vmu);
06962       vms->newmessages--;  /* Fix new message count */
06963    }
06964 #endif
06965 
06966    return 0;
06967 }

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

utility used by base_encode()

Definition at line 4131 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

04132 {
04133    if (bio->linelength >= BASELINELEN) {
04134       if (fputs(ENDL, so) == EOF) {
04135          return -1;
04136       }
04137 
04138       bio->linelength = 0;
04139    }
04140 
04141    if (putc(((unsigned char) c), so) == EOF) {
04142       return -1;
04143    }
04144 
04145    bio->linelength++;
04146 
04147    return 1;
04148 }

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

Definition at line 7727 of file app_voicemail.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, ast_unlock_path(), ast_vm_user::context, count_messages(), create_dirpath(), vm_state::curbox, vm_state::curdir, ERROR_LOCK_PATH, last_message_index(), vm_state::lastmsg, LOG_NOTICE, ast_vm_user::maxmsg, mbox(), resequence_mailbox(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

Referenced by vm_execmain().

07728 {
07729    int count_msg, last_msg;
07730 
07731    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07732 
07733    /* Rename the member vmbox HERE so that we don't try to return before
07734     * we know what's going on.
07735     */
07736    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07737 
07738    /* Faster to make the directory than to check if it exists. */
07739    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07740 
07741    /* traverses directory using readdir (or select query for ODBC) */
07742    count_msg = count_messages(vmu, vms->curdir);
07743    if (count_msg < 0) {
07744       return count_msg;
07745    } else {
07746       vms->lastmsg = count_msg - 1;
07747    }
07748 
07749    if (vm_allocate_dh(vms, vmu, count_msg)) {
07750       return -1;
07751    }
07752 
07753    /*
07754    The following test is needed in case sequencing gets messed up.
07755    There appears to be more than one way to mess up sequence, so
07756    we will not try to find all of the root causes--just fix it when
07757    detected.
07758    */
07759 
07760    if (vm_lock_path(vms->curdir)) {
07761       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07762       return ERROR_LOCK_PATH;
07763    }
07764 
07765    /* for local storage, checks directory for messages up to maxmsg limit */
07766    last_msg = last_message_index(vmu, vms->curdir);
07767    ast_unlock_path(vms->curdir);
07768 
07769    if (last_msg < -1) {
07770       return last_msg;
07771 #ifndef ODBC_STORAGE
07772    } else if (vms->lastmsg != last_msg) {
07773       ast_log(LOG_NOTICE, "Resequencing mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
07774         resequence_mailbox(vmu, vms->curdir, count_msg);
07775 #endif
07776    }
07777 
07778    return 0;
07779 }

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

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

07514 {
07515    int res = 0;
07516    char filename[256], *cid;
07517    const char *origtime, *context, *category, *duration, *flag;
07518    struct ast_config *msg_cfg;
07519    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07520 
07521    vms->starting = 0;
07522    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07523    adsi_message(chan, vms);
07524    if (!vms->curmsg)
07525       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07526    else if (vms->curmsg == vms->lastmsg)
07527       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07528 
07529    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07530    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07531    msg_cfg = ast_config_load(filename, config_flags);
07532    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07533       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07534       return 0;
07535    }
07536    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07537 
07538    /* Play the word urgent if we are listening to urgent messages */
07539    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07540       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07541    }
07542 
07543    if (!res) {
07544       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07545       /* POLISH syntax */
07546       if (!strncasecmp(chan->language, "pl", 2)) {
07547          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07548             int ten, one;
07549             char nextmsg[256];
07550             ten = (vms->curmsg + 1) / 10;
07551             one = (vms->curmsg + 1) % 10;
07552 
07553             if (vms->curmsg < 20) {
07554                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07555                res = wait_file2(chan, vms, nextmsg);
07556             } else {
07557                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07558                res = wait_file2(chan, vms, nextmsg);
07559                if (one > 0) {
07560                   if (!res) {
07561                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07562                      res = wait_file2(chan, vms, nextmsg);
07563                   }
07564                }
07565             }
07566          }
07567          if (!res)
07568             res = wait_file2(chan, vms, "vm-message");
07569       /* HEBREW syntax */
07570       } else if (!strncasecmp(chan->language, "he", 2)) {
07571          if (!vms->curmsg) {
07572             res = wait_file2(chan, vms, "vm-message");
07573             res = wait_file2(chan, vms, "vm-first");
07574          } else if (vms->curmsg == vms->lastmsg) {
07575             res = wait_file2(chan, vms, "vm-message");
07576             res = wait_file2(chan, vms, "vm-last");
07577          } else {
07578             res = wait_file2(chan, vms, "vm-message");
07579             res = wait_file2(chan, vms, "vm-number");
07580             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07581          }
07582       /* VIETNAMESE syntax */
07583       } else if (!strncasecmp(chan->language, "vi", 2)) {
07584          if (!vms->curmsg) {
07585             res = wait_file2(chan, vms, "vm-message");
07586             res = wait_file2(chan, vms, "vm-first");
07587          } else if (vms->curmsg == vms->lastmsg) {
07588             res = wait_file2(chan, vms, "vm-message");
07589             res = wait_file2(chan, vms, "vm-last");
07590          } else {
07591             res = wait_file2(chan, vms, "vm-message");
07592             res = wait_file2(chan, vms, "vm-number");
07593             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07594          }
07595       } else {
07596          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07597             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07598          } else { /* DEFAULT syntax */
07599             res = wait_file2(chan, vms, "vm-message");
07600          }
07601          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07602             if (!res) {
07603                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07604             }
07605          }
07606       }
07607    }
07608 
07609    if (!msg_cfg) {
07610       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07611       return 0;
07612    }
07613 
07614    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07615       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07616       DISPOSE(vms->curdir, vms->curmsg);
07617       ast_config_destroy(msg_cfg);
07618       return 0;
07619    }
07620 
07621    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07622    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07623    category = ast_variable_retrieve(msg_cfg, "message", "category");
07624 
07625    context = ast_variable_retrieve(msg_cfg, "message", "context");
07626    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07627       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07628    if (!res) {
07629       res = play_message_category(chan, category);
07630    }
07631    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07632       res = play_message_datetime(chan, vmu, origtime, filename);
07633    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07634       res = play_message_callerid(chan, vms, cid, context, 0);
07635    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07636       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07637    /* Allow pressing '1' to skip envelope / callerid */
07638    if (res == '1')
07639       res = 0;
07640    ast_config_destroy(msg_cfg);
07641 
07642    if (!res) {
07643       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07644       vms->heard[vms->curmsg] = 1;
07645 #ifdef IMAP_STORAGE
07646       /*IMAP storage stores any prepended message from a forward
07647        * as a separate file from the rest of the message
07648        */
07649       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07650          wait_file(chan, vms, vms->introfn);
07651       }
07652 #endif
07653       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07654          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07655          res = 0;
07656       }
07657    }
07658    DISPOSE(vms->curdir, vms->curmsg);
07659    return res;
07660 }

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

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

07400 {
07401    int res = 0;
07402    int i;
07403    char *callerid, *name;
07404    char prefile[PATH_MAX] = "";
07405    
07406 
07407    /* If voicemail cid is not enabled, or we didn't get cid or context from
07408     * the attribute file, leave now.
07409     *
07410     * TODO Still need to change this so that if this function is called by the
07411     * message envelope (and someone is explicitly requesting to hear the CID),
07412     * it does not check to see if CID is enabled in the config file.
07413     */
07414    if ((cid == NULL)||(context == NULL))
07415       return res;
07416 
07417    /* Strip off caller ID number from name */
07418    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07419    ast_callerid_parse(cid, &name, &callerid);
07420    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07421       /* Check for internal contexts and only */
07422       /* say extension when the call didn't come from an internal context in the list */
07423       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07424          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07425          if ((strcmp(cidinternalcontexts[i], context) == 0))
07426             break;
07427       }
07428       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07429          if (!res) {
07430             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07431             if (!ast_strlen_zero(prefile)) {
07432             /* See if we can find a recorded name for this person instead of their extension number */
07433                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07434                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07435                   if (!callback)
07436                      res = wait_file2(chan, vms, "vm-from");
07437                   res = ast_stream_and_wait(chan, prefile, "");
07438                } else {
07439                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07440                   /* Say "from extension" as one saying to sound smoother */
07441                   if (!callback)
07442                      res = wait_file2(chan, vms, "vm-from-extension");
07443                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07444                }
07445             }
07446          }
07447       } else if (!res) {
07448          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07449          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07450          if (!callback)
07451             res = wait_file2(chan, vms, "vm-from-phonenumber");
07452          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07453       }
07454    } else {
07455       /* Number unknown */
07456       ast_debug(1, "VM-CID: From an unknown number\n");
07457       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07458       res = wait_file2(chan, vms, "vm-unknown-caller");
07459    }
07460    return res;
07461 }

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

Definition at line 7310 of file app_voicemail.c.

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

Referenced by play_message().

07311 {
07312    int res = 0;
07313 
07314    if (!ast_strlen_zero(category))
07315       res = ast_play_and_wait(chan, category);
07316 
07317    if (res) {
07318       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07319       res = 0;
07320    }
07321 
07322    return res;
07323 }

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

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

07326 {
07327    int res = 0;
07328    struct vm_zone *the_zone = NULL;
07329    time_t t;
07330 
07331    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07332       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07333       return 0;
07334    }
07335 
07336    /* Does this user have a timezone specified? */
07337    if (!ast_strlen_zero(vmu->zonetag)) {
07338       /* Find the zone in the list */
07339       struct vm_zone *z;
07340       AST_LIST_LOCK(&zones);
07341       AST_LIST_TRAVERSE(&zones, z, list) {
07342          if (!strcmp(z->name, vmu->zonetag)) {
07343             the_zone = z;
07344             break;
07345          }
07346       }
07347       AST_LIST_UNLOCK(&zones);
07348    }
07349 
07350 /* No internal variable parsing for now, so we'll comment it out for the time being */
07351 #if 0
07352    /* Set the DIFF_* variables */
07353    ast_localtime(&t, &time_now, NULL);
07354    tv_now = ast_tvnow();
07355    ast_localtime(&tv_now, &time_then, NULL);
07356 
07357    /* Day difference */
07358    if (time_now.tm_year == time_then.tm_year)
07359       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07360    else
07361       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07362    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07363 
07364    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07365 #endif
07366    if (the_zone) {
07367       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07368    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07369       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07370    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07371       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07372    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07373       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);
07374    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07375       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07376    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07377       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07378    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07379       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07380    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07381       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);
07382    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07383       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07384    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07385       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07386    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07387       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);
07388    } else {
07389       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07390    }
07391 #if 0
07392    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07393 #endif
07394    return res;
07395 }

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

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

07464 {
07465    int res = 0;
07466    int durationm;
07467    int durations;
07468    /* Verify that we have a duration for the message */
07469    if (duration == NULL)
07470       return res;
07471 
07472    /* Convert from seconds to minutes */
07473    durations = atoi(duration);
07474    durationm = (durations / 60);
07475 
07476    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07477 
07478    if ((!res) && (durationm >= minduration)) {
07479       res = wait_file2(chan, vms, "vm-duration");
07480 
07481       /* POLISH syntax */
07482       if (!strncasecmp(chan->language, "pl", 2)) {
07483          div_t num = div(durationm, 10);
07484 
07485          if (durationm == 1) {
07486             res = ast_play_and_wait(chan, "digits/1z");
07487             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07488          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07489             if (num.rem == 2) {
07490                if (!num.quot) {
07491                   res = ast_play_and_wait(chan, "digits/2-ie");
07492                } else {
07493                   res = say_and_wait(chan, durationm - 2 , chan->language);
07494                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07495                }
07496             } else {
07497                res = say_and_wait(chan, durationm, chan->language);
07498             }
07499             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07500          } else {
07501             res = say_and_wait(chan, durationm, chan->language);
07502             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07503          }
07504       /* DEFAULT syntax */
07505       } else {
07506          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07507          res = wait_file2(chan, vms, "vm-minutes");
07508       }
07509    }
07510    return res;
07511 }

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

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

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11169 of file app_voicemail.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11170 {
11171    int new = 0, old = 0, urgent = 0;
11172 
11173    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11174 
11175    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11176       mwi_sub->old_urgent = urgent;
11177       mwi_sub->old_new = new;
11178       mwi_sub->old_old = old;
11179       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11180       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11181    }
11182 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11185 {
11186    struct mwi_sub *mwi_sub;
11187 
11188    AST_RWLIST_RDLOCK(&mwi_subs);
11189    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11190       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11191          poll_subscribed_mailbox(mwi_sub);
11192       }
11193    }
11194    AST_RWLIST_UNLOCK(&mwi_subs);
11195 }

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

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

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

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

06857 {
06858    struct ast_event *event;
06859    char *mailbox, *context;
06860 
06861    /* Strip off @default */
06862    context = mailbox = ast_strdupa(box);
06863    strsep(&context, "@");
06864    if (ast_strlen_zero(context))
06865       context = "default";
06866 
06867    if (!(event = ast_event_new(AST_EVENT_MWI,
06868          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06869          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06870          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06871          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06872          AST_EVENT_IE_END))) {
06873       return;
06874    }
06875 
06876    ast_event_queue_and_cache(event);
06877 }

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

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

12231                                                                                            {
12232    struct ast_config *pwconf;
12233    struct ast_flags config_flags = { 0 };
12234 
12235    pwconf = ast_config_load(secretfn, config_flags);
12236    if (pwconf) {
12237       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12238       if (val) {
12239          ast_copy_string(password, val, passwordlen);
12240          return;
12241       }
12242    }
12243    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12244 }

static int reload ( void   )  [static]

Definition at line 12668 of file app_voicemail.c.

References load_config().

12669 {
12670    return load_config(1);
12671 }

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 resequence_mailbox ( struct ast_vm_user vmu,
char *  dir,
int  stopcount 
) [static]

Definition at line 6026 of file app_voicemail.c.

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

Referenced by open_mailbox().

06027 {
06028     /* we know the actual number of messages, so stop process when number is hit */
06029 
06030     int x, dest;
06031     char sfn[PATH_MAX];
06032     char dfn[PATH_MAX];
06033 
06034     if (vm_lock_path(dir))
06035         return ERROR_LOCK_PATH;
06036 
06037     for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06038         make_file(sfn, sizeof(sfn), dir, x);
06039         if (EXISTS(dir, x, sfn, NULL)) {
06040 
06041             if (x != dest) {
06042                 make_file(dfn, sizeof(dfn), dir, dest);
06043                 RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06044             }
06045 
06046             dest++;
06047         }
06048     }
06049     ast_unlock_path(dir);
06050 
06051     return dest;
06052 }

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

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

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

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

06063 {
06064 #ifdef IMAP_STORAGE
06065    /* we must use mbox(x) folder names, and copy the message there */
06066    /* simple. huh? */
06067    char sequence[10];
06068    char mailbox[256];
06069    int res;
06070 
06071    /* get the real IMAP message number for this message */
06072    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06073    
06074    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06075    ast_mutex_lock(&vms->lock);
06076    /* if save to Old folder, put in INBOX as read */
06077    if (box == OLD_FOLDER) {
06078       mail_setflag(vms->mailstream, sequence, "\\Seen");
06079       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06080    } else if (box == NEW_FOLDER) {
06081       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06082       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06083    }
06084    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06085       ast_mutex_unlock(&vms->lock);
06086       return 0;
06087    }
06088    /* Create the folder if it don't exist */
06089    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06090    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06091    if (mail_create(vms->mailstream, mailbox) == NIL) 
06092       ast_debug(5, "Folder exists.\n");
06093    else
06094       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06095    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06096    ast_mutex_unlock(&vms->lock);
06097    return res;
06098 #else
06099    char *dir = vms->curdir;
06100    char *username = vms->username;
06101    char *context = vmu->context;
06102    char sfn[PATH_MAX];
06103    char dfn[PATH_MAX];
06104    char ddir[PATH_MAX];
06105    const char *dbox = mbox(vmu, box);
06106    int x, i;
06107    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06108 
06109    if (vm_lock_path(ddir))
06110       return ERROR_LOCK_PATH;
06111 
06112    x = last_message_index(vmu, ddir) + 1;
06113 
06114    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06115       x--;
06116       for (i = 1; i <= x; i++) {
06117          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06118          make_file(sfn, sizeof(sfn), ddir, i);
06119          make_file(dfn, sizeof(dfn), ddir, i - 1);
06120          if (EXISTS(ddir, i, sfn, NULL)) {
06121             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06122          } else
06123             break;
06124       }
06125    } else {
06126       if (x >= vmu->maxmsg) {
06127          ast_unlock_path(ddir);
06128          return -1;
06129       }
06130    }
06131    make_file(sfn, sizeof(sfn), dir, msg);
06132    make_file(dfn, sizeof(dfn), ddir, x);
06133    if (strcmp(sfn, dfn)) {
06134       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06135    }
06136    ast_unlock_path(ddir);
06137 #endif
06138    return 0;
06139 }

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

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

06056 {
06057    int d;
06058    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06059    return d;
06060 }

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

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

12218 {
12219    int res = -1;
12220    char dir[PATH_MAX];
12221    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12222    ast_debug(2, "About to try retrieving name file %s\n", dir);
12223    RETRIEVE(dir, -1, mailbox, context);
12224    if (ast_fileexists(dir, NULL, NULL)) {
12225       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12226    }
12227    DISPOSE(dir, -1);
12228    return res;
12229 }

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

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

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

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

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

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

10827 {
10828    struct ast_config *cfg;
10829    const char *cat = NULL;
10830 
10831    if (!(cfg = ast_load_realtime_multientry("voicemail", 
10832       "context", context, SENTINEL))) {
10833       return CLI_FAILURE;
10834    }
10835 
10836    ast_cli(fd,
10837       "\n"
10838       "=============================================================\n"
10839       "=== Configured Voicemail Users ==============================\n"
10840       "=============================================================\n"
10841       "===\n");
10842 
10843    while ((cat = ast_category_browse(cfg, cat))) {
10844       struct ast_variable *var = NULL;
10845       ast_cli(fd,
10846          "=== Mailbox ...\n"
10847          "===\n");
10848       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
10849          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
10850       ast_cli(fd,
10851          "===\n"
10852          "=== ---------------------------------------------------------\n"
10853          "===\n");
10854    }
10855 
10856    ast_cli(fd,
10857       "=============================================================\n"
10858       "\n");
10859 
10860    ast_config_destroy(cfg);
10861 
10862    return CLI_SUCCESS;
10863 }

static void start_poll_thread ( void   )  [static]

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

11340 {
11341    poll_thread_run = 0;
11342 
11343    if (mwi_sub_sub) {
11344       ast_event_unsubscribe(mwi_sub_sub);
11345       mwi_sub_sub = NULL;
11346    }
11347 
11348    if (mwi_unsub_sub) {
11349       ast_event_unsubscribe(mwi_unsub_sub);
11350       mwi_unsub_sub = NULL;
11351    }
11352 
11353    ast_mutex_lock(&poll_lock);
11354    ast_cond_signal(&poll_cond);
11355    ast_mutex_unlock(&poll_lock);
11356 
11357    pthread_join(poll_thread, NULL);
11358 
11359    poll_thread = AST_PTHREADT_NULL;
11360 }

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

11486 {
11487    char *current;
11488 
11489    /* Add 16 for fudge factor */
11490    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11491 
11492    ast_str_reset(str);
11493    
11494    /* Substitute strings \r, \n, and \t into the appropriate characters */
11495    for (current = (char *) value; *current; current++) {
11496       if (*current == '\\') {
11497          current++;
11498          if (!*current) {
11499             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11500             break;
11501          }
11502          switch (*current) {
11503          case 'r':
11504             ast_str_append(&str, 0, "\r");
11505             break;
11506          case 'n':
11507 #ifdef IMAP_STORAGE
11508             if (!str->used || str->str[str->used - 1] != '\r') {
11509                ast_str_append(&str, 0, "\r");
11510             }
11511 #endif
11512             ast_str_append(&str, 0, "\n");
11513             break;
11514          case 't':
11515             ast_str_append(&str, 0, "\t");
11516             break;
11517          default:
11518             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11519             break;
11520          }
11521       } else {
11522          ast_str_append(&str, 0, "%c", *current);
11523       }
11524    }
11525 
11526    return ast_str_buffer(str);
11527 }

static int unload_module ( void   )  [static]

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

12674 {
12675    int res;
12676 
12677    res = ast_unregister_application(app);
12678    res |= ast_unregister_application(app2);
12679    res |= ast_unregister_application(app3);
12680    res |= ast_unregister_application(app4);
12681    res |= ast_unregister_application(sayname_app);
12682    res |= ast_custom_function_unregister(&mailbox_exists_acf);
12683    res |= ast_manager_unregister("VoicemailUsersList");
12684    res |= ast_data_unregister(NULL);
12685 #ifdef TEST_FRAMEWORK
12686    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
12687    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
12688    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
12689    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
12690 #endif
12691    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12692    ast_uninstall_vm_functions();
12693    ao2_ref(inprocess_container, -1);
12694 
12695    if (poll_thread != AST_PTHREADT_NULL)
12696       stop_poll_thread();
12697 
12698    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
12699    ast_unload_realtime("voicemail");
12700    ast_unload_realtime("voicemail_data");
12701 
12702    free_vm_users();
12703    free_vm_zones();
12704    return res;
12705 }

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

09561 {
09562    int useadsi = 0, valid = 0, logretries = 0;
09563    char password[AST_MAX_EXTENSION]="", *passptr;
09564    struct ast_vm_user vmus, *vmu = NULL;
09565 
09566    /* If ADSI is supported, setup login screen */
09567    adsi_begin(chan, &useadsi);
09568    if (!skipuser && useadsi)
09569       adsi_login(chan);
09570    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09571       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09572       return -1;
09573    }
09574    
09575    /* Authenticate them and get their mailbox/password */
09576    
09577    while (!valid && (logretries < max_logins)) {
09578       /* Prompt for, and read in the username */
09579       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09580          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09581          return -1;
09582       }
09583       if (ast_strlen_zero(mailbox)) {
09584          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09585             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09586          } else {
09587             ast_verb(3, "Username not entered\n"); 
09588             return -1;
09589          }
09590       } else if (mailbox[0] == '*') {
09591          /* user entered '*' */
09592          if (ast_exists_extension(chan, chan->context, "a", 1,
09593             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09594             return -1;
09595          }
09596          mailbox[0] = '\0';
09597       }
09598 
09599       if (useadsi)
09600          adsi_password(chan);
09601 
09602       if (!ast_strlen_zero(prefix)) {
09603          char fullusername[80] = "";
09604          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09605          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09606          ast_copy_string(mailbox, fullusername, mailbox_size);
09607       }
09608 
09609       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09610       vmu = find_user(&vmus, context, mailbox);
09611       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09612          /* saved password is blank, so don't bother asking */
09613          password[0] = '\0';
09614       } else {
09615          if (ast_streamfile(chan, vm_password, chan->language)) {
09616             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09617             return -1;
09618          }
09619          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09620             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09621             return -1;
09622          } else if (password[0] == '*') {
09623             /* user entered '*' */
09624             if (ast_exists_extension(chan, chan->context, "a", 1,
09625                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09626                mailbox[0] = '*';
09627                return -1;
09628             }
09629             mailbox[0] = '\0';
09630          }
09631       }
09632 
09633       if (vmu) {
09634          passptr = vmu->password;
09635          if (passptr[0] == '-') passptr++;
09636       }
09637       if (vmu && !strcmp(passptr, password))
09638          valid++;
09639       else {
09640          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09641          if (!ast_strlen_zero(prefix))
09642             mailbox[0] = '\0';
09643       }
09644       logretries++;
09645       if (!valid) {
09646          if (skipuser || logretries >= max_logins) {
09647             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09648                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09649                return -1;
09650             }
09651          } else {
09652             if (useadsi)
09653                adsi_login(chan);
09654             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09655                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09656                return -1;
09657             }
09658          }
09659          if (ast_waitstream(chan, "")) /* Channel is hung up */
09660             return -1;
09661       }
09662    }
09663    if (!valid && (logretries >= max_logins)) {
09664       ast_stopstream(chan);
09665       ast_play_and_wait(chan, "vm-goodbye");
09666       return -1;
09667    }
09668    if (vmu && !skipuser) {
09669       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09670    }
09671    return 0;
09672 }

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

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

10722 {
10723    struct ast_vm_user svm;
10724    char *context, *box;
10725    AST_DECLARE_APP_ARGS(args,
10726       AST_APP_ARG(mbox);
10727       AST_APP_ARG(options);
10728    );
10729    static int dep_warning = 0;
10730 
10731    if (ast_strlen_zero(data)) {
10732       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10733       return -1;
10734    }
10735 
10736    if (!dep_warning) {
10737       dep_warning = 1;
10738       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10739    }
10740 
10741    box = ast_strdupa(data);
10742 
10743    AST_STANDARD_APP_ARGS(args, box);
10744 
10745    if (args.options) {
10746    }
10747 
10748    if ((context = strchr(args.mbox, '@'))) {
10749       *context = '\0';
10750       context++;
10751    }
10752 
10753    if (find_user(&svm, context, args.mbox)) {
10754       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10755    } else
10756       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10757 
10758    return 0;
10759 }

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

09538 {
09539    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09540       return vm_browse_messages_es(chan, vms, vmu);
09541    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09542       return vm_browse_messages_gr(chan, vms, vmu);
09543    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09544       return vm_browse_messages_he(chan, vms, vmu);
09545    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09546       return vm_browse_messages_it(chan, vms, vmu);
09547    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09548       return vm_browse_messages_pt(chan, vms, vmu);
09549    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09550       return vm_browse_messages_vi(chan, vms, vmu);
09551    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09552       return vm_browse_messages_zh(chan, vms, vmu);
09553    } else {                                             /* Default to English syntax */
09554       return vm_browse_messages_en(chan, vms, vmu);
09555    }
09556 }

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

09377 {
09378    int cmd = 0;
09379 
09380    if (vms->lastmsg > -1) {
09381       cmd = play_message(chan, vmu, vms);
09382    } else {
09383       cmd = ast_play_and_wait(chan, "vm-youhave");
09384       if (!cmd) 
09385          cmd = ast_play_and_wait(chan, "vm-no");
09386       if (!cmd) {
09387          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09388          cmd = ast_play_and_wait(chan, vms->fn);
09389       }
09390       if (!cmd)
09391          cmd = ast_play_and_wait(chan, "vm-messages");
09392    }
09393    return cmd;
09394 }

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

09431 {
09432    int cmd;
09433 
09434    if (vms->lastmsg > -1) {
09435       cmd = play_message(chan, vmu, vms);
09436    } else {
09437       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09438       if (!cmd)
09439          cmd = ast_play_and_wait(chan, "vm-messages");
09440       if (!cmd) {
09441          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09442          cmd = ast_play_and_wait(chan, vms->fn);
09443       }
09444    }
09445    return cmd;
09446 }

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

09325 {
09326    int cmd = 0;
09327 
09328    if (vms->lastmsg > -1) {
09329       cmd = play_message(chan, vmu, vms);
09330    } else {
09331       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09332       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09333          if (!cmd) {
09334             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09335             cmd = ast_play_and_wait(chan, vms->fn);
09336          }
09337          if (!cmd)
09338             cmd = ast_play_and_wait(chan, "vm-messages");
09339       } else {
09340          if (!cmd)
09341             cmd = ast_play_and_wait(chan, "vm-messages");
09342          if (!cmd) {
09343             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09344             cmd = ast_play_and_wait(chan, vms->fn);
09345          }
09346       }
09347    } 
09348    return cmd;
09349 }

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

Definition at line 9352 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

09353 {
09354    int cmd = 0;
09355 
09356    if (vms->lastmsg > -1) {
09357       cmd = play_message(chan, vmu, vms);
09358    } else {
09359       if (!strcasecmp(vms->fn, "INBOX")) {
09360          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09361       } else {
09362          cmd = ast_play_and_wait(chan, "vm-nomessages");
09363       }
09364    }
09365    return cmd;
09366 }

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

09405 {
09406    int cmd;
09407 
09408    if (vms->lastmsg > -1) {
09409       cmd = play_message(chan, vmu, vms);
09410    } else {
09411       cmd = ast_play_and_wait(chan, "vm-no");
09412       if (!cmd)
09413          cmd = ast_play_and_wait(chan, "vm-message");
09414       if (!cmd) {
09415          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09416          cmd = ast_play_and_wait(chan, vms->fn);
09417       }
09418    }
09419    return cmd;
09420 }

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

09457 {
09458    int cmd;
09459 
09460    if (vms->lastmsg > -1) {
09461       cmd = play_message(chan, vmu, vms);
09462    } else {
09463       cmd = ast_play_and_wait(chan, "vm-no");
09464       if (!cmd) {
09465          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09466          cmd = ast_play_and_wait(chan, vms->fn);
09467       }
09468       if (!cmd)
09469          cmd = ast_play_and_wait(chan, "vm-messages");
09470    }
09471    return cmd;
09472 }

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

09511 {
09512    int cmd = 0;
09513 
09514    if (vms->lastmsg > -1) {
09515       cmd = play_message(chan, vmu, vms);
09516    } else {
09517       cmd = ast_play_and_wait(chan, "vm-no");
09518       if (!cmd) {
09519          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09520          cmd = ast_play_and_wait(chan, vms->fn);
09521       }
09522    }
09523    return cmd;
09524 }

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

09483 {
09484    int cmd;
09485 
09486    if (vms->lastmsg > -1) {
09487       cmd = play_message(chan, vmu, vms);
09488    } else {
09489       cmd = ast_play_and_wait(chan, "vm-you");
09490       if (!cmd) 
09491          cmd = ast_play_and_wait(chan, "vm-haveno");
09492       if (!cmd)
09493          cmd = ast_play_and_wait(chan, "vm-messages");
09494       if (!cmd) {
09495          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09496          cmd = ast_play_and_wait(chan, vms->fn);
09497       }
09498    }
09499    return cmd;
09500 }

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

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

04074 {
04075    char *txt;
04076    int txtsize = 0;
04077 
04078    txtsize = (strlen(file) + 5)*sizeof(char);
04079    txt = alloca(txtsize);
04080    /* Sprintf here would safe because we alloca'd exactly the right length,
04081     * but trying to eliminate all sprintf's anyhow
04082     */
04083    if (ast_check_realtime("voicemail_data")) {
04084       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04085    }
04086    snprintf(txt, txtsize, "%s.txt", file);
04087    unlink(txt);
04088    return ast_filedelete(file, NULL);
04089 }

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

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

10405 {
10406    int res = 0;
10407    char *tmp;
10408    struct leave_vm_options leave_options;
10409    struct ast_flags flags = { 0 };
10410    char *opts[OPT_ARG_ARRAY_SIZE];
10411    AST_DECLARE_APP_ARGS(args,
10412       AST_APP_ARG(argv0);
10413       AST_APP_ARG(argv1);
10414    );
10415    
10416    memset(&leave_options, 0, sizeof(leave_options));
10417 
10418    if (chan->_state != AST_STATE_UP)
10419       ast_answer(chan);
10420 
10421    if (!ast_strlen_zero(data)) {
10422       tmp = ast_strdupa(data);
10423       AST_STANDARD_APP_ARGS(args, tmp);
10424       if (args.argc == 2) {
10425          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10426             return -1;
10427          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10428          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10429             int gain;
10430 
10431             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10432                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10433                return -1;
10434             } else {
10435                leave_options.record_gain = (signed char) gain;
10436             }
10437          }
10438          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10439             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10440                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10441          }
10442       }
10443    } else {
10444       char temp[256];
10445       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10446       if (res < 0)
10447          return res;
10448       if (ast_strlen_zero(temp))
10449          return 0;
10450       args.argv0 = ast_strdupa(temp);
10451    }
10452 
10453    res = leave_voicemail(chan, args.argv0, &leave_options);
10454    if (res == 't') {
10455       ast_play_and_wait(chan, "vm-goodbye");
10456       res = 0;
10457    }
10458 
10459    if (res == OPERATOR_EXIT) {
10460       res = 0;
10461    }
10462 
10463    if (res == ERROR_LOCK_PATH) {
10464       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10465       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10466       res = 0;
10467    }
10468 
10469    return res;
10470 }

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

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

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

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

06713 {
06714 #ifdef IMAP_STORAGE
06715    int res;
06716 #endif
06717    int cmd = 0;
06718    int retries = 0, prepend_duration = 0, already_recorded = 0;
06719    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06720    char textfile[PATH_MAX];
06721    struct ast_config *msg_cfg;
06722    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06723 #ifndef IMAP_STORAGE
06724    signed char zero_gain = 0;
06725 #endif
06726    const char *duration_str;
06727 
06728    /* Must always populate duration correctly */
06729    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06730    strcpy(textfile, msgfile);
06731    strcpy(backup, msgfile);
06732    strcpy(backup_textfile, msgfile);
06733    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06734    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06735    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06736 
06737    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06738       *duration = atoi(duration_str);
06739    } else {
06740       *duration = 0;
06741    }
06742 
06743    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06744       if (cmd)
06745          retries = 0;
06746       switch (cmd) {
06747       case '1': 
06748 
06749 #ifdef IMAP_STORAGE
06750          /* Record new intro file */
06751          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06752          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06753          res = ast_play_and_wait(chan, INTRO);
06754          res = ast_play_and_wait(chan, "beep");
06755          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, record_gain, vms, flag);
06756          cmd = 't';
06757 #else
06758 
06759          /* prepend a message to the current message, update the metadata and return */
06760 
06761          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06762          strcpy(textfile, msgfile);
06763          strncat(textfile, ".txt", sizeof(textfile) - 1);
06764          *duration = 0;
06765 
06766          /* if we can't read the message metadata, stop now */
06767          if (!msg_cfg) {
06768             cmd = 0;
06769             break;
06770          }
06771          
06772          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06773 #ifndef IMAP_STORAGE
06774          if (already_recorded) {
06775             ast_filecopy(backup, msgfile, NULL);
06776             copy(backup_textfile, textfile);
06777          }
06778          else {
06779             ast_filecopy(msgfile, backup, NULL);
06780             copy(textfile, backup_textfile);
06781          }
06782 #endif
06783          already_recorded = 1;
06784 
06785          if (record_gain)
06786             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06787 
06788          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06789          if (cmd == 'S') {
06790             ast_filerename(backup, msgfile, NULL);
06791          }
06792 
06793          if (record_gain)
06794             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06795 
06796          
06797          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06798             *duration = atoi(duration_str);
06799 
06800          if (prepend_duration) {
06801             struct ast_category *msg_cat;
06802             /* need enough space for a maximum-length message duration */
06803             char duration_buf[12];
06804 
06805             *duration += prepend_duration;
06806             msg_cat = ast_category_get(msg_cfg, "message");
06807             snprintf(duration_buf, 11, "%ld", *duration);
06808             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06809                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06810             }
06811          }
06812 
06813 #endif
06814          break;
06815       case '2': 
06816          /* NULL out introfile so we know there is no intro! */
06817 #ifdef IMAP_STORAGE
06818          *vms->introfn = '\0';
06819 #endif
06820          cmd = 't';
06821          break;
06822       case '*':
06823          cmd = '*';
06824          break;
06825       default: 
06826          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
06827             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06828          if (!cmd)
06829             cmd = ast_play_and_wait(chan, "vm-starmain");
06830             /* "press star to return to the main menu" */
06831          if (!cmd)
06832             cmd = ast_waitfordigit(chan, 6000);
06833          if (!cmd)
06834             retries++;
06835          if (retries > 3)
06836             cmd = 't';
06837       }
06838    }
06839 
06840    if (msg_cfg)
06841       ast_config_destroy(msg_cfg);
06842    if (prepend_duration)
06843       *duration = prepend_duration;
06844 
06845    if (already_recorded && cmd == -1) {
06846       /* restore original message if prepention cancelled */
06847       ast_filerename(backup, msgfile, NULL);
06848       rename(backup_textfile, textfile);
06849    }
06850 
06851    if (cmd == 't' || cmd == 'S')
06852       cmd = 0;
06853    return cmd;
06854 }

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

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

Referenced by vm_execmain().

09016 {
09017    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09018       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09019    } else {             /* Default to ENGLISH */
09020       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09021    }
09022 }

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

08915 {
08916    int res = 0;
08917    /* Play instructions and wait for new command */
08918    while (!res) {
08919       if (vms->starting) {
08920          if (vms->lastmsg > -1) {
08921             if (skipadvanced)
08922                res = ast_play_and_wait(chan, "vm-onefor-full");
08923             else
08924                res = ast_play_and_wait(chan, "vm-onefor");
08925             if (!res)
08926                res = vm_play_folder_name(chan, vms->vmbox);
08927          }
08928          if (!res) {
08929             if (skipadvanced)
08930                res = ast_play_and_wait(chan, "vm-opts-full");
08931             else
08932                res = ast_play_and_wait(chan, "vm-opts");
08933          }
08934       } else {
08935          /* Added for additional help */
08936          if (skipadvanced) {
08937             res = ast_play_and_wait(chan, "vm-onefor-full");
08938             if (!res)
08939                res = vm_play_folder_name(chan, vms->vmbox);
08940             res = ast_play_and_wait(chan, "vm-opts-full");
08941          }
08942          /* Logic:
08943           * If the current message is not the first OR
08944           * if we're listening to the first new message and there are
08945           * also urgent messages, then prompt for navigation to the
08946           * previous message
08947           */
08948          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08949             res = ast_play_and_wait(chan, "vm-prev");
08950          }
08951          if (!res && !skipadvanced)
08952             res = ast_play_and_wait(chan, "vm-advopts");
08953          if (!res)
08954             res = ast_play_and_wait(chan, "vm-repeat");
08955          /* Logic:
08956           * If we're not listening to the last message OR
08957           * we're listening to the last urgent message and there are
08958           * also new non-urgent messages, then prompt for navigation
08959           * to the next message
08960           */
08961          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08962             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08963             res = ast_play_and_wait(chan, "vm-next");
08964          }
08965          if (!res) {
08966             if (!vms->deleted[vms->curmsg])
08967                res = ast_play_and_wait(chan, "vm-delete");
08968             else
08969                res = ast_play_and_wait(chan, "vm-undelete");
08970             if (!res)
08971                res = ast_play_and_wait(chan, "vm-toforward");
08972             if (!res)
08973                res = ast_play_and_wait(chan, "vm-savemessage");
08974          }
08975       }
08976       if (!res) {
08977          res = ast_play_and_wait(chan, "vm-helpexit");
08978       }
08979       if (!res)
08980          res = ast_waitfordigit(chan, 6000);
08981       if (!res) {
08982          vms->repeats++;
08983          if (vms->repeats > 2) {
08984             res = 't';
08985          }
08986       }
08987    }
08988    return res;
08989 }

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

08992 {
08993    int res = 0;
08994    /* Play instructions and wait for new command */
08995    while (!res) {
08996       if (vms->lastmsg > -1) {
08997          res = ast_play_and_wait(chan, "vm-listen");
08998          if (!res)
08999             res = vm_play_folder_name(chan, vms->vmbox);
09000          if (!res)
09001             res = ast_play_and_wait(chan, "press");
09002          if (!res)
09003             res = ast_play_and_wait(chan, "digits/1");
09004       }
09005       if (!res)
09006          res = ast_play_and_wait(chan, "vm-opts");
09007       if (!res) {
09008          vms->starting = 0;
09009          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09010       }
09011    }
09012    return res;
09013 }

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

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

08853 {
08854    char prefile[256];
08855    
08856    /* Notify the user that the temp greeting is set and give them the option to remove it */
08857    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08858    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08859       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08860       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08861          ast_play_and_wait(chan, "vm-tempgreetactive");
08862       }
08863       DISPOSE(prefile, -1);
08864    }
08865 
08866    /* Play voicemail intro - syntax is different for different languages */
08867    if (0) {
08868       return 0;
08869    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08870       return vm_intro_cs(chan, vms);
08871    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08872       static int deprecation_warning = 0;
08873       if (deprecation_warning++ % 10 == 0) {
08874          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08875       }
08876       return vm_intro_cs(chan, vms);
08877    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08878       return vm_intro_de(chan, vms);
08879    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08880       return vm_intro_es(chan, vms);
08881    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08882       return vm_intro_fr(chan, vms);
08883    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08884       return vm_intro_gr(chan, vms);
08885    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08886       return vm_intro_he(chan, vms);
08887    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08888       return vm_intro_it(chan, vms);
08889    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08890       return vm_intro_nl(chan, vms);
08891    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08892       return vm_intro_no(chan, vms);
08893    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08894       return vm_intro_pl(chan, vms);
08895    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08896       return vm_intro_pt_BR(chan, vms);
08897    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08898       return vm_intro_pt(chan, vms);
08899    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08900       return vm_intro_multilang(chan, vms, "n");
08901    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08902       return vm_intro_se(chan, vms);
08903    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08904       return vm_intro_multilang(chan, vms, "n");
08905    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
08906       return vm_intro_vi(chan, vms);
08907    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08908       return vm_intro_zh(chan, vms);
08909    } else {                                             /* Default to ENGLISH */
08910       return vm_intro_en(chan, vms);
08911    }
08912 }

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

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

08723 {
08724    int res;
08725    res = ast_play_and_wait(chan, "vm-youhave");
08726    if (!res) {
08727       if (vms->newmessages) {
08728          if (vms->newmessages == 1) {
08729             res = ast_play_and_wait(chan, "digits/jednu");
08730          } else {
08731             res = say_and_wait(chan, vms->newmessages, chan->language);
08732          }
08733          if (!res) {
08734             if ((vms->newmessages == 1))
08735                res = ast_play_and_wait(chan, "vm-novou");
08736             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08737                res = ast_play_and_wait(chan, "vm-nove");
08738             if (vms->newmessages > 4)
08739                res = ast_play_and_wait(chan, "vm-novych");
08740          }
08741          if (vms->oldmessages && !res)
08742             res = ast_play_and_wait(chan, "vm-and");
08743          else if (!res) {
08744             if ((vms->newmessages == 1))
08745                res = ast_play_and_wait(chan, "vm-zpravu");
08746             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08747                res = ast_play_and_wait(chan, "vm-zpravy");
08748             if (vms->newmessages > 4)
08749                res = ast_play_and_wait(chan, "vm-zprav");
08750          }
08751       }
08752       if (!res && vms->oldmessages) {
08753          res = say_and_wait(chan, vms->oldmessages, chan->language);
08754          if (!res) {
08755             if ((vms->oldmessages == 1))
08756                res = ast_play_and_wait(chan, "vm-starou");
08757             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08758                res = ast_play_and_wait(chan, "vm-stare");
08759             if (vms->oldmessages > 4)
08760                res = ast_play_and_wait(chan, "vm-starych");
08761          }
08762          if (!res) {
08763             if ((vms->oldmessages == 1))
08764                res = ast_play_and_wait(chan, "vm-zpravu");
08765             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08766                res = ast_play_and_wait(chan, "vm-zpravy");
08767             if (vms->oldmessages > 4)
08768                res = ast_play_and_wait(chan, "vm-zprav");
08769          }
08770       }
08771       if (!res) {
08772          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08773             res = ast_play_and_wait(chan, "vm-no");
08774             if (!res)
08775                res = ast_play_and_wait(chan, "vm-zpravy");
08776          }
08777       }
08778    }
08779    return res;
08780 }

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

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

08419 {
08420    /* Introduce messages they have */
08421    int res;
08422    res = ast_play_and_wait(chan, "vm-youhave");
08423    if (!res) {
08424       if (vms->newmessages) {
08425          if ((vms->newmessages == 1))
08426             res = ast_play_and_wait(chan, "digits/1F");
08427          else
08428             res = say_and_wait(chan, vms->newmessages, chan->language);
08429          if (!res)
08430             res = ast_play_and_wait(chan, "vm-INBOX");
08431          if (vms->oldmessages && !res)
08432             res = ast_play_and_wait(chan, "vm-and");
08433          else if (!res) {
08434             if ((vms->newmessages == 1))
08435                res = ast_play_and_wait(chan, "vm-message");
08436             else
08437                res = ast_play_and_wait(chan, "vm-messages");
08438          }
08439             
08440       }
08441       if (!res && vms->oldmessages) {
08442          if (vms->oldmessages == 1)
08443             res = ast_play_and_wait(chan, "digits/1F");
08444          else
08445             res = say_and_wait(chan, vms->oldmessages, chan->language);
08446          if (!res)
08447             res = ast_play_and_wait(chan, "vm-Old");
08448          if (!res) {
08449             if (vms->oldmessages == 1)
08450                res = ast_play_and_wait(chan, "vm-message");
08451             else
08452                res = ast_play_and_wait(chan, "vm-messages");
08453          }
08454       }
08455       if (!res) {
08456          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08457             res = ast_play_and_wait(chan, "vm-no");
08458             if (!res)
08459                res = ast_play_and_wait(chan, "vm-messages");
08460          }
08461       }
08462    }
08463    return res;
08464 }

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

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

08168 {
08169    int res;
08170 
08171    /* Introduce messages they have */
08172    res = ast_play_and_wait(chan, "vm-youhave");
08173    if (!res) {
08174       if (vms->urgentmessages) {
08175          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08176          if (!res)
08177             res = ast_play_and_wait(chan, "vm-Urgent");
08178          if ((vms->oldmessages || vms->newmessages) && !res) {
08179             res = ast_play_and_wait(chan, "vm-and");
08180          } else if (!res) {
08181             if ((vms->urgentmessages == 1))
08182                res = ast_play_and_wait(chan, "vm-message");
08183             else
08184                res = ast_play_and_wait(chan, "vm-messages");
08185          }
08186       }
08187       if (vms->newmessages) {
08188          res = say_and_wait(chan, vms->newmessages, chan->language);
08189          if (!res)
08190             res = ast_play_and_wait(chan, "vm-INBOX");
08191          if (vms->oldmessages && !res)
08192             res = ast_play_and_wait(chan, "vm-and");
08193          else if (!res) {
08194             if ((vms->newmessages == 1))
08195                res = ast_play_and_wait(chan, "vm-message");
08196             else
08197                res = ast_play_and_wait(chan, "vm-messages");
08198          }
08199             
08200       }
08201       if (!res && vms->oldmessages) {
08202          res = say_and_wait(chan, vms->oldmessages, chan->language);
08203          if (!res)
08204             res = ast_play_and_wait(chan, "vm-Old");
08205          if (!res) {
08206             if (vms->oldmessages == 1)
08207                res = ast_play_and_wait(chan, "vm-message");
08208             else
08209                res = ast_play_and_wait(chan, "vm-messages");
08210          }
08211       }
08212       if (!res) {
08213          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08214             res = ast_play_and_wait(chan, "vm-no");
08215             if (!res)
08216                res = ast_play_and_wait(chan, "vm-messages");
08217          }
08218       }
08219    }
08220    return res;
08221 }

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

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

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

static int vm_intro_fr ( 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             res = ast_play_and_wait(chan, "vm-INBOX");
08575          if (vms->oldmessages && !res)
08576             res = ast_play_and_wait(chan, "vm-and");
08577          else if (!res) {
08578             if ((vms->newmessages == 1))
08579                res = ast_play_and_wait(chan, "vm-message");
08580             else
08581                res = ast_play_and_wait(chan, "vm-messages");
08582          }
08583             
08584       }
08585       if (!res && vms->oldmessages) {
08586          res = say_and_wait(chan, vms->oldmessages, chan->language);
08587          if (!res)
08588             res = ast_play_and_wait(chan, "vm-Old");
08589          if (!res) {
08590             if (vms->oldmessages == 1)
08591                res = ast_play_and_wait(chan, "vm-message");
08592             else
08593                res = ast_play_and_wait(chan, "vm-messages");
08594          }
08595       }
08596       if (!res) {
08597          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08598             res = ast_play_and_wait(chan, "vm-no");
08599             if (!res)
08600                res = ast_play_and_wait(chan, "vm-messages");
08601          }
08602       }
08603    }
08604    return res;
08605 }

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

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

07967 {
07968    int res = 0;
07969 
07970    if (vms->newmessages) {
07971       res = ast_play_and_wait(chan, "vm-youhave");
07972       if (!res) 
07973          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07974       if (!res) {
07975          if ((vms->newmessages == 1)) {
07976             res = ast_play_and_wait(chan, "vm-INBOX");
07977             if (!res)
07978                res = ast_play_and_wait(chan, "vm-message");
07979          } else {
07980             res = ast_play_and_wait(chan, "vm-INBOXs");
07981             if (!res)
07982                res = ast_play_and_wait(chan, "vm-messages");
07983          }
07984       }
07985    } else if (vms->oldmessages){
07986       res = ast_play_and_wait(chan, "vm-youhave");
07987       if (!res)
07988          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07989       if ((vms->oldmessages == 1)){
07990          res = ast_play_and_wait(chan, "vm-Old");
07991          if (!res)
07992             res = ast_play_and_wait(chan, "vm-message");
07993       } else {
07994          res = ast_play_and_wait(chan, "vm-Olds");
07995          if (!res)
07996             res = ast_play_and_wait(chan, "vm-messages");
07997       }
07998    } else if (!vms->oldmessages && !vms->newmessages) 
07999       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08000    return res;
08001 }

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

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

08101 {
08102    int res = 0;
08103 
08104    /* Introduce messages they have */
08105    if (!res) {
08106       if ((vms->newmessages) || (vms->oldmessages)) {
08107          res = ast_play_and_wait(chan, "vm-youhave");
08108       }
08109       /*
08110        * The word "shtei" refers to the number 2 in hebrew when performing a count
08111        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08112        * an element, this is one of them.
08113        */
08114       if (vms->newmessages) {
08115          if (!res) {
08116             if (vms->newmessages == 1) {
08117                res = ast_play_and_wait(chan, "vm-INBOX1");
08118             } else {
08119                if (vms->newmessages == 2) {
08120                   res = ast_play_and_wait(chan, "vm-shtei");
08121                } else {
08122                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08123                }
08124                res = ast_play_and_wait(chan, "vm-INBOX");
08125             }
08126          }
08127          if (vms->oldmessages && !res) {
08128             res = ast_play_and_wait(chan, "vm-and");
08129             if (vms->oldmessages == 1) {
08130                res = ast_play_and_wait(chan, "vm-Old1");
08131             } else {
08132                if (vms->oldmessages == 2) {
08133                   res = ast_play_and_wait(chan, "vm-shtei");
08134                } else {
08135                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08136                }
08137                res = ast_play_and_wait(chan, "vm-Old");
08138             }
08139          }
08140       }
08141       if (!res && vms->oldmessages && !vms->newmessages) {
08142          if (!res) {
08143             if (vms->oldmessages == 1) {
08144                res = ast_play_and_wait(chan, "vm-Old1");
08145             } else {
08146                if (vms->oldmessages == 2) {
08147                   res = ast_play_and_wait(chan, "vm-shtei");
08148                } else {
08149                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08150                }
08151                res = ast_play_and_wait(chan, "vm-Old");
08152             }
08153          }
08154       }
08155       if (!res) {
08156          if (!vms->oldmessages && !vms->newmessages) {
08157             if (!res) {
08158                res = ast_play_and_wait(chan, "vm-nomessages");
08159             }
08160          }
08161       }
08162    }
08163    return res;
08164 }

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

Definition at line 8224 of file app_voicemail.c.

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

Referenced by vm_intro().

08225 {
08226    /* Introduce messages they have */
08227    int res;
08228    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08229       res = ast_play_and_wait(chan, "vm-no") ||
08230          ast_play_and_wait(chan, "vm-message");
08231    else
08232       res = ast_play_and_wait(chan, "vm-youhave");
08233    if (!res && vms->newmessages) {
08234       res = (vms->newmessages == 1) ?
08235          ast_play_and_wait(chan, "digits/un") ||
08236          ast_play_and_wait(chan, "vm-nuovo") ||
08237          ast_play_and_wait(chan, "vm-message") :
08238          /* 2 or more new messages */
08239          say_and_wait(chan, vms->newmessages, chan->language) ||
08240          ast_play_and_wait(chan, "vm-nuovi") ||
08241          ast_play_and_wait(chan, "vm-messages");
08242       if (!res && vms->oldmessages)
08243          res = ast_play_and_wait(chan, "vm-and");
08244    }
08245    if (!res && vms->oldmessages) {
08246       res = (vms->oldmessages == 1) ?
08247          ast_play_and_wait(chan, "digits/un") ||
08248          ast_play_and_wait(chan, "vm-vecchio") ||
08249          ast_play_and_wait(chan, "vm-message") :
08250          /* 2 or more old messages */
08251          say_and_wait(chan, vms->oldmessages, chan->language) ||
08252          ast_play_and_wait(chan, "vm-vecchi") ||
08253          ast_play_and_wait(chan, "vm-messages");
08254    }
08255    return res;
08256 }

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

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

08061 {
08062    int res;
08063    int lastnum = 0;
08064 
08065    res = ast_play_and_wait(chan, "vm-youhave");
08066 
08067    if (!res && vms->newmessages) {
08068       lastnum = vms->newmessages;
08069 
08070       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08071          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08072       }
08073 
08074       if (!res && vms->oldmessages) {
08075          res = ast_play_and_wait(chan, "vm-and");
08076       }
08077    }
08078 
08079    if (!res && vms->oldmessages) {
08080       lastnum = vms->oldmessages;
08081 
08082       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08083          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08084       }
08085    }
08086 
08087    if (!res) {
08088       if (lastnum == 0) {
08089          res = ast_play_and_wait(chan, "vm-no");
08090       }
08091       if (!res) {
08092          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08093       }
08094    }
08095 
08096    return res;
08097 }

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

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

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

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

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

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

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

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

08260 {
08261    /* Introduce messages they have */
08262    int res;
08263    div_t num;
08264 
08265    if (!vms->oldmessages && !vms->newmessages) {
08266       res = ast_play_and_wait(chan, "vm-no");
08267       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08268       return res;
08269    } else {
08270       res = ast_play_and_wait(chan, "vm-youhave");
08271    }
08272 
08273    if (vms->newmessages) {
08274       num = div(vms->newmessages, 10);
08275       if (vms->newmessages == 1) {
08276          res = ast_play_and_wait(chan, "digits/1-a");
08277          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08278          res = res ? res : ast_play_and_wait(chan, "vm-message");
08279       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08280          if (num.rem == 2) {
08281             if (!num.quot) {
08282                res = ast_play_and_wait(chan, "digits/2-ie");
08283             } else {
08284                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08285                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08286             }
08287          } else {
08288             res = say_and_wait(chan, vms->newmessages, chan->language);
08289          }
08290          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08291          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08292       } else {
08293          res = say_and_wait(chan, vms->newmessages, chan->language);
08294          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08295          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08296       }
08297       if (!res && vms->oldmessages)
08298          res = ast_play_and_wait(chan, "vm-and");
08299    }
08300    if (!res && vms->oldmessages) {
08301       num = div(vms->oldmessages, 10);
08302       if (vms->oldmessages == 1) {
08303          res = ast_play_and_wait(chan, "digits/1-a");
08304          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08305          res = res ? res : ast_play_and_wait(chan, "vm-message");
08306       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08307          if (num.rem == 2) {
08308             if (!num.quot) {
08309                res = ast_play_and_wait(chan, "digits/2-ie");
08310             } else {
08311                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08312                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08313             }
08314          } else {
08315             res = say_and_wait(chan, vms->oldmessages, chan->language);
08316          }
08317          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08318          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08319       } else {
08320          res = say_and_wait(chan, vms->oldmessages, chan->language);
08321          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08322          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08323       }
08324    }
08325 
08326    return res;
08327 }

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

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

08660 {
08661    /* Introduce messages they have */
08662    int res;
08663    res = ast_play_and_wait(chan, "vm-youhave");
08664    if (!res) {
08665       if (vms->newmessages) {
08666          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08667          if (!res) {
08668             if ((vms->newmessages == 1)) {
08669                res = ast_play_and_wait(chan, "vm-message");
08670                if (!res)
08671                   res = ast_play_and_wait(chan, "vm-INBOXs");
08672             } else {
08673                res = ast_play_and_wait(chan, "vm-messages");
08674                if (!res)
08675                   res = ast_play_and_wait(chan, "vm-INBOX");
08676             }
08677          }
08678          if (vms->oldmessages && !res)
08679             res = ast_play_and_wait(chan, "vm-and");
08680       }
08681       if (!res && vms->oldmessages) {
08682          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08683          if (!res) {
08684             if (vms->oldmessages == 1) {
08685                res = ast_play_and_wait(chan, "vm-message");
08686                if (!res)
08687                   res = ast_play_and_wait(chan, "vm-Olds");
08688             } else {
08689                res = ast_play_and_wait(chan, "vm-messages");
08690                if (!res)
08691                   res = ast_play_and_wait(chan, "vm-Old");
08692             }
08693          }
08694       }
08695       if (!res) {
08696          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08697             res = ast_play_and_wait(chan, "vm-no");
08698             if (!res)
08699                res = ast_play_and_wait(chan, "vm-messages");
08700          }
08701       }
08702    }
08703    return res;
08704 }

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

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

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

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

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

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

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

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

08823 {
08824    int res;
08825 
08826    /* Introduce messages they have */
08827    res = ast_play_and_wait(chan, "vm-youhave");
08828    if (!res) {
08829       if (vms->newmessages) {
08830          res = say_and_wait(chan, vms->newmessages, chan->language);
08831          if (!res)
08832             res = ast_play_and_wait(chan, "vm-INBOX");
08833          if (vms->oldmessages && !res)
08834             res = ast_play_and_wait(chan, "vm-and");
08835       }
08836       if (!res && vms->oldmessages) {
08837          res = say_and_wait(chan, vms->oldmessages, chan->language);
08838          if (!res)
08839             res = ast_play_and_wait(chan, "vm-Old");        
08840       }
08841       if (!res) {
08842          if (!vms->oldmessages && !vms->newmessages) {
08843             res = ast_play_and_wait(chan, "vm-no");
08844             if (!res)
08845                res = ast_play_and_wait(chan, "vm-message");
08846          }
08847       }
08848    }
08849    return res;
08850 }

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

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

08784 {
08785    int res;
08786    /* Introduce messages they have */
08787    res = ast_play_and_wait(chan, "vm-you");
08788 
08789    if (!res && vms->newmessages) {
08790       res = ast_play_and_wait(chan, "vm-have");
08791       if (!res)
08792          res = say_and_wait(chan, vms->newmessages, chan->language);
08793       if (!res)
08794          res = ast_play_and_wait(chan, "vm-tong");
08795       if (!res)
08796          res = ast_play_and_wait(chan, "vm-INBOX");
08797       if (vms->oldmessages && !res)
08798          res = ast_play_and_wait(chan, "vm-and");
08799       else if (!res) 
08800          res = ast_play_and_wait(chan, "vm-messages");
08801    }
08802    if (!res && vms->oldmessages) {
08803       res = ast_play_and_wait(chan, "vm-have");
08804       if (!res)
08805          res = say_and_wait(chan, vms->oldmessages, chan->language);
08806       if (!res)
08807          res = ast_play_and_wait(chan, "vm-tong");
08808       if (!res)
08809          res = ast_play_and_wait(chan, "vm-Old");
08810       if (!res)
08811          res = ast_play_and_wait(chan, "vm-messages");
08812    }
08813    if (!res && !vms->oldmessages && !vms->newmessages) {
08814       res = ast_play_and_wait(chan, "vm-haveno");
08815       if (!res)
08816          res = ast_play_and_wait(chan, "vm-messages");
08817    }
08818    return res;
08819 }

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

09026 {
09027    int cmd = 0;
09028    int duration = 0;
09029    int tries = 0;
09030    char newpassword[80] = "";
09031    char newpassword2[80] = "";
09032    char prefile[PATH_MAX] = "";
09033    unsigned char buf[256];
09034    int bytes = 0;
09035 
09036    if (ast_adsi_available(chan)) {
09037       bytes += adsi_logo(buf + bytes);
09038       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09039       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09040       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09041       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09042       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09043    }
09044 
09045    /* First, have the user change their password 
09046       so they won't get here again */
09047    for (;;) {
09048       newpassword[1] = '\0';
09049       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09050       if (cmd == '#')
09051          newpassword[0] = '\0';
09052       if (cmd < 0 || cmd == 't' || cmd == '#')
09053          return cmd;
09054       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09055       if (cmd < 0 || cmd == 't' || cmd == '#')
09056          return cmd;
09057       cmd = check_password(vmu, newpassword); /* perform password validation */
09058       if (cmd != 0) {
09059          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09060          cmd = ast_play_and_wait(chan, vm_invalid_password);
09061       } else {
09062          newpassword2[1] = '\0';
09063          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09064          if (cmd == '#')
09065             newpassword2[0] = '\0';
09066          if (cmd < 0 || cmd == 't' || cmd == '#')
09067             return cmd;
09068          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09069          if (cmd < 0 || cmd == 't' || cmd == '#')
09070             return cmd;
09071          if (!strcmp(newpassword, newpassword2))
09072             break;
09073          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09074          cmd = ast_play_and_wait(chan, vm_mismatch);
09075       }
09076       if (++tries == 3)
09077          return -1;
09078       if (cmd != 0) {
09079          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09080       }
09081    }
09082    if (pwdchange & PWDCHANGE_INTERNAL)
09083       vm_change_password(vmu, newpassword);
09084    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09085       vm_change_password_shell(vmu, newpassword);
09086 
09087    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09088    cmd = ast_play_and_wait(chan, vm_passchanged);
09089 
09090    /* If forcename is set, have the user record their name */  
09091    if (ast_test_flag(vmu, VM_FORCENAME)) {
09092       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09093       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09094          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09095          if (cmd < 0 || cmd == 't' || cmd == '#')
09096             return cmd;
09097       }
09098    }
09099 
09100    /* If forcegreetings is set, have the user record their greetings */
09101    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09102       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09103       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09104          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09105          if (cmd < 0 || cmd == 't' || cmd == '#')
09106             return cmd;
09107       }
09108 
09109       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09110       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09111          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09112          if (cmd < 0 || cmd == 't' || cmd == '#')
09113             return cmd;
09114       }
09115    }
09116 
09117    return cmd;
09118 }

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

09121 {
09122    int cmd = 0;
09123    int retries = 0;
09124    int duration = 0;
09125    char newpassword[80] = "";
09126    char newpassword2[80] = "";
09127    char prefile[PATH_MAX] = "";
09128    unsigned char buf[256];
09129    int bytes = 0;
09130 
09131    if (ast_adsi_available(chan)) {
09132       bytes += adsi_logo(buf + bytes);
09133       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09134       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09135       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09136       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09137       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09138    }
09139    while ((cmd >= 0) && (cmd != 't')) {
09140       if (cmd)
09141          retries = 0;
09142       switch (cmd) {
09143       case '1': /* Record your unavailable message */
09144          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09145          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09146          break;
09147       case '2':  /* Record your busy message */
09148          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09149          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09150          break;
09151       case '3': /* Record greeting */
09152          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09153          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09154          break;
09155       case '4':  /* manage the temporary greeting */
09156          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09157          break;
09158       case '5': /* change password */
09159          if (vmu->password[0] == '-') {
09160             cmd = ast_play_and_wait(chan, "vm-no");
09161             break;
09162          }
09163          newpassword[1] = '\0';
09164          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09165          if (cmd == '#')
09166             newpassword[0] = '\0';
09167          else {
09168             if (cmd < 0)
09169                break;
09170             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09171                break;
09172             }
09173          }
09174          cmd = check_password(vmu, newpassword); /* perform password validation */
09175          if (cmd != 0) {
09176             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09177             cmd = ast_play_and_wait(chan, vm_invalid_password);
09178             if (!cmd) {
09179                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09180             }
09181             break;
09182          }
09183          newpassword2[1] = '\0';
09184          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09185          if (cmd == '#')
09186             newpassword2[0] = '\0';
09187          else {
09188             if (cmd < 0)
09189                break;
09190 
09191             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09192                break;
09193             }
09194          }
09195          if (strcmp(newpassword, newpassword2)) {
09196             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09197             cmd = ast_play_and_wait(chan, vm_mismatch);
09198             if (!cmd) {
09199                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09200             }
09201             break;
09202          }
09203          if (pwdchange & PWDCHANGE_INTERNAL)
09204             vm_change_password(vmu, newpassword);
09205          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09206             vm_change_password_shell(vmu, newpassword);
09207 
09208          ast_debug(1, "User %s set password to %s of length %d\n",
09209             vms->username, newpassword, (int) strlen(newpassword));
09210          cmd = ast_play_and_wait(chan, vm_passchanged);
09211          break;
09212       case '*': 
09213          cmd = 't';
09214          break;
09215       default: 
09216          cmd = 0;
09217          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09218          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09219          if (ast_fileexists(prefile, NULL, NULL)) {
09220             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09221          }
09222          DISPOSE(prefile, -1);
09223          if (!cmd) {
09224             cmd = ast_play_and_wait(chan, "vm-options");
09225          }
09226          if (!cmd) {
09227             cmd = ast_waitfordigit(chan, 6000);
09228          }
09229          if (!cmd) {
09230             retries++;
09231          }
09232          if (retries > 3) {
09233             cmd = 't';
09234          }
09235       }
09236    }
09237    if (cmd == 't')
09238       cmd = 0;
09239    return cmd;
09240 }

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

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

07930 {
07931    int cmd;
07932 
07933    if (  !strncasecmp(chan->language, "it", 2) ||
07934         !strncasecmp(chan->language, "es", 2) ||
07935         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07936       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07937       return cmd ? cmd : ast_play_and_wait(chan, box);
07938    } else if (!strncasecmp(chan->language, "gr", 2)) {
07939       return vm_play_folder_name_gr(chan, box);
07940    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07941       return ast_play_and_wait(chan, box);
07942    } else if (!strncasecmp(chan->language, "pl", 2)) {
07943       return vm_play_folder_name_pl(chan, box);
07944    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07945       return vm_play_folder_name_ua(chan, box);
07946    } else if (!strncasecmp(chan->language, "vi", 2)) {
07947       return ast_play_and_wait(chan, box);
07948    } else {  /* Default English */
07949       cmd = ast_play_and_wait(chan, box);
07950       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07951    }
07952 }

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

Definition at line 7882 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07883 {
07884    int cmd;
07885    char *buf;
07886 
07887    buf = alloca(strlen(box) + 2);
07888    strcpy(buf, box);
07889    strcat(buf, "s");
07890 
07891    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07892       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07893       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07894    } else {
07895       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07896       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07897    }
07898 }

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

Definition at line 7900 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07901 {
07902    int cmd;
07903 
07904    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07905       if (!strcasecmp(box, "vm-INBOX"))
07906          cmd = ast_play_and_wait(chan, "vm-new-e");
07907       else
07908          cmd = ast_play_and_wait(chan, "vm-old-e");
07909       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07910    } else {
07911       cmd = ast_play_and_wait(chan, "vm-messages");
07912       return cmd ? cmd : ast_play_and_wait(chan, box);
07913    }
07914 }

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

Definition at line 7916 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

07917 {
07918    int cmd;
07919 
07920    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07921       cmd = ast_play_and_wait(chan, "vm-messages");
07922       return cmd ? cmd : ast_play_and_wait(chan, box);
07923    } else {
07924       cmd = ast_play_and_wait(chan, box);
07925       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07926    }
07927 }

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

09259 {
09260    int cmd = 0;
09261    int retries = 0;
09262    int duration = 0;
09263    char prefile[PATH_MAX] = "";
09264    unsigned char buf[256];
09265    int bytes = 0;
09266 
09267    if (ast_adsi_available(chan)) {
09268       bytes += adsi_logo(buf + bytes);
09269       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09270       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09271       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09272       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09273       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09274    }
09275 
09276    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09277    while ((cmd >= 0) && (cmd != 't')) {
09278       if (cmd)
09279          retries = 0;
09280       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09281       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09282          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09283          cmd = 't';  
09284       } else {
09285          switch (cmd) {
09286          case '1':
09287             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09288             break;
09289          case '2':
09290             DELETE(prefile, -1, prefile, vmu);
09291             ast_play_and_wait(chan, "vm-tempremoved");
09292             cmd = 't';  
09293             break;
09294          case '*': 
09295             cmd = 't';
09296             break;
09297          default:
09298             cmd = ast_play_and_wait(chan,
09299                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09300                   "vm-tempgreeting2" : "vm-tempgreeting");
09301             if (!cmd)
09302                cmd = ast_waitfordigit(chan, 6000);
09303             if (!cmd)
09304                retries++;
09305             if (retries > 3)
09306                cmd = 't';
09307          }
09308       }
09309       DISPOSE(prefile, -1);
09310    }
09311    if (cmd == 't')
09312       cmd = 0;
09313    return cmd;
09314 }

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

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

11148 {
11149    struct ast_vm_user *user;
11150 
11151    AST_LIST_LOCK(&users);
11152    AST_LIST_TRAVERSE(&users, user, list) {
11153       vm_users_data_provider_get_helper(search, data_root, user);
11154    }
11155    AST_LIST_UNLOCK(&users);
11156 
11157    return 0;
11158 }

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

11101 {
11102    struct ast_data *data_user, *data_zone;
11103    struct ast_data *data_state;
11104    struct vm_zone *zone = NULL;
11105    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11106    char ext_context[256] = "";
11107 
11108    data_user = ast_data_add_node(data_root, "user");
11109    if (!data_user) {
11110       return -1;
11111    }
11112 
11113    ast_data_add_structure(ast_vm_user, data_user, user);
11114 
11115    AST_LIST_LOCK(&zones);
11116    AST_LIST_TRAVERSE(&zones, zone, list) {
11117       if (!strcmp(zone->name, user->zonetag)) {
11118          break;
11119       }
11120    }
11121    AST_LIST_UNLOCK(&zones);
11122 
11123    /* state */
11124    data_state = ast_data_add_node(data_user, "state");
11125    if (!data_state) {
11126       return -1;
11127    }
11128    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11129    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11130    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11131    ast_data_add_int(data_state, "newmsg", newmsg);
11132    ast_data_add_int(data_state, "oldmsg", oldmsg);
11133 
11134    if (zone) {
11135       data_zone = ast_data_add_node(data_user, "zone");
11136       ast_data_add_structure(vm_zone, data_zone, zone);
11137    }
11138 
11139    if (!ast_data_search_match(search, data_user)) {
11140       ast_data_remove_node(data_root, data_user);
11141    }
11142 
11143    return 0;
11144 }

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

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

10786 {
10787    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
10788    struct ast_vm_user vmus;
10789    char *options = NULL;
10790    int silent = 0, skipuser = 0;
10791    int res = -1;
10792    
10793    if (data) {
10794       s = ast_strdupa(data);
10795       user = strsep(&s, ",");
10796       options = strsep(&s, ",");
10797       if (user) {
10798          s = user;
10799          user = strsep(&s, "@");
10800          context = strsep(&s, "");
10801          if (!ast_strlen_zero(user))
10802             skipuser++;
10803          ast_copy_string(mailbox, user, sizeof(mailbox));
10804       }
10805    }
10806 
10807    if (options) {
10808       silent = (strchr(options, 's')) != NULL;
10809    }
10810 
10811    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
10812       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
10813       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
10814       ast_play_and_wait(chan, "auth-thankyou");
10815       res = 0;
10816    } else if (mailbox[0] == '*') {
10817       /* user entered '*' */
10818       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
10819          res = 0; /* prevent hangup */
10820       }
10821    }
10822 
10823    return res;
10824 }

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

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

12273 {
12274    char *context;
12275    char *args_copy;
12276    int res;
12277 
12278    if (ast_strlen_zero(data)) {
12279       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12280       return -1;
12281    }
12282 
12283    args_copy = ast_strdupa(data);
12284    if ((context = strchr(args_copy, '@'))) {
12285       *context++ = '\0';
12286    } else {
12287       context = "default";
12288    }
12289 
12290    if ((res = sayname(chan, args_copy, context) < 0)) {
12291       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12292       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12293       if (!res) {
12294          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12295       }
12296    }
12297 
12298    return res;
12299 }

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

04306 {
04307    const struct vm_zone *z = NULL;
04308    struct timeval t = ast_tvnow();
04309 
04310    /* Does this user have a timezone specified? */
04311    if (!ast_strlen_zero(vmu->zonetag)) {
04312       /* Find the zone in the list */
04313       AST_LIST_LOCK(&zones);
04314       AST_LIST_TRAVERSE(&zones, z, list) {
04315          if (!strcmp(z->name, vmu->zonetag))
04316             break;
04317       }
04318       AST_LIST_UNLOCK(&zones);
04319    }
04320    ast_localtime(&t, tm, z ? z->timezone : NULL);
04321    return tm;
04322 }

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

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

07298 {
07299    int res;
07300    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07301       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07302    return res;
07303 }

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

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

12246                                                                               {
12247    struct ast_config *conf;
12248    struct ast_category *cat;
12249    struct ast_variable *var;
12250 
12251    if (!(conf=ast_config_new())) {
12252       ast_log(LOG_ERROR, "Error creating new config structure\n");
12253       return -1;
12254    }
12255    if (!(cat=ast_category_new("general","",1))) {
12256       ast_log(LOG_ERROR, "Error creating new category structure\n");
12257       return -1;
12258    }
12259    if (!(var=ast_variable_new("password",password,""))) {
12260       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12261       return -1;
12262    }
12263    ast_category_append(conf,cat);
12264    ast_variable_append(cat,var);
12265    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12266       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12267       return -1;
12268    }
12269    return 0;
12270 }


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 13260 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 13260 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 11022 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 10780 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 11165 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 11160 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 Mon Jun 27 16:51:01 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7