Wed Jan 8 2020 09:49:55

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
 

Macros

#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 /* 1 second */
 
#define STORE(a, b, c, d, e, f, g, h, i, j)
 
#define tdesc   "Comedian Mail (Voicemail System)"
 
#define VALID_DTMF   "1234567890*#" /* Yes ABCD are valid dtmf but what phones have those? */
 
#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, NEW_FOLDER, OLD_FOLDER,
  WORK_FOLDER, FAMILY_FOLDER, FRIENDS_FOLDER, GREETINGS_FOLDER,
  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,
  OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3,
  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), 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), 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, OPT_PWLOC_VOICEMAILCONF = 0,
  OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2, 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 actual_load_config (int reload, struct ast_config *cfg, struct ast_config *ucfg)
 
static int add_email_attachment (FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
 
static void adsi_begin (struct ast_channel *chan, int *useadsi)
 
static void adsi_delete (struct ast_channel *chan, struct vm_state *vms)
 
static void adsi_folders (struct ast_channel *chan, int start, char *label)
 
static void adsi_goodbye (struct ast_channel *chan)
 
static int adsi_load_vmail (struct ast_channel *chan, int *useadsi)
 
static void adsi_login (struct ast_channel *chan)
 
static int adsi_logo (unsigned char *buf)
 
static void adsi_message (struct ast_channel *chan, struct vm_state *vms)
 
static void adsi_password (struct ast_channel *chan)
 
static void adsi_status (struct ast_channel *chan, struct vm_state *vms)
 
static void adsi_status2 (struct ast_channel *chan, struct vm_state *vms)
 
static int advanced_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
 The advanced options within a message. More...
 
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. More...
 
static void apply_options (struct ast_vm_user *vmu, const char *options)
 Destructively Parse options and apply. More...
 
static void apply_options_full (struct ast_vm_user *retval, struct ast_variable *var)
 Loads the options specific to a voicemail user. More...
 
 AST_DATA_STRUCTURE (ast_vm_user, DATA_EXPORT_VM_USERS)
 
 AST_DATA_STRUCTURE (vm_zone, DATA_EXPORT_VM_ZONES)
 
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. More...
 
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. More...
 
 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. More...
 
static int change_password_realtime (struct ast_vm_user *vmu, const char *password)
 Performs a change of the voicemail passowrd in the realtime engine. More...
 
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. More...
 
static int check_password (struct ast_vm_user *vmu, char *password)
 Check that password meets minimum required length. More...
 
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. More...
 
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. More...
 
static void copy_plain_file (char *frompath, char *topath)
 Copies a voicemail information (envelope) file. More...
 
static int count_messages (struct ast_vm_user *vmu, char *dir)
 Find all .txt files - even if they are not in sequence from 0000. More...
 
static int create_dirpath (char *dest, int len, const char *context, const char *ext, const char *folder)
 basically mkdir -p $dest/$context/$ext/$folder More...
 
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. More...
 
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. More...
 
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. More...
 
static void free_user (struct ast_vm_user *vmu)
 
static void free_vm_users (void)
 Free the users structure. More...
 
static void free_vm_zones (void)
 Free the zones structure. More...
 
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. More...
 
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 More...
 
static int get_folder2 (struct ast_channel *chan, char *fn, int start)
 plays a prompt and waits for a keypress. More...
 
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. More...
 
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. More...
 
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. More...
 
static int has_voicemail (const char *mailbox, const char *folder)
 Determines if the given folder has messages. More...
 
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() More...
 
static int inchar (struct baseio *bio, FILE *fi)
 utility used by base_encode() More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
static int manager_list_voicemail_users (struct mansession *s, const struct message *m)
 Manager list voicemail users command. More...
 
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. More...
 
static int ochar (struct baseio *bio, int c, FILE *so)
 utility used by base_encode() More...
 
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, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
 
static void poll_subscribed_mailbox (struct mwi_sub *mwi_sub)
 
static void poll_subscribed_mailboxes (void)
 
static void populate_defaults (struct ast_vm_user *vmu)
 Sets default voicemail system options to a voicemail user. More...
 
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. More...
 
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. More...
 
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. More...
 
static const char * substitute_escapes (const char *value)
 
static int unload_module (void)
 
static int valid_config (const struct ast_config *cfg)
 Check if configuration file is valid. More...
 
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. More...
 
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. More...
 
static int vm_browse_messages_he (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 
static int vm_browse_messages_latin (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Common LATIN languages syntax for 'You have N messages' greeting. More...
 
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. More...
 
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. More...
 
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
 The handler for the change password option. More...
 
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. More...
 
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. More...
 
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. More...
 
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'. More...
 
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. More...
 
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", }
 
static char * addesc = "Comedian Mail"
 
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
 
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
 
static int adsiver = 1
 
static char * app = "VoiceMail"
 
static char * app2 = "VoiceMailMain"
 
static char * app3 = "MailboxExists"
 
static char * app4 = "VMAuthenticate"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static char callcontext [AST_MAX_CONTEXT] = ""
 
static char charset [32] = "ISO-8859-1"
 
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
 
static struct ast_cli_entry cli_voicemail []
 
static char dialcontext [AST_MAX_CONTEXT] = ""
 
static char * emailbody = NULL
 
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
 
static char * emailsubject = NULL
 
static char exitcontext [AST_MAX_CONTEXT] = ""
 
static char ext_pass_check_cmd [128]
 
static char ext_pass_cmd [128]
 
static char externnotify [160]
 
static char fromstring [100]
 
static struct ast_flags globalflags = {0}
 
struct ao2_containerinprocess_container
 
static char listen_control_forward_key [12]
 
static char listen_control_pause_key [12]
 
static char listen_control_restart_key [12]
 
static char listen_control_reverse_key [12]
 
static char listen_control_stop_key [12]
 
static char locale [20]
 
static struct ast_custom_function mailbox_exists_acf
 
static const char *const mailbox_folders []
 
static char mailcmd [160]
 
static int maxdeletedmsg
 
static int maxgreet
 
static int maxlogins
 
static int maxmsg
 
static int maxsilence
 
static int minpassword
 
static struct ast_event_submwi_sub_sub
 
static struct mwi_subs mwi_subs = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
 
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 struct users users = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
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_prepend_timeout [80] = "vm-then-pound"
 
static char vm_reenterpassword [80] = "vm-reenterpassword"
 
static char VM_SPOOL_DIR [PATH_MAX]
 
static struct ast_data_handler vm_users_data_provider
 
static char vmfmts [80]
 
static int vmmaxsecs
 
static int vmminsecs
 
static double volgain
 
static struct zones zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
static char zonetag [80]
 

Detailed Description

Comedian Mail - Voicemail System.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
ExtRef:

unixODBC (http://www.unixodbc.org/)

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.

Macro Definition Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 430 of file app_voicemail.c.

Referenced by actual_load_config().

#define BASELINELEN   72

Definition at line 453 of file app_voicemail.c.

Referenced by ochar().

#define BASEMAXINLINE   256

Definition at line 454 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

#define CHUNKSIZE   65536

Definition at line 427 of file app_voicemail.c.

#define COMMAND_TIMEOUT   5000

Definition at line 423 of file app_voicemail.c.

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

Definition at line 741 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

#define DATA_EXPORT_VM_USERS (   USER)

Definition at line 11296 of file app_voicemail.c.

#define DATA_EXPORT_VM_ZONES (   ZONE)
Value:
ZONE(vm_zone, timezone, AST_DATA_STRING) \
ZONE(vm_zone, msg_format, AST_DATA_STRING)
static const char name[]

Definition at line 11323 of file app_voicemail.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 435 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 437 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 438 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 436 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 439 of file app_voicemail.c.

Referenced by actual_load_config().

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 811 of file app_voicemail.c.

Referenced by actual_load_config().

#define DELETE (   a,
  b,
  c,
 
)    (vm_delete(c))
#define ENDL   "\n"

Definition at line 458 of file app_voicemail.c.

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

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

Definition at line 739 of file app_voicemail.c.

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

#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"

Definition at line 446 of file app_voicemail.c.

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

#define MAX_DATETIME_FORMAT   512

Definition at line 461 of file app_voicemail.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 462 of file app_voicemail.c.

Referenced by actual_load_config(), and play_message_callerid().

#define MAXMSG   100

Definition at line 448 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

#define MAXMSGLIMIT   9999

Definition at line 449 of file app_voicemail.c.

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

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 451 of file app_voicemail.c.

Referenced by actual_load_config().

#define OPERATOR_EXIT   300

Definition at line 484 of file app_voicemail.c.

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

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 754 of file app_voicemail.c.

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

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 753 of file app_voicemail.c.

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

#define RENAME (   a,
  b,
  c,
  d,
  e,
  f,
  g,
 
)    (rename_file(g,h));
#define RETRIEVE (   a,
  b,
  c,
 
)
#define SENDMAIL   "/usr/sbin/sendmail -t"

Definition at line 444 of file app_voicemail.c.

Referenced by actual_load_config().

#define SMDI_MWI_WAIT_TIMEOUT   1000 /* 1 second */

Definition at line 421 of file app_voicemail.c.

Referenced by run_externnotify().

#define STORE (   a,
  b,
  c,
  d,
  e,
  f,
  g,
  h,
  i,
 
)
#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 763 of file app_voicemail.c.

#define VALID_DTMF   "1234567890*#" /* Yes ABCD are valid dtmf but what phones have those? */

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

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

#define VM_DELETE   (1 << 12)

Delete message after sending notification

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

Referenced by actual_load_config(), and forward_message().

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 468 of file app_voicemail.c.

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

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 472 of file app_voicemail.c.

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

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 471 of file app_voicemail.c.

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

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 482 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 481 of file app_voicemail.c.

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

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 480 of file app_voicemail.c.

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

#define VM_OPERATOR   (1 << 1)

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

Definition at line 465 of file app_voicemail.c.

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

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 473 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

#define VM_REVIEW   (1 << 0)

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

Definition at line 464 of file app_voicemail.c.

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

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 466 of file app_voicemail.c.

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

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 469 of file app_voicemail.c.

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

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 478 of file app_voicemail.c.

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

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 470 of file app_voicemail.c.

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

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 467 of file app_voicemail.c.

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

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 479 of file app_voicemail.c.

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

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 677 of file app_voicemail.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 429 of file app_voicemail.c.

Referenced by load_config(), and vm_change_password().

#define VOICEMAIL_DIR_MODE   0777

Definition at line 425 of file app_voicemail.c.

Referenced by create_dirpath(), and leave_voicemail().

#define VOICEMAIL_FILE_MODE   0666

Definition at line 426 of file app_voicemail.c.

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

Enumeration Type Documentation

enum vm_box
Enumerator
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 487 of file app_voicemail.c.

Enumerator
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 508 of file app_voicemail.c.

508  {
509  OPT_ARG_RECORDGAIN = 0,
510  OPT_ARG_PLAYFOLDER = 1,
511  OPT_ARG_DTMFEXIT = 2,
512  /* This *must* be the last value in this enum! */
513  OPT_ARG_ARRAY_SIZE = 3,
514 };
Enumerator
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
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 496 of file app_voicemail.c.

496  {
497  OPT_SILENT = (1 << 0),
498  OPT_BUSY_GREETING = (1 << 1),
499  OPT_UNAVAIL_GREETING = (1 << 2),
500  OPT_RECORDGAIN = (1 << 3),
501  OPT_PREPEND_MAILBOX = (1 << 4),
502  OPT_AUTOPLAY = (1 << 6),
503  OPT_DTMFEXIT = (1 << 7),
504  OPT_MESSAGE_Urgent = (1 << 8),
505  OPT_MESSAGE_PRIORITY = (1 << 9)
506 };
Enumerator
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 516 of file app_voicemail.c.

Function Documentation

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

Definition at line 5422 of file app_voicemail.c.

References ast_strlen_zero().

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

5423 {
5424  DIR *dir;
5425  struct dirent *de;
5426  char fn[256];
5427  int ret = 0;
5428 
5429  /* If no mailbox, return immediately */
5430  if (ast_strlen_zero(mailbox))
5431  return 0;
5432 
5433  if (ast_strlen_zero(folder))
5434  folder = "INBOX";
5435  if (ast_strlen_zero(context))
5436  context = "default";
5437 
5438  snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
5439 
5440  if (!(dir = opendir(fn)))
5441  return 0;
5442 
5443  while ((de = readdir(dir))) {
5444  if (!strncasecmp(de->d_name, "msg", 3)) {
5445  if (shortcircuit) {
5446  ret = 1;
5447  break;
5448  } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
5449  ret++;
5450  }
5451  }
5452  }
5453 
5454  closedir(dir);
5455 
5456  return ret;
5457 }
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static char VM_SPOOL_DIR[PATH_MAX]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static void __reg_module ( void  )
static

Definition at line 13643 of file app_voicemail.c.

static void __unreg_module ( void  )
static

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

11000 {
11001  struct ast_vm_user svm;
11003  AST_APP_ARG(mbox);
11005  );
11006 
11007  AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11008 
11009  if (ast_strlen_zero(arg.mbox)) {
11010  ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11011  return -1;
11012  }
11013 
11014  ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11015  return 0;
11016 }
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static const char * mbox(struct ast_vm_user *vmu, int id)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
Definition: app.h:619
static int actual_load_config ( int  reload,
struct ast_config cfg,
struct ast_config ucfg 
)
static

Definition at line 11833 of file app_voicemail.c.

References append_mailbox(), apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, AST_LOG_WARNING, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, ast_vm_user::context, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, find_or_create(), free_vm_users(), free_vm_zones(), is_valid_dtmf(), ast_variable::lineno, LOG_ERROR, ast_vm_user::mailbox, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, vm_zone::msg_format, ast_variable::name, vm_zone::name, ast_variable::next, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, vm_zone::timezone, ast_variable::value, var, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_PBXSKIP, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, and VM_TEMPGREETWARN.

Referenced by load_config().

11834 {
11835  struct ast_vm_user *current;
11836  char *cat;
11837  struct ast_variable *var;
11838  const char *val;
11839  char *q, *stringp, *tmp;
11840  int x;
11841  unsigned int tmpadsi[4];
11842  char secretfn[PATH_MAX] = "";
11843 
11844 #ifdef IMAP_STORAGE
11845  ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
11846 #endif
11847  /* set audio control prompts */
11853 
11854  /* Free all the users structure */
11855  free_vm_users();
11856 
11857  /* Free all the zones structure */
11858  free_vm_zones();
11859 
11860  AST_LIST_LOCK(&users);
11861 
11862  memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
11863  memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
11864 
11865  if (cfg) {
11866  /* General settings */
11867 
11868  if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
11869  val = "default";
11870  ast_copy_string(userscontext, val, sizeof(userscontext));
11871  /* Attach voice message to mail message ? */
11872  if (!(val = ast_variable_retrieve(cfg, "general", "attach")))
11873  val = "yes";
11875 
11876  if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
11877  val = "no";
11879 
11880  volgain = 0.0;
11881  if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
11882  sscanf(val, "%30lf", &volgain);
11883 
11884 #ifdef ODBC_STORAGE
11885  strcpy(odbc_database, "asterisk");
11886  if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
11887  ast_copy_string(odbc_database, val, sizeof(odbc_database));
11888  }
11889  strcpy(odbc_table, "voicemessages");
11890  if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
11891  ast_copy_string(odbc_table, val, sizeof(odbc_table));
11892  }
11893 #endif
11894  /* Mail command */
11895  strcpy(mailcmd, SENDMAIL);
11896  if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
11897  ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
11898 
11899  maxsilence = 0;
11900  if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
11901  maxsilence = atoi(val);
11902  if (maxsilence > 0)
11903  maxsilence *= 1000;
11904  }
11905 
11906  if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
11907  maxmsg = MAXMSG;
11908  } else {
11909  maxmsg = atoi(val);
11910  if (maxmsg < 0) {
11911  ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
11912  maxmsg = MAXMSG;
11913  } else if (maxmsg > MAXMSGLIMIT) {
11914  ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11915  maxmsg = MAXMSGLIMIT;
11916  }
11917  }
11918 
11919  if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
11920  maxdeletedmsg = 0;
11921  } else {
11922  if (sscanf(val, "%30d", &x) == 1)
11923  maxdeletedmsg = x;
11924  else if (ast_true(val))
11926  else
11927  maxdeletedmsg = 0;
11928 
11929  if (maxdeletedmsg < 0) {
11930  ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
11932  } else if (maxdeletedmsg > MAXMSGLIMIT) {
11933  ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11935  }
11936  }
11937 
11938  /* Load date format config for voicemail mail */
11939  if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
11941  }
11942 
11943  /* Load date format config for voicemail pager mail */
11944  if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
11946  }
11947 
11948  /* External password changing command */
11949  if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
11950  ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11952  } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
11953  ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11955  }
11956 
11957  /* External password validation command */
11958  if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
11960  ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
11961  }
11962 
11963 #ifdef IMAP_STORAGE
11964  /* IMAP server address */
11965  if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
11966  ast_copy_string(imapserver, val, sizeof(imapserver));
11967  } else {
11968  ast_copy_string(imapserver, "localhost", sizeof(imapserver));
11969  }
11970  /* IMAP server port */
11971  if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
11972  ast_copy_string(imapport, val, sizeof(imapport));
11973  } else {
11974  ast_copy_string(imapport, "143", sizeof(imapport));
11975  }
11976  /* IMAP server flags */
11977  if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
11978  ast_copy_string(imapflags, val, sizeof(imapflags));
11979  }
11980  /* IMAP server master username */
11981  if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
11982  ast_copy_string(authuser, val, sizeof(authuser));
11983  }
11984  /* IMAP server master password */
11985  if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
11986  ast_copy_string(authpassword, val, sizeof(authpassword));
11987  }
11988  /* Expunge on exit */
11989  if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
11990  if (ast_false(val))
11991  expungeonhangup = 0;
11992  else
11993  expungeonhangup = 1;
11994  } else {
11995  expungeonhangup = 1;
11996  }
11997  /* IMAP voicemail folder */
11998  if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
11999  ast_copy_string(imapfolder, val, sizeof(imapfolder));
12000  } else {
12001  ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
12002  }
12003  if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
12004  ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
12005  }
12006  if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
12007  imapgreetings = ast_true(val);
12008  } else {
12009  imapgreetings = 0;
12010  }
12011  if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
12012  ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
12013  } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
12014  /* Also support greetingsfolder as documented in voicemail.conf.sample */
12015  ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
12016  } else {
12017  ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
12018  }
12019 
12020  /* There is some very unorthodox casting done here. This is due
12021  * to the way c-client handles the argument passed in. It expects a
12022  * void pointer and casts the pointer directly to a long without
12023  * first dereferencing it. */
12024  if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
12025  mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
12026  } else {
12027  mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
12028  }
12029 
12030  if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
12031  mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
12032  } else {
12033  mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
12034  }
12035 
12036  if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
12037  mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
12038  } else {
12039  mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
12040  }
12041 
12042  if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
12043  mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
12044  } else {
12045  mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
12046  }
12047 
12048  /* Increment configuration version */
12049  imapversion++;
12050 #endif
12051  /* External voicemail notify application */
12052  if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
12053  ast_copy_string(externnotify, val, sizeof(externnotify));
12054  ast_debug(1, "found externnotify: %s\n", externnotify);
12055  } else {
12056  externnotify[0] = '\0';
12057  }
12058 
12059  /* SMDI voicemail notification */
12060  if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
12061  ast_debug(1, "Enabled SMDI voicemail notification\n");
12062  if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
12064  } else {
12065  ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
12066  smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
12067  }
12068  if (!smdi_iface) {
12069  ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
12070  }
12071  }
12072 
12073  /* Silence treshold */
12075  if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
12076  silencethreshold = atoi(val);
12077 
12078  if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
12079  val = ASTERISK_USERNAME;
12080  ast_copy_string(serveremail, val, sizeof(serveremail));
12081 
12082  vmmaxsecs = 0;
12083  if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
12084  if (sscanf(val, "%30d", &x) == 1) {
12085  vmmaxsecs = x;
12086  } else {
12087  ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
12088  }
12089  } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
12090  static int maxmessage_deprecate = 0;
12091  if (maxmessage_deprecate == 0) {
12092  maxmessage_deprecate = 1;
12093  ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
12094  }
12095  if (sscanf(val, "%30d", &x) == 1) {
12096  vmmaxsecs = x;
12097  } else {
12098  ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
12099  }
12100  }
12101 
12102  vmminsecs = 0;
12103  if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
12104  if (sscanf(val, "%30d", &x) == 1) {
12105  vmminsecs = x;
12106  if (maxsilence / 1000 >= vmminsecs) {
12107  ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
12108  }
12109  } else {
12110  ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
12111  }
12112  } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
12113  static int maxmessage_deprecate = 0;
12114  if (maxmessage_deprecate == 0) {
12115  maxmessage_deprecate = 1;
12116  ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
12117  }
12118  if (sscanf(val, "%30d", &x) == 1) {
12119  vmminsecs = x;
12120  if (maxsilence / 1000 >= vmminsecs) {
12121  ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
12122  }
12123  } else {
12124  ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
12125  }
12126  }
12127 
12128  val = ast_variable_retrieve(cfg, "general", "format");
12129  if (!val) {
12130  val = "wav";
12131  } else {
12132  tmp = ast_strdupa(val);
12133  val = ast_format_str_reduce(tmp);
12134  if (!val) {
12135  ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
12136  val = "wav";
12137  }
12138  }
12139  ast_copy_string(vmfmts, val, sizeof(vmfmts));
12140 
12141  skipms = 3000;
12142  if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
12143  if (sscanf(val, "%30d", &x) == 1) {
12144  maxgreet = x;
12145  } else {
12146  ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
12147  }
12148  }
12149 
12150  if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
12151  if (sscanf(val, "%30d", &x) == 1) {
12152  skipms = x;
12153  } else {
12154  ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
12155  }
12156  }
12157 
12158  maxlogins = 3;
12159  if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
12160  if (sscanf(val, "%30d", &x) == 1) {
12161  maxlogins = x;
12162  } else {
12163  ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
12164  }
12165  }
12166 
12168  if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
12169  if (sscanf(val, "%30d", &x) == 1) {
12170  minpassword = x;
12171  } else {
12172  ast_log(AST_LOG_WARNING, "Invalid minimum password length. Default to %d\n", minpassword);
12173  }
12174  }
12175 
12176  /* Force new user to record name ? */
12177  if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
12178  val = "no";
12180 
12181  /* Force new user to record greetings ? */
12182  if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
12183  val = "no";
12185 
12186  if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
12187  ast_debug(1, "VM_CID Internal context string: %s\n", val);
12188  stringp = ast_strdupa(val);
12189  for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
12190  if (!ast_strlen_zero(stringp)) {
12191  q = strsep(&stringp, ",");
12192  while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
12193  q++;
12195  ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
12196  } else {
12197  cidinternalcontexts[x][0] = '\0';
12198  }
12199  }
12200  }
12201  if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
12202  ast_debug(1, "VM Review Option disabled globally\n");
12203  val = "no";
12204  }
12206 
12207  /* Temporary greeting reminder */
12208  if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
12209  ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
12210  val = "no";
12211  } else {
12212  ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
12213  }
12215  if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
12216  ast_debug(1, "VM next message wrap disabled globally\n");
12217  val = "no";
12218  }
12220 
12221  if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
12222  ast_debug(1, "VM Operator break disabled globally\n");
12223  val = "no";
12224  }
12226 
12227  if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
12228  ast_debug(1, "VM CID Info before msg disabled globally\n");
12229  val = "no";
12230  }
12232 
12233  if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
12234  ast_debug(1, "Send Voicemail msg disabled globally\n");
12235  val = "no";
12236  }
12238 
12239  if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
12240  ast_debug(1, "ENVELOPE before msg enabled globally\n");
12241  val = "yes";
12242  }
12244 
12245  if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
12246  ast_debug(1, "Move Heard enabled globally\n");
12247  val = "yes";
12248  }
12250 
12251  if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
12252  ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
12253  val = "no";
12254  }
12256 
12257  if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
12258  ast_debug(1, "Duration info before msg enabled globally\n");
12259  val = "yes";
12260  }
12262 
12263  saydurationminfo = 2;
12264  if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
12265  if (sscanf(val, "%30d", &x) == 1) {
12266  saydurationminfo = x;
12267  } else {
12268  ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
12269  }
12270  }
12271 
12272  if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
12273  ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
12274  val = "no";
12275  }
12277 
12278  if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
12279  ast_copy_string(dialcontext, val, sizeof(dialcontext));
12280  ast_debug(1, "found dialout context: %s\n", dialcontext);
12281  } else {
12282  dialcontext[0] = '\0';
12283  }
12284 
12285  if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
12286  ast_copy_string(callcontext, val, sizeof(callcontext));
12287  ast_debug(1, "found callback context: %s\n", callcontext);
12288  } else {
12289  callcontext[0] = '\0';
12290  }
12291 
12292  if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
12293  ast_copy_string(exitcontext, val, sizeof(exitcontext));
12294  ast_debug(1, "found operator context: %s\n", exitcontext);
12295  } else {
12296  exitcontext[0] = '\0';
12297  }
12298 
12299  /* load password sounds configuration */
12300  if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
12301  ast_copy_string(vm_password, val, sizeof(vm_password));
12302  if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
12304  if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
12306  if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
12308  if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
12310  if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
12311  ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
12312  if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
12314  }
12315  if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
12317  }
12318  /* load configurable audio prompts */
12319  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
12321  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
12323  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
12325  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
12327  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
12329 
12330  if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory")))
12331  val = "no";
12333 
12334  if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
12335  val = "voicemail.conf";
12336  }
12337  if (!(strcmp(val, "spooldir"))) {
12339  } else {
12341  }
12342 
12344  if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
12345  if (sscanf(val, "%30u", &poll_freq) != 1) {
12347  ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
12348  }
12349  }
12350 
12351  poll_mailboxes = 0;
12352  if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
12353  poll_mailboxes = ast_true(val);
12354 
12355  memset(fromstring, 0, sizeof(fromstring));
12356  memset(pagerfromstring, 0, sizeof(pagerfromstring));
12357  strcpy(charset, "ISO-8859-1");
12358  if (emailbody) {
12360  emailbody = NULL;
12361  }
12362  if (emailsubject) {
12364  emailsubject = NULL;
12365  }
12366  if (pagerbody) {
12368  pagerbody = NULL;
12369  }
12370  if (pagersubject) {
12372  pagersubject = NULL;
12373  }
12374  if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
12376  if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
12377  ast_copy_string(fromstring, val, sizeof(fromstring));
12378  if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
12380  if ((val = ast_variable_retrieve(cfg, "general", "charset")))
12381  ast_copy_string(charset, val, sizeof(charset));
12382  if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
12383  sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12384  for (x = 0; x < 4; x++) {
12385  memcpy(&adsifdn[x], &tmpadsi[x], 1);
12386  }
12387  }
12388  if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
12389  sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12390  for (x = 0; x < 4; x++) {
12391  memcpy(&adsisec[x], &tmpadsi[x], 1);
12392  }
12393  }
12394  if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
12395  if (atoi(val)) {
12396  adsiver = atoi(val);
12397  }
12398  }
12399  if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
12400  ast_copy_string(zonetag, val, sizeof(zonetag));
12401  }
12402  if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
12403  ast_copy_string(locale, val, sizeof(locale));
12404  }
12405  if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
12407  }
12408  if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
12410  }
12411  if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
12413  }
12414  if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
12416  }
12417 
12418  /* load mailboxes from users.conf */
12419  if (ucfg) {
12420  for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
12421  if (!strcasecmp(cat, "general")) {
12422  continue;
12423  }
12424  if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
12425  continue;
12426  if ((current = find_or_create(userscontext, cat))) {
12427  populate_defaults(current);
12428  apply_options_full(current, ast_variable_browse(ucfg, cat));
12429  ast_copy_string(current->context, userscontext, sizeof(current->context));
12430  if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
12432  }
12433 
12434  switch (current->passwordlocation) {
12435  case OPT_PWLOC_SPOOLDIR:
12436  snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
12437  read_password_from_file(secretfn, current->password, sizeof(current->password));
12438  }
12439  }
12440  }
12441  }
12442 
12443  /* load mailboxes from voicemail.conf */
12444  cat = ast_category_browse(cfg, NULL);
12445  while (cat) {
12446  if (strcasecmp(cat, "general")) {
12447  var = ast_variable_browse(cfg, cat);
12448  if (strcasecmp(cat, "zonemessages")) {
12449  /* Process mailboxes in this context */
12450  while (var) {
12451  append_mailbox(cat, var->name, var->value);
12452  var = var->next;
12453  }
12454  } else {
12455  /* Timezones in this context */
12456  while (var) {
12457  struct vm_zone *z;
12458  if ((z = ast_malloc(sizeof(*z)))) {
12459  char *msg_format, *tzone;
12460  msg_format = ast_strdupa(var->value);
12461  tzone = strsep(&msg_format, "|,");
12462  if (msg_format) {
12463  ast_copy_string(z->name, var->name, sizeof(z->name));
12464  ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
12465  ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
12466  AST_LIST_LOCK(&zones);
12469  } else {
12470  ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
12471  ast_free(z);
12472  }
12473  } else {
12475  return -1;
12476  }
12477  var = var->next;
12478  }
12479  }
12480  }
12481  cat = ast_category_browse(cfg, cat);
12482  }
12483 
12485 
12489  stop_poll_thread();;
12490 
12491  return 0;
12492  } else {
12494  ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
12495  return 0;
12496  }
12497 }
#define VM_TEMPGREETWARN
static int saydurationminfo
static char userscontext[AST_MAX_EXTENSION]
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void free_vm_zones(void)
Free the zones structure.
static char ext_pass_cmd[128]
static const char * substitute_escapes(const char *value)
static int minpassword
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
char * strsep(char **str, const char *delims)
static char mailcmd[160]
char msg_format[512]
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
#define MAX_NUM_CID_CONTEXTS
static unsigned char adsifdn[4]
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ast_expr2.c:325
static void free_vm_users(void)
Free the users structure.
char name[80]
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
static char pagerdateformat[32]
static int adsiver
#define VM_SAYDURATION
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int maxsilence
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
char timezone[80]
static int pwdchange
int lineno
Definition: config.h:87
static int maxdeletedmsg
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
Definition: res_smdi.c:627
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define AST_LOG_WARNING
Definition: logger.h:149
#define var
Definition: ast_expr2f.c:606
static unsigned char adsisec[4]
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY
#define VM_MESSAGEWRAP
static int maxgreet
static pthread_t poll_thread
static char listen_control_reverse_key[12]
#define VM_ATTACH
static char locale[20]
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
Definition: config.c:614
static char externnotify[160]
static int vmminsecs
static char * emailsubject
list of users found in the config file
static struct ast_smdi_interface * smdi_iface
static char fromstring[100]
#define VM_SAYCID
#define VM_SVMAIL
static char * emailbody
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY
static char pagerfromstring[100]
static char * pagerbody
#define VM_SEARCH
#define VM_ENVELOPE
static int passwordlocation
static char exitcontext[AST_MAX_CONTEXT]
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define MINPASSWORD
const char * value
Definition: config.h:79
#define AST_LOG_ERROR
Definition: logger.h:160
#define MAXMSG
static char dialcontext[AST_MAX_CONTEXT]
#define VM_FORCENAME
static struct ast_flags globalflags
#define DEFAULT_LISTEN_CONTROL_STOP_KEY
#define AST_PTHREADT_NULL
Definition: lock.h:65
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int silencethreshold
char mailbox[AST_MAX_EXTENSION]
int passwordlocation
static char vm_reenterpassword[80]
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
char context[AST_MAX_CONTEXT]
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
#define VM_MOVEHEARD
const char * name
Definition: config.h:77
char * ast_format_str_reduce(char *fmts)
Definition: file.c:1382
static char zonetag[80]
static double volgain
static char VM_SPOOL_DIR[PATH_MAX]
#define PWDCHANGE_INTERNAL
static char vm_mismatch[80]
static char vm_pls_try_again[80]
static char vm_invalid_password[80]
#define DEFAULT_POLL_FREQ
#define VM_PBXSKIP
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define VM_OPERATOR
static char callcontext[AST_MAX_CONTEXT]
static int skipms
#define LOG_ERROR
Definition: logger.h:155
static char ext_pass_check_cmd[128]
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static unsigned int poll_mailboxes
static char listen_control_restart_key[12]
#define VM_REVIEW
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ast_free(a)
Definition: astmm.h:97
static char emaildateformat[32]
static char vm_passchanged[80]
static int maxlogins
static char listen_control_pause_key[12]
#define SENDMAIL
static char charset[32]
static char listen_control_forward_key[12]
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
static int vmmaxsecs
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static void start_poll_thread(void)
#define AST_LOG_DEBUG
Definition: logger.h:127
static struct ast_vm_user * find_or_create(const char *context, const char *box)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
#define VM_SKIPAFTERCMD
static char * pagersubject
static int append_mailbox(const char *context, const char *box, const char *data)
#define MAXMSGLIMIT
static char vm_password[80]
#define ASTERISK_USERNAME
#define VM_DIRECFORWARD
#define PWDCHANGE_EXTERNAL
static int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
struct ast_variable * next
Definition: config.h:82
#define VM_FWDURGAUTO
static int maxmsg
static char vm_newpassword[80]
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1880
#define ast_malloc(a)
Definition: astmm.h:91
static char vmfmts[80]
static char serveremail[80]
static char listen_control_stop_key[12]
char password[80]
#define VM_FORCEGREET
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
static unsigned int poll_freq
static void stop_poll_thread(void)
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static char vm_prepend_timeout[80]
struct vm_zone::@66 list
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 4836 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().

4837 {
4838  char tmpdir[256], newtmp[256];
4839  char fname[256];
4840  char tmpcmd[256];
4841  int tmpfd = -1;
4842  int soxstatus = 0;
4843 
4844  /* Eww. We want formats to tell us their own MIME type */
4845  char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
4846 
4847  if (vmu->volgain < -.001 || vmu->volgain > .001) {
4848  create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
4849  snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
4850  tmpfd = mkstemp(newtmp);
4851  chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
4852  ast_debug(3, "newtmp: %s\n", newtmp);
4853  if (tmpfd > -1) {
4854  snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
4855  if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
4856  attach = newtmp;
4857  ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
4858  } else {
4859  ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
4860  soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
4861  ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
4862  }
4863  }
4864  }
4865  fprintf(p, "--%s" ENDL, bound);
4866  if (msgnum > -1)
4867  fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
4868  else
4869  fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
4870  fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
4871  fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
4872  if (msgnum > -1)
4873  fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
4874  else
4875  fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
4876  snprintf(fname, sizeof(fname), "%s.%s", attach, format);
4877  base_encode(fname, p);
4878  if (last)
4879  fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
4880  if (tmpfd > -1) {
4881  if (soxstatus == 0) {
4882  unlink(fname);
4883  }
4884  close(tmpfd);
4885  unlink(newtmp);
4886  }
4887  return 0;
4888 }
double volgain
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
char mailbox[AST_MAX_EXTENSION]
static int my_umask
char context[AST_MAX_CONTEXT]
#define ENDL
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int base_encode(char *filename, FILE *so)
Performs a base 64 encode algorithm on the contents of a File.
#define VOICEMAIL_FILE_MODE
static snd_pcm_format_t format
Definition: chan_alsa.c:93
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static void adsi_begin ( struct ast_channel chan,
int *  useadsi 
)
static

Definition at line 6445 of file app_voicemail.c.

References adsi_load_vmail(), ast_adsi_available(), ast_adsi_load_session(), ast_log(), and AST_LOG_WARNING.

Referenced by vm_authenticate(), and vm_execmain().

6446 {
6447  int x;
6448  if (!ast_adsi_available(chan))
6449  return;
6450  x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
6451  if (x < 0)
6452  return;
6453  if (!x) {
6454  if (adsi_load_vmail(chan, useadsi)) {
6455  ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
6456  return;
6457  }
6458  } else
6459  *useadsi = 1;
6460 }
static unsigned char adsifdn[4]
static int adsiver
#define AST_LOG_WARNING
Definition: logger.h:149
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay...
Definition: adsi.c:76
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
static void adsi_delete ( struct ast_channel chan,
struct vm_state vms 
)
static

Definition at line 6640 of file app_voicemail.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_set_keys(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_mutex_lock, ast_mutex_unlock, vm_state::curmsg, vm_state::deleted, and vm_state::lastmsg.

Referenced by vm_execmain().

6641 {
6642  int bytes = 0;
6643  unsigned char buf[256];
6644  unsigned char keys[8];
6645 
6646  int x;
6647 
6648  if (!ast_adsi_available(chan))
6649  return;
6650 
6651  /* New meaning for keys */
6652  for (x = 0; x < 5; x++)
6653  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
6654 
6655  keys[6] = 0x0;
6656  keys[7] = 0x0;
6657 
6658  if (!vms->curmsg) {
6659  /* No prev key, provide "Folder" instead */
6660  keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
6661  }
6662  if (vms->curmsg >= vms->lastmsg) {
6663  /* If last message ... */
6664  if (vms->curmsg) {
6665  /* but not only message, provide "Folder" instead */
6666  keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
6667  } else {
6668  /* Otherwise if only message, leave blank */
6669  keys[3] = 1;
6670  }
6671  }
6672 
6673  /* If deleted, show "undeleted" */
6674 #ifdef IMAP_STORAGE
6675  ast_mutex_lock(&vms->lock);
6676 #endif
6677  if (vms->deleted[vms->curmsg]) {
6678  keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
6679  }
6680 #ifdef IMAP_STORAGE
6681  ast_mutex_unlock(&vms->lock);
6682 #endif
6683 
6684  /* Except "Exit" */
6685  keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
6686  bytes += ast_adsi_set_keys(buf + bytes, keys);
6687  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6688 
6689  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6690 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
#define ADSI_KEY_SKT
Definition: adsi.h:117
int * deleted
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
#define ADSI_KEY_APPS
Definition: adsi.h:109
#define ast_mutex_unlock(a)
Definition: lock.h:156
static void adsi_folders ( struct ast_channel chan,
int  start,
char *  label 
)
static

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

6511 {
6512  unsigned char buf[256];
6513  int bytes = 0;
6514  unsigned char keys[8];
6515  int x, y;
6516 
6517  if (!ast_adsi_available(chan))
6518  return;
6519 
6520  for (x = 0; x < 5; x++) {
6521  y = ADSI_KEY_APPS + 12 + start + x;
6522  if (y > ADSI_KEY_APPS + 12 + 4)
6523  y = 0;
6524  keys[x] = ADSI_KEY_SKT | y;
6525  }
6526  keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
6527  keys[6] = 0;
6528  keys[7] = 0;
6529 
6530  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
6531  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
6532  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6533  bytes += ast_adsi_set_keys(buf + bytes, keys);
6534  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6535 
6536  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6537 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
#define ADSI_KEY_SKT
Definition: adsi.h:117
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
#define ADSI_JUST_CENT
Definition: adsi.h:114
#define ADSI_KEY_APPS
Definition: adsi.h:109
static void adsi_goodbye ( struct ast_channel chan)
static

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

6796 {
6797  unsigned char buf[256];
6798  int bytes = 0;
6799 
6800  if (!ast_adsi_available(chan))
6801  return;
6802  bytes += adsi_logo(buf + bytes);
6803  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
6804  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
6805  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6806  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6807 
6808  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6809 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
static int adsi_logo(unsigned char *buf)
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
#define ADSI_JUST_CENT
Definition: adsi.h:114
static int adsi_load_vmail ( struct ast_channel chan,
int *  useadsi 
)
static

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

6317 {
6318  unsigned char buf[256];
6319  int bytes = 0;
6320  int x;
6321  char num[5];
6322 
6323  *useadsi = 0;
6324  bytes += ast_adsi_data_mode(buf + bytes);
6325  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6326 
6327  bytes = 0;
6328  bytes += adsi_logo(buf);
6329  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
6330 #ifdef DISPLAY
6331  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
6332 #endif
6333  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6334  bytes += ast_adsi_data_mode(buf + bytes);
6335  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6336 
6338  bytes = 0;
6339  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
6340  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
6341  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6342  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6343  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6344  return 0;
6345  }
6346 
6347 #ifdef DISPLAY
6348  /* Add a dot */
6349  bytes = 0;
6350  bytes += ast_adsi_logo(buf);
6351  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
6352  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
6353  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6354  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6355 #endif
6356  bytes = 0;
6357  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
6358  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
6359  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
6360  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
6361  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
6362  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
6363  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
6364 
6365 #ifdef DISPLAY
6366  /* Add another dot */
6367  bytes = 0;
6368  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
6369  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6370 
6371  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6372  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6373 #endif
6374 
6375  bytes = 0;
6376  /* These buttons we load but don't use yet */
6377  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
6378  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
6379  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
6380  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
6381  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
6382  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
6383  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
6384 
6385 #ifdef DISPLAY
6386  /* Add another dot */
6387  bytes = 0;
6388  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
6389  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6390  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6391 #endif
6392 
6393  bytes = 0;
6394  for (x = 0; x < 5; x++) {
6395  snprintf(num, sizeof(num), "%d", x);
6396  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
6397  }
6398  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
6399  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
6400 
6401 #ifdef DISPLAY
6402  /* Add another dot */
6403  bytes = 0;
6404  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
6405  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6406  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6407 #endif
6408 
6409  if (ast_adsi_end_download(chan)) {
6410  bytes = 0;
6411  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
6412  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
6413  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6414  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6415  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6416  return 0;
6417  }
6418  bytes = 0;
6419  bytes += ast_adsi_download_disconnect(buf + bytes);
6420  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6421  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
6422 
6423  ast_debug(1, "Done downloading scripts...\n");
6424 
6425 #ifdef DISPLAY
6426  /* Add last dot */
6427  bytes = 0;
6428  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
6429  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6430 #endif
6431  ast_debug(1, "Restarting session...\n");
6432 
6433  bytes = 0;
6434  /* Load the session now */
6435  if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
6436  *useadsi = 1;
6437  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
6438  } else
6439  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
6440 
6441  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6442  return 0;
6443 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
Definition: adsi.c:32
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
static unsigned char adsifdn[4]
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
Definition: adsi.c:219
static int adsi_logo(unsigned char *buf)
static int adsiver
static unsigned char adsisec[4]
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay...
Definition: adsi.c:76
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
Definition: adsi.c:208
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ADSI_COMM_PAGE
Definition: adsi.h:107
static const char * mbox(struct ast_vm_user *vmu, int id)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
static char * addesc
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
int ast_adsi_end_download(struct ast_channel *chan)
Definition: adsi.c:43
int ast_adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Creates &quot;load soft key&quot; parameters.
Definition: adsi.c:296
#define ADSI_MSG_DOWNLOAD
Definition: adsi.h:33
#define ADSI_JUST_CENT
Definition: adsi.h:114
#define ADSI_KEY_APPS
Definition: adsi.h:109
static void adsi_login ( struct ast_channel chan)
static

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

6463 {
6464  unsigned char buf[256];
6465  int bytes = 0;
6466  unsigned char keys[8];
6467  int x;
6468  if (!ast_adsi_available(chan))
6469  return;
6470 
6471  for (x = 0; x < 8; x++)
6472  keys[x] = 0;
6473  /* Set one key for next */
6474  keys[3] = ADSI_KEY_APPS + 3;
6475 
6476  bytes += adsi_logo(buf + bytes);
6477  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
6478  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
6479  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6480  bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
6481  bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
6482  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
6483  bytes += ast_adsi_set_keys(buf + bytes, keys);
6484  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6485  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6486 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
static int adsi_logo(unsigned char *buf)
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define ADSI_DIR_FROM_LEFT
Definition: adsi.h:120
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
Definition: adsi.c:329
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
int ast_adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Creates &quot;load soft key&quot; parameters.
Definition: adsi.c:296
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
Definition: adsi.c:318
#define ADSI_JUST_CENT
Definition: adsi.h:114
#define ADSI_KEY_APPS
Definition: adsi.h:109
static int adsi_logo ( unsigned char *  buf)
static

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

6309 {
6310  int bytes = 0;
6311  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
6312  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
6313  return bytes;
6314 }
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
#define ADSI_JUST_CENT
Definition: adsi.h:114
static void adsi_message ( struct ast_channel chan,
struct vm_state vms 
)
static

Definition at line 6539 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_callerid_parse(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), buf1, buf2, vm_state::curbox, vm_state::curmsg, vm_state::deleted, f, vm_state::fn, vm_state::lastmsg, name, and strsep().

Referenced by play_message(), and vm_execmain().

6540 {
6541  int bytes = 0;
6542  unsigned char buf[256];
6543  char buf1[256], buf2[256];
6544  char fn2[PATH_MAX];
6545 
6546  char cid[256] = "";
6547  char *val;
6548  char *name, *num;
6549  char datetime[21] = "";
6550  FILE *f;
6551 
6552  unsigned char keys[8];
6553 
6554  int x;
6555 
6556  if (!ast_adsi_available(chan))
6557  return;
6558 
6559  /* Retrieve important info */
6560  snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
6561  f = fopen(fn2, "r");
6562  if (f) {
6563  while (!feof(f)) {
6564  if (!fgets((char *) buf, sizeof(buf), f)) {
6565  continue;
6566  }
6567  if (!feof(f)) {
6568  char *stringp = NULL;
6569  stringp = (char *) buf;
6570  strsep(&stringp, "=");
6571  val = strsep(&stringp, "=");
6572  if (!ast_strlen_zero(val)) {
6573  if (!strcmp((char *) buf, "callerid"))
6574  ast_copy_string(cid, val, sizeof(cid));
6575  if (!strcmp((char *) buf, "origdate"))
6576  ast_copy_string(datetime, val, sizeof(datetime));
6577  }
6578  }
6579  }
6580  fclose(f);
6581  }
6582  /* New meaning for keys */
6583  for (x = 0; x < 5; x++)
6584  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
6585  keys[6] = 0x0;
6586  keys[7] = 0x0;
6587 
6588  if (!vms->curmsg) {
6589  /* No prev key, provide "Folder" instead */
6590  keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
6591  }
6592  if (vms->curmsg >= vms->lastmsg) {
6593  /* If last message ... */
6594  if (vms->curmsg) {
6595  /* but not only message, provide "Folder" instead */
6596  keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
6597  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6598 
6599  } else {
6600  /* Otherwise if only message, leave blank */
6601  keys[3] = 1;
6602  }
6603  }
6604 
6605  if (!ast_strlen_zero(cid)) {
6606  ast_callerid_parse(cid, &name, &num);
6607  if (!name)
6608  name = num;
6609  } else
6610  name = "Unknown Caller";
6611 
6612  /* If deleted, show "undeleted" */
6613 #ifdef IMAP_STORAGE
6614  ast_mutex_lock(&vms->lock);
6615 #endif
6616  if (vms->deleted[vms->curmsg]) {
6617  keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
6618  }
6619 #ifdef IMAP_STORAGE
6620  ast_mutex_unlock(&vms->lock);
6621 #endif
6622 
6623  /* Except "Exit" */
6624  keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
6625  snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
6626  strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
6627  snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
6628 
6629  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
6630  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
6631  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
6632  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
6633  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6634  bytes += ast_adsi_set_keys(buf + bytes, keys);
6635  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6636 
6637  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6638 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
char * strsep(char **str, const char *delims)
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
Definition: ast_expr2.c:325
char fn[PATH_MAX]
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
static struct ast_threadstorage buf2
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
#define ADSI_KEY_SKT
Definition: adsi.h:117
static struct ast_threadstorage buf1
static const char name[]
int * deleted
static struct ast_format f[]
Definition: format_g726.c:181
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char curbox[80]
#define ADSI_KEY_APPS
Definition: adsi.h:109
#define ast_mutex_unlock(a)
Definition: lock.h:156
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1009
static void adsi_password ( struct ast_channel chan)
static

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

6489 {
6490  unsigned char buf[256];
6491  int bytes = 0;
6492  unsigned char keys[8];
6493  int x;
6494  if (!ast_adsi_available(chan))
6495  return;
6496 
6497  for (x = 0; x < 8; x++)
6498  keys[x] = 0;
6499  /* Set one key for next */
6500  keys[3] = ADSI_KEY_APPS + 3;
6501 
6502  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6503  bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
6504  bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
6505  bytes += ast_adsi_set_keys(buf + bytes, keys);
6506  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6507  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6508 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define ADSI_DIR_FROM_LEFT
Definition: adsi.h:120
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
Definition: adsi.c:329
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
Definition: adsi.c:318
#define ADSI_KEY_APPS
Definition: adsi.h:109
static void adsi_status ( struct ast_channel chan,
struct vm_state vms 
)
static

Definition at line 6692 of file app_voicemail.c.

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

Referenced by vm_execmain().

6693 {
6694  unsigned char buf[256] = "";
6695  char buf1[256] = "", buf2[256] = "";
6696  int bytes = 0;
6697  unsigned char keys[8];
6698  int x;
6699 
6700  char *newm = (vms->newmessages == 1) ? "message" : "messages";
6701  char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
6702  if (!ast_adsi_available(chan))
6703  return;
6704  if (vms->newmessages) {
6705  snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
6706  if (vms->oldmessages) {
6707  strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
6708  snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
6709  } else {
6710  snprintf(buf2, sizeof(buf2), "%s.", newm);
6711  }
6712  } else if (vms->oldmessages) {
6713  snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
6714  snprintf(buf2, sizeof(buf2), "%s.", oldm);
6715  } else {
6716  strcpy(buf1, "You have no messages.");
6717  buf2[0] = ' ';
6718  buf2[1] = '\0';
6719  }
6720  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
6721  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
6722  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6723 
6724  for (x = 0; x < 6; x++)
6725  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
6726  keys[6] = 0;
6727  keys[7] = 0;
6728 
6729  /* Don't let them listen if there are none */
6730  if (vms->lastmsg < 0)
6731  keys[0] = 1;
6732  bytes += ast_adsi_set_keys(buf + bytes, keys);
6733 
6734  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6735 
6736  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6737 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
int oldmessages
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
static struct ast_threadstorage buf2
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
#define ADSI_KEY_SKT
Definition: adsi.h:117
static struct ast_threadstorage buf1
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int newmessages
#define ADSI_KEY_APPS
Definition: adsi.h:109
static void adsi_status2 ( struct ast_channel chan,
struct vm_state vms 
)
static

Definition at line 6739 of file app_voicemail.c.

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

Referenced by vm_execmain().

6740 {
6741  unsigned char buf[256] = "";
6742  char buf1[256] = "", buf2[256] = "";
6743  int bytes = 0;
6744  unsigned char keys[8];
6745  int x;
6746 
6747  char *mess = (vms->lastmsg == 0) ? "message" : "messages";
6748 
6749  if (!ast_adsi_available(chan))
6750  return;
6751 
6752  /* Original command keys */
6753  for (x = 0; x < 6; x++)
6754  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
6755 
6756  keys[6] = 0;
6757  keys[7] = 0;
6758 
6759  if ((vms->lastmsg + 1) < 1)
6760  keys[0] = 0;
6761 
6762  snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
6763  strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
6764 
6765  if (vms->lastmsg + 1)
6766  snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
6767  else
6768  strcpy(buf2, "no messages.");
6769  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
6770  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
6771  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
6772  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
6773  bytes += ast_adsi_set_keys(buf + bytes, keys);
6774 
6775  bytes += ast_adsi_voice_mode(buf + bytes, 0);
6776 
6777  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
6778 
6779 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
static struct ast_threadstorage buf2
#define ADSI_JUST_LEFT
Definition: adsi.h:112
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
#define ADSI_KEY_SKT
Definition: adsi.h:117
static struct ast_threadstorage buf1
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
char curbox[80]
#define ADSI_KEY_APPS
Definition: adsi.h:109
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_gainProvides handling for the play message envelope, call the person back, or reply to message.
Returns
zero on success, -1 on error.

Definition at line 13205 of file app_voicemail.c.

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log(), AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_test_suite_event_notify, ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, context, 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(), name, play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, valid_config(), and wait_file().

Referenced by vm_execmain().

13206 {
13207  int res = 0;
13208  char filename[PATH_MAX];
13209  struct ast_config *msg_cfg = NULL;
13210  const char *origtime, *context;
13211  char *name, *num;
13212  int retries = 0;
13213  char *cid;
13214  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
13215 
13216  vms->starting = 0;
13217 
13218  make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13219 
13220  /* Retrieve info from VM attribute file */
13221  snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
13222  RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
13223  msg_cfg = ast_config_load(filename, config_flags);
13224  DISPOSE(vms->curdir, vms->curmsg);
13225  if (!valid_config(msg_cfg)) {
13226  ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
13227  return 0;
13228  }
13229 
13230  if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
13231  ast_config_destroy(msg_cfg);
13232  return 0;
13233  }
13234 
13235  cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
13236 
13237  context = ast_variable_retrieve(msg_cfg, "message", "context");
13238  if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
13239  context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
13240  switch (option) {
13241  case 3: /* Play message envelope */
13242  if (!res)
13243  res = play_message_datetime(chan, vmu, origtime, filename);
13244  if (!res)
13245  res = play_message_callerid(chan, vms, cid, context, 0);
13246 
13247  res = 't';
13248  break;
13249 
13250  case 2: /* Call back */
13251 
13252  if (ast_strlen_zero(cid))
13253  break;
13254 
13255  ast_callerid_parse(cid, &name, &num);
13256  while ((res > -1) && (res != 't')) {
13257  switch (res) {
13258  case '1':
13259  if (num) {
13260  /* Dial the CID number */
13261  res = dialout(chan, vmu, num, vmu->callback);
13262  if (res) {
13263  ast_config_destroy(msg_cfg);
13264  return 9;
13265  }
13266  } else {
13267  res = '2';
13268  }
13269  break;
13270 
13271  case '2':
13272  /* Want to enter a different number, can only do this if there's a dialout context for this user */
13273  if (!ast_strlen_zero(vmu->dialout)) {
13274  res = dialout(chan, vmu, NULL, vmu->dialout);
13275  if (res) {
13276  ast_config_destroy(msg_cfg);
13277  return 9;
13278  }
13279  } else {
13280  ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
13281  res = ast_play_and_wait(chan, "vm-sorry");
13282  }
13283  ast_config_destroy(msg_cfg);
13284  return res;
13285  case '*':
13286  res = 't';
13287  break;
13288  case '3':
13289  case '4':
13290  case '5':
13291  case '6':
13292  case '7':
13293  case '8':
13294  case '9':
13295  case '0':
13296 
13297  res = ast_play_and_wait(chan, "vm-sorry");
13298  retries++;
13299  break;
13300  default:
13301  if (num) {
13302  ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
13303  res = ast_play_and_wait(chan, "vm-num-i-have");
13304  if (!res)
13305  res = play_message_callerid(chan, vms, num, vmu->context, 1);
13306  if (!res)
13307  res = ast_play_and_wait(chan, "vm-tocallnum");
13308  /* Only prompt for a caller-specified number if there is a dialout context specified */
13309  if (!ast_strlen_zero(vmu->dialout)) {
13310  if (!res)
13311  res = ast_play_and_wait(chan, "vm-calldiffnum");
13312  }
13313  } else {
13314  res = ast_play_and_wait(chan, "vm-nonumber");
13315  if (!ast_strlen_zero(vmu->dialout)) {
13316  if (!res)
13317  res = ast_play_and_wait(chan, "vm-toenternumber");
13318  }
13319  }
13320  if (!res) {
13321  res = ast_play_and_wait(chan, "vm-star-cancel");
13322  }
13323  if (!res) {
13324  res = ast_waitfordigit(chan, 6000);
13325  }
13326  if (!res) {
13327  retries++;
13328  if (retries > 3) {
13329  res = 't';
13330  }
13331  }
13332  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
13333  break;
13334 
13335  }
13336  if (res == 't')
13337  res = 0;
13338  else if (res == '*')
13339  res = -1;
13340  }
13341  break;
13342 
13343  case 1: /* Reply */
13344  /* Send reply directly to sender */
13345  if (ast_strlen_zero(cid))
13346  break;
13347 
13348  ast_callerid_parse(cid, &name, &num);
13349  if (!num) {
13350  ast_verb(3, "No CID number available, no reply sent\n");
13351  if (!res)
13352  res = ast_play_and_wait(chan, "vm-nonumber");
13353  ast_config_destroy(msg_cfg);
13354  return res;
13355  } else {
13356  struct ast_vm_user vmu2;
13357  if (find_user(&vmu2, vmu->context, num)) {
13358  struct leave_vm_options leave_options;
13359  char mailbox[AST_MAX_EXTENSION * 2 + 2];
13360  snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
13361 
13362  ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
13363 
13364  memset(&leave_options, 0, sizeof(leave_options));
13365  leave_options.record_gain = record_gain;
13366  res = leave_voicemail(chan, mailbox, &leave_options);
13367  if (!res)
13368  res = 't';
13369  ast_config_destroy(msg_cfg);
13370  return res;
13371  } else {
13372  /* Sender has no mailbox, can't reply */
13373  ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
13374  ast_play_and_wait(chan, "vm-nobox");
13375  res = 't';
13376  ast_config_destroy(msg_cfg);
13377  return res;
13378  }
13379  }
13380  res = 0;
13381 
13382  break;
13383  }
13384 
13385  ast_config_destroy(msg_cfg);
13386 
13387 #ifndef IMAP_STORAGE
13388  if (!res) {
13389  make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13390  vms->heard[msg] = 1;
13391  res = wait_file(chan, vms, vms->fn);
13392  }
13393 #endif
13394  return res;
13395 }
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
char fn[PATH_MAX]
#define AST_LOG_WARNING
Definition: logger.h:149
char curdir[PATH_MAX]
#define DISPOSE(a, b)
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
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 appropria...
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
#define AST_MAX_EXTENSION
Definition: channel.h:135
char context[AST_MAX_CONTEXT]
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
int * heard
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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 struct ast_vm_user * find_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 const char name[]
Structure used to handle boolean flags.
Definition: utils.h:200
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:635
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
signed char record_gain
Definition: app_minivm.c:637
char dialout[80]
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
char callback[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1009
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static int append_mailbox ( const char *  context,
const char *  box,
const char *  data 
)
static

Definition at line 10726 of file app_voicemail.c.

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

Referenced by actual_load_config().

10727 {
10728  /* Assumes lock is already held */
10729  char *tmp;
10730  char *stringp;
10731  char *s;
10732  struct ast_vm_user *vmu;
10733  char *mailbox_full;
10734  int new = 0, old = 0, urgent = 0;
10735  char secretfn[PATH_MAX] = "";
10736 
10737  tmp = ast_strdupa(data);
10738 
10739  if (!(vmu = find_or_create(context, box)))
10740  return -1;
10741 
10742  populate_defaults(vmu);
10743 
10744  stringp = tmp;
10745  if ((s = strsep(&stringp, ","))) {
10746  if (!ast_strlen_zero(s) && s[0] == '*') {
10747  ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
10748  "\n\tmust be reset in voicemail.conf.\n", box);
10749  }
10750  /* assign password regardless of validity to prevent NULL password from being assigned */
10751  ast_copy_string(vmu->password, s, sizeof(vmu->password));
10752  }
10753  if (stringp && (s = strsep(&stringp, ","))) {
10754  ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10755  }
10756  if (stringp && (s = strsep(&stringp, ","))) {
10757  ast_copy_string(vmu->email, s, sizeof(vmu->email));
10758  }
10759  if (stringp && (s = strsep(&stringp, ","))) {
10760  ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10761  }
10762  if (stringp && (s = strsep(&stringp, ","))) {
10763  apply_options(vmu, s);
10764  }
10765 
10766  switch (vmu->passwordlocation) {
10767  case OPT_PWLOC_SPOOLDIR:
10768  snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10769  read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10770  }
10771 
10772  mailbox_full = ast_alloca(strlen(box) + strlen(context) + 1);
10773  strcpy(mailbox_full, box);
10774  strcat(mailbox_full, "@");
10775  strcat(mailbox_full, context);
10776 
10777  inboxcount2(mailbox_full, &urgent, &new, &old);
10778  queue_mwi_event(mailbox_full, urgent, new, old);
10779 
10780  return 0;
10781 }
char fullname[80]
char * strsep(char **str, const char *delims)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define LOG_WARNING
Definition: logger.h:144
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
int passwordlocation
char context[AST_MAX_CONTEXT]
static char VM_SPOOL_DIR[PATH_MAX]
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
char pager[80]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static struct ast_vm_user * find_or_create(const char *context, const char *box)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char email[80]
char password[80]
static void queue_mwi_event(const char *box, int urgent, int new, int old)
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static void apply_option ( struct ast_vm_user vmu,
const char *  var,
const char *  value 
)
static

Sets a a specific property value.

Parameters
vmuThe voicemail user object to work with.
varThe name of the property to be set.
valueThe 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 1056 of file app_voicemail.c.

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

Referenced by apply_options(), and apply_options_full().

1057 {
1058  int x;
1059  if (!strcasecmp(var, "attach")) {
1061  } else if (!strcasecmp(var, "attachfmt")) {
1062  ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
1063  } else if (!strcasecmp(var, "serveremail")) {
1064  ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
1065  } else if (!strcasecmp(var, "emailbody")) {
1067  } else if (!strcasecmp(var, "emailsubject")) {
1069  } else if (!strcasecmp(var, "language")) {
1070  ast_copy_string(vmu->language, value, sizeof(vmu->language));
1071  } else if (!strcasecmp(var, "tz")) {
1072  ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
1073  } else if (!strcasecmp(var, "locale")) {
1074  ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
1075 #ifdef IMAP_STORAGE
1076  } else if (!strcasecmp(var, "imapuser")) {
1077  ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
1078  vmu->imapversion = imapversion;
1079  } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
1080  ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
1081  vmu->imapversion = imapversion;
1082  } else if (!strcasecmp(var, "imapfolder")) {
1083  ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
1084  } else if (!strcasecmp(var, "imapvmshareid")) {
1085  ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
1086  vmu->imapversion = imapversion;
1087 #endif
1088  } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
1090  } else if (!strcasecmp(var, "saycid")){
1092  } else if (!strcasecmp(var, "sendvoicemail")){
1094  } else if (!strcasecmp(var, "review")){
1096  } else if (!strcasecmp(var, "tempgreetwarn")){
1098  } else if (!strcasecmp(var, "messagewrap")){
1100  } else if (!strcasecmp(var, "operator")) {
1102  } else if (!strcasecmp(var, "envelope")){
1104  } else if (!strcasecmp(var, "moveheard")){
1106  } else if (!strcasecmp(var, "sayduration")){
1108  } else if (!strcasecmp(var, "saydurationm")){
1109  if (sscanf(value, "%30d", &x) == 1) {
1110  vmu->saydurationm = x;
1111  } else {
1112  ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
1113  }
1114  } else if (!strcasecmp(var, "forcename")){
1116  } else if (!strcasecmp(var, "forcegreetings")){
1118  } else if (!strcasecmp(var, "callback")) {
1119  ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
1120  } else if (!strcasecmp(var, "dialout")) {
1121  ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
1122  } else if (!strcasecmp(var, "exitcontext")) {
1123  ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
1124  } else if (!strcasecmp(var, "minsecs")) {
1125  if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
1126  vmu->minsecs = x;
1127  } else {
1128  ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1129  vmu->minsecs = vmminsecs;
1130  }
1131  } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
1132  vmu->maxsecs = atoi(value);
1133  if (vmu->maxsecs <= 0) {
1134  ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
1135  vmu->maxsecs = vmmaxsecs;
1136  } else {
1137  vmu->maxsecs = atoi(value);
1138  }
1139  if (!strcasecmp(var, "maxmessage"))
1140  ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1141  } else if (!strcasecmp(var, "maxmsg")) {
1142  vmu->maxmsg = atoi(value);
1143  /* Accept maxmsg=0 (Greetings only voicemail) */
1144  if (vmu->maxmsg < 0) {
1145  ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
1146  vmu->maxmsg = MAXMSG;
1147  } else if (vmu->maxmsg > MAXMSGLIMIT) {
1148  ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
1149  vmu->maxmsg = MAXMSGLIMIT;
1150  }
1151  } else if (!strcasecmp(var, "nextaftercmd")) {
1153  } else if (!strcasecmp(var, "backupdeleted")) {
1154  if (sscanf(value, "%30d", &x) == 1)
1155  vmu->maxdeletedmsg = x;
1156  else if (ast_true(value))
1157  vmu->maxdeletedmsg = MAXMSG;
1158  else
1159  vmu->maxdeletedmsg = 0;
1160 
1161  if (vmu->maxdeletedmsg < 0) {
1162  ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
1163  vmu->maxdeletedmsg = MAXMSG;
1164  } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
1165  ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
1166  vmu->maxdeletedmsg = MAXMSGLIMIT;
1167  }
1168  } else if (!strcasecmp(var, "volgain")) {
1169  sscanf(value, "%30lf", &vmu->volgain);
1170  } else if (!strcasecmp(var, "passwordlocation")) {
1171  if (!strcasecmp(value, "spooldir")) {
1173  } else {
1175  }
1176  } else if (!strcasecmp(var, "options")) {
1177  apply_options(vmu, value);
1178  }
1179 }
double volgain
#define VM_TEMPGREETWARN
static const char * substitute_escapes(const char *value)
#define ast_strdup(a)
Definition: astmm.h:109
char attachfmt[20]
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define VM_SAYDURATION
#define LOG_WARNING
Definition: logger.h:144
#define AST_LOG_WARNING
Definition: logger.h:149
#define var
Definition: ast_expr2f.c:606
#define VM_MESSAGEWRAP
#define VM_ATTACH
static int vmminsecs
int value
Definition: syslog.c:39
char locale[20]
char * emailsubject
#define VM_SAYCID
#define VM_SVMAIL
#define VM_ENVELOPE
#define MAXMSG
#define VM_FORCENAME
#define VM_DELETE
int passwordlocation
#define VM_MOVEHEARD
char zonetag[80]
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
#define VM_OPERATOR
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
char * emailbody
#define VM_REVIEW
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
char exit[80]
char language[MAX_LANGUAGE]
static int vmmaxsecs
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char dialout[80]
#define VM_SKIPAFTERCMD
#define MAXMSGLIMIT
char callback[80]
char serveremail[80]
#define VM_FORCEGREET
static void apply_options ( struct ast_vm_user vmu,
const char *  options 
)
static

Destructively Parse options and apply.

Definition at line 1297 of file app_voicemail.c.

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

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

1298 {
1299  char *stringp;
1300  char *s;
1301  char *var, *value;
1302  stringp = ast_strdupa(options);
1303  while ((s = strsep(&stringp, "|"))) {
1304  value = s;
1305  if ((var = strsep(&value, "=")) && value) {
1306  apply_option(vmu, var, value);
1307  }
1308  }
1309 }
char * strsep(char **str, const char *delims)
#define var
Definition: ast_expr2f.c:606
int value
Definition: syslog.c:39
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a a specific property value.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
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 1316 of file app_voicemail.c.

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

Referenced by actual_load_config(), and find_user_realtime().

1317 {
1318  for (; var; var = var->next) {
1319  if (!strcasecmp(var->name, "vmsecret")) {
1320  ast_copy_string(retval->password, var->value, sizeof(retval->password));
1321  } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
1322  if (ast_strlen_zero(retval->password)) {
1323  if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
1324  ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
1325  "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
1326  } else {
1327  ast_copy_string(retval->password, var->value, sizeof(retval->password));
1328  }
1329  }
1330  } else if (!strcasecmp(var->name, "uniqueid")) {
1331  ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
1332  } else if (!strcasecmp(var->name, "pager")) {
1333  ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
1334  } else if (!strcasecmp(var->name, "email")) {
1335  ast_copy_string(retval->email, var->value, sizeof(retval->email));
1336  } else if (!strcasecmp(var->name, "fullname")) {
1337  ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
1338  } else if (!strcasecmp(var->name, "context")) {
1339  ast_copy_string(retval->context, var->value, sizeof(retval->context));
1340  } else if (!strcasecmp(var->name, "emailsubject")) {
1341  ast_free(retval->emailsubject);
1343  } else if (!strcasecmp(var->name, "emailbody")) {
1344  ast_free(retval->emailbody);
1345  retval->emailbody = ast_strdup(substitute_escapes(var->value));
1346 #ifdef IMAP_STORAGE
1347  } else if (!strcasecmp(var->name, "imapuser")) {
1348  ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
1349  retval->imapversion = imapversion;
1350  } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
1351  ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
1352  retval->imapversion = imapversion;
1353  } else if (!strcasecmp(var->name, "imapfolder")) {
1354  ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
1355  } else if (!strcasecmp(var->name, "imapvmshareid")) {
1356  ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
1357  retval->imapversion = imapversion;
1358 #endif
1359  } else
1360  apply_option(retval, var->name, var->value);
1361  }
1362 }
char uniqueid[80]
char fullname[80]
static const char * substitute_escapes(const char *value)
#define ast_strdup(a)
Definition: astmm.h:109
#define LOG_WARNING
Definition: logger.h:144
#define var
Definition: ast_expr2f.c:606
char * emailsubject
const char * value
Definition: config.h:79
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
const char * name
Definition: config.h:77
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a a specific property value.
char pager[80]
char * emailbody
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_variable * next
Definition: config.h:82
char email[80]
char password[80]
AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)
AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)
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
endAn expandable buffer for holding the result
maxlenAlways zero, but see
See Also
ast_str
Parameters
startA string to be encoded
preambleThe length of the first line already used for this string, to ensure that each line maintains a maximum length of 76 chars.
postamblethe length of any additional characters appended to the line, used to ensure proper field wrapping.
Return values
Theencoded string.

Definition at line 4511 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

4512 {
4513  struct ast_str *tmp = ast_str_alloca(80);
4514  int first_section = 1;
4515 
4516  ast_str_reset(*end);
4517  ast_str_set(&tmp, -1, "=?%s?Q?", charset);
4518  for (; *start; start++) {
4519  int need_encoding = 0;
4520  if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
4521  need_encoding = 1;
4522  }
4523  if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
4524  (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
4525  (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
4526  (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
4527  /* Start new line */
4528  ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
4529  ast_str_set(&tmp, -1, "=?%s?Q?", charset);
4530  first_section = 0;
4531  }
4532  if (need_encoding && *start == ' ') {
4533  ast_str_append(&tmp, -1, "_");
4534  } else if (need_encoding) {
4535  ast_str_append(&tmp, -1, "=%hhX", *start);
4536  } else {
4537  ast_str_append(&tmp, -1, "%c", *start);
4538  }
4539  }
4540  ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
4541  return ast_str_buffer(*end);
4542 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
#define ast_str_alloca(init_len)
Definition: strings.h:608
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static char charset[32]
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
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
fromThe string to work with.
bufThe buffer into which to write the modified quoted string.
maxlenAlways zero, but see
See Also
ast_str
Returns
The destination string with quotes wrapped on it (the to field).

Definition at line 4439 of file app_voicemail.c.

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

Referenced by make_email_file(), and sendpage().

4440 {
4441  const char *ptr;
4442 
4443  /* We're only ever passing 0 to maxlen, so short output isn't possible */
4444  ast_str_set(buf, maxlen, "\"");
4445  for (ptr = from; *ptr; ptr++) {
4446  if (*ptr == '"' || *ptr == '\\') {
4447  ast_str_append(buf, maxlen, "\\%c", *ptr);
4448  } else {
4449  ast_str_append(buf, maxlen, "%c", *ptr);
4450  }
4451  }
4452  ast_str_append(buf, maxlen, "\"");
4453 
4454  return ast_str_buffer(*buf);
4455 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
AST_TEST_DEFINE ( test_voicemail_vmuser  )

Definition at line 10783 of file app_voicemail.c.

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

10784 {
10785  int res = 0;
10786  struct ast_vm_user *vmu;
10787  /* language parameter seems to only be used for display in manager action */
10788  static const char options_string[] = "attach=yes|attachfmt=wav49|"
10789  "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10790  "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10791  "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10792  "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10793  "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10794  "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
10795  "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
10796  "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
10797 #ifdef IMAP_STORAGE
10798  static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10799  "imapfolder=INBOX|imapvmshareid=6000";
10800 #endif
10801 
10802  switch (cmd) {
10803  case TEST_INIT:
10804  info->name = "vmuser";
10805  info->category = "/apps/app_voicemail/";
10806  info->summary = "Vmuser unit test";
10807  info->description =
10808  "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10809  return AST_TEST_NOT_RUN;
10810  case TEST_EXECUTE:
10811  break;
10812  }
10813 
10814  if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10815  return AST_TEST_NOT_RUN;
10816  }
10817  populate_defaults(vmu);
10818  ast_set_flag(vmu, VM_ALLOCED);
10819 
10820  apply_options(vmu, options_string);
10821 
10822  if (!ast_test_flag(vmu, VM_ATTACH)) {
10823  ast_test_status_update(test, "Parse failure for attach option\n");
10824  res = 1;
10825  }
10826  if (strcasecmp(vmu->attachfmt, "wav49")) {
10827  ast_test_status_update(test, "Parse failure for attachftm option\n");
10828  res = 1;
10829  }
10830  if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10831  ast_test_status_update(test, "Parse failure for serveremail option\n");
10832  res = 1;
10833  }
10834  if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
10835  ast_test_status_update(test, "Parse failure for emailsubject option\n");
10836  res = 1;
10837  }
10838  if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
10839  ast_test_status_update(test, "Parse failure for emailbody option\n");
10840  res = 1;
10841  }
10842  if (strcasecmp(vmu->zonetag, "central")) {
10843  ast_test_status_update(test, "Parse failure for tz option\n");
10844  res = 1;
10845  }
10846  if (!ast_test_flag(vmu, VM_DELETE)) {
10847  ast_test_status_update(test, "Parse failure for delete option\n");
10848  res = 1;
10849  }
10850  if (!ast_test_flag(vmu, VM_SAYCID)) {
10851  ast_test_status_update(test, "Parse failure for saycid option\n");
10852  res = 1;
10853  }
10854  if (!ast_test_flag(vmu, VM_SVMAIL)) {
10855  ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10856  res = 1;
10857  }
10858  if (!ast_test_flag(vmu, VM_REVIEW)) {
10859  ast_test_status_update(test, "Parse failure for review option\n");
10860  res = 1;
10861  }
10862  if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10863  ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10864  res = 1;
10865  }
10866  if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10867  ast_test_status_update(test, "Parse failure for messagewrap option\n");
10868  res = 1;
10869  }
10870  if (!ast_test_flag(vmu, VM_OPERATOR)) {
10871  ast_test_status_update(test, "Parse failure for operator option\n");
10872  res = 1;
10873  }
10874  if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10875  ast_test_status_update(test, "Parse failure for envelope option\n");
10876  res = 1;
10877  }
10878  if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10879  ast_test_status_update(test, "Parse failure for moveheard option\n");
10880  res = 1;
10881  }
10882  if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10883  ast_test_status_update(test, "Parse failure for sayduration option\n");
10884  res = 1;
10885  }
10886  if (vmu->saydurationm != 5) {
10887  ast_test_status_update(test, "Parse failure for saydurationm option\n");
10888  res = 1;
10889  }
10890  if (!ast_test_flag(vmu, VM_FORCENAME)) {
10891  ast_test_status_update(test, "Parse failure for forcename option\n");
10892  res = 1;
10893  }
10894  if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10895  ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10896  res = 1;
10897  }
10898  if (strcasecmp(vmu->callback, "somecontext")) {
10899  ast_test_status_update(test, "Parse failure for callbacks option\n");
10900  res = 1;
10901  }
10902  if (strcasecmp(vmu->dialout, "somecontext2")) {
10903  ast_test_status_update(test, "Parse failure for dialout option\n");
10904  res = 1;
10905  }
10906  if (strcasecmp(vmu->exit, "somecontext3")) {
10907  ast_test_status_update(test, "Parse failure for exitcontext option\n");
10908  res = 1;
10909  }
10910  if (vmu->minsecs != 10) {
10911  ast_test_status_update(test, "Parse failure for minsecs option\n");
10912  res = 1;
10913  }
10914  if (vmu->maxsecs != 100) {
10915  ast_test_status_update(test, "Parse failure for maxsecs option\n");
10916  res = 1;
10917  }
10918  if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10919  ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10920  res = 1;
10921  }
10922  if (vmu->maxdeletedmsg != 50) {
10923  ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10924  res = 1;
10925  }
10926  if (vmu->volgain != 1.3) {
10927  ast_test_status_update(test, "Parse failure for volgain option\n");
10928  res = 1;
10929  }
10930  if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10931  ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10932  res = 1;
10933  }
10934 #ifdef IMAP_STORAGE
10935  apply_options(vmu, option_string2);
10936 
10937  if (strcasecmp(vmu->imapuser, "imapuser")) {
10938  ast_test_status_update(test, "Parse failure for imapuser option\n");
10939  res = 1;
10940  }
10941  if (strcasecmp(vmu->imappassword, "imappasswd")) {
10942  ast_test_status_update(test, "Parse failure for imappasswd option\n");
10943  res = 1;
10944  }
10945  if (strcasecmp(vmu->imapfolder, "INBOX")) {
10946  ast_test_status_update(test, "Parse failure for imapfolder option\n");
10947  res = 1;
10948  }
10949  if (strcasecmp(vmu->imapvmshareid, "6000")) {
10950  ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
10951  res = 1;
10952  }
10953 #endif
10954 
10955  free_user(vmu);
10956  return res ? AST_TEST_FAIL : AST_TEST_PASS;
10957 }
double volgain
#define VM_TEMPGREETWARN
char attachfmt[20]
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define VM_SAYDURATION
#define VM_MESSAGEWRAP
#define VM_ATTACH
char * emailsubject
#define VM_SAYCID
#define VM_SVMAIL
#define VM_ENVELOPE
#define VM_FORCENAME
#define VM_DELETE
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int passwordlocation
#define VM_MOVEHEARD
char zonetag[80]
static void free_user(struct ast_vm_user *vmu)
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
#define VM_OPERATOR
char * emailbody
#define VM_REVIEW
char exit[80]
#define ast_calloc(a, b)
Definition: astmm.h:82
char dialout[80]
#define VM_SKIPAFTERCMD
#define VM_ALLOCED
char callback[80]
char serveremail[80]
#define VM_FORCEGREET
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static int base_encode ( char *  filename,
FILE *  so 
)
static

Performs a base 64 encode algorithm on the contents of a File.

Parameters
filenameThe path to the file to be encoded. Must be readable, file is opened in read mode.
soA 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 4315 of file app_voicemail.c.

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

Referenced by add_email_attachment().

4316 {
4317  static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
4318  'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
4319  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
4320  '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
4321  int i, hiteof = 0;
4322  FILE *fi;
4323  struct baseio bio;
4324 
4325  memset(&bio, 0, sizeof(bio));
4326  bio.iocp = BASEMAXINLINE;
4327 
4328  if (!(fi = fopen(filename, "rb"))) {
4329  ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
4330  return -1;
4331  }
4332 
4333  while (!hiteof){
4334  unsigned char igroup[3], ogroup[4];
4335  int c, n;
4336 
4337  memset(igroup, 0, sizeof(igroup));
4338 
4339  for (n = 0; n < 3; n++) {
4340  if ((c = inchar(&bio, fi)) == EOF) {
4341  hiteof = 1;
4342  break;
4343  }
4344 
4345  igroup[n] = (unsigned char) c;
4346  }
4347 
4348  if (n > 0) {
4349  ogroup[0]= dtable[igroup[0] >> 2];
4350  ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
4351  ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
4352  ogroup[3]= dtable[igroup[2] & 0x3F];
4353 
4354  if (n < 3) {
4355  ogroup[3] = '=';
4356 
4357  if (n < 2)
4358  ogroup[2] = '=';
4359  }
4360 
4361  for (i = 0; i < 4; i++)
4362  ochar(&bio, ogroup[i], so);
4363  }
4364  }
4365 
4366  fclose(fi);
4367 
4368  if (fputs(ENDL, so) == EOF) {
4369  return 0;
4370  }
4371 
4372  return 1;
4373 }
#define AST_LOG_WARNING
Definition: logger.h:149
#define ENDL
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int ochar(struct baseio *bio, int c, FILE *so)
utility used by base_encode()
int errno
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
#define BASEMAXINLINE
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
vmuThe voicemail user to change the password for.
passwordThe 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 1275 of file app_voicemail.c.

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

Referenced by vm_change_password().

1276 {
1277  int res = -1;
1278  if (!strcmp(vmu->password, password)) {
1279  /* No change (but an update would return 0 rows updated, so we opt out here) */
1280  return 0;
1281  }
1282 
1283  if (strlen(password) > 10) {
1284  ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
1285  }
1286  if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
1287  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
1288  ast_copy_string(vmu->password, password, sizeof(vmu->password));
1289  res = 0;
1290  }
1291  return res;
1292 }
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
Definition: config.c:2703
Definition: config.h:68
#define SENTINEL
Definition: compiler.h:75
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: config.c:2606
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char password[80]
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 4484 of file app_voicemail.c.

References str.

Referenced by make_email_file(), and sendpage().

4485 {
4486  for (; *str; str++) {
4487  if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
4488  return 1;
4489  }
4490  }
4491  return 0;
4492 }
const char * str
Definition: app_jack.c:144
static int check_password ( struct ast_vm_user vmu,
char *  password 
)
static

Check that password meets minimum required length.

Parameters
vmuThe voicemail user to change the password for.
passwordThe password string to check
Returns
zero on ok, 1 on not ok.

Definition at line 1234 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 vm_newuser(), and vm_options().

1235 {
1236  /* check minimum length */
1237  if (strlen(password) < minpassword)
1238  return 1;
1239  /* check that password does not contain '*' character */
1240  if (!ast_strlen_zero(password) && password[0] == '*')
1241  return 1;
1243  char cmd[255], buf[255];
1244 
1245  ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
1246 
1247  snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
1248  if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
1249  ast_debug(5, "Result: %s\n", buf);
1250  if (!strncasecmp(buf, "VALID", 5)) {
1251  ast_debug(3, "Passed password check: '%s'\n", buf);
1252  return 0;
1253  } else if (!strncasecmp(buf, "FAILURE", 7)) {
1254  ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
1255  return 0;
1256  } else {
1257  ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
1258  return 1;
1259  }
1260  }
1261  }
1262  return 0;
1263 }
static char * vm_check_password_shell(char *command, char *buf, size_t len)
static int minpassword
#define AST_LOG_WARNING
Definition: logger.h:149
#define AST_LOG_NOTICE
Definition: logger.h:138
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
static char ext_pass_check_cmd[128]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LOG_DEBUG
Definition: logger.h:127
char password[80]
static int close_mailbox ( struct vm_state vms,
struct ast_vm_user vmu 
)
static

Definition at line 8004 of file app_voicemail.c.

References ast_check_realtime(), ast_debug, ast_free, ast_log(), AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_test_flag, ast_unlock_path(), ast_vm_user::context, vm_state::curbox, vm_state::curdir, vm_state::curmsg, DELETE, vm_state::deleted, vm_state::dh_arraysize, ERROR_LOCK_PATH, EXISTS, vm_state::fn, vm_state::heard, last_message_index(), vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by vm_execmain().

8005 {
8006  int x = 0;
8007  int last_msg_idx = 0;
8008 
8009 #ifndef IMAP_STORAGE
8010  int res = 0, nummsg;
8011  char fn2[PATH_MAX];
8012 #endif
8013 
8014  if (vms->lastmsg <= -1) {
8015  goto done;
8016  }
8017 
8018  vms->curmsg = -1;
8019 #ifndef IMAP_STORAGE
8020  /* Get the deleted messages fixed */
8021  if (vm_lock_path(vms->curdir)) {
8022  return ERROR_LOCK_PATH;
8023  }
8024 
8025  /* update count as message may have arrived while we've got mailbox open */
8026  last_msg_idx = last_message_index(vmu, vms->curdir);
8027  if (last_msg_idx != vms->lastmsg) {
8028  ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
8029  }
8030 
8031  /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
8032  for (x = 0; x < last_msg_idx + 1; x++) {
8033  if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
8034  /* Save this message. It's not in INBOX or hasn't been heard */
8035  make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
8036  if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
8037  break;
8038  }
8039  vms->curmsg++;
8040  make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
8041  if (strcmp(vms->fn, fn2)) {
8042  RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
8043  }
8044  } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
8045  /* Move to old folder before deleting */
8046  res = save_to_folder(vmu, vms, x, 1);
8047  if (res == ERROR_LOCK_PATH) {
8048  /* If save failed do not delete the message */
8049  ast_log(AST_LOG_WARNING, "Save failed. Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
8050  vms->deleted[x] = 0;
8051  vms->heard[x] = 0;
8052  --x;
8053  }
8054  } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
8055  /* Move to deleted folder */
8056  res = save_to_folder(vmu, vms, x, 10);
8057  if (res == ERROR_LOCK_PATH) {
8058  /* If save failed do not delete the message */
8059  vms->deleted[x] = 0;
8060  vms->heard[x] = 0;
8061  --x;
8062  }
8063  } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
8064  /* If realtime storage enabled - we should explicitly delete this message,
8065  cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
8066  make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
8067  if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
8068  DELETE(vms->curdir, x, vms->fn, vmu);
8069  }
8070  }
8071  }
8072 
8073  /* Delete ALL remaining messages */
8074  nummsg = x - 1;
8075  for (x = vms->curmsg + 1; x <= nummsg; x++) {
8076  make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
8077  if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
8078  DELETE(vms->curdir, x, vms->fn, vmu);
8079  }
8080  }
8081  ast_unlock_path(vms->curdir);
8082 #else /* defined(IMAP_STORAGE) */
8083  ast_mutex_lock(&vms->lock);
8084  if (vms->deleted) {
8085  /* Since we now expunge after each delete, deleting in reverse order
8086  * ensures that no reordering occurs between each step. */
8087  last_msg_idx = vms->dh_arraysize;
8088  for (x = last_msg_idx - 1; x >= 0; x--) {
8089  if (vms->deleted[x]) {
8090  ast_debug(3, "IMAP delete of %d\n", x);
8091  DELETE(vms->curdir, x, vms->fn, vmu);
8092  }
8093  }
8094  }
8095 #endif
8096 
8097 done:
8098  if (vms->deleted) {
8099  ast_free(vms->deleted);
8100  vms->deleted = NULL;
8101  }
8102  if (vms->heard) {
8103  ast_free(vms->heard);
8104  vms->heard = NULL;
8105  }
8106  vms->dh_arraysize = 0;
8107 #ifdef IMAP_STORAGE
8108  ast_mutex_unlock(&vms->lock);
8109 #endif
8110 
8111  return 0;
8112 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
char fn[PATH_MAX]
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
#define AST_LOG_WARNING
Definition: logger.h:149
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:155
int dh_arraysize
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 appropria...
#define AST_LOG_NOTICE
Definition: logger.h:138
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define VM_MOVEHEARD
#define DELETE(a, b, c, d)
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. ...
int * heard
#define RENAME(a, b, c, d, e, f, g, h)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
int * deleted
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
#define EXISTS(a, b, c, d)
char curbox[80]
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
#define ast_mutex_unlock(a)
Definition: lock.h:156
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
static char* complete_voicemail_show_users ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 11103 of file app_voicemail.c.

References AST_LIST_TRAVERSE, ast_strdup, and ast_vm_user::context.

Referenced by handle_voicemail_show_users().

11104 {
11105  int which = 0;
11106  int wordlen;
11107  struct ast_vm_user *vmu;
11108  const char *context = "";
11109 
11110  /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11111  if (pos > 4)
11112  return NULL;
11113  if (pos == 3)
11114  return (state == 0) ? ast_strdup("for") : NULL;
11115  wordlen = strlen(word);
11116  AST_LIST_TRAVERSE(&users, vmu, list) {
11117  if (!strncasecmp(word, vmu->context, wordlen)) {
11118  if (context && strcmp(context, vmu->context) && ++which > state)
11119  return ast_strdup(vmu->context);
11120  /* ignore repeated contexts ? */
11121  context = vmu->context;
11122  }
11123  }
11124  return NULL;
11125 }
#define ast_strdup(a)
Definition: astmm.h:109
list of users found in the config file
Definition: ael.tab.c:203
struct ast_vm_user::@65 list
char context[AST_MAX_CONTEXT]
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int copy ( char *  infile,
char *  outfile 
)
static

Utility function to copy a file.

Parameters
infileThe path to the file to be copied. The file must be readable, it is opened in read only mode.
outfileThe 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 4120 of file app_voicemail.c.

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

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

4121 {
4122  int ifd;
4123  int ofd;
4124  int res;
4125  int len;
4126  char buf[4096];
4127 
4128 #ifdef HARDLINK_WHEN_POSSIBLE
4129  /* Hard link if possible; saves disk space & is faster */
4130  if (link(infile, outfile)) {
4131 #endif
4132  if ((ifd = open(infile, O_RDONLY)) < 0) {
4133  ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
4134  return -1;
4135  }
4136  if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
4137  ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
4138  close(ifd);
4139  return -1;
4140  }
4141  do {
4142  len = read(ifd, buf, sizeof(buf));
4143  if (len < 0) {
4144  ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
4145  close(ifd);
4146  close(ofd);
4147  unlink(outfile);
4148  } else if (len) {
4149  res = write(ofd, buf, len);
4150  if (errno == ENOMEM || errno == ENOSPC || res != len) {
4151  ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
4152  close(ifd);
4153  close(ofd);
4154  unlink(outfile);
4155  }
4156  }
4157  } while (len);
4158  close(ifd);
4159  close(ofd);
4160  return 0;
4161 #ifdef HARDLINK_WHEN_POSSIBLE
4162  } else {
4163  /* Hard link succeeded */
4164  return 0;
4165  }
4166 #endif
4167 }
#define AST_LOG_WARNING
Definition: logger.h:149
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define VOICEMAIL_FILE_MODE
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
flagThis is only used by file storage based mailboxes.
Returns
zero on success, -1 on error.

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

5357 {
5358  char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
5359  const char *frombox = mbox(vmu, imbox);
5360  const char *userfolder;
5361  int recipmsgnum;
5362  int res = 0;
5363 
5364  ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
5365 
5366  if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
5367  userfolder = "Urgent";
5368  } else {
5369  userfolder = "INBOX";
5370  }
5371 
5372  create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
5373 
5374  if (!dir)
5375  make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
5376  else
5377  ast_copy_string(fromdir, dir, sizeof(fromdir));
5378 
5379  make_file(frompath, sizeof(frompath), fromdir, msgnum);
5380  make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
5381 
5382  if (vm_lock_path(todir))
5383  return ERROR_LOCK_PATH;
5384 
5385  recipmsgnum = last_message_index(recip, todir) + 1;
5386  if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
5387  make_file(topath, sizeof(topath), todir, recipmsgnum);
5388 #ifndef ODBC_STORAGE
5389  if (EXISTS(fromdir, msgnum, frompath, chan->language)) {
5390  COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
5391  } else {
5392 #endif
5393  /* If we are prepending a message for ODBC, then the message already
5394  * exists in the database, but we want to force copying from the
5395  * filesystem (since only the FS contains the prepend). */
5396  copy_plain_file(frompath, topath);
5397  STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
5398  vm_delete(topath);
5399 #ifndef ODBC_STORAGE
5400  }
5401 #endif
5402  } else {
5403  ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
5404  res = -1;
5405  }
5406  ast_unlock_path(todir);
5407  notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
5408  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
5409  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
5410  flag);
5411 
5412  return res;
5413 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
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 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 appropria...
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
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.
#define ERROR_LOCK_PATH
static void copy_plain_file(char *frompath, char *topath)
Copies a voicemail information (envelope) file.
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
char * str
Subscriber name (Malloced)
Definition: channel.h:214
static int inprocess_count(const char *context, const char *mailbox, int delta)
static const char * mbox(struct ast_vm_user *vmu, int id)
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 appropria...
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define AST_LOG_NOTICE
Definition: logger.h:138
#define AST_LOG_ERROR
Definition: logger.h:160
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
char context[AST_MAX_CONTEXT]
#define COPY(a, b, c, d, e, f, g, h)
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 vm_delete(char *file)
Removes the voicemail sound and information file.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define STORE(a, b, c, d, e, f, g, h, i, j)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
#define EXISTS(a, b, c, d)
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
static int maxmsg
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
const ast_string_field language
Definition: channel.h:787
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
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 4178 of file app_voicemail.c.

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

Referenced by copy_message().

4179 {
4180  char frompath2[PATH_MAX], topath2[PATH_MAX];
4181  struct ast_variable *tmp,*var = NULL;
4182  const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
4183  ast_filecopy(frompath, topath, NULL);
4184  snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
4185  snprintf(topath2, sizeof(topath2), "%s.txt", topath);
4186  if (ast_check_realtime("voicemail_data")) {
4187  var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
4188  /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
4189  for (tmp = var; tmp; tmp = tmp->next) {
4190  if (!strcasecmp(tmp->name, "origmailbox")) {
4191  origmailbox = tmp->value;
4192  } else if (!strcasecmp(tmp->name, "context")) {
4193  context = tmp->value;
4194  } else if (!strcasecmp(tmp->name, "macrocontext")) {
4195  macrocontext = tmp->value;
4196  } else if (!strcasecmp(tmp->name, "exten")) {
4197  exten = tmp->value;
4198  } else if (!strcasecmp(tmp->name, "priority")) {
4199  priority = tmp->value;
4200  } else if (!strcasecmp(tmp->name, "callerchan")) {
4201  callerchan = tmp->value;
4202  } else if (!strcasecmp(tmp->name, "callerid")) {
4203  callerid = tmp->value;
4204  } else if (!strcasecmp(tmp->name, "origdate")) {
4205  origdate = tmp->value;
4206  } else if (!strcasecmp(tmp->name, "origtime")) {
4207  origtime = tmp->value;
4208  } else if (!strcasecmp(tmp->name, "category")) {
4209  category = tmp->value;
4210  } else if (!strcasecmp(tmp->name, "duration")) {
4211  duration = tmp->value;
4212  }
4213  }
4214  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);
4215  }
4216  copy(frompath2, topath2);
4217  ast_variables_destroy(var);
4218 }
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:941
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
Definition: config.c:2726
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2548
static int copy(char *infile, char *outfile)
Utility function to copy a file.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
#define SENTINEL
Definition: compiler.h:75
const char * value
Definition: config.h:79
const char * name
Definition: config.h:77
struct ast_variable * next
Definition: config.h:82
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
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
dirThis 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 4015 of file app_voicemail.c.

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

Referenced by leave_voicemail(), manager_list_voicemail_users(), and open_mailbox().

4016 {
4017 
4018  int vmcount = 0;
4019  DIR *vmdir = NULL;
4020  struct dirent *vment = NULL;
4021 
4022  if (vm_lock_path(dir))
4023  return ERROR_LOCK_PATH;
4024 
4025  if ((vmdir = opendir(dir))) {
4026  while ((vment = readdir(vmdir))) {
4027  if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
4028  vmcount++;
4029  }
4030  }
4031  closedir(vmdir);
4032  }
4033  ast_unlock_path(dir);
4034 
4035  return vmcount;
4036 }
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
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
destString. base directory.
lenLength of dest.
contextString. Ignored if is null or empty string.
extString. Ignored if is null or empty string.
folderString. Ignored if is null or empty string.
Returns
-1 on failure, 0 on success.

Definition at line 1698 of file app_voicemail.c.

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

Referenced by add_email_attachment(), copy_message(), invent_message(), leave_voicemail(), open_mailbox(), and save_to_folder().

1699 {
1700  mode_t mode = VOICEMAIL_DIR_MODE;
1701  int res;
1702 
1703  make_dir(dest, len, context, ext, folder);
1704  if ((res = ast_mkdir(dest, mode))) {
1705  ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
1706  return -1;
1707  }
1708  return 0;
1709 }
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 appropria...
#define AST_LOG_WARNING
Definition: logger.h:149
const char * ext
Definition: http.c:112
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define VOICEMAIL_DIR_MODE
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
static int dialout ( struct ast_channel chan,
struct ast_vm_user vmu,
char *  num,
char *  outgoing_context 
)
static

Definition at line 13132 of file app_voicemail.c.

References ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, ast_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().

13133 {
13134  int cmd = 0;
13135  char destination[80] = "";
13136  int retries = 0;
13137 
13138  if (!num) {
13139  ast_verb(3, "Destination number will be entered manually\n");
13140  while (retries < 3 && cmd != 't') {
13141  destination[1] = '\0';
13142  destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13143  if (!cmd)
13144  destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13145  if (!cmd)
13146  destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13147  if (!cmd) {
13148  cmd = ast_waitfordigit(chan, 6000);
13149  if (cmd)
13150  destination[0] = cmd;
13151  }
13152  if (!cmd) {
13153  retries++;
13154  } else {
13155 
13156  if (cmd < 0)
13157  return 0;
13158  if (cmd == '*') {
13159  ast_verb(3, "User hit '*' to cancel outgoing call\n");
13160  return 0;
13161  }
13162  if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0)
13163  retries++;
13164  else
13165  cmd = 't';
13166  }
13167  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13168  }
13169  if (retries >= 3) {
13170  return 0;
13171  }
13172 
13173  } else {
13174  if (option_verbose > 2)
13175  ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13176  ast_copy_string(destination, num, sizeof(destination));
13177  }
13178 
13179  if (!ast_strlen_zero(destination)) {
13180  if (destination[strlen(destination) -1 ] == '*')
13181  return 0;
13182  if (option_verbose > 2)
13183  ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13184  ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13185  ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13186  chan->priority = 0;
13187  return 9;
13188  }
13189  return 0;
13190 }
int priority
Definition: channel.h:841
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define VERBOSE_PREFIX_3
Definition: logger.h:43
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
int option_verbose
Definition: asterisk.c:181
#define ast_verb(level,...)
Definition: logger.h:243
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:5837
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static struct ast_vm_user* find_or_create ( const char *  context,
const char *  box 
)
static

Definition at line 10686 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

10687 {
10688  struct ast_vm_user *vmu;
10689 
10690  if (!ast_strlen_zero(box) && box[0] == '*') {
10691  ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character. The '*' character,"
10692  "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10693  "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
10694  "\n\tand will be ignored.\n", box, context);
10695  return NULL;
10696  }
10697 
10698  AST_LIST_TRAVERSE(&users, vmu, list) {
10699  if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10700  if (strcasecmp(vmu->context, context)) {
10701  ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10702  \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10703  \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10704  \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10705  }
10706  ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10707  return NULL;
10708  }
10709  if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10710  ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10711  return NULL;
10712  }
10713  }
10714 
10715  if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10716  return NULL;
10717 
10718  ast_copy_string(vmu->context, context, sizeof(vmu->context));
10719  ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10720 
10722 
10723  return vmu;
10724 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
list of users found in the config file
#define VM_SEARCH
struct ast_vm_user::@65 list
static struct ast_flags globalflags
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
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 1437 of file app_voicemail.c.

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

Referenced by acf_mailbox_exists(), advanced_options(), forward_message(), leave_voicemail(), vm_authenticate(), vm_box_exists(), and vm_execmain().

1438 {
1439  /* This function could be made to generate one from a database, too */
1440  struct ast_vm_user *vmu = NULL, *cur;
1441  AST_LIST_LOCK(&users);
1442 
1444  context = "default";
1445 
1446  AST_LIST_TRAVERSE(&users, cur, list) {
1447 #ifdef IMAP_STORAGE
1448  if (cur->imapversion != imapversion) {
1449  continue;
1450  }
1451 #endif
1452  if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
1453  break;
1454  if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1455  break;
1456  }
1457  if (cur) {
1458  /* Make a copy, so that on a reload, we have no race */
1459  if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
1460  *vmu = *cur;
1461  if (!ivm) {
1462  vmu->emailbody = ast_strdup(cur->emailbody);
1463  vmu->emailsubject = ast_strdup(cur->emailsubject);
1464  }
1465  ast_set2_flag(vmu, !ivm, VM_ALLOCED);
1466  AST_LIST_NEXT(vmu, list) = NULL;
1467  }
1468  } else
1469  vmu = find_user_realtime(ivm, context, mailbox);
1471  return vmu;
1472 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_strdup(a)
Definition: astmm.h:109
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
list of users found in the config file
char * emailsubject
#define VM_SEARCH
struct ast_vm_user::@65 list
static struct ast_flags globalflags
static struct ast_vm_user * find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the realtime engine.
char * emailbody
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define VM_ALLOCED
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define ast_malloc(a)
Definition: astmm.h:91
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
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
mailboxThis 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 1396 of file app_voicemail.c.

References apply_options_full(), ast_calloc, ast_copy_string(), ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), free_user(), ast_vm_user::mailbox, populate_defaults(), SENTINEL, var, VM_ALLOCED, and VM_SEARCH.

Referenced by find_user().

1397 {
1398  struct ast_variable *var;
1399  struct ast_vm_user *retval;
1400 
1401  if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
1402  if (ivm) {
1403  memset(retval, 0, sizeof(*retval));
1404  }
1405  populate_defaults(retval);
1406  if (!ivm) {
1407  ast_set_flag(retval, VM_ALLOCED);
1408  }
1409  if (mailbox) {
1410  ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
1411  }
1412  if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
1413  var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
1414  } else {
1415  var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
1416  }
1417  if (var) {
1418  apply_options_full(retval, var);
1419  ast_variables_destroy(var);
1420  } else {
1421  if (!ivm)
1422  free_user(retval);
1423  retval = NULL;
1424  }
1425  }
1426  return retval;
1427 }
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2548
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
#define VM_SEARCH
#define SENTINEL
Definition: compiler.h:75
static struct ast_flags globalflags
char mailbox[AST_MAX_EXTENSION]
static void free_user(struct ast_vm_user *vmu)
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define VM_ALLOCED
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
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_messageUsed 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
urgentReads the destination mailbox(es) from keypad input for CID, or if use_directory feature is enabled, the Directory.

When in the leave message mode (is_new_message == 1):

  • allow the leaving of a message for ourselves. (Will not allow us to forward a message to ourselves, when is_new_message == 0).
  • attempt to determine the context and and mailbox, and then invoke leave_message() function to record and store the message.

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

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

Definition at line 7206 of file app_voicemail.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_waitfordigit(), ast_channel::caller, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), vm_state::fn, free_user(), ast_party_caller::id, inboxcount(), inprocess_count(), ast_channel::language, leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), serveremail, 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().

7207 {
7208 #ifdef IMAP_STORAGE
7209  int todircount = 0;
7210  struct vm_state *dstvms;
7211 #endif
7212  char username[70]="";
7213  char fn[PATH_MAX]; /* for playback of name greeting */
7214  char ecodes[16] = "#";
7215  int res = 0, cmd = 0;
7216  struct ast_vm_user *receiver = NULL, *vmtmp;
7218  char *stringp;
7219  const char *s;
7220  int saved_messages = 0;
7221  int valid_extensions = 0;
7222  char *dir;
7223  int curmsg;
7224  char urgent_str[7] = "";
7225  int prompt_played = 0;
7226 #ifndef IMAP_STORAGE
7227  char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
7228 #endif
7230  ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
7231  }
7232 
7233  if (vms == NULL) return -1;
7234  dir = vms->curdir;
7235  curmsg = vms->curmsg;
7236 
7237  ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
7238  while (!res && !valid_extensions) {
7239  int use_directory = 0;
7241  int done = 0;
7242  int retries = 0;
7243  cmd = 0;
7244  while ((cmd >= 0) && !done ){
7245  if (cmd)
7246  retries = 0;
7247  switch (cmd) {
7248  case '1':
7249  use_directory = 0;
7250  done = 1;
7251  break;
7252  case '2':
7253  use_directory = 1;
7254  done = 1;
7255  break;
7256  case '*':
7257  cmd = 't';
7258  done = 1;
7259  break;
7260  default:
7261  /* Press 1 to enter an extension press 2 to use the directory */
7262  cmd = ast_play_and_wait(chan, "vm-forward");
7263  if (!cmd) {
7264  cmd = ast_waitfordigit(chan, 3000);
7265  }
7266  if (!cmd) {
7267  retries++;
7268  }
7269  if (retries > 3) {
7270  cmd = 't';
7271  done = 1;
7272  }
7273  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
7274  }
7275  }
7276  if (cmd < 0 || cmd == 't')
7277  break;
7278  }
7279 
7280  if (use_directory) {
7281  /* use app_directory */
7282 
7283  char old_context[sizeof(chan->context)];
7284  char old_exten[sizeof(chan->exten)];
7285  int old_priority;
7286  struct ast_app* directory_app;
7287 
7288  directory_app = pbx_findapp("Directory");
7289  if (directory_app) {
7290  char vmcontext[256];
7291  /* make backup copies */
7292  memcpy(old_context, chan->context, sizeof(chan->context));
7293  memcpy(old_exten, chan->exten, sizeof(chan->exten));
7294  old_priority = chan->priority;
7295 
7296  /* call the the Directory, changes the channel */
7297  snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
7298  res = pbx_exec(chan, directory_app, vmcontext);
7299 
7300  ast_copy_string(username, chan->exten, sizeof(username));
7301 
7302  /* restore the old context, exten, and priority */
7303  memcpy(chan->context, old_context, sizeof(chan->context));
7304  memcpy(chan->exten, old_exten, sizeof(chan->exten));
7305  chan->priority = old_priority;
7306  } else {
7307  ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
7309  }
7310  } else {
7311  /* Ask for an extension */
7312  res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
7313  prompt_played++;
7314  if (res || prompt_played > 4)
7315  break;
7316  if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
7317  break;
7318  }
7319 
7320  /* start all over if no username */
7321  if (ast_strlen_zero(username))
7322  continue;
7323  stringp = username;
7324  s = strsep(&stringp, "*");
7325  /* start optimistic */
7326  valid_extensions = 1;
7327  while (s) {
7328  if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
7329  int oldmsgs;
7330  int newmsgs;
7331  int capacity;
7332  if (inboxcount(s, &newmsgs, &oldmsgs)) {
7333  ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
7334  /* Shouldn't happen, but allow trying another extension if it does */
7335  res = ast_play_and_wait(chan, "pbx-invalid");
7336  valid_extensions = 0;
7337  break;
7338  }
7339  capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
7340  if ((newmsgs + oldmsgs) >= capacity) {
7341  ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
7342  res = ast_play_and_wait(chan, "vm-mailboxfull");
7343  valid_extensions = 0;
7344  while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
7345  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
7346  free_user(vmtmp);
7347  }
7348  inprocess_count(receiver->mailbox, receiver->context, -1);
7349  break;
7350  }
7351  AST_LIST_INSERT_HEAD(&extensions, receiver, list);
7352  } else {
7353  /* XXX Optimization for the future. When we encounter a single bad extension,
7354  * bailing out on all of the extensions may not be the way to go. We should
7355  * probably just bail on that single extension, then allow the user to enter
7356  * several more. XXX
7357  */
7358  while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
7359  free_user(receiver);
7360  }
7361  ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
7362  /* "I am sorry, that's not a valid extension. Please try again." */
7363  res = ast_play_and_wait(chan, "pbx-invalid");
7364  valid_extensions = 0;
7365  break;
7366  }
7367 
7368  /* play name if available, else play extension number */
7369  snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
7370  RETRIEVE(fn, -1, s, receiver->context);
7371  if (ast_fileexists(fn, NULL, NULL) > 0) {
7372  res = ast_stream_and_wait(chan, fn, ecodes);
7373  if (res) {
7374  DISPOSE(fn, -1);
7375  return res;
7376  }
7377  } else {
7378  res = ast_say_digit_str(chan, s, ecodes, chan->language);
7379  }
7380  DISPOSE(fn, -1);
7381 
7382  s = strsep(&stringp, "*");
7383  }
7384  /* break from the loop of reading the extensions */
7385  if (valid_extensions)
7386  break;
7387  }
7388  /* check if we're clear to proceed */
7389  if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
7390  return res;
7391  if (is_new_message == 1) {
7392  struct leave_vm_options leave_options;
7393  char mailbox[AST_MAX_EXTENSION * 2 + 2];
7394  snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
7395 
7396  /* Send VoiceMail */
7397  memset(&leave_options, 0, sizeof(leave_options));
7398  leave_options.record_gain = record_gain;
7399  cmd = leave_voicemail(chan, mailbox, &leave_options);
7400  } else {
7401  /* Forward VoiceMail */
7402  long duration = 0;
7403  struct vm_state vmstmp;
7404  int copy_msg_result = 0;
7405  memcpy(&vmstmp, vms, sizeof(vmstmp));
7406 
7407  RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
7408 
7409  cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
7410  if (!cmd) {
7411  AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
7412 #ifdef IMAP_STORAGE
7413  int attach_user_voicemail;
7414  char *myserveremail = serveremail;
7415 
7416  /* get destination mailbox */
7417  dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
7418  if (!dstvms) {
7419  dstvms = create_vm_state_from_user(vmtmp);
7420  }
7421  if (dstvms) {
7422  init_mailstream(dstvms, 0);
7423  if (!dstvms->mailstream) {
7424  ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
7425  } else {
7426  copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
7427  run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str);
7428  }
7429  } else {
7430  ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
7431  }
7432  if (!ast_strlen_zero(vmtmp->serveremail))
7433  myserveremail = vmtmp->serveremail;
7434  attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
7435  /* NULL category for IMAP storage */
7436  sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
7437  dstvms->curbox,
7438  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
7439  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
7440  vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
7441  NULL, urgent_str);
7442 #else
7443  copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
7444 #endif
7445  saved_messages++;
7447  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
7448  free_user(vmtmp);
7449  if (res)
7450  break;
7451  }
7453  if (saved_messages > 0 && !copy_msg_result) {
7454  /* give confirmation that the message was saved */
7455  /* commented out since we can't forward batches yet
7456  if (saved_messages == 1)
7457  res = ast_play_and_wait(chan, "vm-message");
7458  else
7459  res = ast_play_and_wait(chan, "vm-messages");
7460  if (!res)
7461  res = ast_play_and_wait(chan, "vm-saved"); */
7462 #ifdef IMAP_STORAGE
7463  /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
7464  if (ast_strlen_zero(vmstmp.introfn))
7465 #endif
7466  res = ast_play_and_wait(chan, "vm-msgsaved");
7467  }
7468 #ifndef IMAP_STORAGE
7469  else {
7470  /* with IMAP, mailbox full warning played by imap_check_limits */
7471  res = ast_play_and_wait(chan, "vm-mailboxfull");
7472  }
7473  /* Restore original message without prepended message if backup exists */
7474  make_file(msgfile, sizeof(msgfile), dir, curmsg);
7475  strcpy(textfile, msgfile);
7476  strcpy(backup, msgfile);
7477  strcpy(backup_textfile, msgfile);
7478  strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
7479  strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
7480  strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7481  if (ast_fileexists(backup, NULL, NULL) > 0) {
7482  ast_filerename(backup, msgfile, NULL);
7483  rename(backup_textfile, textfile);
7484  }
7485 #endif
7486  }
7487  DISPOSE(dir, curmsg);
7488 #ifndef IMAP_STORAGE
7489  if (cmd) { /* assuming hangup, cleanup backup file */
7490  make_file(msgfile, sizeof(msgfile), dir, curmsg);
7491  strcpy(textfile, msgfile);
7492  strcpy(backup_textfile, msgfile);
7493  strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
7494  strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7495  rename(backup_textfile, textfile);
7496  }
7497 #endif
7498  }
7499 
7500  /* If anything failed above, we still have this list to free */
7501  while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
7502  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
7503  free_user(vmtmp);
7504  }
7505  return res ? res : cmd;
7506 }
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)
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
char * strsep(char **str, const char *delims)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int priority
Definition: channel.h:841
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
char fn[PATH_MAX]
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define AST_LOG_WARNING
Definition: logger.h:149
char curdir[PATH_MAX]
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8415
char * str
Subscriber name (Malloced)
Definition: channel.h:214
#define VM_ATTACH
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static int inprocess_count(const char *context, const char *mailbox, int delta)
#define DISPOSE(a, b)
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
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 appropria...
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static void run_externnotify(char *context, char *extension, const char *flag)
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define AST_LOG_ERROR
Definition: logger.h:160
static struct ast_flags globalflags
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char username[80]
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
char context[AST_MAX_CONTEXT]
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
static char VM_SPOOL_DIR[PATH_MAX]
static void free_user(struct ast_vm_user *vmu)
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:345
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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.
#define LOG_NOTICE
Definition: logger.h:133
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.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
#define STORE(a, b, c, d, e, f, g, h, i, j)
#define ast_clear_flag(p, flag)
Definition: utils.h:77
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:635
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
signed char record_gain
Definition: app_minivm.c:637
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
ast_app: A registered application
Definition: pbx.c:971
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
char curbox[80]
#define VM_DIRECFORWARD
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:936
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.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define VM_FWDURGAUTO
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:5837
static char vmfmts[80]
static char serveremail[80]
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
const ast_string_field language
Definition: channel.h:787
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static void free_user ( struct ast_vm_user vmu)
static

Definition at line 1753 of file app_voicemail.c.

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

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

1754 {
1755  if (ast_test_flag(vmu, VM_ALLOCED)) {
1756 
1757  ast_free(vmu->emailbody);
1758  vmu->emailbody = NULL;
1759 
1760  ast_free(vmu->emailsubject);
1761  vmu->emailsubject = NULL;
1762 
1763  ast_free(vmu);
1764  }
1765 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
char * emailsubject
char * emailbody
#define ast_free(a)
Definition: astmm.h:97
#define VM_ALLOCED
static void free_vm_users ( void  )
static

Free the users structure.

Definition at line 11715 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11716 {
11717  struct ast_vm_user *current;
11718  AST_LIST_LOCK(&users);
11719  while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11720  ast_set_flag(current, VM_ALLOCED);
11721  free_user(current);
11722  }
11724 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
list of users found in the config file
struct ast_vm_user::@65 list
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
static void free_user(struct ast_vm_user *vmu)
#define VM_ALLOCED
static void free_vm_zones ( void  )
static

Free the zones structure.

Definition at line 11727 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11728 {
11729  struct vm_zone *zcur;
11730  AST_LIST_LOCK(&zones);
11731  while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11732  free_zone(zcur);
11734 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void free_zone(struct vm_zone *z)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct vm_zone::@66 list
static void free_zone ( struct vm_zone z)
static

Definition at line 5124 of file app_voicemail.c.

References ast_free.

Referenced by free_vm_zones().

5125 {
5126  ast_free(z);
5127 }
#define ast_free(a)
Definition: astmm.h:97
static int get_date ( char *  s,
int  len 
)
static

Gets the current date and time, as formatted string.

Parameters
sThe buffer to hold the output formatted date.
lenthe 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 5080 of file app_voicemail.c.

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

Referenced by leave_voicemail().

5081 {
5082  struct ast_tm tm;
5083  struct timeval t = ast_tvnow();
5084 
5085  ast_localtime(&t, &tm, "UTC");
5086 
5087  return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
5088 }
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
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 6815 of file app_voicemail.c.

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

Referenced by get_folder2().

6816 {
6817  int x;
6818  int d;
6819  char fn[PATH_MAX];
6820  d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
6821  if (d)
6822  return d;
6823  for (x = start; x < 5; x++) { /* For all folders */
6824  if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
6825  return d;
6826  d = ast_play_and_wait(chan, "vm-for"); /* "for" */
6827  if (d)
6828  return d;
6829  snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
6830 
6831  /* The inbox folder can have its name changed under certain conditions
6832  * so this checks if the sound file exists for the inbox folder name and
6833  * if it doesn't, plays the default name instead. */
6834  if (x == 0) {
6835  if (ast_fileexists(fn, NULL, NULL)) {
6836  d = vm_play_folder_name(chan, fn);
6837  } else {
6838  ast_verb(1, "failed to find %s\n", fn);
6839  d = vm_play_folder_name(chan, "vm-INBOX");
6840  }
6841  } else {
6842  ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
6843  d = vm_play_folder_name(chan, fn);
6844  }
6845 
6846  if (d)
6847  return d;
6848  d = ast_waitfordigit(chan, 500);
6849  if (d)
6850  return d;
6851  }
6852 
6853  d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
6854  if (d)
6855  return d;
6856  d = ast_waitfordigit(chan, 4000);
6857  return d;
6858 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define AST_DIGIT_ANY
Definition: file.h:47
#define ast_verb(level,...)
Definition: logger.h:243
static const char * mbox(struct ast_vm_user *vmu, int id)
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
const ast_string_field language
Definition: channel.h:787
static int get_folder2 ( struct ast_channel chan,
char *  fn,
int  start 
)
static

plays a prompt and waits for a keypress.

Parameters
chan
fnthe name of the voice prompt file to be played. For example, 'vm-changeto', 'vm-savefolder'
startDoes 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 6872 of file app_voicemail.c.

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

Referenced by vm_execmain().

6873 {
6874  int res = 0;
6875  int loops = 0;
6876 
6877  res = ast_play_and_wait(chan, fn); /* Folder name */
6878  while (((res < '0') || (res > '9')) &&
6879  (res != '#') && (res >= 0) &&
6880  loops < 4) {
6881  res = get_folder(chan, 0);
6882  loops++;
6883  }
6884  if (loops == 4) { /* give up */
6885  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
6886  return '#';
6887  }
6888  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
6889  return res;
6890 }
static int get_folder(struct ast_channel *chan, int start)
get_folder: Folder menu Plays &quot;press 1 for INBOX messages&quot; etc. Should possibly be internationalized ...
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
static int get_folder_by_name ( const char *  name)
static

Definition at line 1740 of file app_voicemail.c.

References ARRAY_LEN.

Referenced by vm_execmain().

1741 {
1742  size_t i;
1743 
1744  for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
1745  if (strcasecmp(name, mailbox_folders[i]) == 0) {
1746  return i;
1747  }
1748  }
1749 
1750  return -1;
1751 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char *const mailbox_folders[]
static const char name[]
static int handle_subscribe ( void *  datap)
static

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

Referenced by mwi_sub_event_cb().

11486 {
11487  unsigned int len;
11488  struct mwi_sub *mwi_sub;
11489  struct mwi_sub_task *p = datap;
11490 
11491  len = sizeof(*mwi_sub);
11492  if (!ast_strlen_zero(p->mailbox))
11493  len += strlen(p->mailbox);
11494 
11495  if (!ast_strlen_zero(p->context))
11496  len += strlen(p->context) + 1; /* Allow for seperator */
11497 
11498  if (!(mwi_sub = ast_calloc(1, len)))
11499  return -1;
11500 
11501  mwi_sub->uniqueid = p->uniqueid;
11502  if (!ast_strlen_zero(p->mailbox))
11503  strcpy(mwi_sub->mailbox, p->mailbox);
11504 
11505  if (!ast_strlen_zero(p->context)) {
11506  strcat(mwi_sub->mailbox, "@");
11507  strcat(mwi_sub->mailbox, p->context);
11508  }
11509 
11511  AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11513  ast_free((void *) p->mailbox);
11514  ast_free((void *) p->context);
11515  ast_free(p);
11516  poll_subscribed_mailbox(mwi_sub);
11517  return 0;
11518 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char * context
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
An MWI subscription.
static void poll_subscribed_mailbox(struct mwi_sub *mwi_sub)
const char * mailbox
static struct ast_event_sub * mwi_sub
Definition: res_jabber.c:394
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
uint32_t uniqueid
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:97
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
#define ast_calloc(a, b)
Definition: astmm.h:82
static int handle_unsubscribe ( void *  datap)
static

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

Referenced by mwi_unsub_event_cb().

11464 {
11465  struct mwi_sub *mwi_sub;
11466  uint32_t *uniqueid = datap;
11467 
11469  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11470  if (mwi_sub->uniqueid == *uniqueid) {
11471  AST_LIST_REMOVE_CURRENT(entry);
11472  break;
11473  }
11474  }
11477 
11478  if (mwi_sub)
11479  mwi_sub_destroy(mwi_sub);
11480 
11481  ast_free(uniqueid);
11482  return 0;
11483 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
An MWI subscription.
static struct ast_event_sub * mwi_sub
Definition: res_jabber.c:394
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
static void mwi_sub_destroy(struct mwi_sub *mwi_sub)
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
#define ast_free(a)
Definition: astmm.h:97
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
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 11240 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.

11241 {
11242  switch (cmd) {
11243  case CLI_INIT:
11244  e->command = "voicemail reload";
11245  e->usage =
11246  "Usage: voicemail reload\n"
11247  " Reload voicemail configuration\n";
11248  return NULL;
11249  case CLI_GENERATE:
11250  return NULL;
11251  }
11252 
11253  if (a->argc != 2)
11254  return CLI_SHOWUSAGE;
11255 
11256  ast_cli(a->fd, "Reloading voicemail configuration...\n");
11257  load_config(1);
11258 
11259  return CLI_SUCCESS;
11260 }
static int load_config(int reload)
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
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 11128 of file app_voicemail.c.

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

11129 {
11130  struct ast_vm_user *vmu;
11131 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11132  const char *context = NULL;
11133  int users_counter = 0;
11134 
11135  switch (cmd) {
11136  case CLI_INIT:
11137  e->command = "voicemail show users";
11138  e->usage =
11139  "Usage: voicemail show users [for <context>]\n"
11140  " Lists all mailboxes currently set up\n";
11141  return NULL;
11142  case CLI_GENERATE:
11143  return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11144  }
11145 
11146  if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11147  return CLI_SHOWUSAGE;
11148  if (a->argc == 5) {
11149  if (strcmp(a->argv[3],"for"))
11150  return CLI_SHOWUSAGE;
11151  context = a->argv[4];
11152  }
11153 
11154  if (ast_check_realtime("voicemail")) {
11155  if (!context) {
11156  ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11157  return CLI_SHOWUSAGE;
11158  }
11159  return show_users_realtime(a->fd, context);
11160  }
11161 
11162  AST_LIST_LOCK(&users);
11163  if (AST_LIST_EMPTY(&users)) {
11164  ast_cli(a->fd, "There are no voicemail users currently defined\n");
11166  return CLI_FAILURE;
11167  }
11168  if (!context) {
11169  ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11170  } else {
11171  int count = 0;
11172  AST_LIST_TRAVERSE(&users, vmu, list) {
11173  if (!strcmp(context, vmu->context)) {
11174  count++;
11175  break;
11176  }
11177  }
11178  if (count) {
11179  ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11180  } else {
11181  ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11183  return CLI_FAILURE;
11184  }
11185  }
11186  AST_LIST_TRAVERSE(&users, vmu, list) {
11187  int newmsgs = 0, oldmsgs = 0;
11188  char count[12], tmp[256] = "";
11189 
11190  if (!context || !strcmp(context, vmu->context)) {
11191  snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11192  inboxcount(tmp, &newmsgs, &oldmsgs);
11193  snprintf(count, sizeof(count), "%d", newmsgs);
11194  ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11195  users_counter++;
11196  }
11197  }
11199  ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11200  return CLI_SUCCESS;
11201 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char fullname[80]
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
list of users found in the config file
const char * line
Definition: cli.h:156
static char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
struct ast_vm_user::@65 list
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
char zonetag[80]
const char *const * argv
Definition: cli.h:155
#define HVSU_OUTPUT_FORMAT
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
static char * show_users_realtime(int fd, const char *context)
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
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 11204 of file app_voicemail.c.

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

11205 {
11206  struct vm_zone *zone;
11207 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11208  char *res = CLI_SUCCESS;
11209 
11210  switch (cmd) {
11211  case CLI_INIT:
11212  e->command = "voicemail show zones";
11213  e->usage =
11214  "Usage: voicemail show zones\n"
11215  " Lists zone message formats\n";
11216  return NULL;
11217  case CLI_GENERATE:
11218  return NULL;
11219  }
11220 
11221  if (a->argc != 3)
11222  return CLI_SHOWUSAGE;
11223 
11224  AST_LIST_LOCK(&zones);
11225  if (!AST_LIST_EMPTY(&zones)) {
11226  ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11227  AST_LIST_TRAVERSE(&zones, zone, list) {
11228  ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11229  }
11230  } else {
11231  ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11232  res = CLI_FAILURE;
11233  }
11235 
11236  return res;
11237 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char msg_format[512]
char name[80]
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char timezone[80]
Definition: cli.h:146
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
#define HVSZ_OUTPUT_FORMAT
struct vm_zone::@66 list
static int has_voicemail ( const char *  mailbox,
const char *  folder 
)
static

Determines if the given folder has messages.

Parameters
mailboxThe @ delimited string for user. If no context is found, uses 'default' for the context.
folderthe 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 5468 of file app_voicemail.c.

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

Referenced by load_module(), and vm_execmain().

5469 {
5470  char tmp[256], *tmp2 = tmp, *box, *context;
5471  ast_copy_string(tmp, mailbox, sizeof(tmp));
5472  if (ast_strlen_zero(folder)) {
5473  folder = "INBOX";
5474  }
5475  while ((box = strsep(&tmp2, ",&"))) {
5476  if ((context = strchr(box, '@')))
5477  *context++ = '\0';
5478  else
5479  context = "default";
5480  if (__has_voicemail(context, box, folder, 1))
5481  return 1;
5482  /* If we are checking INBOX, we should check Urgent as well */
5483  if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
5484  return 1;
5485  }
5486  }
5487  return 0;
5488 }
char * strsep(char **str, const char *delims)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static int inboxcount ( const char *  mailbox,
int *  newmsgs,
int *  oldmsgs 
)
static

Definition at line 5550 of file app_voicemail.c.

References inboxcount2().

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

5551 {
5552  int urgentmsgs = 0;
5553  int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
5554  if (newmsgs) {
5555  *newmsgs += urgentmsgs;
5556  }
5557  return res;
5558 }
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static int inboxcount2 ( const char *  mailbox,
int *  urgentmsgs,
int *  newmsgs,
int *  oldmsgs 
)
static

Definition at line 5491 of file app_voicemail.c.

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

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

5492 {
5493  char tmp[256];
5494  char *context;
5495 
5496  /* If no mailbox, return immediately */
5497  if (ast_strlen_zero(mailbox))
5498  return 0;
5499 
5500  if (newmsgs)
5501  *newmsgs = 0;
5502  if (oldmsgs)
5503  *oldmsgs = 0;
5504  if (urgentmsgs)
5505  *urgentmsgs = 0;
5506 
5507  if (strchr(mailbox, ',')) {
5508  int tmpnew, tmpold, tmpurgent;
5509  char *mb, *cur;
5510 
5511  ast_copy_string(tmp, mailbox, sizeof(tmp));
5512  mb = tmp;
5513  while ((cur = strsep(&mb, ", "))) {
5514  if (!ast_strlen_zero(cur)) {
5515  if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
5516  return -1;
5517  else {
5518  if (newmsgs)
5519  *newmsgs += tmpnew;
5520  if (oldmsgs)
5521  *oldmsgs += tmpold;
5522  if (urgentmsgs)
5523  *urgentmsgs += tmpurgent;
5524  }
5525  }
5526  }
5527  return 0;
5528  }
5529 
5530  ast_copy_string(tmp, mailbox, sizeof(tmp));
5531 
5532  if ((context = strchr(tmp, '@')))
5533  *context++ = '\0';
5534  else
5535  context = "default";
5536 
5537  if (newmsgs)
5538  *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
5539  if (oldmsgs)
5540  *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
5541  if (urgentmsgs)
5542  *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
5543 
5544  return 0;
5545 }
char * strsep(char **str, const char *delims)
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static int inbuf ( struct baseio bio,
FILE *  fi 
)
static

utility used by inchar(), for base_encode()

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

4251 {
4252  int l;
4253 
4254  if (bio->ateof)
4255  return 0;
4256 
4257  if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
4258  if (ferror(fi))
4259  return -1;
4260 
4261  bio->ateof = 1;
4262  return 0;
4263  }
4264 
4265  bio->iolen = l;
4266  bio->iocp = 0;
4267 
4268  return 1;
4269 }
unsigned char iobuf[BASEMAXINLINE]
#define BASEMAXINLINE
static int inchar ( struct baseio bio,
FILE *  fi 
)
static

utility used by base_encode()

Definition at line 4274 of file app_voicemail.c.

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

Referenced by base_encode().

4275 {
4276  if (bio->iocp>=bio->iolen) {
4277  if (!inbuf(bio, fi))
4278  return EOF;
4279  }
4280 
4281  return bio->iobuf[bio->iocp++];
4282 }
unsigned char iobuf[BASEMAXINLINE]
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static int inprocess_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 935 of file app_voicemail.c.

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

Referenced by load_module().

936 {
937  struct inprocess *i = obj, *j = arg;
938  if (strcmp(i->mailbox, j->mailbox)) {
939  return 0;
940  }
941  return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
942 }
char * context
char mailbox[0]
static int inprocess_count ( const char *  context,
const char *  mailbox,
int  delta 
)
static

Definition at line 944 of file app_voicemail.c.

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

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

945 {
946  struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
947  arg->context = arg->mailbox + strlen(mailbox) + 1;
948  strcpy(arg->mailbox, mailbox); /* SAFE */
949  strcpy(arg->context, context); /* SAFE */
951  if ((i = ao2_find(inprocess_container, arg, 0))) {
952  int ret = ast_atomic_fetchadd_int(&i->count, delta);
954  ao2_ref(i, -1);
955  return ret;
956  }
957  if (delta < 0) {
958  ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
959  }
960  if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
962  return 0;
963  }
964  i->context = i->mailbox + strlen(mailbox) + 1;
965  strcpy(i->mailbox, mailbox); /* SAFE */
966  strcpy(i->context, context); /* SAFE */
967  i->count = delta;
970  ao2_ref(i, -1);
971  return 0;
972 }
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define LOG_WARNING
Definition: logger.h:144
#define ao2_unlock(a)
Definition: astobj2.h:497
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
char * context
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
char mailbox[0]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
struct ao2_container * inprocess_container
static int inprocess_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 929 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

930 {
931  const struct inprocess *i = obj;
932  return atoi(i->mailbox);
933 }
char mailbox[0]
static int invent_message ( struct ast_channel chan,
char *  context,
char *  ext,
int  busy,
char *  ecodes 
)
static

Definition at line 5090 of file app_voicemail.c.

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

Referenced by leave_voicemail().

5091 {
5092  int res;
5093  char fn[PATH_MAX];
5094  char dest[PATH_MAX];
5095 
5096  snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
5097 
5098  if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
5099  ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
5100  return -1;
5101  }
5102 
5103  RETRIEVE(fn, -1, ext, context);
5104  if (ast_fileexists(fn, NULL, NULL) > 0) {
5105  res = ast_stream_and_wait(chan, fn, ecodes);
5106  if (res) {
5107  DISPOSE(fn, -1);
5108  return res;
5109  }
5110  } else {
5111  /* Dispose just in case */
5112  DISPOSE(fn, -1);
5113  res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
5114  if (res)
5115  return res;
5116  res = ast_say_digit_str(chan, ext, ecodes, chan->language);
5117  if (res)
5118  return res;
5119  }
5120  res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
5121  return res;
5122 }
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define AST_LOG_WARNING
Definition: logger.h:149
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8415
#define DISPOSE(a, b)
const char * ext
Definition: http.c:112
static char VM_SPOOL_DIR[PATH_MAX]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
#define RETRIEVE(a, b, c, d)
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
const ast_string_field language
Definition: channel.h:787
static int is_valid_dtmf ( const char *  key)
static

Determines if a DTMF key entered is valid.

Parameters
keyThe 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 1371 of file app_voicemail.c.

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

Referenced by actual_load_config().

1372 {
1373  int i;
1374  char *local_key = ast_strdupa(key);
1375 
1376  for (i = 0; i < strlen(key); ++i) {
1377  if (!strchr(VALID_DTMF, *local_key)) {
1378  ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
1379  return 0;
1380  }
1381  local_key++;
1382  }
1383  return 1;
1384 }
#define AST_LOG_WARNING
Definition: logger.h:149
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define VALID_DTMF
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
dirthe 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 4069 of file app_voicemail.c.

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

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

4070 {
4071  int x;
4072  unsigned char map[MAXMSGLIMIT] = "";
4073  DIR *msgdir;
4074  struct dirent *msgdirent;
4075  int msgdirint;
4076  char extension[4];
4077  int stopcount = 0;
4078 
4079  /* Reading the entire directory into a file map scales better than
4080  * doing a stat repeatedly on a predicted sequence. I suspect this
4081  * is partially due to stat(2) internally doing a readdir(2) itself to
4082  * find each file. */
4083  if (!(msgdir = opendir(dir))) {
4084  return -1;
4085  }
4086 
4087  while ((msgdirent = readdir(msgdir))) {
4088  if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
4089  map[msgdirint] = 1;
4090  stopcount++;
4091  ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4092  }
4093  }
4094  closedir(msgdir);
4095 
4096  for (x = 0; x < vmu->maxmsg; x++) {
4097  if (map[x] == 1) {
4098  stopcount--;
4099  } else if (map[x] == 0 && !stopcount) {
4100  break;
4101  }
4102  }
4103 
4104  return x - 1;
4105 }
static int * map
Definition: misdn_config.c:434
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define MAXMSGLIMIT
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
optionsOPT_BUSY_GREETING, OPT_UNAVAIL_GREETING
Returns
zero on success, -1 on error.

Definition at line 5626 of file app_voicemail.c.

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

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

5627 {
5628 #ifdef IMAP_STORAGE
5629  int newmsgs, oldmsgs;
5630 #else
5631  char urgdir[PATH_MAX];
5632 #endif
5633  char txtfile[PATH_MAX];
5634  char tmptxtfile[PATH_MAX];
5635  struct vm_state *vms = NULL;
5636  char callerid[256];
5637  FILE *txt;
5638  char date[256];
5639  int txtdes;
5640  int res = 0;
5641  int msgnum;
5642  int duration = 0;
5643  int sound_duration = 0;
5644  int ausemacro = 0;
5645  int ousemacro = 0;
5646  int ouseexten = 0;
5647  char tmpdur[16];
5648  char priority[16];
5649  char origtime[16];
5650  char dir[PATH_MAX];
5651  char tmpdir[PATH_MAX];
5652  char fn[PATH_MAX];
5653  char prefile[PATH_MAX] = "";
5654  char tempfile[PATH_MAX] = "";
5655  char ext_context[256] = "";
5656  char fmt[80];
5657  char *context;
5658  char ecodes[17] = "#";
5659  struct ast_str *tmp = ast_str_create(16);
5660  char *tmpptr;
5661  struct ast_vm_user *vmu;
5662  struct ast_vm_user svm;
5663  const char *category = NULL;
5664  const char *code;
5665  const char *alldtmf = "0123456789ABCD*#";
5666  char flag[80];
5667 
5668  if (!tmp) {
5669  return -1;
5670  }
5671 
5672  ast_str_set(&tmp, 0, "%s", ext);
5673  ext = ast_str_buffer(tmp);
5674  if ((context = strchr(ext, '@'))) {
5675  *context++ = '\0';
5676  tmpptr = strchr(context, '&');
5677  } else {
5678  tmpptr = strchr(ext, '&');
5679  }
5680 
5681  if (tmpptr)
5682  *tmpptr++ = '\0';
5683 
5684  ast_channel_lock(chan);
5685  if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
5686  category = ast_strdupa(category);
5687  }
5688  ast_channel_unlock(chan);
5689 
5690  if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
5691  ast_copy_string(flag, "Urgent", sizeof(flag));
5692  } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
5693  ast_copy_string(flag, "PRIORITY", sizeof(flag));
5694  } else {
5695  flag[0] = '\0';
5696  }
5697 
5698  ast_debug(3, "Before find_user\n");
5699  if (!(vmu = find_user(&svm, context, ext))) {
5700  ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
5701  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
5702  ast_free(tmp);
5703  return res;
5704  }
5705  /* Setup pre-file if appropriate */
5706  if (strcmp(vmu->context, "default"))
5707  snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
5708  else
5709  ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
5710 
5711  /* Set the path to the prefile. Will be one of
5712  VM_SPOOL_DIRcontext/ext/busy
5713  VM_SPOOL_DIRcontext/ext/unavail
5714  Depending on the flag set in options.
5715  */
5716  if (ast_test_flag(options, OPT_BUSY_GREETING)) {
5717  snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
5718  } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
5719  snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
5720  }
5721  /* Set the path to the tmpfile as
5722  VM_SPOOL_DIR/context/ext/temp
5723  and attempt to create the folder structure.
5724  */
5725  snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
5726  if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
5727  ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
5728  ast_free(tmp);
5729  return -1;
5730  }
5731  RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
5732  if (ast_fileexists(tempfile, NULL, NULL) > 0)
5733  ast_copy_string(prefile, tempfile, sizeof(prefile));
5734 
5735  DISPOSE(tempfile, -1);
5736  /* It's easier just to try to make it than to check for its existence */
5737 #ifndef IMAP_STORAGE
5738  create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
5739 #else
5740  snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
5741  if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
5742  ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
5743  }
5744 #endif
5745 
5746  /* Check current or macro-calling context for special extensions */
5747  if (ast_test_flag(vmu, VM_OPERATOR)) {
5748  if (!ast_strlen_zero(vmu->exit)) {
5749  if (ast_exists_extension(chan, vmu->exit, "o", 1,
5750  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5751  strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
5752  ouseexten = 1;
5753  }
5754  } else if (ast_exists_extension(chan, chan->context, "o", 1,
5755  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5756  strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
5757  ouseexten = 1;
5758  } else if (!ast_strlen_zero(chan->macrocontext)
5759  && ast_exists_extension(chan, chan->macrocontext, "o", 1,
5760  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5761  strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
5762  ousemacro = 1;
5763  }
5764  }
5765 
5766  if (!ast_strlen_zero(vmu->exit)) {
5767  if (ast_exists_extension(chan, vmu->exit, "a", 1,
5768  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5769  strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
5770  }
5771  } else if (ast_exists_extension(chan, chan->context, "a", 1,
5772  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5773  strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
5774  } else if (!ast_strlen_zero(chan->macrocontext)
5775  && ast_exists_extension(chan, chan->macrocontext, "a", 1,
5776  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5777  strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
5778  ausemacro = 1;
5779  }
5780 
5781  if (ast_test_flag(options, OPT_DTMFEXIT)) {
5782  for (code = alldtmf; *code; code++) {
5783  char e[2] = "";
5784  e[0] = *code;
5785  if (strchr(ecodes, e[0]) == NULL
5786  && ast_canmatch_extension(chan,
5787  (!ast_strlen_zero(options->exitcontext) ? options->exitcontext : chan->context),
5788  e, 1, S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
5789  strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
5790  }
5791  }
5792  }
5793 
5794  /* Play the beginning intro if desired */
5795  if (!ast_strlen_zero(prefile)) {
5796 #ifdef ODBC_STORAGE
5797  int success =
5798 #endif
5799  RETRIEVE(prefile, -1, ext, context);
5800  if (ast_fileexists(prefile, NULL, NULL) > 0) {
5801  if (ast_streamfile(chan, prefile, chan->language) > -1)
5802  res = ast_waitstream(chan, ecodes);
5803 #ifdef ODBC_STORAGE
5804  if (success == -1) {
5805  /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
5806  ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
5807  store_file(prefile, vmu->mailbox, vmu->context, -1);
5808  }
5809 #endif
5810  } else {
5811  ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
5812  res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
5813  }
5814  DISPOSE(prefile, -1);
5815  if (res < 0) {
5816  ast_debug(1, "Hang up during prefile playback\n");
5817  free_user(vmu);
5818  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
5819  ast_free(tmp);
5820  return -1;
5821  }
5822  }
5823  if (res == '#') {
5824  /* On a '#' we skip the instructions */
5825  ast_set_flag(options, OPT_SILENT);
5826  res = 0;
5827  }
5828  /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
5829  if (vmu->maxmsg == 0) {
5830  if (option_debug > 2)
5831  ast_log(LOG_DEBUG, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
5832  pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
5833  goto leave_vm_out;
5834  }
5835  if (!res && !ast_test_flag(options, OPT_SILENT)) {
5836  res = ast_stream_and_wait(chan, INTRO, ecodes);
5837  if (res == '#') {
5838  ast_set_flag(options, OPT_SILENT);
5839  res = 0;
5840  }
5841  }
5842  if (res > 0)
5843  ast_stopstream(chan);
5844  /* Check for a '*' here in case the caller wants to escape from voicemail to something
5845  other than the operator -- an automated attendant or mailbox login for example */
5846  if (res == '*') {
5847  chan->exten[0] = 'a';
5848  chan->exten[1] = '\0';
5849  if (!ast_strlen_zero(vmu->exit)) {
5850  ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
5851  } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
5852  ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
5853  }
5854  chan->priority = 0;
5855  free_user(vmu);
5856  pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
5857  ast_free(tmp);
5858  return 0;
5859  }
5860 
5861  /* Check for a '0' here */
5862  if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
5863  transfer:
5864  if (ouseexten || ousemacro) {
5865  chan->exten[0] = 'o';
5866  chan->exten[1] = '\0';
5867  if (!ast_strlen_zero(vmu->exit)) {
5868  ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
5869  } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
5870  ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
5871  }
5872  ast_play_and_wait(chan, "transfer");
5873  chan->priority = 0;
5874  free_user(vmu);
5875  pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
5876  }
5877  ast_free(tmp);
5878  return OPERATOR_EXIT;
5879  }
5880 
5881  /* Allow all other digits to exit Voicemail and return to the dialplan */
5882  if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
5883  if (!ast_strlen_zero(options->exitcontext)) {
5884  ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
5885  }
5886  free_user(vmu);
5887  ast_free(tmp);
5888  pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
5889  return res;
5890  }
5891 
5892  if (res < 0) {
5893  free_user(vmu);
5894  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
5895  ast_free(tmp);
5896  return -1;
5897  }
5898  /* The meat of recording the message... All the announcements and beeps have been played*/
5899  ast_copy_string(fmt, vmfmts, sizeof(fmt));
5900  if (!ast_strlen_zero(fmt)) {
5901  msgnum = 0;
5902 
5903 #ifdef IMAP_STORAGE
5904  /* Is ext a mailbox? */
5905  /* must open stream for this user to get info! */
5906  res = inboxcount(ext_context, &newmsgs, &oldmsgs);
5907  if (res < 0) {
5908  ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
5909  ast_free(tmp);
5910  return -1;
5911  }
5912  if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
5913  /* It is possible under certain circumstances that inboxcount did not
5914  * create a vm_state when it was needed. This is a catchall which will
5915  * rarely be used.
5916  */
5917  if (!(vms = create_vm_state_from_user(vmu))) {
5918  ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
5919  ast_free(tmp);
5920  return -1;
5921  }
5922  }
5923  vms->newmessages++;
5924 
5925  /* here is a big difference! We add one to it later */
5926  msgnum = newmsgs + oldmsgs;
5927  ast_debug(3, "Messagecount set to %d\n", msgnum);
5928  snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
5929  /* set variable for compatibility */
5930  pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
5931 
5932  if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
5933  goto leave_vm_out;
5934  }
5935 #else
5936  if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
5937  res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
5938  if (!res)
5939  res = ast_waitstream(chan, "");
5940  ast_log(AST_LOG_WARNING, "No more messages possible\n");
5941  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
5942  inprocess_count(vmu->mailbox, vmu->context, -1);
5943  goto leave_vm_out;
5944  }
5945 
5946 #endif
5947  snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
5948  txtdes = mkstemp(tmptxtfile);
5949  chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
5950  if (txtdes < 0) {
5951  res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
5952  if (!res)
5953  res = ast_waitstream(chan, "");
5954  ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
5955  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
5956  inprocess_count(vmu->mailbox, vmu->context, -1);
5957  goto leave_vm_out;
5958  }
5959 
5960  /* Now play the beep once we have the message number for our next message. */
5961  if (res >= 0) {
5962  /* Unless we're *really* silent, try to send the beep */
5963  res = ast_stream_and_wait(chan, "beep", "");
5964  }
5965 
5966  /* Store information in real-time storage */
5967  if (ast_check_realtime("voicemail_data")) {
5968  snprintf(priority, sizeof(priority), "%d", chan->priority);
5969  snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
5970  get_date(date, sizeof(date));
5971  ast_callerid_merge(callerid, sizeof(callerid),
5972  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
5973  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
5974  "Unknown");
5975  ast_store_realtime("voicemail_data",
5976  "origmailbox", ext,
5977  "context", chan->context,
5978  "macrocontext", chan->macrocontext,
5979  "exten", chan->exten,
5980  "priority", priority,
5981  "callerchan", chan->name,
5982  "callerid", callerid,
5983  "origdate", date,
5984  "origtime", origtime,
5985  "category", S_OR(category, ""),
5986  "filename", tmptxtfile,
5987  SENTINEL);
5988  }
5989 
5990  /* Store information */
5991  txt = fdopen(txtdes, "w+");
5992  if (txt) {
5993  get_date(date, sizeof(date));
5994  ast_callerid_merge(callerid, sizeof(callerid),
5995  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
5996  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
5997  "Unknown");
5998  fprintf(txt,
5999  ";\n"
6000  "; Message Information file\n"
6001  ";\n"
6002  "[message]\n"
6003  "origmailbox=%s\n"
6004  "context=%s\n"
6005  "macrocontext=%s\n"
6006  "exten=%s\n"
6007  "rdnis=%s\n"
6008  "priority=%d\n"
6009  "callerchan=%s\n"
6010  "callerid=%s\n"
6011  "origdate=%s\n"
6012  "origtime=%ld\n"
6013  "category=%s\n",
6014  ext,
6015  chan->context,
6016  chan->macrocontext,
6017  chan->exten,
6019  chan->redirecting.from.number.str, "unknown"),
6020  chan->priority,
6021  chan->name,
6022  callerid,
6023  date, (long) time(NULL),
6024  category ? category : "");
6025  } else {
6026  ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
6027  inprocess_count(vmu->mailbox, vmu->context, -1);
6028  if (ast_check_realtime("voicemail_data")) {
6029  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
6030  }
6031  res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
6032  goto leave_vm_out;
6033  }
6034  res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag);
6035 
6036  if (txt) {
6037  fprintf(txt, "flag=%s\n", flag);
6038  if (sound_duration < vmu->minsecs) {
6039  fclose(txt);
6040  ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->minsecs);
6041  ast_filedelete(tmptxtfile, NULL);
6042  unlink(tmptxtfile);
6043  if (ast_check_realtime("voicemail_data")) {
6044  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
6045  }
6046  inprocess_count(vmu->mailbox, vmu->context, -1);
6047  } else {
6048  fprintf(txt, "duration=%d\n", duration);
6049  fclose(txt);
6050  if (vm_lock_path(dir)) {
6051  ast_log(AST_LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6052  /* Delete files */
6053  ast_filedelete(tmptxtfile, NULL);
6054  unlink(tmptxtfile);
6055  inprocess_count(vmu->mailbox, vmu->context, -1);
6056  } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
6057  ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
6058  unlink(tmptxtfile);
6059  ast_unlock_path(dir);
6060  inprocess_count(vmu->mailbox, vmu->context, -1);
6061  if (ast_check_realtime("voicemail_data")) {
6062  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
6063  }
6064  } else {
6065 #ifndef IMAP_STORAGE
6066  msgnum = last_message_index(vmu, dir) + 1;
6067 #endif
6068  make_file(fn, sizeof(fn), dir, msgnum);
6069 
6070  /* assign a variable with the name of the voicemail file */
6071 #ifndef IMAP_STORAGE
6072  pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
6073 #else
6074  pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
6075 #endif
6076 
6077  snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
6078  ast_filerename(tmptxtfile, fn, NULL);
6079  rename(tmptxtfile, txtfile);
6080  inprocess_count(vmu->mailbox, vmu->context, -1);
6081 
6082  /* Properly set permissions on voicemail text descriptor file.
6083  Unfortunately mkstemp() makes this file 0600 on most unix systems. */
6084  if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
6085  ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
6086 
6087  ast_unlock_path(dir);
6088  if (ast_check_realtime("voicemail_data")) {
6089  snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
6090  ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
6091  }
6092  /* We must store the file first, before copying the message, because
6093  * ODBC storage does the entire copy with SQL.
6094  */
6095  if (ast_fileexists(fn, NULL, NULL) > 0) {
6096  STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
6097  }
6098 
6099  /* Are there to be more recipients of this message? */
6100  while (tmpptr) {
6101  struct ast_vm_user recipu, *recip;
6102  char *exten, *cntx;
6103 
6104  exten = strsep(&tmpptr, "&");
6105  cntx = strchr(exten, '@');
6106  if (cntx) {
6107  *cntx = '\0';
6108  cntx++;
6109  }
6110  if ((recip = find_user(&recipu, cntx, exten))) {
6111  copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
6112  free_user(recip);
6113  }
6114  }
6115 #ifndef IMAP_STORAGE
6116  if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
6117  /* Move the message from INBOX to Urgent folder if this is urgent! */
6118  char sfn[PATH_MAX];
6119  char dfn[PATH_MAX];
6120  int x;
6121  /* It's easier just to try to make it than to check for its existence */
6122  create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
6123  x = last_message_index(vmu, urgdir) + 1;
6124  make_file(sfn, sizeof(sfn), dir, msgnum);
6125  make_file(dfn, sizeof(dfn), urgdir, x);
6126  ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
6127  RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
6128  /* Notification must happen for this new message in Urgent folder, not INBOX */
6129  ast_copy_string(fn, dfn, sizeof(fn));
6130  msgnum = x;
6131  }
6132 #endif
6133  /* Notification needs to happen after the copy, though. */
6134  if (ast_fileexists(fn, NULL, NULL)) {
6135 #ifdef IMAP_STORAGE
6136  notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
6137  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
6138  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
6139  flag);
6140 #else
6141  notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
6142  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
6143  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
6144  flag);
6145 #endif
6146  }
6147 
6148  /* Disposal needs to happen after the optional move and copy */
6149  if (ast_fileexists(fn, NULL, NULL)) {
6150  DISPOSE(dir, msgnum);
6151  }
6152  }
6153  }
6154  } else {
6155  inprocess_count(vmu->mailbox, vmu->context, -1);
6156  }
6157  if (res == '0') {
6158  goto transfer;
6159  } else if (res > 0 && res != 't')
6160  res = 0;
6161 
6162  if (sound_duration < vmu->minsecs)
6163  /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
6164  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
6165  else
6166  pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
6167  } else
6168  ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
6169 leave_vm_out:
6170  free_user(vmu);
6171 
6172 #ifdef IMAP_STORAGE
6173  /* expunge message - use UID Expunge if supported on IMAP server*/
6174  ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
6175  if (expungeonhangup == 1) {
6176  ast_mutex_lock(&vms->lock);
6177 #ifdef HAVE_IMAP_TK2006
6178  if (LEVELUIDPLUS (vms->mailstream)) {
6179  mail_expunge_full(vms->mailstream, NIL, EX_UID);
6180  } else
6181 #endif
6182  mail_expunge(vms->mailstream);
6183  ast_mutex_unlock(&vms->lock);
6184  }
6185 #endif
6186 
6187  ast_free(tmp);
6188  return res;
6189 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
Definition: config.c:2726
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
char * strsep(char **str, const char *delims)
int priority
Definition: channel.h:841
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define ast_test_flag(p, flag)
Definition: utils.h:63
int option_debug
Definition: asterisk.c:182
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:449
char fn[PATH_MAX]
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
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.
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
#define AST_LOG_WARNING
Definition: logger.h:149
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
char * str
Subscriber name (Malloced)
Definition: channel.h:214
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
#define INTRO
#define ast_mutex_lock(a)
Definition: lock.h:155
static int inprocess_count(const char *context, const char *mailbox, int delta)
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:931
#define DISPOSE(a, b)
#define LOG_DEBUG
Definition: logger.h:122
const char * ext
Definition: http.c:112
#define ast_verb(level,...)
Definition: logger.h:243
static int transfer
Definition: chan_mgcp.c:187
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:5415
static int get_date(char *s, int len)
Gets the current date and time, as formatted string.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
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 appropria...
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: config.c:2679
#define AST_LOG_NOTICE
Definition: logger.h:138
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define SENTINEL
Definition: compiler.h:75
#define AST_LOG_ERROR
Definition: logger.h:160
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1074
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
Definition: config.c:2750
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
static int my_umask
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
char context[AST_MAX_CONTEXT]
static char VM_SPOOL_DIR[PATH_MAX]
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
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 void free_user(struct ast_vm_user *vmu)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define VM_OPERATOR
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
#define RENAME(a, b, c, d, e, f, g, h)
#define OPERATOR_EXIT
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
char exit[80]
#define VOICEMAIL_DIR_MODE
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.
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
int errno
#define ast_free(a)
Definition: astmm.h:97
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
#define STORE(a, b, c, d, e, f, g, h, i, j)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
#define RETRIEVE(a, b, c, d)
signed char record_gain
Definition: app_minivm.c:637
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
#define VOICEMAIL_FILE_MODE
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:936
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char vmfmts[80]
int newmessages
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
const ast_string_field language
Definition: channel.h:787
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define ast_mutex_unlock(a)
Definition: lock.h:156
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int load_config ( int  reload)
static

Definition at line 11783 of file app_voicemail.c.

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

Referenced by handle_voicemail_reload(), load_module(), and reload().

11784 {
11785  struct ast_config *cfg, *ucfg;
11786  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11787  int res;
11788 
11789  ast_unload_realtime("voicemail");
11790  ast_unload_realtime("voicemail_data");
11791 
11792  if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11793  if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11794  return 0;
11795  } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11796  ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
11797  ucfg = NULL;
11798  }
11799  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11800  if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11801  ast_config_destroy(ucfg);
11802  ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
11803  return 0;
11804  }
11805  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11806  ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
11807  return 0;
11808  } else {
11809  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11810  if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11811  ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
11812  ucfg = NULL;
11813  }
11814  }
11815 
11816  res = actual_load_config(reload, cfg, ucfg);
11817 
11818  ast_config_destroy(cfg);
11819  ast_config_destroy(ucfg);
11820 
11821  return res;
11822 }
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: config.c:2630
static int reload(void)
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define VOICEMAIL_CONFIG
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int load_module ( void  )
static

Definition at line 13084 of file app_voicemail.c.

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

13085 {
13086  int res;
13087  my_umask = umask(0);
13088  umask(my_umask);
13089 
13091  return AST_MODULE_LOAD_DECLINE;
13092  }
13093 
13094  /* compute the location of the voicemail spool directory */
13095  snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13096 
13097  if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13098  ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor. MWI will not work\n");
13099  }
13100 
13101  if ((res = load_config(0)))
13102  return res;
13103 
13111 #ifdef TEST_FRAMEWORK
13112  res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13113  res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13114  res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13115  res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13116  res |= AST_TEST_REGISTER(test_voicemail_load_config);
13117 #endif
13118 
13119  if (res)
13120  return res;
13121 
13124 
13126  ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13127  ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13128 
13129  return res;
13130 }
static int load_config(int reload)
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
Manager list voicemail users command.
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
#define AST_LOG_WARNING
Definition: logger.h:149
static struct ast_data_entry vm_data_providers[]
static int vm_box_exists(struct ast_channel *chan, const char *data)
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static int messagecount(const char *context, const char *mailbox, const char *folder)
Definition: config.h:68
static char * sayname_app
static int inprocess_hash_fn(const void *obj, const int flags)
#define SENTINEL
Definition: compiler.h:75
static struct ast_custom_function mailbox_exists_acf
static int vmsayname_exec(struct ast_channel *chan, const char *data)
static char * app
static int vm_execmain(struct ast_channel *chan, const char *data)
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
static int my_umask
static char VM_SPOOL_DIR[PATH_MAX]
#define ast_data_register_multiple(data_entries, entries)
Definition: data.h:377
static struct ast_taskprocessor * mwi_subscription_tps
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_cli_entry cli_voicemail[]
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
static char * app2
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: config.c:2606
void ast_install_vm_functions(int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), int(*inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs), int(*messagecount_func)(const char *context, const char *mailbox, const char *folder), int(*sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context))
Set voicemail function callbacks.
Definition: app.c:399
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
static char * app3
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
static char * app4
static int vm_exec(struct ast_channel *chan, const char *data)
static int vmauthenticate(struct ast_channel *chan, const char *data)
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
struct ao2_container * inprocess_container
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
destThe variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
lenThe 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 1652 of file app_voicemail.c.

Referenced by copy_message(), create_dirpath(), make_email_file(), manager_list_voicemail_users(), notify_new_message(), and prep_email_sub_vars().

1653 {
1654  return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
1655 }
const char * ext
Definition: http.c:112
static char VM_SPOOL_DIR[PATH_MAX]
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
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
pThe output file to generate the email contents into.
srcemailThe email address to send the email to, presumably the email address for the owner of the mailbox.
vmuThe voicemail user who is sending the voicemail.
msgnumThe message index in the mailbox folder.
context
mailboxThe voicemail box to read the voicemail to be notified in this email.
fromfolder
cidnumThe caller ID number.
cidnameThe caller ID name.
attachthe name of the sound file to be attached to the email, if attach_user_voicemail == 1.
attach2
formatThe message sound file format. i.e. .wav
durationThe time of the message content, in seconds.
attach_user_voicemailif 1, the sound file is attached to the email.
chan
category
imapif == 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.
flagThe 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 4567 of file app_voicemail.c.

References add_email_attachment(), ast_channel_unref, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_localtime(), ast_log(), AST_LOG_WARNING, ast_random(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime(), ast_strftime_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, ast_vm_user::emailsubject, emailsubject, ENDL, first_line, ast_vm_user::fullname, 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(), valid_config(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

4568 {
4569  char date[256];
4570  char host[MAXHOSTNAMELEN] = "";
4571  char who[256];
4572  char bound[256];
4573  char dur[256];
4574  struct ast_tm tm;
4575  char enc_cidnum[256] = "", enc_cidname[256] = "";
4576  struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
4577  char *greeting_attachment;
4578  char filename[256];
4579 
4580  if (!str1 || !str2) {
4581  ast_free(str1);
4582  ast_free(str2);
4583  return;
4584  }
4585 
4586  if (cidnum) {
4587  strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
4588  }
4589  if (cidname) {
4590  strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
4591  }
4592  gethostname(host, sizeof(host) - 1);
4593 
4594  if (strchr(srcemail, '@')) {
4595  ast_copy_string(who, srcemail, sizeof(who));
4596  } else {
4597  snprintf(who, sizeof(who), "%s@%s", srcemail, host);
4598  }
4599 
4600  greeting_attachment = strrchr(ast_strdupa(attach), '/');
4601  if (greeting_attachment) {
4602  *greeting_attachment++ = '\0';
4603  }
4604 
4605  snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
4606  ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
4607  fprintf(p, "Date: %s" ENDL, date);
4608 
4609  /* Set date format for voicemail mail */
4610  ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
4611 
4612  if (!ast_strlen_zero(fromstring)) {
4613  struct ast_channel *ast;
4614  if ((ast = ast_dummy_channel_alloc())) {
4615  char *ptr;
4616  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
4617  ast_str_substitute_variables(&str1, 0, ast, fromstring);
4618 
4619  if (check_mime(ast_str_buffer(str1))) {
4620  int first_line = 1;
4621  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
4622  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
4623  *ptr = '\0';
4624  fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
4625  first_line = 0;
4626  /* Substring is smaller, so this will never grow */
4627  ast_str_set(&str2, 0, "%s", ptr + 1);
4628  }
4629  fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
4630  } else {
4631  fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
4632  }
4633  ast = ast_channel_unref(ast);
4634  } else {
4635  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
4636  }
4637  } else {
4638  fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
4639  }
4640 
4641  if (check_mime(vmu->fullname)) {
4642  int first_line = 1;
4643  char *ptr;
4644  ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
4645  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
4646  *ptr = '\0';
4647  fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
4648  first_line = 0;
4649  /* Substring is smaller, so this will never grow */
4650  ast_str_set(&str2, 0, "%s", ptr + 1);
4651  }
4652  fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
4653  } else {
4654  fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
4655  }
4656 
4658  char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
4659  struct ast_channel *ast;
4660  if ((ast = ast_dummy_channel_alloc())) {
4661  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
4662  ast_str_substitute_variables(&str1, 0, ast, e_subj);
4663  if (check_mime(ast_str_buffer(str1))) {
4664  int first_line = 1;
4665  char *ptr;
4666  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
4667  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
4668  *ptr = '\0';
4669  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
4670  first_line = 0;
4671  /* Substring is smaller, so this will never grow */
4672  ast_str_set(&str2, 0, "%s", ptr + 1);
4673  }
4674  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
4675  } else {
4676  fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
4677  }
4678  ast = ast_channel_unref(ast);
4679  } else {
4680  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
4681  }
4682  } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
4683  if (ast_strlen_zero(flag)) {
4684  fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
4685  } else {
4686  fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
4687  }
4688  } else {
4689  if (ast_strlen_zero(flag)) {
4690  fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
4691  } else {
4692  fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
4693  }
4694  }
4695 
4696  fprintf(p, "Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
4697  (unsigned int) ast_random(), mailbox, (int) getpid(), host);
4698  if (imap) {
4699  /* additional information needed for IMAP searching */
4700  fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
4701  /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
4702  fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
4703  fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
4704 #ifdef IMAP_STORAGE
4705  fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
4706 #else
4707  fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
4708 #endif
4709  /* flag added for Urgent */
4710  fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
4711  fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
4712  fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
4713  fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
4714  fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
4715  fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
4716  if (!ast_strlen_zero(category)) {
4717  fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
4718  } else {
4719  fprintf(p, "X-Asterisk-VM-Category: " ENDL);
4720  }
4721  fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
4722  fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
4723  fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
4724  }
4725  if (!ast_strlen_zero(cidnum)) {
4726  fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
4727  }
4728  if (!ast_strlen_zero(cidname)) {
4729  fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
4730  }
4731  fprintf(p, "MIME-Version: 1.0" ENDL);
4732  if (attach_user_voicemail) {
4733  /* Something unique. */
4734  snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%u", msgnum + 1, mailbox,
4735  (int) getpid(), (unsigned int) ast_random());
4736 
4737  fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
4738  fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
4739  fprintf(p, "--%s" ENDL, bound);
4740  }
4741  fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
4742  if (emailbody || vmu->emailbody) {
4743  char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
4744  struct ast_channel *ast;
4745  if ((ast = ast_dummy_channel_alloc())) {
4746  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
4747  ast_str_substitute_variables(&str1, 0, ast, e_body);
4748 #ifdef IMAP_STORAGE
4749  {
4750  /* Convert body to native line terminators for IMAP backend */
4751  char *line = ast_str_buffer(str1), *next;
4752  do {
4753  /* Terminate line before outputting it to the file */
4754  if ((next = strchr(line, '\n'))) {
4755  *next++ = '\0';
4756  }
4757  fprintf(p, "%s" ENDL, line);
4758  line = next;
4759  } while (!ast_strlen_zero(line));
4760  }
4761 #else
4762  fprintf(p, "%s" ENDL, ast_str_buffer(str1));
4763 #endif
4764  ast = ast_channel_unref(ast);
4765  } else {
4766  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
4767  }
4768  } else if (msgnum > -1) {
4769  if (strcmp(vmu->mailbox, mailbox)) {
4770  /* Forwarded type */
4771  struct ast_config *msg_cfg;
4772  const char *v;
4773  int inttime;
4774  char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
4775  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
4776  /* Retrieve info from VM attribute file */
4777  make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
4778  make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
4779  if (strlen(fromfile) < sizeof(fromfile) - 5) {
4780  strcat(fromfile, ".txt");
4781  }
4782  if ((msg_cfg = ast_config_load(fromfile, config_flags)) && valid_config(msg_cfg)) {
4783  if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
4784  ast_copy_string(origcallerid, v, sizeof(origcallerid));
4785  }
4786 
4787  /* You might be tempted to do origdate, except that a) it's in the wrong
4788  * format, and b) it's missing for IMAP recordings. */
4789  if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
4790  struct timeval tv = { inttime, };
4791  struct ast_tm tm;
4792  ast_localtime(&tv, &tm, NULL);
4793  ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
4794  }
4795  fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
4796  " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
4797  "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
4798  " chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
4799  msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
4800  date, origcallerid, origdate);
4801  ast_config_destroy(msg_cfg);
4802  } else {
4803  goto plain_message;
4804  }
4805  } else {
4806 plain_message:
4807  fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
4808  "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
4809  "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
4810  ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
4811  (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
4812  }
4813  } else {
4814  fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
4815  "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
4816  }
4817 
4818  if (imap || attach_user_voicemail) {
4819  if (!ast_strlen_zero(attach2)) {
4820  snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
4821  ast_debug(5, "creating second attachment filename %s\n", filename);
4822  add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
4823  snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
4824  ast_debug(5, "creating attachment filename %s\n", filename);
4825  add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
4826  } else {
4827  snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
4828  ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
4829  add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
4830  }
4831  }
4832  ast_free(str1);
4833  ast_free(str2);
4834 }
Main Channel structure associated with a channel.
Definition: channel.h:742
char fullname[80]
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
int priority
Definition: channel.h:841
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define ast_test_flag(p, flag)
Definition: utils.h:63
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 appropria...
static struct ast_tm * vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
fill in *tm for current time according to the proper timezone, if any.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define AST_LOG_WARNING
Definition: logger.h:149
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
#define MAXHOSTNAMELEN
Definition: network.h:69
static int check_mime(const char *str)
Check if the string would need encoding within the MIME standard, to avoid confusing certain mail sof...
static char * emailsubject
char locale[20]
static char fromstring[100]
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
char * emailsubject
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 appropria...
static char * emailbody
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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.
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static struct ast_flags globalflags
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
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)
char context[AST_MAX_CONTEXT]
long int ast_random(void)
Definition: utils.c:1640
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2280
#define ENDL
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...
#define VM_PBXSKIP
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
char * emailbody
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
static char emaildateformat[32]
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
Structure used to handle boolean flags.
Definition: utils.h:200
static char charset[32]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct timeval tv
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
Definition: channel.c:1391
static snd_pcm_format_t format
Definition: chan_alsa.c:93
char email[80]
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 ...
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
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 char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
yylloc first_line
Definition: ast_expr2.c:1857
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
destThe variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
lenThe 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 1669 of file app_voicemail.c.

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

1670 {
1671  return snprintf(dest, len, "%s/msg%04d", dir, num);
1672 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int manager_list_voicemail_users ( struct mansession s,
const struct message m 
)
static

Manager list voicemail users command.

Definition at line 11614 of file app_voicemail.c.

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

11615 {
11616  struct ast_vm_user *vmu = NULL;
11617  const char *id = astman_get_header(m, "ActionID");
11618  char actionid[128] = "";
11619 
11620  if (!ast_strlen_zero(id))
11621  snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11622 
11623  AST_LIST_LOCK(&users);
11624 
11625  if (AST_LIST_EMPTY(&users)) {
11626  astman_send_ack(s, m, "There are no voicemail users currently defined.");
11628  return RESULT_SUCCESS;
11629  }
11630 
11631  astman_send_ack(s, m, "Voicemail user list will follow");
11632 
11633  AST_LIST_TRAVERSE(&users, vmu, list) {
11634  char dirname[256];
11635 
11636 #ifdef IMAP_STORAGE
11637  int new, old;
11638  inboxcount(vmu->mailbox, &new, &old);
11639 #endif
11640 
11641  make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11642  astman_append(s,
11643  "%s"
11644  "Event: VoicemailUserEntry\r\n"
11645  "VMContext: %s\r\n"
11646  "VoiceMailbox: %s\r\n"
11647  "Fullname: %s\r\n"
11648  "Email: %s\r\n"
11649  "Pager: %s\r\n"
11650  "ServerEmail: %s\r\n"
11651  "MailCommand: %s\r\n"
11652  "Language: %s\r\n"
11653  "TimeZone: %s\r\n"
11654  "Callback: %s\r\n"
11655  "Dialout: %s\r\n"
11656  "UniqueID: %s\r\n"
11657  "ExitContext: %s\r\n"
11658  "SayDurationMinimum: %d\r\n"
11659  "SayEnvelope: %s\r\n"
11660  "SayCID: %s\r\n"
11661  "AttachMessage: %s\r\n"
11662  "AttachmentFormat: %s\r\n"
11663  "DeleteMessage: %s\r\n"
11664  "VolumeGain: %.2f\r\n"
11665  "CanReview: %s\r\n"
11666  "CallOperator: %s\r\n"
11667  "MaxMessageCount: %d\r\n"
11668  "MaxMessageLength: %d\r\n"
11669  "NewMessageCount: %d\r\n"
11670 #ifdef IMAP_STORAGE
11671  "OldMessageCount: %d\r\n"
11672  "IMAPUser: %s\r\n"
11673 #endif
11674  "\r\n",
11675  actionid,
11676  vmu->context,
11677  vmu->mailbox,
11678  vmu->fullname,
11679  vmu->email,
11680  vmu->pager,
11682  mailcmd,
11683  vmu->language,
11684  vmu->zonetag,
11685  vmu->callback,
11686  vmu->dialout,
11687  vmu->uniqueid,
11688  vmu->exit,
11689  vmu->saydurationm,
11690  ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11691  ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11692  ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11693  vmu->attachfmt,
11694  ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11695  vmu->volgain,
11696  ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11697  ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11698  vmu->maxmsg,
11699  vmu->maxsecs,
11700 #ifdef IMAP_STORAGE
11701  new, old, vmu->imapuser
11702 #else
11703  count_messages(vmu, dirname)
11704 #endif
11705  );
11706  }
11707  astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11708 
11710 
11711  return RESULT_SUCCESS;
11712 }
double volgain
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char uniqueid[80]
char fullname[80]
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
static char mailcmd[160]
char attachfmt[20]
#define ast_test_flag(p, flag)
Definition: utils.h:63
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 appropria...
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
#define VM_ATTACH
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
list of users found in the config file
#define VM_SAYCID
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
#define VM_ENVELOPE
#define VM_DELETE
struct ast_vm_user::@65 list
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
char zonetag[80]
#define VM_OPERATOR
char pager[80]
#define VM_REVIEW
char exit[80]
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char language[MAX_LANGUAGE]
char dialout[80]
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
char callback[80]
char serveremail[80]
#define RESULT_SUCCESS
Definition: cli.h:39
char email[80]
static char serveremail[80]
static void* mb_poll_thread ( void *  data)
static

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

11436 {
11437  while (poll_thread_run) {
11438  struct timespec ts = { 0, };
11439  struct timeval wait;
11440 
11441  wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11442  ts.tv_sec = wait.tv_sec;
11443  ts.tv_nsec = wait.tv_usec * 1000;
11444 
11448 
11449  if (!poll_thread_run)
11450  break;
11451 
11453  }
11454 
11455  return NULL;
11456 }
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_mutex_lock(a)
Definition: lock.h:155
static ast_cond_t poll_cond
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:191
static ast_mutex_t poll_lock
static void poll_subscribed_mailboxes(void)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: utils.c:1587
static unsigned char poll_thread_run
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:172
static unsigned int poll_freq
#define ast_mutex_unlock(a)
Definition: lock.h:156
static const char* mbox ( struct ast_vm_user vmu,
int  id 
)
static

Definition at line 1730 of file app_voicemail.c.

References ARRAY_LEN, and id.

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

1731 {
1732 #ifdef IMAP_STORAGE
1733  if (vmu && id == 0) {
1734  return vmu->imapfolder;
1735  }
1736 #endif
1737  return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
1738 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char *const mailbox_folders[]
enum queue_result id
Definition: app_queue.c:1090
static int messagecount ( const char *  context,
const char *  mailbox,
const char *  folder 
)
static

Definition at line 5417 of file app_voicemail.c.

References __has_voicemail().

Referenced by load_module().

5418 {
5419  return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
5420 }
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static void mwi_sub_destroy ( struct mwi_sub mwi_sub)
static

Definition at line 11458 of file app_voicemail.c.

References ast_free.

Referenced by handle_unsubscribe().

11459 {
11460  ast_free(mwi_sub);
11461 }
#define ast_free(a)
Definition: astmm.h:97
static void mwi_sub_event_cb ( const struct ast_event event,
void *  userdata 
)
static

Definition at line 11546 of file app_voicemail.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_SUB, ast_free, ast_log(), ast_strdup, ast_taskprocessor_push(), mwi_sub_task::context, handle_subscribe(), LOG_ERROR, mwi_sub_task::mailbox, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

11547 {
11548  struct mwi_sub_task *mwist;
11549 
11550  if (ast_event_get_type(event) != AST_EVENT_SUB)
11551  return;
11552 
11554  return;
11555 
11556  if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11557  ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11558  return;
11559  }
11563 
11565  ast_free(mwist);
11566  }
11567 }
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
Definition: event.c:1070
#define ast_strdup(a)
Definition: astmm.h:109
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static int handle_subscribe(void *datap)
const char * context
const char * mailbox
Context IE Used by AST_EVENT_MWI Payload type: str.
Definition: event_defs.h:121
uint32_t uniqueid
Event type Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
Definition: event_defs.h:95
static struct ast_taskprocessor * mwi_subscription_tps
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
#define ast_calloc(a, b)
Definition: astmm.h:82
Unique ID Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
Definition: event_defs.h:89
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
Definition: event.c:1102
Mailbox name.
Definition: event_defs.h:83
static void mwi_unsub_event_cb ( const struct ast_event event,
void *  userdata 
)
static

Definition at line 11520 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_log(), ast_taskprocessor_push(), handle_unsubscribe(), LOG_ERROR, and mwi_sub_task::uniqueid.

Referenced by start_poll_thread().

11521 {
11522  uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11523 
11524  if (!uniqueid) {
11525  ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11526  return;
11527  }
11528 
11529  if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11530  ast_free(uniqueid);
11531  return;
11532  }
11533 
11535  ast_free(uniqueid);
11536  return;
11537  }
11538 
11540  *uniqueid = u;
11542  ast_free(uniqueid);
11543  }
11544 }
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
Definition: event.c:1070
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static int handle_unsubscribe(void *datap)
uint32_t uniqueid
Event type Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
Definition: event_defs.h:95
static struct ast_taskprocessor * mwi_subscription_tps
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
#define ast_calloc(a, b)
Definition: astmm.h:82
Unique ID Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
Definition: event_defs.h:89
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
cidnumThe Caller ID phone number value.
cidnameThe Caller ID name value.
flag
Returns
zero on success, -1 on error.

Definition at line 7103 of file app_voicemail.c.

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_unlock, ast_log(), AST_LOG_WARNING, ast_manager_event, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_vm_user::attachfmt, ast_vm_user::context, vm_state::curmsg, DELETE, DISPOSE, ast_vm_user::email, EVENT_FLAG_CALL, ast_vm_user::mailbox, make_dir(), make_file(), mbox(), vm_state::newmessages, ast_vm_user::pager, pbx_builtin_getvar_helper(), queue_mwi_event(), RETRIEVE, run_externnotify(), sendmail(), sendpage(), ast_vm_user::serveremail, serveremail, strsep(), VM_ATTACH, VM_DELETE, and vm_delete().

Referenced by copy_message(), and leave_voicemail().

7104 {
7105  char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
7106  int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
7107  const char *category;
7108  char *myserveremail = serveremail;
7109 
7110  ast_channel_lock(chan);
7111  if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
7112  category = ast_strdupa(category);
7113  }
7114  ast_channel_unlock(chan);
7115 
7116 #ifndef IMAP_STORAGE
7117  make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
7118 #else
7119  snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
7120 #endif
7121  make_file(fn, sizeof(fn), todir, msgnum);
7122  snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
7123 
7124  if (!ast_strlen_zero(vmu->attachfmt)) {
7125  if (strstr(fmt, vmu->attachfmt))
7126  fmt = vmu->attachfmt;
7127  else
7128  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);
7129  }
7130 
7131  /* Attach only the first format */
7132  fmt = ast_strdupa(fmt);
7133  stringp = fmt;
7134  strsep(&stringp, "|");
7135 
7136  if (!ast_strlen_zero(vmu->serveremail))
7137  myserveremail = vmu->serveremail;
7138 
7139  if (!ast_strlen_zero(vmu->email)) {
7140  int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
7141 
7142  if (attach_user_voicemail)
7143  RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
7144 
7145  /* XXX possible imap issue, should category be NULL XXX */
7146  sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
7147 
7148  if (attach_user_voicemail)
7149  DISPOSE(todir, msgnum);
7150  }
7151 
7152  if (!ast_strlen_zero(vmu->pager)) {
7153  sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
7154  }
7155 
7156  if (ast_test_flag(vmu, VM_DELETE))
7157  DELETE(todir, msgnum, fn, vmu);
7158 
7159  /* Leave voicemail for someone */
7160  if (ast_app_has_voicemail(ext_context, NULL))
7161  ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
7162 
7163  queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
7164 
7165  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);
7166  run_externnotify(vmu->context, vmu->mailbox, flag);
7167 
7168 #ifdef IMAP_STORAGE
7169  vm_delete(fn); /* Delete the file, but not the IMAP message */
7170  if (ast_test_flag(vmu, VM_DELETE)) { /* Delete the IMAP message if delete = yes */
7171  vm_imap_delete(NULL, vms->curmsg, vmu);
7172  vms->newmessages--; /* Fix new message count */
7173  }
7174 #endif
7175 
7176  return 0;
7177 }
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)
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * strsep(char **str, const char *delims)
char attachfmt[20]
#define ast_test_flag(p, flag)
Definition: utils.h:63
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 appropria...
int ast_app_has_voicemail(const char *mailbox, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to &quot;INBOX&quot;. If folder is &quot;INBOX&quot;, includes the number of messages in the &quot;Urgent&quot; folder.
Definition: app.c:421
#define AST_LOG_WARNING
Definition: logger.h:149
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define VM_ATTACH
#define DISPOSE(a, b)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static const char * mbox(struct ast_vm_user *vmu, int id)
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
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 appropria...
static void run_externnotify(char *context, char *extension, const char *flag)
#define VM_DELETE
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define DELETE(a, b, c, d)
static char VM_SPOOL_DIR[PATH_MAX]
static int vm_delete(char *file)
Removes the voicemail sound and information file.
int ast_app_inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: app.c:455
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
char pager[80]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define RETRIEVE(a, b, c, d)
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)
char serveremail[80]
char email[80]
static char serveremail[80]
int newmessages
static void queue_mwi_event(const char *box, int urgent, int new, int old)
static int ochar ( struct baseio bio,
int  c,
FILE *  so 
)
static

utility used by base_encode()

Definition at line 4287 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

4288 {
4289  if (bio->linelength >= BASELINELEN) {
4290  if (fputs(ENDL, so) == EOF) {
4291  return -1;
4292  }
4293 
4294  bio->linelength = 0;
4295  }
4296 
4297  if (putc(((unsigned char) c), so) == EOF) {
4298  return -1;
4299  }
4300 
4301  bio->linelength++;
4302 
4303  return 1;
4304 }
#define ENDL
int linelength
#define BASELINELEN
static int open_mailbox ( struct vm_state vms,
struct ast_vm_user vmu,
int  box 
)
static

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

7952 {
7953  int count_msg, last_msg;
7954 
7955  ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
7956 
7957  /* Rename the member vmbox HERE so that we don't try to return before
7958  * we know what's going on.
7959  */
7960  snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
7961 
7962  /* Faster to make the directory than to check if it exists. */
7963  create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
7964 
7965  /* traverses directory using readdir (or select query for ODBC) */
7966  count_msg = count_messages(vmu, vms->curdir);
7967  if (count_msg < 0) {
7968  return count_msg;
7969  } else {
7970  vms->lastmsg = count_msg - 1;
7971  }
7972 
7973  if (vm_allocate_dh(vms, vmu, count_msg)) {
7974  return -1;
7975  }
7976 
7977  /*
7978  The following test is needed in case sequencing gets messed up.
7979  There appears to be more than one way to mess up sequence, so
7980  we will not try to find all of the root causes--just fix it when
7981  detected.
7982  */
7983 
7984  if (vm_lock_path(vms->curdir)) {
7985  ast_log(AST_LOG_ERROR, "Could not open mailbox %s: mailbox is locked\n", vms->curdir);
7986  return ERROR_LOCK_PATH;
7987  }
7988 
7989  /* for local storage, checks directory for messages up to maxmsg limit */
7990  last_msg = last_message_index(vmu, vms->curdir);
7991  ast_unlock_path(vms->curdir);
7992 
7993  if (last_msg < -1) {
7994  return last_msg;
7995  } else if (vms->lastmsg != last_msg) {
7996  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);
7997  resequence_mailbox(vmu, vms->curdir, count_msg);
7998  }
7999 
8000  return 0;
8001 }
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
char curdir[PATH_MAX]
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
char vmbox[PATH_MAX]
static const char * mbox(struct ast_vm_user *vmu, int id)
#define AST_LOG_ERROR
Definition: logger.h:160
char username[80]
char context[AST_MAX_CONTEXT]
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. ...
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
char curbox[80]
static int play_message ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms 
)
static

Definition at line 7725 of file app_voicemail.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, context, 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, valid_config(), VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

Referenced by vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_browse_messages_vi(), vm_browse_messages_zh(), and vm_execmain().

7726 {
7727  int res = 0;
7728  char filename[256], *cid;
7729  const char *origtime, *context, *category, *duration, *flag;
7730  struct ast_config *msg_cfg;
7731  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
7732 
7733  vms->starting = 0;
7734  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
7735  adsi_message(chan, vms);
7736  if (!vms->curmsg) {
7737  res = wait_file2(chan, vms, "vm-first"); /* "First" */
7738  } else if (vms->curmsg == vms->lastmsg) {
7739  res = wait_file2(chan, vms, "vm-last"); /* "last" */
7740  }
7741 
7742  snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
7743  RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
7744  msg_cfg = ast_config_load(filename, config_flags);
7745  if (!valid_config(msg_cfg)) {
7746  ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
7747  return 0;
7748  }
7749  flag = ast_variable_retrieve(msg_cfg, "message", "flag");
7750 
7751  /* Play the word urgent if we are listening to urgent messages */
7752  if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
7753  res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
7754  }
7755 
7756  if (!res) {
7757  /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
7758  /* POLISH syntax */
7759  if (!strncasecmp(chan->language, "pl", 2)) {
7760  if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
7761  int ten, one;
7762  char nextmsg[256];
7763  ten = (vms->curmsg + 1) / 10;
7764  one = (vms->curmsg + 1) % 10;
7765 
7766  if (vms->curmsg < 20) {
7767  snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
7768  res = wait_file2(chan, vms, nextmsg);
7769  } else {
7770  snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
7771  res = wait_file2(chan, vms, nextmsg);
7772  if (one > 0) {
7773  if (!res) {
7774  snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
7775  res = wait_file2(chan, vms, nextmsg);
7776  }
7777  }
7778  }
7779  }
7780  if (!res)
7781  res = wait_file2(chan, vms, "vm-message");
7782  /* HEBREW syntax */
7783  } else if (!strncasecmp(chan->language, "he", 2)) {
7784  if (!vms->curmsg) {
7785  res = wait_file2(chan, vms, "vm-message");
7786  res = wait_file2(chan, vms, "vm-first");
7787  } else if (vms->curmsg == vms->lastmsg) {
7788  res = wait_file2(chan, vms, "vm-message");
7789  res = wait_file2(chan, vms, "vm-last");
7790  } else {
7791  res = wait_file2(chan, vms, "vm-message");
7792  res = wait_file2(chan, vms, "vm-number");
7793  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
7794  }
7795  /* VIETNAMESE syntax */
7796  } else if (!strncasecmp(chan->language, "vi", 2)) {
7797  if (!vms->curmsg) {
7798  res = wait_file2(chan, vms, "vm-message");
7799  res = wait_file2(chan, vms, "vm-first");
7800  } else if (vms->curmsg == vms->lastmsg) {
7801  res = wait_file2(chan, vms, "vm-message");
7802  res = wait_file2(chan, vms, "vm-last");
7803  } else {
7804  res = wait_file2(chan, vms, "vm-message");
7805  res = wait_file2(chan, vms, "vm-number");
7806  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
7807  }
7808  } else {
7809  if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
7810  res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
7811  } else { /* DEFAULT syntax */
7812  res = wait_file2(chan, vms, "vm-message");
7813  }
7814  if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
7815  if (!res) {
7816  ast_test_suite_event_notify("PLAYBACK", "Message: message number");
7817  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
7818  }
7819  }
7820  }
7821  }
7822 
7823  if (!valid_config(msg_cfg)) {
7824  ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
7825  return 0;
7826  }
7827 
7828  if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
7829  ast_log(AST_LOG_WARNING, "No origtime?!\n");
7830  DISPOSE(vms->curdir, vms->curmsg);
7831  ast_config_destroy(msg_cfg);
7832  return 0;
7833  }
7834 
7835  cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
7836  duration = ast_variable_retrieve(msg_cfg, "message", "duration");
7837  category = ast_variable_retrieve(msg_cfg, "message", "category");
7838 
7839  context = ast_variable_retrieve(msg_cfg, "message", "context");
7840  if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
7841  context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
7842  if (!res) {
7843  res = play_message_category(chan, category);
7844  }
7845  if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
7846  res = play_message_datetime(chan, vmu, origtime, filename);
7847  }
7848  if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
7849  res = play_message_callerid(chan, vms, cid, context, 0);
7850  }
7851  if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
7852  res = play_message_duration(chan, vms, duration, vmu->saydurationm);
7853  }
7854  /* Allow pressing '1' to skip envelope / callerid */
7855  if (res == '1') {
7856  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
7857  res = 0;
7858  }
7859  ast_config_destroy(msg_cfg);
7860 
7861  if (!res) {
7862  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
7863 #ifdef IMAP_STORAGE
7864  ast_mutex_lock(&vms->lock);
7865 #endif
7866  vms->heard[vms->curmsg] = 1;
7867 #ifdef IMAP_STORAGE
7868  ast_mutex_unlock(&vms->lock);
7869  /*IMAP storage stores any prepended message from a forward
7870  * as a separate file from the rest of the message
7871  */
7872  if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
7873  wait_file(chan, vms, vms->introfn);
7874  }
7875 #endif
7876  if ((res = wait_file(chan, vms, vms->fn)) < 0) {
7877  ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
7878  res = 0;
7879  }
7880  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
7881  }
7882  DISPOSE(vms->curdir, vms->curmsg);
7883  return res;
7884 }
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define AST_DIGIT_ANY
Definition: file.h:47
#define ast_test_flag(p, flag)
Definition: utils.h:63
char fn[PATH_MAX]
#define VM_SAYDURATION
#define LOG_WARNING
Definition: logger.h:144
#define AST_LOG_WARNING
Definition: logger.h:149
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:155
#define DISPOSE(a, b)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define VM_SAYCID
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
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 appropria...
#define VM_ENVELOPE
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
int * heard
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
#define RETRIEVE(a, b, c, d)
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static int play_message_category(struct ast_channel *chan, const char *category)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
const ast_string_field language
Definition: channel.h:787
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static int play_message_callerid ( struct ast_channel chan,
struct vm_state vms,
char *  cid,
const char *  context,
int  callback 
)
static

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

Referenced by advanced_options(), and play_message().

7612 {
7613  int res = 0;
7614  int i;
7615  char *callerid, *name;
7616  char prefile[PATH_MAX] = "";
7617 
7618 
7619  /* If voicemail cid is not enabled, or we didn't get cid or context from
7620  * the attribute file, leave now.
7621  *
7622  * TODO Still need to change this so that if this function is called by the
7623  * message envelope (and someone is explicitly requesting to hear the CID),
7624  * it does not check to see if CID is enabled in the config file.
7625  */
7626  if ((cid == NULL)||(context == NULL))
7627  return res;
7628 
7629  /* Strip off caller ID number from name */
7630  ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
7631  ast_callerid_parse(cid, &name, &callerid);
7632  if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
7633  /* Check for internal contexts and only */
7634  /* say extension when the call didn't come from an internal context in the list */
7635  for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
7636  ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
7637  if ((strcmp(cidinternalcontexts[i], context) == 0))
7638  break;
7639  }
7640  if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
7641  if (!res) {
7642  snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
7643  if (!ast_strlen_zero(prefile)) {
7644  /* See if we can find a recorded name for this person instead of their extension number */
7645  if (ast_fileexists(prefile, NULL, NULL) > 0) {
7646  ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
7647  if (!callback)
7648  res = wait_file2(chan, vms, "vm-from");
7649  res = ast_stream_and_wait(chan, prefile, "");
7650  } else {
7651  ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
7652  /* Say "from extension" as one saying to sound smoother */
7653  if (!callback)
7654  res = wait_file2(chan, vms, "vm-from-extension");
7655  res = ast_say_digit_str(chan, callerid, "", chan->language);
7656  }
7657  }
7658  }
7659  } else if (!res) {
7660  ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
7661  /* Since this is all nicely figured out, why not say "from phone number" in this case? */
7662  if (!callback)
7663  res = wait_file2(chan, vms, "vm-from-phonenumber");
7664  res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
7665  }
7666  } else {
7667  /* Number unknown */
7668  ast_debug(1, "VM-CID: From an unknown number\n");
7669  /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
7670  res = wait_file2(chan, vms, "vm-unknown-caller");
7671  }
7672  return res;
7673 }
#define MAX_NUM_CID_CONTEXTS
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8415
#define ast_verb(level,...)
Definition: logger.h:243
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static char VM_SPOOL_DIR[PATH_MAX]
static const char name[]
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
const ast_string_field language
Definition: channel.h:787
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1009
static int play_message_category ( struct ast_channel chan,
const char *  category 
)
static

Definition at line 7522 of file app_voicemail.c.

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

Referenced by play_message().

7523 {
7524  int res = 0;
7525 
7526  if (!ast_strlen_zero(category))
7527  res = ast_play_and_wait(chan, category);
7528 
7529  if (res) {
7530  ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
7531  res = 0;
7532  }
7533 
7534  return res;
7535 }
#define AST_LOG_WARNING
Definition: logger.h:149
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int play_message_datetime ( struct ast_channel chan,
struct ast_vm_user vmu,
const char *  origtime,
const char *  filename 
)
static

Definition at line 7537 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

7538 {
7539  int res = 0;
7540  struct vm_zone *the_zone = NULL;
7541  time_t t;
7542 
7543  if (ast_get_time_t(origtime, &t, 0, NULL)) {
7544  ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
7545  return 0;
7546  }
7547 
7548  /* Does this user have a timezone specified? */
7549  if (!ast_strlen_zero(vmu->zonetag)) {
7550  /* Find the zone in the list */
7551  struct vm_zone *z;
7552  AST_LIST_LOCK(&zones);
7553  AST_LIST_TRAVERSE(&zones, z, list) {
7554  if (!strcmp(z->name, vmu->zonetag)) {
7555  the_zone = z;
7556  break;
7557  }
7558  }
7560  }
7561 
7562 /* No internal variable parsing for now, so we'll comment it out for the time being */
7563 #if 0
7564  /* Set the DIFF_* variables */
7565  ast_localtime(&t, &time_now, NULL);
7566  tv_now = ast_tvnow();
7567  ast_localtime(&tv_now, &time_then, NULL);
7568 
7569  /* Day difference */
7570  if (time_now.tm_year == time_then.tm_year)
7571  snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
7572  else
7573  snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
7574  pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
7575 
7576  /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
7577 #endif
7578  if (the_zone) {
7579  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
7580  } else if (!strncasecmp(chan->language, "de", 2)) { /* GERMAN syntax */
7581  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
7582  } else if (!strncasecmp(chan->language, "gr", 2)) { /* GREEK syntax */
7583  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
7584  } else if (!strncasecmp(chan->language, "it", 2)) { /* ITALIAN syntax */
7585  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);
7586  } else if (!strncasecmp(chan->language, "nl", 2)) { /* DUTCH syntax */
7587  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
7588  } else if (!strncasecmp(chan->language, "no", 2)) { /* NORWEGIAN syntax */
7589  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
7590  } else if (!strncasecmp(chan->language, "pl", 2)) { /* POLISH syntax */
7591  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
7592  } else if (!strncasecmp(chan->language, "pt_BR", 5)) { /* Brazillian PORTUGUESE syntax */
7593  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);
7594  } else if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
7595  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
7596  } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
7597  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
7598  } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
7599  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);
7600  } else {
7601  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
7602  }
7603 #if 0
7604  pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
7605 #endif
7606  return res;
7607 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char msg_format[512]
char name[80]
#define AST_DIGIT_ANY
Definition: file.h:47
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char timezone[80]
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define AST_LOG_WARNING
Definition: logger.h:149
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: utils.c:2118
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char zonetag[80]
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
Definition: say.h:168
const ast_string_field language
Definition: channel.h:787
struct vm_zone::@66 list
static int play_message_duration ( struct ast_channel chan,
struct vm_state vms,
const char *  duration,
int  minduration 
)
static

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

7676 {
7677  int res = 0;
7678  int durationm;
7679  int durations;
7680  /* Verify that we have a duration for the message */
7681  if (duration == NULL)
7682  return res;
7683 
7684  /* Convert from seconds to minutes */
7685  durations = atoi(duration);
7686  durationm = (durations / 60);
7687 
7688  ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
7689 
7690  if ((!res) && (durationm >= minduration)) {
7691  res = wait_file2(chan, vms, "vm-duration");
7692 
7693  /* POLISH syntax */
7694  if (!strncasecmp(chan->language, "pl", 2)) {
7695  div_t num = div(durationm, 10);
7696 
7697  if (durationm == 1) {
7698  res = ast_play_and_wait(chan, "digits/1z");
7699  res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
7700  } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
7701  if (num.rem == 2) {
7702  if (!num.quot) {
7703  res = ast_play_and_wait(chan, "digits/2-ie");
7704  } else {
7705  res = say_and_wait(chan, durationm - 2 , chan->language);
7706  res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
7707  }
7708  } else {
7709  res = say_and_wait(chan, durationm, chan->language);
7710  }
7711  res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
7712  } else {
7713  res = say_and_wait(chan, durationm, chan->language);
7714  res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
7715  }
7716  /* DEFAULT syntax */
7717  } else {
7718  res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
7719  res = wait_file2(chan, vms, "vm-minutes");
7720  }
7721  }
7722  return res;
7723 }
#define AST_DIGIT_ANY
Definition: file.h:47
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
const ast_string_field language
Definition: channel.h:787
static int play_record_review ( struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime,
char *  fmt,
int  outsidecaller,
struct ast_vm_user vmu,
int *  duration,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
)
static

Definition at line 13397 of file app_voicemail.c.

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

Referenced by leave_voicemail(), vm_forwardoptions(), vm_newuser(), vm_options(), and vm_tempgreeting().

13400 {
13401  /* Record message & let caller review or re-record it, or set options if applicable */
13402  int res = 0;
13403  int cmd = 0;
13404  int max_attempts = 3;
13405  int attempts = 0;
13406  int recorded = 0;
13407  int msg_exists = 0;
13408  signed char zero_gain = 0;
13409  char tempfile[PATH_MAX];
13410  char *acceptdtmf = "#";
13411  char *canceldtmf = "";
13412  int canceleddtmf = 0;
13413 
13414  /* Note that urgent and private are for flagging messages as such in the future */
13415 
13416  /* barf if no pointer passed to store duration in */
13417  if (duration == NULL) {
13418  ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13419  return -1;
13420  }
13421 
13422  if (!outsidecaller)
13423  snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13424  else
13425  ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13426 
13427  cmd = '3'; /* Want to start by recording */
13428 
13429  while ((cmd >= 0) && (cmd != 't')) {
13430  switch (cmd) {
13431  case '1':
13432  if (!msg_exists) {
13433  /* In this case, 1 is to record a message */
13434  cmd = '3';
13435  break;
13436  } else {
13437  /* Otherwise 1 is to save the existing message */
13438  ast_verb(3, "Saving message as is\n");
13439  if (!outsidecaller)
13440  ast_filerename(tempfile, recordfile, NULL);
13441  ast_stream_and_wait(chan, "vm-msgsaved", "");
13442  if (!outsidecaller) {
13443  /* Saves to IMAP server only if imapgreeting=yes */
13444  STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13445  DISPOSE(recordfile, -1);
13446  }
13447  cmd = 't';
13448  return res;
13449  }
13450  case '2':
13451  /* Review */
13452  ast_verb(3, "Reviewing the message\n");
13453  cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13454  break;
13455  case '3':
13456  msg_exists = 0;
13457  /* Record */
13458  if (recorded == 1)
13459  ast_verb(3, "Re-recording the message\n");
13460  else
13461  ast_verb(3, "Recording the message\n");
13462 
13463  if (recorded && outsidecaller) {
13464  cmd = ast_play_and_wait(chan, INTRO);
13465  cmd = ast_play_and_wait(chan, "beep");
13466  }
13467  recorded = 1;
13468  /* 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 */
13469  if (record_gain)
13470  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13471  if (ast_test_flag(vmu, VM_OPERATOR))
13472  canceldtmf = "0";
13473  cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13474  if (strchr(canceldtmf, cmd)) {
13475  /* need this flag here to distinguish between pressing '0' during message recording or after */
13476  canceleddtmf = 1;
13477  }
13478  if (record_gain)
13479  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13480  if (cmd == -1) {
13481  /* User has hung up, no options to give */
13482  if (!outsidecaller) {
13483  /* user was recording a greeting and they hung up, so let's delete the recording. */
13484  ast_filedelete(tempfile, NULL);
13485  }
13486  return cmd;
13487  }
13488  if (cmd == '0') {
13489  break;
13490  } else if (cmd == '*') {
13491  break;
13492 #if 0
13493  } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13494  /* Message is too short */
13495  ast_verb(3, "Message too short\n");
13496  cmd = ast_play_and_wait(chan, "vm-tooshort");
13497  cmd = ast_filedelete(tempfile, NULL);
13498  break;
13499  } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13500  /* Message is all silence */
13501  ast_verb(3, "Nothing recorded\n");
13502  cmd = ast_filedelete(tempfile, NULL);
13503  cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13504  if (!cmd)
13505  cmd = ast_play_and_wait(chan, "vm-speakup");
13506  break;
13507 #endif
13508  } else {
13509  /* If all is well, a message exists */
13510  msg_exists = 1;
13511  cmd = 0;
13512  }
13513  break;
13514  case '4':
13515  if (outsidecaller) { /* only mark vm messages */
13516  /* Mark Urgent */
13517  if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13518  ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13519  res = ast_play_and_wait(chan, "vm-marked-urgent");
13520  strcpy(flag, "Urgent");
13521  } else if (flag) {
13522  ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13523  res = ast_play_and_wait(chan, "vm-marked-nonurgent");
13524  strcpy(flag, "");
13525  } else {
13526  ast_play_and_wait(chan, "vm-sorry");
13527  }
13528  cmd = 0;
13529  } else {
13530  cmd = ast_play_and_wait(chan, "vm-sorry");
13531  }
13532  break;
13533  case '5':
13534  case '6':
13535  case '7':
13536  case '8':
13537  case '9':
13538  case '*':
13539  case '#':
13540  cmd = ast_play_and_wait(chan, "vm-sorry");
13541  break;
13542 #if 0
13543 /* XXX Commented out for the moment because of the dangers of deleting
13544  a message while recording (can put the message numbers out of sync) */
13545  case '*':
13546  /* Cancel recording, delete message, offer to take another message*/
13547  cmd = ast_play_and_wait(chan, "vm-deleted");
13548  cmd = ast_filedelete(tempfile, NULL);
13549  if (outsidecaller) {
13550  res = vm_exec(chan, NULL);
13551  return res;
13552  }
13553  else
13554  return 1;
13555 #endif
13556  case '0':
13557  if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13558  cmd = ast_play_and_wait(chan, "vm-sorry");
13559  break;
13560  }
13561  if (msg_exists || recorded) {
13562  cmd = ast_play_and_wait(chan, "vm-saveoper");
13563  if (!cmd)
13564  cmd = ast_waitfordigit(chan, 3000);
13565  if (cmd == '1') {
13566  ast_filerename(tempfile, recordfile, NULL);
13567  ast_play_and_wait(chan, "vm-msgsaved");
13568  cmd = '0';
13569  } else if (cmd == '4') {
13570  if (flag) {
13571  ast_play_and_wait(chan, "vm-marked-urgent");
13572  strcpy(flag, "Urgent");
13573  }
13574  ast_play_and_wait(chan, "vm-msgsaved");
13575  cmd = '0';
13576  } else {
13577  ast_play_and_wait(chan, "vm-deleted");
13578  DELETE(tempfile, -1, tempfile, vmu);
13579  cmd = '0';
13580  }
13581  }
13582  return cmd;
13583  default:
13584  /* If the caller is an ouside caller, and the review option is enabled,
13585  allow them to review the message, but let the owner of the box review
13586  their OGM's */
13587  if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13588  return cmd;
13589  if (msg_exists) {
13590  cmd = ast_play_and_wait(chan, "vm-review");
13591  if (!cmd && outsidecaller) {
13592  if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13593  cmd = ast_play_and_wait(chan, "vm-review-urgent");
13594  } else if (flag) {
13595  cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13596  }
13597  }
13598  } else {
13599  cmd = ast_play_and_wait(chan, "vm-torerecord");
13600  if (!cmd)
13601  cmd = ast_waitfordigit(chan, 600);
13602  }
13603 
13604  if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13605  cmd = ast_play_and_wait(chan, "vm-reachoper");
13606  if (!cmd)
13607  cmd = ast_waitfordigit(chan, 600);
13608  }
13609 #if 0
13610  if (!cmd)
13611  cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13612 #endif
13613  if (!cmd)
13614  cmd = ast_waitfordigit(chan, 6000);
13615  if (!cmd) {
13616  attempts++;
13617  }
13618  if (attempts > max_attempts) {
13619  cmd = 't';
13620  }
13621  }
13622  }
13623  if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13624  /* Hang up or timeout, so delete the recording. */
13625  ast_filedelete(tempfile, NULL);
13626  }
13627 
13628  if (cmd != 't' && outsidecaller)
13629  ast_play_and_wait(chan, "vm-goodbye");
13630 
13631  return cmd;
13632 }
int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence_ms, const char *path, const char *acceptdtmf, const char *canceldtmf)
Record a file based on input from a channel This function will play &quot;auth-thankyou&quot; upon successful r...
Definition: app.c:1178
#define AST_DIGIT_ANY
Definition: file.h:47
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define VERBOSE_PREFIX_3
Definition: logger.h:43
static int maxsilence
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
#define AST_LOG_WARNING
Definition: logger.h:149
#define INTRO
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:931
#define DISPOSE(a, b)
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
#define ast_verb(level,...)
Definition: logger.h:243
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int silencethreshold
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define DELETE(a, b, c, d)
#define VM_OPERATOR
#define VM_REVIEW
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
#define STORE(a, b, c, d, e, f, g, h, i, j)
static char acceptdtmf
Definition: chan_agent.c:227
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_OPTION_RXGAIN
Definition: frame.h:463
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:936
static int vm_exec(struct ast_channel *chan, const char *data)
static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub)
static

Definition at line 11407 of file app_voicemail.c.

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

Referenced by handle_subscribe(), and poll_subscribed_mailboxes().

11408 {
11409  int new = 0, old = 0, urgent = 0;
11410 
11411  inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11412 
11413  if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11414  mwi_sub->old_urgent = urgent;
11415  mwi_sub->old_new = new;
11416  mwi_sub->old_old = old;
11417  queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11418  run_externnotify(NULL, mwi_sub->mailbox, NULL);
11419  }
11420 }
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static void run_externnotify(char *context, char *extension, const char *flag)
static void queue_mwi_event(const char *box, int urgent, int new, int old)
static void poll_subscribed_mailboxes ( void  )
static

Definition at line 11422 of file app_voicemail.c.

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

Referenced by mb_poll_thread().

11423 {
11424  struct mwi_sub *mwi_sub;
11425 
11427  AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11428  if (!ast_strlen_zero(mwi_sub->mailbox)) {
11429  poll_subscribed_mailbox(mwi_sub);
11430  }
11431  }
11433 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
An MWI subscription.
static void poll_subscribed_mailbox(struct mwi_sub *mwi_sub)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static struct ast_event_sub * mwi_sub
Definition: res_jabber.c:394
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static void populate_defaults ( struct ast_vm_user vmu)
static

Sets default voicemail system options to a voicemail user.

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

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

Definition at line 1014 of file app_voicemail.c.

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, ast_free, ast_vm_user::callback, ast_vm_user::dialout, ast_vm_user::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, ast_vm_user::locale, ast_vm_user::maxdeletedmsg, maxdeletedmsg, ast_vm_user::maxmsg, maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_vm_user::passwordlocation, passwordlocation, ast_vm_user::saydurationm, saydurationminfo, vmmaxsecs, vmminsecs, ast_vm_user::volgain, volgain, and ast_vm_user::zonetag.

Referenced by actual_load_config(), append_mailbox(), AST_TEST_DEFINE(), and find_user_realtime().

1015 {
1018  if (saydurationminfo) {
1020  }
1021  ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
1022  ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
1023  ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
1024  ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
1025  ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
1026  if (vmminsecs) {
1027  vmu->minsecs = vmminsecs;
1028  }
1029  if (vmmaxsecs) {
1030  vmu->maxsecs = vmmaxsecs;
1031  }
1032  if (maxmsg) {
1033  vmu->maxmsg = maxmsg;
1034  }
1035  if (maxdeletedmsg) {
1037  }
1038  vmu->volgain = volgain;
1039  ast_free(vmu->emailsubject);
1040  vmu->emailsubject = NULL;
1041  ast_free(vmu->emailbody);
1042  vmu->emailbody = NULL;
1043 #ifdef IMAP_STORAGE
1044  ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
1045 #endif
1046 }
double volgain
static int saydurationminfo
static int maxdeletedmsg
static char locale[20]
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
static int vmminsecs
char locale[20]
char * emailsubject
static int passwordlocation
static char exitcontext[AST_MAX_CONTEXT]
static char dialcontext[AST_MAX_CONTEXT]
static struct ast_flags globalflags
int passwordlocation
static char zonetag[80]
static double volgain
char zonetag[80]
static char callcontext[AST_MAX_CONTEXT]
char * emailbody
char exit[80]
#define ast_free(a)
Definition: astmm.h:97
#define AST_FLAGS_ALL
Definition: utils.h:196
static int vmmaxsecs
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char dialout[80]
char callback[80]
static int maxmsg
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 4375 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, ast_vm_user::context, ast_vm_user::fullname, ast_vm_user::locale, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, pbx_builtin_setvar_helper(), S_OR, and valid_config().

Referenced by make_email_file(), and sendpage().

4376 {
4377  char callerid[256];
4378  char num[12];
4379  char fromdir[256], fromfile[256];
4380  struct ast_config *msg_cfg;
4381  const char *origcallerid, *origtime;
4382  char origcidname[80], origcidnum[80], origdate[80];
4383  int inttime;
4384  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
4385 
4386  /* Prepare variables for substitution in email body and subject */
4387  pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
4388  pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
4389  snprintf(num, sizeof(num), "%d", msgnum);
4390  pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
4391  pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
4392  pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
4393  pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
4394  ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
4395  pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
4396  pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
4397  pbx_builtin_setvar_helper(ast, "VM_DATE", date);
4398  pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
4399  pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
4400 
4401  /* Retrieve info from VM attribute file */
4402  make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
4403  make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
4404  if (strlen(fromfile) < sizeof(fromfile) - 5) {
4405  strcat(fromfile, ".txt");
4406  }
4407  if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
4408  if (option_debug > 0) {
4409  ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
4410  }
4411  return;
4412  }
4413 
4414  if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
4415  pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
4416  ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
4417  pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
4418  pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
4419  }
4420 
4421  if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
4422  struct timeval tv = { inttime, };
4423  struct ast_tm tm;
4424  ast_localtime(&tv, &tm, NULL);
4425  ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
4426  pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
4427  }
4428  ast_config_destroy(msg_cfg);
4429 }
char fullname[80]
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1093
int option_debug
Definition: asterisk.c:182
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 appropria...
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define LOG_DEBUG
Definition: logger.h:122
char locale[20]
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
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 appropria...
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1074
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2280
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static char emaildateformat[32]
Structure used to handle boolean flags.
Definition: utils.h:200
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct timeval tv
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static void queue_mwi_event ( const char *  box,
int  urgent,
int  new,
int  old 
)
static

Definition at line 7066 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(), context, mailbox, and strsep().

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

7067 {
7068  struct ast_event *event;
7069  char *mailbox, *context;
7070 
7071  /* Strip off @default */
7072  context = mailbox = ast_strdupa(box);
7073  strsep(&context, "@");
7074  if (ast_strlen_zero(context))
7075  context = "default";
7076 
7077  if (!(event = ast_event_new(AST_EVENT_MWI,
7082  AST_EVENT_IE_END))) {
7083  return;
7084  }
7085 
7087 }
An event.
Definition: event.c:85
char * strsep(char **str, const char *delims)
int ast_event_queue_and_cache(struct ast_event *event)
Queue and cache an event.
Definition: event.c:1465
Number of new messages Used by: AST_EVENT_MWI Payload type: UINT.
Definition: event_defs.h:71
Number of Used by: AST_EVENT_MWI Payload type: UINT.
Definition: event_defs.h:77
Context IE Used by AST_EVENT_MWI Payload type: str.
Definition: event_defs.h:121
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
Definition: event.c:1202
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
Mailbox name.
Definition: event_defs.h:83
static void read_password_from_file ( const char *  secretfn,
char *  password,
int  passwordlen 
)
static

Definition at line 12513 of file app_voicemail.c.

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

Referenced by actual_load_config(), and append_mailbox().

12513  {
12514  struct ast_config *pwconf;
12515  struct ast_flags config_flags = { 0 };
12516 
12517  pwconf = ast_config_load(secretfn, config_flags);
12518  if (valid_config(pwconf)) {
12519  const char *val = ast_variable_retrieve(pwconf, "general", "password");
12520  if (val) {
12521  ast_copy_string(password, val, passwordlen);
12522  ast_config_destroy(pwconf);
12523  return;
12524  }
12525  ast_config_destroy(pwconf);
12526  }
12527  ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12528 }
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
Definition: ast_expr2.c:325
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
Structure used to handle boolean flags.
Definition: utils.h:200
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static int reload ( void  )
static

Definition at line 13044 of file app_voicemail.c.

References load_config().

13045 {
13046  return load_config(1);
13047 }
static int load_config(int reload)
static void rename_file ( char *  sfn,
char *  dfn 
)
static

Renames a message in a mailbox folder.

Parameters
sfnThe path to the mailbox information and data file to be renamed.
dfnThe 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 4045 of file app_voicemail.c.

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

4046 {
4047  char stxt[PATH_MAX];
4048  char dtxt[PATH_MAX];
4049  ast_filerename(sfn, dfn, NULL);
4050  snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
4051  snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
4052  if (ast_check_realtime("voicemail_data")) {
4053  ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
4054  }
4055  rename(stxt, dtxt);
4056 }
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: config.c:2679
#define SENTINEL
Definition: compiler.h:75
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:936
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
static int resequence_mailbox ( struct ast_vm_user vmu,
char *  dir,
int  stopcount 
)
static

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

6193 {
6194  /* we know the actual number of messages, so stop process when number is hit */
6195 
6196  int x, dest;
6197  char sfn[PATH_MAX];
6198  char dfn[PATH_MAX];
6199 
6200  if (vm_lock_path(dir)) {
6201  return ERROR_LOCK_PATH;
6202  }
6203 
6204  for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
6205  make_file(sfn, sizeof(sfn), dir, x);
6206  if (EXISTS(dir, x, sfn, NULL)) {
6207 
6208  if (x != dest) {
6209  make_file(dfn, sizeof(dfn), dir, dest);
6210  RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
6211  }
6212 
6213  dest++;
6214  }
6215  }
6216  ast_unlock_path(dir);
6217 
6218  return dest;
6219 }
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
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 appropria...
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define RENAME(a, b, c, d, e, f, g, h)
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
#define EXISTS(a, b, c, d)
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
newpassThis does the actual change password work, called by the vm_change_password() function.
Returns
zero on success, -1 on error.

Definition at line 1484 of file app_voicemail.c.

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

Referenced by vm_change_password(), and vm_change_password_shell().

1485 {
1486  /* This function could be made to generate one from a database, too */
1487  struct ast_vm_user *cur;
1488  int res = -1;
1489  AST_LIST_LOCK(&users);
1490  AST_LIST_TRAVERSE(&users, cur, list) {
1491  if ((!context || !strcasecmp(context, cur->context)) &&
1492  (!strcasecmp(mailbox, cur->mailbox)))
1493  break;
1494  }
1495  if (cur) {
1496  ast_copy_string(cur->password, newpass, sizeof(cur->password));
1497  res = 0;
1498  }
1500  return res;
1501 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
list of users found in the config file
struct ast_vm_user::@65 list
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
char password[80]
static void run_externnotify ( char *  context,
char *  extension,
const char *  flag 
)
static

Definition at line 5560 of file app_voicemail.c.

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

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

5561 {
5562  char arguments[255];
5563  char ext_context[256] = "";
5564  int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
5565  struct ast_smdi_mwi_message *mwi_msg;
5566 
5567  if (!ast_strlen_zero(context))
5568  snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
5569  else
5570  ast_copy_string(ext_context, extension, sizeof(ext_context));
5571 
5572  if (smdi_iface) {
5573  if (ast_app_has_voicemail(ext_context, NULL))
5575  else
5577 
5579  ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
5580  if (!strncmp(mwi_msg->cause, "INV", 3))
5581  ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
5582  else if (!strncmp(mwi_msg->cause, "BLK", 3))
5583  ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
5584  ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
5586  } else {
5587  ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
5588  }
5589  }
5590 
5591  if (!ast_strlen_zero(externnotify)) {
5592  if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
5593  ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
5594  } else {
5595  snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
5596  externnotify, S_OR(context, "\"\""),
5597  extension, newvoicemails,
5598  oldvoicemails, urgentvoicemails);
5599  ast_debug(1, "Executing %s\n", arguments);
5600  ast_safe_system(arguments);
5601  }
5602  }
5603 }
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
#define SMDI_MWI_WAIT_TIMEOUT
int ast_app_has_voicemail(const char *mailbox, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to &quot;INBOX&quot;. If folder is &quot;INBOX&quot;, includes the number of messages in the &quot;Urgent&quot; folder.
Definition: app.c:421
#define AST_LOG_WARNING
Definition: logger.h:149
static char externnotify[160]
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static struct ast_smdi_interface * smdi_iface
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
Definition: smdi.h:58
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
Definition: res_smdi.c:319
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_LOG_ERROR
Definition: logger.h:160
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ASTOBJ_UNREF(object, destructor)
Decrement the reference count on an object.
Definition: astobj.h:218
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:56
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg)
ast_smdi_mwi_message destructor.
Definition: res_smdi.c:829
int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
Definition: res_smdi.c:324
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
struct ast_smdi_mwi_message * ast_smdi_mwi_message_wait_station(struct ast_smdi_interface *iface, int timeout, const char *station)
Definition: res_smdi.c:620
An SMDI message waiting indicator message.
Definition: smdi.h:55
static int save_to_folder ( struct ast_vm_user vmu,
struct vm_state vms,
int  msg,
int  box 
)
static

Definition at line 6229 of file app_voicemail.c.

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

Referenced by close_mailbox(), and vm_execmain().

6230 {
6231 #ifdef IMAP_STORAGE
6232  /* we must use mbox(x) folder names, and copy the message there */
6233  /* simple. huh? */
6234  char sequence[10];
6235  char mailbox[256];
6236  int res;
6237 
6238  /* get the real IMAP message number for this message */
6239  snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
6240 
6241  ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
6242  ast_mutex_lock(&vms->lock);
6243  /* if save to Old folder, put in INBOX as read */
6244  if (box == OLD_FOLDER) {
6245  mail_setflag(vms->mailstream, sequence, "\\Seen");
6246  mail_clearflag(vms->mailstream, sequence, "\\Unseen");
6247  } else if (box == NEW_FOLDER) {
6248  mail_setflag(vms->mailstream, sequence, "\\Unseen");
6249  mail_clearflag(vms->mailstream, sequence, "\\Seen");
6250  }
6251  if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
6252  ast_mutex_unlock(&vms->lock);
6253  return 0;
6254  }
6255  /* Create the folder if it don't exist */
6256  imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
6257  ast_debug(5, "Checking if folder exists: %s\n", mailbox);
6258  if (mail_create(vms->mailstream, mailbox) == NIL)
6259  ast_debug(5, "Folder exists.\n");
6260  else
6261  ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
6262  res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
6263  ast_mutex_unlock(&vms->lock);
6264  return res;
6265 #else
6266  char *dir = vms->curdir;
6267  char *username = vms->username;
6268  char *context = vmu->context;
6269  char sfn[PATH_MAX];
6270  char dfn[PATH_MAX];
6271  char ddir[PATH_MAX];
6272  const char *dbox = mbox(vmu, box);
6273  int x, i;
6274  create_dirpath(ddir, sizeof(ddir), context, username, dbox);
6275 
6276  if (vm_lock_path(ddir))
6277  return ERROR_LOCK_PATH;
6278 
6279  x = last_message_index(vmu, ddir) + 1;
6280 
6281  if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
6282  x--;
6283  for (i = 1; i <= x; i++) {
6284  /* Push files down a "slot". The oldest file (msg0000) will be deleted. */
6285  make_file(sfn, sizeof(sfn), ddir, i);
6286  make_file(dfn, sizeof(dfn), ddir, i - 1);
6287  if (EXISTS(ddir, i, sfn, NULL)) {
6288  RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
6289  } else
6290  break;
6291  }
6292  } else {
6293  if (x >= vmu->maxmsg) {
6294  ast_unlock_path(ddir);
6295  return -1;
6296  }
6297  }
6298  make_file(sfn, sizeof(sfn), dir, msg);
6299  make_file(dfn, sizeof(dfn), ddir, x);
6300  if (strcmp(sfn, dfn)) {
6301  COPY(dir, msg, ddir, x, username, context, sfn, dfn);
6302  }
6303  ast_unlock_path(ddir);
6304 #endif
6305  return 0;
6306 }
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: app.c:1668
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:155
static const char * mbox(struct ast_vm_user *vmu, int id)
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 appropria...
#define AST_LOG_NOTICE
Definition: logger.h:138
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char mailbox[AST_MAX_EXTENSION]
char username[80]
char context[AST_MAX_CONTEXT]
#define COPY(a, b, c, d, e, f, g, h)
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. ...
#define RENAME(a, b, c, d, e, f, g, h)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns &#39;timeout&#39;, not if the path does not exist...
#define EXISTS(a, b, c, d)
char curbox[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int say_and_wait ( struct ast_channel chan,
int  num,
const char *  language 
)
static

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

6223 {
6224  int d;
6225  d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
6226  return d;
6227 }
#define AST_DIGIT_ANY
Definition: file.h:47
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
static int sayname ( struct ast_channel chan,
const char *  mailbox,
const char *  context 
)
static

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

12500 {
12501  int res = -1;
12502  char dir[PATH_MAX];
12503  snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12504  ast_debug(2, "About to try retrieving name file %s\n", dir);
12505  RETRIEVE(dir, -1, mailbox, context);
12506  if (ast_fileexists(dir, NULL, NULL)) {
12507  res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12508  }
12509  DISPOSE(dir, -1);
12510  return res;
12511 }
#define AST_DIGIT_ANY
Definition: file.h:47
#define DISPOSE(a, b)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static char VM_SPOOL_DIR[PATH_MAX]
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
#define RETRIEVE(a, b, c, d)
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
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 4890 of file app_voicemail.c.

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

Referenced by forward_message(), and notify_new_message().

4891 {
4892  FILE *p = NULL;
4893  char tmp[80] = "/tmp/astmail-XXXXXX";
4894  char tmp2[256];
4895  char *stringp;
4896 
4897  if (vmu && ast_strlen_zero(vmu->email)) {
4898  ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
4899  return(0);
4900  }
4901 
4902  /* Mail only the first format */
4904  stringp = format;
4905  strsep(&stringp, "|");
4906 
4907  if (!strcmp(format, "wav49"))
4908  format = "WAV";
4909  ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %u\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
4910  /* Make a temporary file instead of piping directly to sendmail, in case the mail
4911  command hangs */
4912  if ((p = vm_mkftemp(tmp)) == NULL) {
4913  ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
4914  return -1;
4915  } else {
4916  make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
4917  fclose(p);
4918  snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
4919  ast_safe_system(tmp2);
4920  ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
4921  }
4922  return 0;
4923 }
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
char * strsep(char **str, const char *delims)
static char mailcmd[160]
static FILE * vm_mkftemp(char *template)
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_LOG_WARNING
Definition: logger.h:149
#define VM_ATTACH
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct ast_flags globalflags
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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 char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static snd_pcm_format_t format
Definition: chan_alsa.c:93
char email[80]
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
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 4925 of file app_voicemail.c.

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

Referenced by notify_new_message().

4926 {
4927  char enc_cidnum[256], enc_cidname[256];
4928  char date[256];
4929  char host[MAXHOSTNAMELEN] = "";
4930  char who[256];
4931  char dur[PATH_MAX];
4932  char tmp[80] = "/tmp/astmail-XXXXXX";
4933  char tmp2[PATH_MAX];
4934  struct ast_tm tm;
4935  FILE *p;
4936  struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
4937 
4938  if (!str1 || !str2) {
4939  ast_free(str1);
4940  ast_free(str2);
4941  return -1;
4942  }
4943 
4944  if (cidnum) {
4945  strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
4946  }
4947  if (cidname) {
4948  strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
4949  }
4950 
4951  if ((p = vm_mkftemp(tmp)) == NULL) {
4952  ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
4953  ast_free(str1);
4954  ast_free(str2);
4955  return -1;
4956  }
4957  gethostname(host, sizeof(host)-1);
4958  if (strchr(srcemail, '@')) {
4959  ast_copy_string(who, srcemail, sizeof(who));
4960  } else {
4961  snprintf(who, sizeof(who), "%s@%s", srcemail, host);
4962  }
4963  snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
4964  ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
4965  fprintf(p, "Date: %s\n", date);
4966 
4967  /* Reformat for custom pager format */
4968  ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
4969 
4971  struct ast_channel *ast;
4972  if ((ast = ast_dummy_channel_alloc())) {
4973  char *ptr;
4974  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
4976 
4977  if (check_mime(ast_str_buffer(str1))) {
4978  int first_line = 1;
4979  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
4980  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
4981  *ptr = '\0';
4982  fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
4983  first_line = 0;
4984  /* Substring is smaller, so this will never grow */
4985  ast_str_set(&str2, 0, "%s", ptr + 1);
4986  }
4987  fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
4988  } else {
4989  fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
4990  }
4991  ast = ast_channel_unref(ast);
4992  } else {
4993  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
4994  }
4995  } else {
4996  fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
4997  }
4998 
4999  if (check_mime(vmu->fullname)) {
5000  int first_line = 1;
5001  char *ptr;
5002  ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
5003  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5004  *ptr = '\0';
5005  fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
5006  first_line = 0;
5007  /* Substring is smaller, so this will never grow */
5008  ast_str_set(&str2, 0, "%s", ptr + 1);
5009  }
5010  fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
5011  } else {
5012  fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
5013  }
5014 
5015  if (!ast_strlen_zero(pagersubject)) {
5016  struct ast_channel *ast;
5017  if ((ast = ast_dummy_channel_alloc())) {
5018  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5020  if (check_mime(ast_str_buffer(str1))) {
5021  int first_line = 1;
5022  char *ptr;
5023  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
5024  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5025  *ptr = '\0';
5026  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5027  first_line = 0;
5028  /* Substring is smaller, so this will never grow */
5029  ast_str_set(&str2, 0, "%s", ptr + 1);
5030  }
5031  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5032  } else {
5033  fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
5034  }
5035  ast = ast_channel_unref(ast);
5036  } else {
5037  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5038  }
5039  } else {
5040  if (ast_strlen_zero(flag)) {
5041  fprintf(p, "Subject: New VM\n\n");
5042  } else {
5043  fprintf(p, "Subject: New %s VM\n\n", flag);
5044  }
5045  }
5046 
5047  if (pagerbody) {
5048  struct ast_channel *ast;
5049  if ((ast = ast_dummy_channel_alloc())) {
5050  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5051  ast_str_substitute_variables(&str1, 0, ast, pagerbody);
5052  fprintf(p, "%s" ENDL, ast_str_buffer(str1));
5053  ast = ast_channel_unref(ast);
5054  } else {
5055  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5056  }
5057  } else {
5058  fprintf(p, "New %s long %s msg in box %s\n"
5059  "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
5060  }
5061 
5062  fclose(p);
5063  snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5064  ast_safe_system(tmp2);
5065  ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
5066  ast_free(str1);
5067  ast_free(str2);
5068  return 0;
5069 }
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
char fullname[80]
static char mailcmd[160]
static FILE * vm_mkftemp(char *template)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
static char pagerdateformat[32]
static struct ast_tm * vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
fill in *tm for current time according to the proper timezone, if any.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
#define AST_LOG_WARNING
Definition: logger.h:149
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
#define MAXHOSTNAMELEN
Definition: network.h:69
static int check_mime(const char *str)
Check if the string would need encoding within the MIME standard, to avoid confusing certain mail sof...
char locale[20]
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
static char pagerfromstring[100]
static char * pagerbody
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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 force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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)
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2280
#define ENDL
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...
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static char * pagersubject
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
Definition: channel.c:1391
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 ...
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
yylloc first_line
Definition: ast_expr2.c:1857
static char* show_users_realtime ( int  fd,
const char *  context 
)
static

Definition at line 11064 of file app_voicemail.c.

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.

Referenced by handle_voicemail_show_users().

11065 {
11066  struct ast_config *cfg;
11067  const char *cat = NULL;
11068 
11069  if (!(cfg = ast_load_realtime_multientry("voicemail",
11070  "context", context, SENTINEL))) {
11071  return CLI_FAILURE;
11072  }
11073 
11074  ast_cli(fd,
11075  "\n"
11076  "=============================================================\n"
11077  "=== Configured Voicemail Users ==============================\n"
11078  "=============================================================\n"
11079  "===\n");
11080 
11081  while ((cat = ast_category_browse(cfg, cat))) {
11082  struct ast_variable *var = NULL;
11083  ast_cli(fd,
11084  "=== Mailbox ...\n"
11085  "===\n");
11086  for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11087  ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11088  ast_cli(fd,
11089  "===\n"
11090  "=== ---------------------------------------------------------\n"
11091  "===\n");
11092  }
11093 
11094  ast_cli(fd,
11095  "=============================================================\n"
11096  "\n");
11097 
11098  ast_config_destroy(cfg);
11099 
11100  return CLI_SUCCESS;
11101 }
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define SENTINEL
Definition: compiler.h:75
const char * value
Definition: config.h:79
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
const char * name
Definition: config.h:77
#define CLI_FAILURE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:43
struct ast_variable * next
Definition: config.h:82
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2650
static void start_poll_thread ( void  )
static

Definition at line 11569 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_log(), ast_pthread_create, LOG_ERROR, mb_poll_thread(), mwi_sub_event_cb(), and mwi_unsub_event_cb().

Referenced by actual_load_config().

11570 {
11571  int errcode;
11572  mwi_sub_sub = ast_event_subscribe(AST_EVENT_SUB, mwi_sub_event_cb, "Voicemail MWI subscription", NULL,
11575 
11576  mwi_unsub_sub = ast_event_subscribe(AST_EVENT_UNSUB, mwi_unsub_event_cb, "Voicemail MWI subscription", NULL,
11579 
11580  if (mwi_sub_sub)
11582 
11583  poll_thread_run = 1;
11584 
11585  if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
11586  ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
11587  }
11588 }
void ast_event_report_subs(const struct ast_event_sub *sub)
Report current subscriptions to a subscription subscriber.
Definition: event.c:701
static pthread_t poll_thread
static void * mb_poll_thread(void *data)
static void mwi_sub_event_cb(const struct ast_event *event, void *userdata)
Event type Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
Definition: event_defs.h:95
static void mwi_unsub_event_cb(const struct ast_event *event, void *userdata)
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:418
static struct ast_event_sub * mwi_unsub_sub
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
static struct ast_event_sub * mwi_sub_sub
static unsigned char poll_thread_run
static void stop_poll_thread ( void  )
static

Definition at line 11590 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

11591 {
11592  poll_thread_run = 0;
11593 
11594  if (mwi_sub_sub) {
11596  mwi_sub_sub = NULL;
11597  }
11598 
11599  if (mwi_unsub_sub) {
11601  mwi_unsub_sub = NULL;
11602  }
11603 
11607 
11608  pthread_join(poll_thread, NULL);
11609 
11611 }
static pthread_t poll_thread
#define ast_mutex_lock(a)
Definition: lock.h:155
static ast_cond_t poll_cond
#define ast_cond_signal(cond)
Definition: lock.h:169
#define AST_PTHREADT_NULL
Definition: lock.h:65
static ast_mutex_t poll_lock
static struct ast_event_sub * mwi_unsub_sub
static struct ast_event_sub * mwi_sub_sub
static unsigned char poll_thread_run
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
#define ast_mutex_unlock(a)
Definition: lock.h:156
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 984 of file app_voicemail.c.

References input().

Referenced by make_email_file(), and sendpage().

985 {
986  char *bufptr = buf;
987  for (; *input; input++) {
988  if (*input < 32) {
989  continue;
990  }
991  *bufptr++ = *input;
992  if (bufptr == buf + buflen - 1) {
993  break;
994  }
995  }
996  *bufptr = '\0';
997  return buf;
998 }
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1575
static const char * substitute_escapes ( const char *  value)
static

Definition at line 11736 of file app_voicemail.c.

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

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

11737 {
11738  char *current;
11739 
11740  /* Add 16 for fudge factor */
11741  struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11742 
11743  ast_str_reset(str);
11744 
11745  /* Substitute strings \r, \n, and \t into the appropriate characters */
11746  for (current = (char *) value; *current; current++) {
11747  if (*current == '\\') {
11748  current++;
11749  if (!*current) {
11750  ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11751  break;
11752  }
11753  switch (*current) {
11754  case '\\':
11755  ast_str_append(&str, 0, "\\");
11756  break;
11757  case 'r':
11758  ast_str_append(&str, 0, "\r");
11759  break;
11760  case 'n':
11761 #ifdef IMAP_STORAGE
11762  if (!str->used || str->str[str->used - 1] != '\r') {
11763  ast_str_append(&str, 0, "\r");
11764  }
11765 #endif
11766  ast_str_append(&str, 0, "\n");
11767  break;
11768  case 't':
11769  ast_str_append(&str, 0, "\t");
11770  break;
11771  default:
11772  ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11773  break;
11774  }
11775  } else {
11776  ast_str_append(&str, 0, "%c", *current);
11777  }
11778  }
11779 
11780  return ast_str_buffer(str);
11781 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
const char * str
Definition: app_jack.c:144
int value
Definition: syslog.c:39
#define AST_LOG_NOTICE
Definition: logger.h:138
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
static int unload_module ( void  )
static

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

13050 {
13051  int res;
13052 
13059  res |= ast_manager_unregister("VoicemailUsersList");
13060  res |= ast_data_unregister(NULL);
13061 #ifdef TEST_FRAMEWORK
13062  res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13063  res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13064  res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13065  res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13066  res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13067 #endif
13071 
13073  stop_poll_thread();
13074 
13076  ast_unload_realtime("voicemail");
13077  ast_unload_realtime("voicemail_data");
13078 
13079  free_vm_users();
13080  free_vm_zones();
13081  return res;
13082 }
static void free_vm_zones(void)
Free the zones structure.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void free_vm_users(void)
Free the users structure.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: config.c:2630
static pthread_t poll_thread
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static char * sayname_app
static struct ast_custom_function mailbox_exists_acf
static char * app
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define ast_data_unregister(path)
Definition: data.h:394
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static struct ast_taskprocessor * mwi_subscription_tps
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
static struct ast_cli_entry cli_voicemail[]
static char * app2
static char * app3
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static char * app4
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
struct ao2_container * inprocess_container
static void stop_poll_thread(void)
void ast_uninstall_vm_functions(void)
Definition: app.c:412
static int valid_config ( const struct ast_config cfg)
inlinestatic

Check if configuration file is valid.

Definition at line 1506 of file app_voicemail.c.

References CONFIG_STATUS_FILEINVALID.

Referenced by advanced_options(), make_email_file(), play_message(), prep_email_sub_vars(), read_password_from_file(), vm_change_password(), and vm_forwardoptions().

1507 {
1508  return cfg && cfg != CONFIG_STATUS_FILEINVALID;
1509 }
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static int vm_allocate_dh ( struct vm_state vms,
struct ast_vm_user vmu,
int  count_msg 
)
static

Definition at line 1767 of file app_voicemail.c.

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

Referenced by open_mailbox().

1767  {
1768 
1769  int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
1770 
1771  /* remove old allocation */
1772  if (vms->deleted) {
1773  ast_free(vms->deleted);
1774  vms->deleted = NULL;
1775  }
1776  if (vms->heard) {
1777  ast_free(vms->heard);
1778  vms->heard = NULL;
1779  }
1780  vms->dh_arraysize = 0;
1781 
1782  if (arraysize > 0) {
1783  if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
1784  return -1;
1785  }
1786  if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
1787  ast_free(vms->deleted);
1788  vms->deleted = NULL;
1789  return -1;
1790  }
1791  vms->dh_arraysize = arraysize;
1792  }
1793 
1794  return 0;
1795 }
int dh_arraysize
int * heard
#define ast_free(a)
Definition: astmm.h:97
int * deleted
#define ast_calloc(a, b)
Definition: astmm.h:82
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 9744 of file app_voicemail.c.

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

Referenced by vm_execmain(), and vmauthenticate().

9747 {
9748  int useadsi = 0, valid = 0, logretries = 0;
9749  char password[AST_MAX_EXTENSION]="", *passptr;
9750  struct ast_vm_user vmus, *vmu = NULL;
9751 
9752  /* If ADSI is supported, setup login screen */
9753  adsi_begin(chan, &useadsi);
9754  if (!skipuser && useadsi)
9755  adsi_login(chan);
9756  if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
9757  ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
9758  return -1;
9759  }
9760 
9761  /* Authenticate them and get their mailbox/password */
9762 
9763  while (!valid && (logretries < max_logins)) {
9764  /* Prompt for, and read in the username */
9765  if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
9766  ast_log(AST_LOG_WARNING, "Couldn't read username\n");
9767  return -1;
9768  }
9769  if (ast_strlen_zero(mailbox)) {
9770  if (chan->caller.id.number.valid && chan->caller.id.number.str) {
9771  ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
9772  } else {
9773  ast_verb(3, "Username not entered\n");
9774  return -1;
9775  }
9776  } else if (mailbox[0] == '*') {
9777  /* user entered '*' */
9778  ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
9779  if (ast_exists_extension(chan, chan->context, "a", 1,
9780  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
9781  return -1;
9782  }
9783  ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
9784  mailbox[0] = '\0';
9785  }
9786 
9787  if (useadsi)
9788  adsi_password(chan);
9789 
9790  if (!ast_strlen_zero(prefix)) {
9791  char fullusername[80] = "";
9792  ast_copy_string(fullusername, prefix, sizeof(fullusername));
9793  strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
9794  ast_copy_string(mailbox, fullusername, mailbox_size);
9795  }
9796 
9797  ast_debug(1, "Before find user for mailbox %s\n", mailbox);
9798  vmu = find_user(&vmus, context, mailbox);
9799  if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
9800  /* saved password is blank, so don't bother asking */
9801  password[0] = '\0';
9802  } else {
9803  if (ast_streamfile(chan, vm_password, chan->language)) {
9804  ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
9805  return -1;
9806  }
9807  if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
9808  ast_log(AST_LOG_WARNING, "Unable to read password\n");
9809  return -1;
9810  } else if (password[0] == '*') {
9811  /* user entered '*' */
9812  ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
9813  if (ast_exists_extension(chan, chan->context, "a", 1,
9814  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
9815  mailbox[0] = '*';
9816  return -1;
9817  }
9818  ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
9819  mailbox[0] = '\0';
9820  /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
9821  vmu = NULL;
9822  }
9823  }
9824 
9825  if (vmu) {
9826  passptr = vmu->password;
9827  if (passptr[0] == '-') passptr++;
9828  }
9829  if (vmu && !strcmp(passptr, password))
9830  valid++;
9831  else {
9832  ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
9833  if (!ast_strlen_zero(prefix))
9834  mailbox[0] = '\0';
9835  }
9836  logretries++;
9837  if (!valid) {
9838  if (skipuser || logretries >= max_logins) {
9839  if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
9840  ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
9841  return -1;
9842  }
9843  } else {
9844  if (useadsi)
9845  adsi_login(chan);
9846  if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
9847  ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
9848  return -1;
9849  }
9850  }
9851  if (ast_waitstream(chan, "")) /* Channel is hung up */
9852  return -1;
9853  }
9854  }
9855  if (!valid && (logretries >= max_logins)) {
9856  ast_stopstream(chan);
9857  ast_play_and_wait(chan, "vm-goodbye");
9858  return -1;
9859  }
9860  if (vmu && !skipuser) {
9861  memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
9862  }
9863  return 0;
9864 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define AST_LOG_WARNING
Definition: logger.h:149
static void adsi_login(struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:243
static void adsi_begin(struct ast_channel *chan, int *useadsi)
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
static void adsi_password(struct ast_channel *chan)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
static char vm_password[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:5837
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
const ast_string_field language
Definition: channel.h:787
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
char password[80]
static char prefix[MAX_PREFIX]
Definition: http.c:107
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int vm_box_exists ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 10959 of file app_voicemail.c.

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

Referenced by load_module().

10960 {
10961  struct ast_vm_user svm;
10962  char *context, *box;
10964  AST_APP_ARG(mbox);
10965  AST_APP_ARG(options);
10966  );
10967  static int dep_warning = 0;
10968 
10969  if (ast_strlen_zero(data)) {
10970  ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10971  return -1;
10972  }
10973 
10974  if (!dep_warning) {
10975  dep_warning = 1;
10976  ast_log(AST_LOG_WARNING, "MailboxExists is deprecated. Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10977  }
10978 
10979  box = ast_strdupa(data);
10980 
10982 
10983  if (args.options) {
10984  }
10985 
10986  if ((context = strchr(args.mbox, '@'))) {
10987  *context = '\0';
10988  context++;
10989  }
10990 
10991  if (find_user(&svm, context, args.mbox)) {
10992  pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10993  } else
10994  pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10995 
10996  return 0;
10997 }
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define AST_LOG_WARNING
Definition: logger.h:149
static const char * mbox(struct ast_vm_user *vmu, int id)
#define AST_LOG_ERROR
Definition: logger.h:160
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
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
chanThe channel for the current user. We read the language property from this.
vmspassed into the language-specific vm_browse_messages function.
vmupassed 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 9726 of file app_voicemail.c.

References ast_channel::language, vm_browse_messages_en(), vm_browse_messages_he(), vm_browse_messages_latin(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

9727 {
9728  if (!strncasecmp(chan->language, "es", 2) ||
9729  !strncasecmp(chan->language, "it", 2) ||
9730  !strncasecmp(chan->language, "pt", 2) ||
9731  !strncasecmp(chan->language, "gr", 2)) { /* SPANISH, ITALIAN, PORTUGUESE or GREEK */
9732  return vm_browse_messages_latin(chan, vms, vmu);
9733  } else if (!strncasecmp(chan->language, "he", 2)) { /* HEBREW */
9734  return vm_browse_messages_he(chan, vms, vmu);
9735  } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE */
9736  return vm_browse_messages_vi(chan, vms, vmu);
9737  } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) */
9738  return vm_browse_messages_zh(chan, vms, vmu);
9739  } else { /* Default to English syntax */
9740  return vm_browse_messages_en(chan, vms, vmu);
9741  }
9742 }
static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Default English syntax for &#39;You have N messages&#39; greeting.
static int vm_browse_messages_vi(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Vietnamese syntax for &#39;You have N messages&#39; greeting.
static int vm_browse_messages_zh(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Chinese (Taiwan)syntax for &#39;You have N messages&#39; greeting.
static int vm_browse_messages_latin(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Common LATIN languages syntax for &#39;You have N messages&#39; greeting.
static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
const ast_string_field language
Definition: channel.h:787
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 9607 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().

9608 {
9609  int cmd = 0;
9610 
9611  if (vms->lastmsg > -1) {
9612  cmd = play_message(chan, vmu, vms);
9613  } else {
9614  cmd = ast_play_and_wait(chan, "vm-youhave");
9615  if (!cmd)
9616  cmd = ast_play_and_wait(chan, "vm-no");
9617  if (!cmd) {
9618  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
9619  cmd = ast_play_and_wait(chan, vms->fn);
9620  }
9621  if (!cmd)
9622  cmd = ast_play_and_wait(chan, "vm-messages");
9623  }
9624  return cmd;
9625 }
char fn[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
char curbox[80]
static int vm_browse_messages_he ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Definition at line 9583 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

9584 {
9585  int cmd = 0;
9586 
9587  if (vms->lastmsg > -1) {
9588  cmd = play_message(chan, vmu, vms);
9589  } else {
9590  if (!strcasecmp(vms->fn, "INBOX")) {
9591  cmd = ast_play_and_wait(chan, "vm-nonewmessages");
9592  } else {
9593  cmd = ast_play_and_wait(chan, "vm-nomessages");
9594  }
9595  }
9596  return cmd;
9597 }
char fn[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_browse_messages_latin ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Common LATIN languages syntax for 'You have N messages' greeting.

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

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

9637 {
9638  int cmd;
9639 
9640  if (vms->lastmsg > -1) {
9641  cmd = play_message(chan, vmu, vms);
9642  } else {
9643  cmd = ast_play_and_wait(chan, "vm-youhaveno");
9644  if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
9645  if (!cmd) {
9646  snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
9647  cmd = ast_play_and_wait(chan, vms->fn);
9648  }
9649  if (!cmd)
9650  cmd = ast_play_and_wait(chan, "vm-messages");
9651  } else {
9652  if (!cmd)
9653  cmd = ast_play_and_wait(chan, "vm-messages");
9654  if (!cmd) {
9655  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
9656  cmd = ast_play_and_wait(chan, vms->fn);
9657  }
9658  }
9659  }
9660  return cmd;
9661 }
char fn[PATH_MAX]
char vmbox[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
char curbox[80]
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 9699 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().

9700 {
9701  int cmd = 0;
9702 
9703  if (vms->lastmsg > -1) {
9704  cmd = play_message(chan, vmu, vms);
9705  } else {
9706  cmd = ast_play_and_wait(chan, "vm-no");
9707  if (!cmd) {
9708  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
9709  cmd = ast_play_and_wait(chan, vms->fn);
9710  }
9711  }
9712  return cmd;
9713 }
char fn[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
char curbox[80]
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 9671 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().

9672 {
9673  int cmd;
9674 
9675  if (vms->lastmsg > -1) {
9676  cmd = play_message(chan, vmu, vms);
9677  } else {
9678  cmd = ast_play_and_wait(chan, "vm-you");
9679  if (!cmd)
9680  cmd = ast_play_and_wait(chan, "vm-haveno");
9681  if (!cmd)
9682  cmd = ast_play_and_wait(chan, "vm-messages");
9683  if (!cmd) {
9684  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
9685  cmd = ast_play_and_wait(chan, vms->fn);
9686  }
9687  }
9688  return cmd;
9689 }
char fn[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
char curbox[80]
static void vm_change_password ( struct ast_vm_user vmu,
const char *  newpassword 
)
static

The handler for the change password option.

Parameters
vmuThe voicemail user to work with.
newpasswordThe 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 1518 of file app_voicemail.c.

References ast_alloca, ast_category_browse(), ast_category_get(), ast_config_destroy(), ast_config_load, ast_config_text_file_save(), ast_copy_string(), ast_debug, ast_free, ast_log(), AST_LOG_WARNING, ast_test_suite_event_notify, ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, 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(), valid_config(), value, var, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser(), and vm_options().

1519 {
1520  struct ast_config *cfg = NULL;
1521  struct ast_variable *var = NULL;
1522  struct ast_category *cat = NULL;
1523  char *category = NULL, *value = NULL, *new = NULL;
1524  const char *tmp = NULL;
1525  struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
1526  char secretfn[PATH_MAX] = "";
1527  int found = 0;
1528 
1529  if (!change_password_realtime(vmu, newpassword))
1530  return;
1531 
1532  /* check if we should store the secret in the spool directory next to the messages */
1533  switch (vmu->passwordlocation) {
1534  case OPT_PWLOC_SPOOLDIR:
1535  snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
1536  if (write_password_to_file(secretfn, newpassword) == 0) {
1537  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
1538  ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
1539  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1540  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1541  break;
1542  } else {
1543  ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1544  }
1545  /* Fall-through */
1547  if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
1548  while ((category = ast_category_browse(cfg, category))) {
1549  if (!strcasecmp(category, vmu->context)) {
1550  if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
1551  ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
1552  break;
1553  }
1554  value = strstr(tmp, ",");
1555  if (!value) {
1556  new = ast_alloca(strlen(newpassword)+1);
1557  sprintf(new, "%s", newpassword);
1558  } else {
1559  new = ast_alloca((strlen(value) + strlen(newpassword) + 1));
1560  sprintf(new, "%s%s", newpassword, value);
1561  }
1562  if (!(cat = ast_category_get(cfg, category))) {
1563  ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
1564  break;
1565  }
1566  ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
1567  found = 1;
1568  }
1569  }
1570  /* save the results */
1571  if (found) {
1572  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1573  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1574  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1575  ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
1576  ast_config_destroy(cfg);
1577  break;
1578  }
1579 
1580  ast_config_destroy(cfg);
1581  }
1582  /* Fall-through */
1583  case OPT_PWLOC_USERSCONF:
1584  /* check users.conf and update the password stored for the mailbox */
1585  /* if no vmsecret entry exists create one. */
1586  if ((cfg = ast_config_load("users.conf", config_flags)) && valid_config(cfg)) {
1587  ast_debug(4, "we are looking for %s\n", vmu->mailbox);
1588  for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
1589  ast_debug(4, "users.conf: %s\n", category);
1590  if (!strcasecmp(category, vmu->mailbox)) {
1591  if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
1592  ast_debug(3, "looks like we need to make vmsecret!\n");
1593  var = ast_variable_new("vmsecret", newpassword, "");
1594  } else {
1595  var = NULL;
1596  }
1597  new = ast_alloca(strlen(newpassword) + 1);
1598  sprintf(new, "%s", newpassword);
1599  if (!(cat = ast_category_get(cfg, category))) {
1600  ast_debug(4, "failed to get category!\n");
1601  ast_free(var);
1602  break;
1603  }
1604  if (!var) {
1605  ast_variable_update(cat, "vmsecret", new, NULL, 0);
1606  } else {
1607  ast_variable_append(cat, var);
1608  }
1609  found = 1;
1610  break;
1611  }
1612  }
1613  /* save the results and clean things up */
1614  if (found) {
1615  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
1616  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1617  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1618  ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
1619  }
1620 
1621  ast_config_destroy(cfg);
1622  }
1623  }
1624 }
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define AST_LOG_WARNING
Definition: logger.h:149
#define var
Definition: ast_expr2f.c:606
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Definition: config.c:1977
int value
Definition: syslog.c:39
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name)
Retrieve a category if it exists.
Definition: config.c:709
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define VOICEMAIL_CONFIG
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
char mailbox[AST_MAX_EXTENSION]
int passwordlocation
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
char context[AST_MAX_CONTEXT]
static int write_password_to_file(const char *secretfn, const char *password)
static char VM_SPOOL_DIR[PATH_MAX]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: config.c:483
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
Update variable value within a config.
Definition: config.c:942
Structure used to handle boolean flags.
Definition: utils.h:200
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
char password[80]
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
static void vm_change_password_shell ( struct ast_vm_user vmu,
char *  newpassword 
)
static

Definition at line 1626 of file app_voicemail.c.

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

Referenced by vm_newuser(), and vm_options().

1627 {
1628  char buf[255];
1629  snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
1630  ast_debug(1, "External password: %s\n",buf);
1631  if (!ast_safe_system(buf)) {
1632  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
1633  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1634  /* Reset the password in memory, too */
1635  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1636  }
1637 }
static char ext_pass_cmd[128]
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char password[80]
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
static char* vm_check_password_shell ( char *  command,
char *  buf,
size_t  len 
)
static

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

1182 {
1183  int fds[2], pid = 0;
1184 
1185  memset(buf, 0, len);
1186 
1187  if (pipe(fds)) {
1188  snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
1189  } else {
1190  /* good to go*/
1191  pid = ast_safe_fork(0);
1192 
1193  if (pid < 0) {
1194  /* ok maybe not */
1195  close(fds[0]);
1196  close(fds[1]);
1197  snprintf(buf, len, "FAILURE: Fork failed");
1198  } else if (pid) {
1199  /* parent */
1200  close(fds[1]);
1201  if (read(fds[0], buf, len) < 0) {
1202  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
1203  }
1204  close(fds[0]);
1205  } else {
1206  /* child */
1208  AST_APP_ARG(v)[20];
1209  );
1210  char *mycmd = ast_strdupa(command);
1211 
1212  close(fds[0]);
1213  dup2(fds[1], STDOUT_FILENO);
1214  close(fds[1]);
1215  ast_close_fds_above_n(STDOUT_FILENO);
1216 
1217  AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
1218 
1219  execv(arg.v[0], arg.v);
1220  printf("FAILURE: %s", strerror(errno));
1221  _exit(0);
1222  }
1223  }
1224  return buf;
1225 }
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: app.c:2242
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
Definition: app.h:619
static int vm_delete ( char *  file)
static

Removes the voicemail sound and information file.

Parameters
fileThe 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 4229 of file app_voicemail.c.

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

Referenced by copy_message(), and notify_new_message().

4230 {
4231  char *txt;
4232  int txtsize = 0;
4233 
4234  txtsize = (strlen(file) + 5)*sizeof(char);
4235  txt = ast_alloca(txtsize);
4236  /* Sprintf here would safe because we alloca'd exactly the right length,
4237  * but trying to eliminate all sprintf's anyhow
4238  */
4239  if (ast_check_realtime("voicemail_data")) {
4240  ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
4241  }
4242  snprintf(txt, txtsize, "%s.txt", file);
4243  unlink(txt);
4244  return ast_filedelete(file, NULL);
4245 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:931
#define SENTINEL
Definition: compiler.h:75
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
Definition: config.c:2750
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
static int vm_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 10618 of file app_voicemail.c.

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

Referenced by load_module(), and play_record_review().

10619 {
10620  int res = 0;
10621  char *tmp;
10622  struct leave_vm_options leave_options;
10623  struct ast_flags flags = { 0 };
10624  char *opts[OPT_ARG_ARRAY_SIZE];
10626  AST_APP_ARG(argv0);
10627  AST_APP_ARG(argv1);
10628  );
10629 
10630  memset(&leave_options, 0, sizeof(leave_options));
10631 
10632  if (chan->_state != AST_STATE_UP)
10633  ast_answer(chan);
10634 
10635  if (!ast_strlen_zero(data)) {
10636  tmp = ast_strdupa(data);
10638  if (args.argc == 2) {
10639  if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10640  return -1;
10642  if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10643  int gain;
10644 
10645  if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10646  ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10647  return -1;
10648  } else {
10649  leave_options.record_gain = (signed char) gain;
10650  }
10651  }
10652  if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10653  if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10654  leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10655  }
10656  }
10657  } else {
10658  char temp[256];
10659  res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10660  if (res < 0)
10661  return res;
10662  if (ast_strlen_zero(temp))
10663  return 0;
10664  args.argv0 = ast_strdupa(temp);
10665  }
10666 
10667  res = leave_voicemail(chan, args.argv0, &leave_options);
10668  if (res == 't') {
10669  ast_play_and_wait(chan, "vm-goodbye");
10670  res = 0;
10671  }
10672 
10673  if (res == OPERATOR_EXIT) {
10674  res = 0;
10675  }
10676 
10677  if (res == ERROR_LOCK_PATH) {
10678  ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10679  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10680  res = 0;
10681  }
10682 
10683  return res;
10684 }
int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
Definition: app.c:178
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ERROR_LOCK_PATH
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
#define AST_LOG_WARNING
Definition: logger.h:149
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define AST_LOG_ERROR
Definition: logger.h:160
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
#define OPERATOR_EXIT
enum ast_channel_state _state
Definition: channel.h:839
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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.
Structure used to handle boolean flags.
Definition: utils.h:200
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:635
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
static struct ast_app_option vm_app_options[128]
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int vm_execmain ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 9866 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_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_LOG_WARNING, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_test_suite_assert, ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, vm_state::context, ast_channel::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, ast_vm_user::dialout, dialout(), ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), vm_state::fn, forward_message(), free_user(), get_folder2(), get_folder_by_name(), has_voicemail(), vm_state::heard, language, ast_vm_user::language, ast_channel::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, OLD_FOLDER, vm_state::oldmessages, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), vm_state::repeats, run_externnotify(), save_to_folder(), say_and_wait(), vm_state::starting, vm_state::urgentmessages, vm_state::username, vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, VM_SVMAIL, and vm_state::vmbox.

Referenced by load_module().

9867 {
9868  /* XXX This is, admittedly, some pretty horrendous code. For some
9869  reason it just seemed a lot easier to do with GOTO's. I feel
9870  like I'm back in my GWBASIC days. XXX */
9871  int res = -1;
9872  int cmd = 0;
9873  int valid = 0;
9874  char prefixstr[80] ="";
9875  char ext_context[256]="";
9876  int box;
9877  int useadsi = 0;
9878  int skipuser = 0;
9879  struct vm_state vms;
9880  struct ast_vm_user *vmu = NULL, vmus;
9881  char *context = NULL;
9882  int silentexit = 0;
9883  struct ast_flags flags = { 0 };
9884  signed char record_gain = 0;
9885  int play_auto = 0;
9886  int play_folder = 0;
9887  int in_urgent = 0;
9888 #ifdef IMAP_STORAGE
9889  int deleted = 0;
9890 #endif
9891 
9892  /* Add the vm_state to the active list and keep it active */
9893  memset(&vms, 0, sizeof(vms));
9894 
9895  vms.lastmsg = -1;
9896 
9897  memset(&vmus, 0, sizeof(vmus));
9898 
9899  ast_test_suite_event_notify("START", "Message: vm_execmain started");
9900  if (chan->_state != AST_STATE_UP) {
9901  ast_debug(1, "Before ast_answer\n");
9902  ast_answer(chan);
9903  }
9904 
9905  if (!ast_strlen_zero(data)) {
9906  char *opts[OPT_ARG_ARRAY_SIZE];
9907  char *parse;
9909  AST_APP_ARG(argv0);
9910  AST_APP_ARG(argv1);
9911  );
9912 
9913  parse = ast_strdupa(data);
9914 
9915  AST_STANDARD_APP_ARGS(args, parse);
9916 
9917  if (args.argc == 2) {
9918  if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
9919  return -1;
9920  if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
9921  int gain;
9922  if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
9923  if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
9924  ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
9925  return -1;
9926  } else {
9927  record_gain = (signed char) gain;
9928  }
9929  } else {
9930  ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
9931  }
9932  }
9933  if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
9934  play_auto = 1;
9935  if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
9936  /* See if it is a folder name first */
9937  if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
9938  if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
9939  play_folder = -1;
9940  }
9941  } else {
9942  play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
9943  }
9944  } else {
9945  ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
9946  }
9947  if (play_folder > 9 || play_folder < 0) {
9949  "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
9950  opts[OPT_ARG_PLAYFOLDER]);
9951  play_folder = 0;
9952  }
9953  }
9954  } else {
9955  /* old style options parsing */
9956  while (*(args.argv0)) {
9957  if (*(args.argv0) == 's')
9958  ast_set_flag(&flags, OPT_SILENT);
9959  else if (*(args.argv0) == 'p')
9961  else
9962  break;
9963  (args.argv0)++;
9964  }
9965 
9966  }
9967 
9968  valid = ast_test_flag(&flags, OPT_SILENT);
9969 
9970  if ((context = strchr(args.argv0, '@')))
9971  *context++ = '\0';
9972 
9973  if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
9974  ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
9975  else
9976  ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
9977 
9978  if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
9979  skipuser++;
9980  else
9981  valid = 0;
9982  }
9983 
9984  if (!valid)
9985  res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
9986 
9987  ast_debug(1, "After vm_authenticate\n");
9988 
9989  if (vms.username[0] == '*') {
9990  ast_debug(1, "user pressed * in context '%s'\n", chan->context);
9991 
9992  /* user entered '*' */
9993  if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
9994  ast_test_suite_event_notify("REDIRECT", "Message: redirecting user to 'a' extension");
9995  res = 0; /* prevent hangup */
9996  goto out;
9997  }
9998  }
9999 
10000  if (!res) {
10001  valid = 1;
10002  if (!skipuser)
10003  vmu = &vmus;
10004  } else {
10005  res = 0;
10006  }
10007 
10008  /* If ADSI is supported, setup login screen */
10009  adsi_begin(chan, &useadsi);
10010 
10011  ast_test_suite_assert(valid);
10012  if (!valid) {
10013  goto out;
10014  }
10015  ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated");
10016 
10017 #ifdef IMAP_STORAGE
10018  pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
10019  pthread_setspecific(ts_vmstate.key, &vms);
10020 
10021  vms.interactive = 1;
10022  vms.updated = 1;
10023  if (vmu)
10024  ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
10025  vmstate_insert(&vms);
10026  init_vm_state(&vms);
10027 #endif
10028 
10029  /* Set language from config to override channel language */
10030  if (!ast_strlen_zero(vmu->language))
10031  ast_string_field_set(chan, language, vmu->language);
10032 
10033  /* Retrieve urgent, old and new message counts */
10034  ast_debug(1, "Before open_mailbox\n");
10035  res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
10036  if (res < 0)
10037  goto out;
10038  vms.oldmessages = vms.lastmsg + 1;
10039  ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
10040  /* check INBOX */
10041  res = open_mailbox(&vms, vmu, NEW_FOLDER);
10042  if (res < 0)
10043  goto out;
10044  vms.newmessages = vms.lastmsg + 1;
10045  ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
10046  /* Start in Urgent */
10047  in_urgent = 1;
10048  res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
10049  if (res < 0)
10050  goto out;
10051  vms.urgentmessages = vms.lastmsg + 1;
10052  ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
10053 
10054  /* Select proper mailbox FIRST!! */
10055  if (play_auto) {
10056  ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages");
10057  if (vms.urgentmessages) {
10058  in_urgent = 1;
10059  res = open_mailbox(&vms, vmu, 11);
10060  } else {
10061  in_urgent = 0;
10062  res = open_mailbox(&vms, vmu, play_folder);
10063  }
10064  if (res < 0)
10065  goto out;
10066 
10067  /* If there are no new messages, inform the user and hangup */
10068  if (vms.lastmsg == -1) {
10069  in_urgent = 0;
10070  cmd = vm_browse_messages(chan, &vms, vmu);
10071  res = 0;
10072  goto out;
10073  }
10074  } else {
10075  if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
10076  /* If we only have old messages start here */
10077  res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
10078  in_urgent = 0;
10079  play_folder = 1;
10080  if (res < 0)
10081  goto out;
10082  } else if (!vms.urgentmessages && vms.newmessages) {
10083  /* If we have new messages but none are urgent */
10084  in_urgent = 0;
10085  res = open_mailbox(&vms, vmu, NEW_FOLDER);
10086  if (res < 0)
10087  goto out;
10088  }
10089  }
10090 
10091  if (useadsi)
10092  adsi_status(chan, &vms);
10093  res = 0;
10094 
10095  /* Check to see if this is a new user */
10096  if (!strcasecmp(vmu->mailbox, vmu->password) &&
10098  if (ast_play_and_wait(chan, "vm-newuser") == -1)
10099  ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
10100  cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
10101  if ((cmd == 't') || (cmd == '#')) {
10102  /* Timeout */
10103  ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out");
10104  res = 0;
10105  goto out;
10106  } else if (cmd < 0) {
10107  /* Hangup */
10108  ast_test_suite_event_notify("HANGUP", "Message: hangup detected");
10109  res = -1;
10110  goto out;
10111  }
10112  }
10113 #ifdef IMAP_STORAGE
10114  ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
10115  if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
10116  ast_debug(1, "*** QUOTA EXCEEDED!!\n");
10117  cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10118  }
10119  ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
10120  if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
10121  ast_log(AST_LOG_WARNING, "No more messages possible. User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
10122  cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10123  }
10124 #endif
10125 
10126  ast_test_suite_event_notify("INTRO", "Message: playing intro menu");
10127  if (play_auto) {
10128  cmd = '1';
10129  } else {
10130  cmd = vm_intro(chan, vmu, &vms);
10131  }
10132  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10133 
10134  vms.repeats = 0;
10135  vms.starting = 1;
10136  while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
10137  /* Run main menu */
10138  switch (cmd) {
10139  case '1': /* First message */
10140  vms.curmsg = 0;
10141  /* Fall through */
10142  case '5': /* Play current message */
10143  ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
10144  cmd = vm_browse_messages(chan, &vms, vmu);
10145  break;
10146  case '2': /* Change folders */
10147  ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder");
10148  if (useadsi)
10149  adsi_folders(chan, 0, "Change to folder...");
10150 
10151  cmd = get_folder2(chan, "vm-changeto", 0);
10152  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10153  if (cmd == '#') {
10154  cmd = 0;
10155  } else if (cmd > 0) {
10156  cmd = cmd - '0';
10157  res = close_mailbox(&vms, vmu);
10158  if (res == ERROR_LOCK_PATH)
10159  goto out;
10160  /* If folder is not urgent, set in_urgent to zero! */
10161  if (cmd != 11) in_urgent = 0;
10162  res = open_mailbox(&vms, vmu, cmd);
10163  if (res < 0)
10164  goto out;
10165  play_folder = cmd;
10166  cmd = 0;
10167  }
10168  if (useadsi)
10169  adsi_status2(chan, &vms);
10170 
10171  if (!cmd) {
10172  cmd = vm_play_folder_name(chan, vms.vmbox);
10173  }
10174 
10175  vms.starting = 1;
10176  vms.curmsg = 0;
10177  break;
10178  case '3': /* Advanced options */
10179  ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");
10180  cmd = 0;
10181  vms.repeats = 0;
10182  while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
10183  switch (cmd) {
10184  case '1': /* Reply */
10185  if (vms.lastmsg > -1 && !vms.starting) {
10186  cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
10187  if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10188  res = cmd;
10189  goto out;
10190  }
10191  } else {
10192  cmd = ast_play_and_wait(chan, "vm-sorry");
10193  }
10194  cmd = 't';
10195  break;
10196  case '2': /* Callback */
10197  if (!vms.starting)
10198  ast_verb(3, "Callback Requested\n");
10199  if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
10200  cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
10201  if (cmd == 9) {
10202  silentexit = 1;
10203  goto out;
10204  } else if (cmd == ERROR_LOCK_PATH) {
10205  res = cmd;
10206  goto out;
10207  }
10208  } else {
10209  cmd = ast_play_and_wait(chan, "vm-sorry");
10210  }
10211  cmd = 't';
10212  break;
10213  case '3': /* Envelope */
10214  if (vms.lastmsg > -1 && !vms.starting) {
10215  cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
10216  if (cmd == ERROR_LOCK_PATH) {
10217  res = cmd;
10218  goto out;
10219  }
10220  } else {
10221  cmd = ast_play_and_wait(chan, "vm-sorry");
10222  }
10223  cmd = 't';
10224  break;
10225  case '4': /* Dialout */
10226  if (!ast_strlen_zero(vmu->dialout)) {
10227  cmd = dialout(chan, vmu, NULL, vmu->dialout);
10228  if (cmd == 9) {
10229  silentexit = 1;
10230  goto out;
10231  }
10232  } else {
10233  cmd = ast_play_and_wait(chan, "vm-sorry");
10234  }
10235  cmd = 't';
10236  break;
10237 
10238  case '5': /* Leave VoiceMail */
10239  if (ast_test_flag(vmu, VM_SVMAIL)) {
10240  cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
10241  if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10242  res = cmd;
10243  goto out;
10244  }
10245  } else {
10246  cmd = ast_play_and_wait(chan, "vm-sorry");
10247  }
10248  cmd = 't';
10249  break;
10250 
10251  case '*': /* Return to main menu */
10252  cmd = 't';
10253  break;
10254 
10255  default:
10256  cmd = 0;
10257  if (!vms.starting) {
10258  cmd = ast_play_and_wait(chan, "vm-toreply");
10259  }
10260  if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
10261  cmd = ast_play_and_wait(chan, "vm-tocallback");
10262  }
10263  if (!cmd && !vms.starting) {
10264  cmd = ast_play_and_wait(chan, "vm-tohearenv");
10265  }
10266  if (!ast_strlen_zero(vmu->dialout) && !cmd) {
10267  cmd = ast_play_and_wait(chan, "vm-tomakecall");
10268  }
10269  if (ast_test_flag(vmu, VM_SVMAIL) && !cmd) {
10270  cmd = ast_play_and_wait(chan, "vm-leavemsg");
10271  }
10272  if (!cmd) {
10273  cmd = ast_play_and_wait(chan, "vm-starmain");
10274  }
10275  if (!cmd) {
10276  cmd = ast_waitfordigit(chan, 6000);
10277  }
10278  if (!cmd) {
10279  vms.repeats++;
10280  }
10281  if (vms.repeats > 3) {
10282  cmd = 't';
10283  }
10284  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10285  }
10286  }
10287  if (cmd == 't') {
10288  cmd = 0;
10289  vms.repeats = 0;
10290  }
10291  break;
10292  case '4': /* Go to the previous message */
10293  ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1);
10294  if (vms.curmsg > 0) {
10295  vms.curmsg--;
10296  cmd = play_message(chan, vmu, &vms);
10297  } else {
10298  /* Check if we were listening to new
10299  messages. If so, go to Urgent messages
10300  instead of saying "no more messages"
10301  */
10302  if (in_urgent == 0 && vms.urgentmessages > 0) {
10303  /* Check for Urgent messages */
10304  in_urgent = 1;
10305  res = close_mailbox(&vms, vmu);
10306  if (res == ERROR_LOCK_PATH)
10307  goto out;
10308  res = open_mailbox(&vms, vmu, 11); /* Open Urgent folder */
10309  if (res < 0)
10310  goto out;
10311  ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
10312  vms.curmsg = vms.lastmsg;
10313  if (vms.lastmsg < 0) {
10314  cmd = ast_play_and_wait(chan, "vm-nomore");
10315  }
10316  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10317  vms.curmsg = vms.lastmsg;
10318  cmd = play_message(chan, vmu, &vms);
10319  } else {
10320  cmd = ast_play_and_wait(chan, "vm-nomore");
10321  }
10322  }
10323  break;
10324  case '6': /* Go to the next message */
10325  ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1);
10326  if (vms.curmsg < vms.lastmsg) {
10327  vms.curmsg++;
10328  cmd = play_message(chan, vmu, &vms);
10329  } else {
10330  if (in_urgent && vms.newmessages > 0) {
10331  /* Check if we were listening to urgent
10332  * messages. If so, go to regular new messages
10333  * instead of saying "no more messages"
10334  */
10335  in_urgent = 0;
10336  res = close_mailbox(&vms, vmu);
10337  if (res == ERROR_LOCK_PATH)
10338  goto out;
10339  res = open_mailbox(&vms, vmu, NEW_FOLDER);
10340  if (res < 0)
10341  goto out;
10342  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10343  vms.curmsg = -1;
10344  if (vms.lastmsg < 0) {
10345  cmd = ast_play_and_wait(chan, "vm-nomore");
10346  }
10347  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10348  vms.curmsg = 0;
10349  cmd = play_message(chan, vmu, &vms);
10350  } else {
10351  cmd = ast_play_and_wait(chan, "vm-nomore");
10352  }
10353  }
10354  break;
10355  case '7': /* Delete the current message */
10356  if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
10357  vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
10358  if (useadsi)
10359  adsi_delete(chan, &vms);
10360  if (vms.deleted[vms.curmsg]) {
10361  if (play_folder == 0) {
10362  if (in_urgent) {
10363  vms.urgentmessages--;
10364  } else {
10365  vms.newmessages--;
10366  }
10367  }
10368  else if (play_folder == 1)
10369  vms.oldmessages--;
10370  cmd = ast_play_and_wait(chan, "vm-deleted");
10371  } else {
10372  if (play_folder == 0) {
10373  if (in_urgent) {
10374  vms.urgentmessages++;
10375  } else {
10376  vms.newmessages++;
10377  }
10378  }
10379  else if (play_folder == 1)
10380  vms.oldmessages++;
10381  cmd = ast_play_and_wait(chan, "vm-undeleted");
10382  }
10383  if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10384  if (vms.curmsg < vms.lastmsg) {
10385  vms.curmsg++;
10386  cmd = play_message(chan, vmu, &vms);
10387  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10388  vms.curmsg = 0;
10389  cmd = play_message(chan, vmu, &vms);
10390  } else {
10391  /* Check if we were listening to urgent
10392  messages. If so, go to regular new messages
10393  instead of saying "no more messages"
10394  */
10395  if (in_urgent == 1) {
10396  /* Check for new messages */
10397  in_urgent = 0;
10398  res = close_mailbox(&vms, vmu);
10399  if (res == ERROR_LOCK_PATH)
10400  goto out;
10401  res = open_mailbox(&vms, vmu, NEW_FOLDER);
10402  if (res < 0)
10403  goto out;
10404  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10405  vms.curmsg = -1;
10406  if (vms.lastmsg < 0) {
10407  cmd = ast_play_and_wait(chan, "vm-nomore");
10408  }
10409  } else {
10410  cmd = ast_play_and_wait(chan, "vm-nomore");
10411  }
10412  }
10413  }
10414  } else /* Delete not valid if we haven't selected a message */
10415  cmd = 0;
10416 #ifdef IMAP_STORAGE
10417  deleted = 1;
10418 #endif
10419  break;
10420 
10421  case '8': /* Forward the current message */
10422  if (vms.lastmsg > -1) {
10423  cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10424  if (cmd == ERROR_LOCK_PATH) {
10425  res = cmd;
10426  goto out;
10427  }
10428  } else {
10429  /* Check if we were listening to urgent
10430  messages. If so, go to regular new messages
10431  instead of saying "no more messages"
10432  */
10433  if (in_urgent == 1 && vms.newmessages > 0) {
10434  /* Check for new messages */
10435  in_urgent = 0;
10436  res = close_mailbox(&vms, vmu);
10437  if (res == ERROR_LOCK_PATH)
10438  goto out;
10439  res = open_mailbox(&vms, vmu, NEW_FOLDER);
10440  if (res < 0)
10441  goto out;
10442  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10443  vms.curmsg = -1;
10444  if (vms.lastmsg < 0) {
10445  cmd = ast_play_and_wait(chan, "vm-nomore");
10446  }
10447  } else {
10448  cmd = ast_play_and_wait(chan, "vm-nomore");
10449  }
10450  }
10451  break;
10452  case '9': /* Save message to folder */
10453  ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
10454  if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
10455  /* No message selected */
10456  cmd = 0;
10457  break;
10458  }
10459  if (useadsi)
10460  adsi_folders(chan, 1, "Save to folder...");
10461  cmd = get_folder2(chan, "vm-savefolder", 1);
10462  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10463  box = 0; /* Shut up compiler */
10464  if (cmd == '#') {
10465  cmd = 0;
10466  break;
10467  } else if (cmd > 0) {
10468  box = cmd = cmd - '0';
10469  cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
10470  if (cmd == ERROR_LOCK_PATH) {
10471  res = cmd;
10472  goto out;
10473 #ifndef IMAP_STORAGE
10474  } else if (!cmd) {
10475  vms.deleted[vms.curmsg] = 1;
10476 #endif
10477  } else {
10478  vms.deleted[vms.curmsg] = 0;
10479  vms.heard[vms.curmsg] = 0;
10480  }
10481  }
10482  make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
10483  if (useadsi)
10484  adsi_message(chan, &vms);
10485  snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
10486  if (!cmd) {
10487  cmd = ast_play_and_wait(chan, "vm-message");
10488  if (!cmd)
10489  cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
10490  if (!cmd)
10491  cmd = ast_play_and_wait(chan, "vm-savedto");
10492  if (!cmd)
10493  cmd = vm_play_folder_name(chan, vms.fn);
10494  } else {
10495  cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10496  }
10498  if (vms.curmsg < vms.lastmsg) {
10499  vms.curmsg++;
10500  cmd = play_message(chan, vmu, &vms);
10501  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10502  vms.curmsg = 0;
10503  cmd = play_message(chan, vmu, &vms);
10504  } else {
10505  /* Check if we were listening to urgent
10506  messages. If so, go to regular new messages
10507  instead of saying "no more messages"
10508  */
10509  if (in_urgent == 1 && vms.newmessages > 0) {
10510  /* Check for new messages */
10511  in_urgent = 0;
10512  res = close_mailbox(&vms, vmu);
10513  if (res == ERROR_LOCK_PATH)
10514  goto out;
10515  res = open_mailbox(&vms, vmu, NEW_FOLDER);
10516  if (res < 0)
10517  goto out;
10518  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10519  vms.curmsg = -1;
10520  if (vms.lastmsg < 0) {
10521  cmd = ast_play_and_wait(chan, "vm-nomore");
10522  }
10523  } else {
10524  cmd = ast_play_and_wait(chan, "vm-nomore");
10525  }
10526  }
10527  }
10528  break;
10529  case '*': /* Help */
10530  if (!vms.starting) {
10531  cmd = ast_play_and_wait(chan, "vm-onefor");
10532  if (!strncasecmp(chan->language, "he", 2)) {
10533  cmd = ast_play_and_wait(chan, "vm-for");
10534  }
10535  if (!cmd)
10536  cmd = vm_play_folder_name(chan, vms.vmbox);
10537  if (!cmd)
10538  cmd = ast_play_and_wait(chan, "vm-opts");
10539  if (!cmd)
10540  cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
10541  } else
10542  cmd = 0;
10543  break;
10544  case '0': /* Mailbox options */
10545  cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
10546  if (useadsi)
10547  adsi_status(chan, &vms);
10548  break;
10549  default: /* Nothing */
10550  ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
10551  cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
10552  break;
10553  }
10554  }
10555  if ((cmd == 't') || (cmd == '#')) {
10556  /* Timeout */
10557  res = 0;
10558  } else {
10559  /* Hangup */
10560  res = -1;
10561  }
10562 
10563 out:
10564  if (res > -1) {
10565  ast_stopstream(chan);
10566  adsi_goodbye(chan);
10567  if (valid && res != OPERATOR_EXIT) {
10568  if (silentexit)
10569  res = ast_play_and_wait(chan, "vm-dialout");
10570  else
10571  res = ast_play_and_wait(chan, "vm-goodbye");
10572  }
10573  if ((valid && res > 0) || res == OPERATOR_EXIT) {
10574  res = 0;
10575  }
10576  if (useadsi)
10578  }
10579  if (vmu)
10580  close_mailbox(&vms, vmu);
10581  if (valid) {
10582  int new = 0, old = 0, urgent = 0;
10583  snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
10584  ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
10585  /* Urgent flag not passwd to externnotify here */
10586  run_externnotify(vmu->context, vmu->mailbox, NULL);
10587  ast_app_inboxcount2(ext_context, &urgent, &new, &old);
10588  queue_mwi_event(ext_context, urgent, new, old);
10589  }
10590 #ifdef IMAP_STORAGE
10591  /* expunge message - use UID Expunge if supported on IMAP server*/
10592  ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10593  if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10594  ast_mutex_lock(&vms.lock);
10595 #ifdef HAVE_IMAP_TK2006
10596  if (LEVELUIDPLUS (vms.mailstream)) {
10597  mail_expunge_full(vms.mailstream, NIL, EX_UID);
10598  } else
10599 #endif
10600  mail_expunge(vms.mailstream);
10601  ast_mutex_unlock(&vms.lock);
10602  }
10603  /* before we delete the state, we should copy pertinent info
10604  * back to the persistent model */
10605  if (vmu) {
10606  vmstate_delete(&vms);
10607  }
10608 #endif
10609  if (vmu)
10610  free_user(vmu);
10611 
10612 #ifdef IMAP_STORAGE
10613  pthread_setspecific(ts_vmstate.key, NULL);
10614 #endif
10615  return res;
10616 }
static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define ast_test_flag(p, flag)
Definition: utils.h:63
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ERROR_LOCK_PATH
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
#define AST_LOG_WARNING
Definition: logger.h:149
#define VM_MESSAGEWRAP
#define EVENT_FLAG_CALL
Definition: manager.h:72
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
#define ast_mutex_lock(a)
Definition: lock.h:155
static int get_folder_by_name(const char *name)
#define ast_verb(level,...)
Definition: logger.h:243
#define ast_test_suite_assert(exp)
Definition: test.h:185
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
#define VM_SVMAIL
static const char * mbox(struct ast_vm_user *vmu, int id)
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
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 appropria...
static void adsi_begin(struct ast_channel *chan, int *useadsi)
static void run_externnotify(char *context, char *extension, const char *flag)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
#define VM_FORCENAME
static struct ast_flags globalflags
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
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 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 void free_user(struct ast_vm_user *vmu)
int ast_app_inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: app.c:455
static int get_folder2(struct ast_channel *chan, char *fn, int start)
plays a prompt and waits for a keypress.
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
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.
#define OPERATOR_EXIT
enum ast_channel_state _state
Definition: channel.h:839
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 void adsi_folders(struct ast_channel *chan, int start, char *label)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:11261
static void adsi_goodbye(struct ast_channel *chan)
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static struct ast_vm_user * find_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 void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static int maxlogins
Structure used to handle boolean flags.
Definition: utils.h:200
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
char language[MAX_LANGUAGE]
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static struct ast_app_option vm_app_options[128]
char dialout[80]
static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define VM_SKIPAFTERCMD
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
char callback[80]
static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int ast_adsi_unload_session(struct ast_channel *chan)
Definition: adsi.c:87
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
static char vmfmts[80]
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
const ast_string_field language
Definition: channel.h:787
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
char password[80]
#define VM_FORCEGREET
#define ast_mutex_unlock(a)
Definition: lock.h:156
static void queue_mwi_event(const char *box, int urgent, int new, int old)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
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 6910 of file app_voicemail.c.

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

Referenced by forward_message().

6912 {
6913  int cmd = 0;
6914  int retries = 0, prepend_duration = 0, already_recorded = 0;
6915  char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
6916  char textfile[PATH_MAX];
6917  struct ast_config *msg_cfg;
6918  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
6919 #ifndef IMAP_STORAGE
6920  signed char zero_gain = 0;
6921 #endif
6922  const char *duration_str;
6923 
6924  /* Must always populate duration correctly */
6925  make_file(msgfile, sizeof(msgfile), curdir, curmsg);
6926  strcpy(textfile, msgfile);
6927  strcpy(backup, msgfile);
6928  strcpy(backup_textfile, msgfile);
6929  strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
6930  strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
6931  strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
6932 
6933  if ((msg_cfg = ast_config_load(textfile, config_flags)) && valid_config(msg_cfg) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
6934  *duration = atoi(duration_str);
6935  } else {
6936  *duration = 0;
6937  }
6938 
6939  while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
6940  if (cmd)
6941  retries = 0;
6942  switch (cmd) {
6943  case '1':
6944 
6945 #ifdef IMAP_STORAGE
6946  /* Record new intro file */
6947  make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
6948  strncat(vms->introfn, "intro", sizeof(vms->introfn));
6949  ast_play_and_wait(chan, INTRO);
6950  ast_play_and_wait(chan, "beep");
6951  cmd = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag);
6952  if (cmd == -1) {
6953  break;
6954  }
6955  cmd = 't';
6956 #else
6957 
6958  /* prepend a message to the current message, update the metadata and return */
6959 
6960  make_file(msgfile, sizeof(msgfile), curdir, curmsg);
6961  strcpy(textfile, msgfile);
6962  strncat(textfile, ".txt", sizeof(textfile) - 1);
6963  *duration = 0;
6964 
6965  /* if we can't read the message metadata, stop now */
6966  if (!valid_config(msg_cfg)) {
6967  cmd = 0;
6968  break;
6969  }
6970 
6971  /* Back up the original file, so we can retry the prepend and restore it after forward. */
6972 #ifndef IMAP_STORAGE
6973  if (already_recorded) {
6974  ast_filecopy(backup, msgfile, NULL);
6975  copy(backup_textfile, textfile);
6976  }
6977  else {
6978  ast_filecopy(msgfile, backup, NULL);
6979  copy(textfile, backup_textfile);
6980  }
6981 #endif
6982  already_recorded = 1;
6983 
6984  if (record_gain)
6985  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
6986 
6987  cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
6988 
6989  if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
6990  ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
6992  ast_filerename(backup, msgfile, NULL);
6993  }
6994 
6995  if (record_gain)
6996  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
6997 
6998 
6999  if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
7000  *duration = atoi(duration_str);
7001 
7002  if (prepend_duration) {
7003  struct ast_category *msg_cat;
7004  /* need enough space for a maximum-length message duration */
7005  char duration_buf[12];
7006 
7007  *duration += prepend_duration;
7008  msg_cat = ast_category_get(msg_cfg, "message");
7009  snprintf(duration_buf, 11, "%ld", *duration);
7010  if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
7011  ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
7012  }
7013  }
7014 
7015 #endif
7016  break;
7017  case '2':
7018  /* NULL out introfile so we know there is no intro! */
7019 #ifdef IMAP_STORAGE
7020  *vms->introfn = '\0';
7021 #endif
7022  cmd = 't';
7023  break;
7024  case '*':
7025  cmd = '*';
7026  break;
7027  default:
7028  /* If time_out and return to menu, reset already_recorded */
7029  already_recorded = 0;
7030 
7031  cmd = ast_play_and_wait(chan, "vm-forwardoptions");
7032  /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
7033  if (!cmd) {
7034  cmd = ast_play_and_wait(chan, "vm-starmain");
7035  /* "press star to return to the main menu" */
7036  }
7037  if (!cmd) {
7038  cmd = ast_waitfordigit(chan, 6000);
7039  }
7040  if (!cmd) {
7041  retries++;
7042  }
7043  if (retries > 3) {
7044  cmd = '*'; /* Let's cancel this beast */
7045  }
7046  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
7047  }
7048  }
7049 
7050  if (valid_config(msg_cfg))
7051  ast_config_destroy(msg_cfg);
7052  if (prepend_duration)
7053  *duration = prepend_duration;
7054 
7055  if (already_recorded && cmd == -1) {
7056  /* restore original message if prepention cancelled */
7057  ast_filerename(backup, msgfile, NULL);
7058  rename(backup_textfile, textfile);
7059  }
7060 
7061  if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */
7062  cmd = 0;
7063  return cmd;
7064 }
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:941
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static int maxsilence
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Definition: config.c:1977
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define INTRO
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
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 appropria...
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name)
Retrieve a category if it exists.
Definition: config.c:709
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static int silencethreshold
static char vm_pls_try_again[80]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
Update variable value within a config.
Definition: config.c:942
Structure used to handle boolean flags.
Definition: utils.h:200
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence_ms)
Record a file based on input frm a channel. Recording is performed in &#39;prepend&#39; mode which works a li...
Definition: app.c:1188
#define AST_OPTION_RXGAIN
Definition: frame.h:463
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:936
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char vm_prepend_timeout[80]
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 9264 of file app_voicemail.c.

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

Referenced by vm_execmain().

9265 {
9266  if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
9267  return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
9268  } else { /* Default to ENGLISH */
9269  return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
9270  }
9271 }
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)
const ast_string_field language
Definition: channel.h:787
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 9152 of file app_voicemail.c.

References ast_mutex_lock, ast_mutex_unlock, 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().

9153 {
9154  int res = 0;
9155  /* Play instructions and wait for new command */
9156  while (!res) {
9157  if (vms->starting) {
9158  if (vms->lastmsg > -1) {
9159  if (skipadvanced)
9160  res = ast_play_and_wait(chan, "vm-onefor-full");
9161  else
9162  res = ast_play_and_wait(chan, "vm-onefor");
9163  if (!res)
9164  res = vm_play_folder_name(chan, vms->vmbox);
9165  }
9166  if (!res) {
9167  if (skipadvanced)
9168  res = ast_play_and_wait(chan, "vm-opts-full");
9169  else
9170  res = ast_play_and_wait(chan, "vm-opts");
9171  }
9172  } else {
9173  /* Added for additional help */
9174  if (skipadvanced) {
9175  res = ast_play_and_wait(chan, "vm-onefor-full");
9176  if (!res)
9177  res = vm_play_folder_name(chan, vms->vmbox);
9178  res = ast_play_and_wait(chan, "vm-opts-full");
9179  }
9180  /* Logic:
9181  * If the current message is not the first OR
9182  * if we're listening to the first new message and there are
9183  * also urgent messages, then prompt for navigation to the
9184  * previous message
9185  */
9186  if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
9187  res = ast_play_and_wait(chan, "vm-prev");
9188  }
9189  if (!res && !skipadvanced)
9190  res = ast_play_and_wait(chan, "vm-advopts");
9191  if (!res)
9192  res = ast_play_and_wait(chan, "vm-repeat");
9193  /* Logic:
9194  * If we're not listening to the last message OR
9195  * we're listening to the last urgent message and there are
9196  * also new non-urgent messages, then prompt for navigation
9197  * to the next message
9198  */
9199  if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
9200  (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
9201  res = ast_play_and_wait(chan, "vm-next");
9202  }
9203  if (!res) {
9204  int curmsg_deleted;
9205 #ifdef IMAP_STORAGE
9206  ast_mutex_lock(&vms->lock);
9207 #endif
9208  curmsg_deleted = vms->deleted[vms->curmsg];
9209 #ifdef IMAP_STORAGE
9210  ast_mutex_unlock(&vms->lock);
9211 #endif
9212  if (!curmsg_deleted) {
9213  res = ast_play_and_wait(chan, "vm-delete");
9214  } else {
9215  res = ast_play_and_wait(chan, "vm-undelete");
9216  }
9217  if (!res) {
9218  res = ast_play_and_wait(chan, "vm-toforward");
9219  }
9220  if (!res) {
9221  res = ast_play_and_wait(chan, "vm-savemessage");
9222  }
9223  }
9224  }
9225  if (!res) {
9226  res = ast_play_and_wait(chan, "vm-helpexit");
9227  }
9228  if (!res)
9229  res = ast_waitfordigit(chan, 6000);
9230  if (!res) {
9231  vms->repeats++;
9232  if (vms->repeats > 2) {
9233  res = 't';
9234  }
9235  }
9236  }
9237  return res;
9238 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define VM_MESSAGEWRAP
#define ast_mutex_lock(a)
Definition: lock.h:155
int urgentmessages
char vmbox[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
int * deleted
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
int newmessages
#define ast_mutex_unlock(a)
Definition: lock.h:156
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 9240 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().

9241 {
9242  int res = 0;
9243  /* Play instructions and wait for new command */
9244  while (!res) {
9245  if (vms->lastmsg > -1) {
9246  res = ast_play_and_wait(chan, "vm-listen");
9247  if (!res)
9248  res = vm_play_folder_name(chan, vms->vmbox);
9249  if (!res)
9250  res = ast_play_and_wait(chan, "press");
9251  if (!res)
9252  res = ast_play_and_wait(chan, "digits/1");
9253  }
9254  if (!res)
9255  res = ast_play_and_wait(chan, "vm-opts");
9256  if (!res) {
9257  vms->starting = 0;
9258  return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
9259  }
9260  }
9261  return res;
9262 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
char vmbox[PATH_MAX]
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int vm_intro ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms 
)
static

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

9091 {
9092  char prefile[256];
9093 
9094  /* Notify the user that the temp greeting is set and give them the option to remove it */
9095  snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
9096  if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
9097  RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
9098  if (ast_fileexists(prefile, NULL, NULL) > 0) {
9099  ast_play_and_wait(chan, "vm-tempgreetactive");
9100  }
9101  DISPOSE(prefile, -1);
9102  }
9103 
9104  /* Play voicemail intro - syntax is different for different languages */
9105  if (0) {
9106  return 0;
9107  } else if (!strncasecmp(chan->language, "cs", 2)) { /* CZECH syntax */
9108  return vm_intro_cs(chan, vms);
9109  } else if (!strncasecmp(chan->language, "cz", 2)) { /* deprecated CZECH syntax */
9110  static int deprecation_warning = 0;
9111  if (deprecation_warning++ % 10 == 0) {
9112  ast_log(LOG_WARNING, "cz is not a standard language code. Please switch to using cs instead.\n");
9113  }
9114  return vm_intro_cs(chan, vms);
9115  } else if (!strncasecmp(chan->language, "de", 2)) { /* GERMAN syntax */
9116  return vm_intro_de(chan, vms);
9117  } else if (!strncasecmp(chan->language, "es", 2)) { /* SPANISH syntax */
9118  return vm_intro_es(chan, vms);
9119  } else if (!strncasecmp(chan->language, "fr", 2)) { /* FRENCH syntax */
9120  return vm_intro_fr(chan, vms);
9121  } else if (!strncasecmp(chan->language, "gr", 2)) { /* GREEK syntax */
9122  return vm_intro_gr(chan, vms);
9123  } else if (!strncasecmp(chan->language, "he", 2)) { /* HEBREW syntax */
9124  return vm_intro_he(chan, vms);
9125  } else if (!strncasecmp(chan->language, "it", 2)) { /* ITALIAN syntax */
9126  return vm_intro_it(chan, vms);
9127  } else if (!strncasecmp(chan->language, "nl", 2)) { /* DUTCH syntax */
9128  return vm_intro_nl(chan, vms);
9129  } else if (!strncasecmp(chan->language, "no", 2)) { /* NORWEGIAN syntax */
9130  return vm_intro_no(chan, vms);
9131  } else if (!strncasecmp(chan->language, "pl", 2)) { /* POLISH syntax */
9132  return vm_intro_pl(chan, vms);
9133  } else if (!strncasecmp(chan->language, "pt_BR", 5)) { /* BRAZILIAN PORTUGUESE syntax */
9134  return vm_intro_pt_BR(chan, vms);
9135  } else if (!strncasecmp(chan->language, "pt", 2)) { /* PORTUGUESE syntax */
9136  return vm_intro_pt(chan, vms);
9137  } else if (!strncasecmp(chan->language, "ru", 2)) { /* RUSSIAN syntax */
9138  return vm_intro_multilang(chan, vms, "n");
9139  } else if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
9140  return vm_intro_se(chan, vms);
9141  } else if (!strncasecmp(chan->language, "ua", 2)) { /* UKRAINIAN syntax */
9142  return vm_intro_multilang(chan, vms, "n");
9143  } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
9144  return vm_intro_vi(chan, vms);
9145  } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
9146  return vm_intro_zh(chan, vms);
9147  } else { /* Default to ENGLISH */
9148  return vm_intro_en(chan, vms);
9149  }
9150 }
#define VM_TEMPGREETWARN
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
static int vm_intro_de(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_it(struct ast_channel *chan, struct vm_state *vms)
#define DISPOSE(a, b)
static int vm_intro_en(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_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int vm_intro_fr(struct ast_channel *chan, struct vm_state *vms)
char mailbox[AST_MAX_EXTENSION]
char username[80]
char context[AST_MAX_CONTEXT]
static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
static char VM_SPOOL_DIR[PATH_MAX]
static int vm_intro_cs(struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_vi(struct ast_channel *chan, struct vm_state *vms)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int vm_intro_es(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_BR(struct ast_channel *chan, struct vm_state *vms)
#define RETRIEVE(a, b, c, d)
static int vm_intro_zh(struct ast_channel *chan, struct vm_state *vms)
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
const ast_string_field language
Definition: channel.h:787
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_cs ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8961 {
8962  int res;
8963  res = ast_play_and_wait(chan, "vm-youhave");
8964  if (!res) {
8965  if (vms->newmessages) {
8966  if (vms->newmessages == 1) {
8967  res = ast_play_and_wait(chan, "digits/jednu");
8968  } else {
8969  res = say_and_wait(chan, vms->newmessages, chan->language);
8970  }
8971  if (!res) {
8972  if ((vms->newmessages == 1))
8973  res = ast_play_and_wait(chan, "vm-novou");
8974  if ((vms->newmessages) > 1 && (vms->newmessages < 5))
8975  res = ast_play_and_wait(chan, "vm-nove");
8976  if (vms->newmessages > 4)
8977  res = ast_play_and_wait(chan, "vm-novych");
8978  }
8979  if (vms->oldmessages && !res)
8980  res = ast_play_and_wait(chan, "vm-and");
8981  else if (!res) {
8982  if ((vms->newmessages == 1))
8983  res = ast_play_and_wait(chan, "vm-zpravu");
8984  if ((vms->newmessages) > 1 && (vms->newmessages < 5))
8985  res = ast_play_and_wait(chan, "vm-zpravy");
8986  if (vms->newmessages > 4)
8987  res = ast_play_and_wait(chan, "vm-zprav");
8988  }
8989  }
8990  if (!res && vms->oldmessages) {
8991  res = say_and_wait(chan, vms->oldmessages, chan->language);
8992  if (!res) {
8993  if ((vms->oldmessages == 1))
8994  res = ast_play_and_wait(chan, "vm-starou");
8995  if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
8996  res = ast_play_and_wait(chan, "vm-stare");
8997  if (vms->oldmessages > 4)
8998  res = ast_play_and_wait(chan, "vm-starych");
8999  }
9000  if (!res) {
9001  if ((vms->oldmessages == 1))
9002  res = ast_play_and_wait(chan, "vm-zpravu");
9003  if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
9004  res = ast_play_and_wait(chan, "vm-zpravy");
9005  if (vms->oldmessages > 4)
9006  res = ast_play_and_wait(chan, "vm-zprav");
9007  }
9008  }
9009  if (!res) {
9010  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9011  res = ast_play_and_wait(chan, "vm-no");
9012  if (!res)
9013  res = ast_play_and_wait(chan, "vm-zpravy");
9014  }
9015  }
9016  }
9017  return res;
9018 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_de ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8657 {
8658  /* Introduce messages they have */
8659  int res;
8660  res = ast_play_and_wait(chan, "vm-youhave");
8661  if (!res) {
8662  if (vms->newmessages) {
8663  if ((vms->newmessages == 1))
8664  res = ast_play_and_wait(chan, "digits/1F");
8665  else
8666  res = say_and_wait(chan, vms->newmessages, chan->language);
8667  if (!res)
8668  res = ast_play_and_wait(chan, "vm-INBOX");
8669  if (vms->oldmessages && !res)
8670  res = ast_play_and_wait(chan, "vm-and");
8671  else if (!res) {
8672  if ((vms->newmessages == 1))
8673  res = ast_play_and_wait(chan, "vm-message");
8674  else
8675  res = ast_play_and_wait(chan, "vm-messages");
8676  }
8677 
8678  }
8679  if (!res && vms->oldmessages) {
8680  if (vms->oldmessages == 1)
8681  res = ast_play_and_wait(chan, "digits/1F");
8682  else
8683  res = say_and_wait(chan, vms->oldmessages, chan->language);
8684  if (!res)
8685  res = ast_play_and_wait(chan, "vm-Old");
8686  if (!res) {
8687  if (vms->oldmessages == 1)
8688  res = ast_play_and_wait(chan, "vm-message");
8689  else
8690  res = ast_play_and_wait(chan, "vm-messages");
8691  }
8692  }
8693  if (!res) {
8694  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8695  res = ast_play_and_wait(chan, "vm-no");
8696  if (!res)
8697  res = ast_play_and_wait(chan, "vm-messages");
8698  }
8699  }
8700  }
8701  return res;
8702 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_en ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8406 {
8407  int res;
8408 
8409  /* Introduce messages they have */
8410  res = ast_play_and_wait(chan, "vm-youhave");
8411  if (!res) {
8412  if (vms->urgentmessages) {
8413  res = say_and_wait(chan, vms->urgentmessages, chan->language);
8414  if (!res)
8415  res = ast_play_and_wait(chan, "vm-Urgent");
8416  if ((vms->oldmessages || vms->newmessages) && !res) {
8417  res = ast_play_and_wait(chan, "vm-and");
8418  } else if (!res) {
8419  if ((vms->urgentmessages == 1))
8420  res = ast_play_and_wait(chan, "vm-message");
8421  else
8422  res = ast_play_and_wait(chan, "vm-messages");
8423  }
8424  }
8425  if (vms->newmessages) {
8426  res = say_and_wait(chan, vms->newmessages, chan->language);
8427  if (!res)
8428  res = ast_play_and_wait(chan, "vm-INBOX");
8429  if (vms->oldmessages && !res)
8430  res = ast_play_and_wait(chan, "vm-and");
8431  else if (!res) {
8432  if ((vms->newmessages == 1))
8433  res = ast_play_and_wait(chan, "vm-message");
8434  else
8435  res = ast_play_and_wait(chan, "vm-messages");
8436  }
8437 
8438  }
8439  if (!res && vms->oldmessages) {
8440  res = say_and_wait(chan, vms->oldmessages, chan->language);
8441  if (!res)
8442  res = ast_play_and_wait(chan, "vm-Old");
8443  if (!res) {
8444  if (vms->oldmessages == 1)
8445  res = ast_play_and_wait(chan, "vm-message");
8446  else
8447  res = ast_play_and_wait(chan, "vm-messages");
8448  }
8449  }
8450  if (!res) {
8451  if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
8452  res = ast_play_and_wait(chan, "vm-no");
8453  if (!res)
8454  res = ast_play_and_wait(chan, "vm-messages");
8455  }
8456  }
8457  }
8458  return res;
8459 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_es ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8706 {
8707  /* Introduce messages they have */
8708  int res;
8709  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8710  res = ast_play_and_wait(chan, "vm-youhaveno");
8711  if (!res)
8712  res = ast_play_and_wait(chan, "vm-messages");
8713  } else {
8714  res = ast_play_and_wait(chan, "vm-youhave");
8715  }
8716  if (!res) {
8717  if (vms->newmessages) {
8718  if (!res) {
8719  if ((vms->newmessages == 1)) {
8720  res = ast_play_and_wait(chan, "digits/1");
8721  if (!res)
8722  res = ast_play_and_wait(chan, "vm-message");
8723  if (!res)
8724  res = ast_play_and_wait(chan, "vm-INBOXs");
8725  } else {
8726  res = say_and_wait(chan, vms->newmessages, chan->language);
8727  if (!res)
8728  res = ast_play_and_wait(chan, "vm-messages");
8729  if (!res)
8730  res = ast_play_and_wait(chan, "vm-INBOX");
8731  }
8732  }
8733  if (vms->oldmessages && !res)
8734  res = ast_play_and_wait(chan, "vm-and");
8735  }
8736  if (vms->oldmessages) {
8737  if (!res) {
8738  if (vms->oldmessages == 1) {
8739  res = ast_play_and_wait(chan, "digits/1");
8740  if (!res)
8741  res = ast_play_and_wait(chan, "vm-message");
8742  if (!res)
8743  res = ast_play_and_wait(chan, "vm-Olds");
8744  } else {
8745  res = say_and_wait(chan, vms->oldmessages, chan->language);
8746  if (!res)
8747  res = ast_play_and_wait(chan, "vm-messages");
8748  if (!res)
8749  res = ast_play_and_wait(chan, "vm-Old");
8750  }
8751  }
8752  }
8753  }
8754 return res;
8755 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_fr ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8804 {
8805  /* Introduce messages they have */
8806  int res;
8807  res = ast_play_and_wait(chan, "vm-youhave");
8808  if (!res) {
8809  if (vms->newmessages) {
8810  res = say_and_wait(chan, vms->newmessages, chan->language);
8811  if (!res)
8812  res = ast_play_and_wait(chan, "vm-INBOX");
8813  if (vms->oldmessages && !res)
8814  res = ast_play_and_wait(chan, "vm-and");
8815  else if (!res) {
8816  if ((vms->newmessages == 1))
8817  res = ast_play_and_wait(chan, "vm-message");
8818  else
8819  res = ast_play_and_wait(chan, "vm-messages");
8820  }
8821 
8822  }
8823  if (!res && vms->oldmessages) {
8824  res = say_and_wait(chan, vms->oldmessages, chan->language);
8825  if (!res)
8826  res = ast_play_and_wait(chan, "vm-Old");
8827  if (!res) {
8828  if (vms->oldmessages == 1)
8829  res = ast_play_and_wait(chan, "vm-message");
8830  else
8831  res = ast_play_and_wait(chan, "vm-messages");
8832  }
8833  }
8834  if (!res) {
8835  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8836  res = ast_play_and_wait(chan, "vm-no");
8837  if (!res)
8838  res = ast_play_and_wait(chan, "vm-messages");
8839  }
8840  }
8841  }
8842  return res;
8843 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_gr ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8205 {
8206  int res = 0;
8207 
8208  if (vms->newmessages) {
8209  res = ast_play_and_wait(chan, "vm-youhave");
8210  if (!res)
8211  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
8212  if (!res) {
8213  if ((vms->newmessages == 1)) {
8214  res = ast_play_and_wait(chan, "vm-INBOX");
8215  if (!res)
8216  res = ast_play_and_wait(chan, "vm-message");
8217  } else {
8218  res = ast_play_and_wait(chan, "vm-INBOXs");
8219  if (!res)
8220  res = ast_play_and_wait(chan, "vm-messages");
8221  }
8222  }
8223  } else if (vms->oldmessages){
8224  res = ast_play_and_wait(chan, "vm-youhave");
8225  if (!res)
8226  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
8227  if ((vms->oldmessages == 1)){
8228  res = ast_play_and_wait(chan, "vm-Old");
8229  if (!res)
8230  res = ast_play_and_wait(chan, "vm-message");
8231  } else {
8232  res = ast_play_and_wait(chan, "vm-Olds");
8233  if (!res)
8234  res = ast_play_and_wait(chan, "vm-messages");
8235  }
8236  } else if (!vms->oldmessages && !vms->newmessages)
8237  res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
8238  return res;
8239 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_he ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8339 {
8340  int res = 0;
8341 
8342  /* Introduce messages they have */
8343  if (!res) {
8344  if ((vms->newmessages) || (vms->oldmessages)) {
8345  res = ast_play_and_wait(chan, "vm-youhave");
8346  }
8347  /*
8348  * The word "shtei" refers to the number 2 in hebrew when performing a count
8349  * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
8350  * an element, this is one of them.
8351  */
8352  if (vms->newmessages) {
8353  if (!res) {
8354  if (vms->newmessages == 1) {
8355  res = ast_play_and_wait(chan, "vm-INBOX1");
8356  } else {
8357  if (vms->newmessages == 2) {
8358  res = ast_play_and_wait(chan, "vm-shtei");
8359  } else {
8360  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
8361  }
8362  res = ast_play_and_wait(chan, "vm-INBOX");
8363  }
8364  }
8365  if (vms->oldmessages && !res) {
8366  res = ast_play_and_wait(chan, "vm-and");
8367  if (vms->oldmessages == 1) {
8368  res = ast_play_and_wait(chan, "vm-Old1");
8369  } else {
8370  if (vms->oldmessages == 2) {
8371  res = ast_play_and_wait(chan, "vm-shtei");
8372  } else {
8373  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
8374  }
8375  res = ast_play_and_wait(chan, "vm-Old");
8376  }
8377  }
8378  }
8379  if (!res && vms->oldmessages && !vms->newmessages) {
8380  if (!res) {
8381  if (vms->oldmessages == 1) {
8382  res = ast_play_and_wait(chan, "vm-Old1");
8383  } else {
8384  if (vms->oldmessages == 2) {
8385  res = ast_play_and_wait(chan, "vm-shtei");
8386  } else {
8387  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
8388  }
8389  res = ast_play_and_wait(chan, "vm-Old");
8390  }
8391  }
8392  }
8393  if (!res) {
8394  if (!vms->oldmessages && !vms->newmessages) {
8395  if (!res) {
8396  res = ast_play_and_wait(chan, "vm-nomessages");
8397  }
8398  }
8399  }
8400  }
8401  return res;
8402 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_it ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8463 {
8464  /* Introduce messages they have */
8465  int res;
8466  if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
8467  res = ast_play_and_wait(chan, "vm-no") ||
8468  ast_play_and_wait(chan, "vm-message");
8469  else
8470  res = ast_play_and_wait(chan, "vm-youhave");
8471  if (!res && vms->newmessages) {
8472  res = (vms->newmessages == 1) ?
8473  ast_play_and_wait(chan, "digits/un") ||
8474  ast_play_and_wait(chan, "vm-nuovo") ||
8475  ast_play_and_wait(chan, "vm-message") :
8476  /* 2 or more new messages */
8477  say_and_wait(chan, vms->newmessages, chan->language) ||
8478  ast_play_and_wait(chan, "vm-nuovi") ||
8479  ast_play_and_wait(chan, "vm-messages");
8480  if (!res && vms->oldmessages)
8481  res = ast_play_and_wait(chan, "vm-and");
8482  }
8483  if (!res && vms->oldmessages) {
8484  res = (vms->oldmessages == 1) ?
8485  ast_play_and_wait(chan, "digits/un") ||
8486  ast_play_and_wait(chan, "vm-vecchio") ||
8487  ast_play_and_wait(chan, "vm-message") :
8488  /* 2 or more old messages */
8489  say_and_wait(chan, vms->oldmessages, chan->language) ||
8490  ast_play_and_wait(chan, "vm-vecchi") ||
8491  ast_play_and_wait(chan, "vm-messages");
8492  }
8493  return res;
8494 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
int newmessages
static int vm_intro_multilang ( struct ast_channel chan,
struct vm_state vms,
const char  message_gender[] 
)
static

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

8299 {
8300  int res;
8301  int lastnum = 0;
8302 
8303  res = ast_play_and_wait(chan, "vm-youhave");
8304 
8305  if (!res && vms->newmessages) {
8306  lastnum = vms->newmessages;
8307 
8308  if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
8309  res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
8310  }
8311 
8312  if (!res && vms->oldmessages) {
8313  res = ast_play_and_wait(chan, "vm-and");
8314  }
8315  }
8316 
8317  if (!res && vms->oldmessages) {
8318  lastnum = vms->oldmessages;
8319 
8320  if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
8321  res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
8322  }
8323  }
8324 
8325  if (!res) {
8326  if (lastnum == 0) {
8327  res = ast_play_and_wait(chan, "vm-no");
8328  }
8329  if (!res) {
8330  res = ast_say_counted_noun(chan, lastnum, "vm-message");
8331  }
8332  }
8333 
8334  return res;
8335 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
int ast_say_counted_adjective(struct ast_channel *chan, int num, const char *adjective, const char *gender)
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_nl ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8847 {
8848  /* Introduce messages they have */
8849  int res;
8850  res = ast_play_and_wait(chan, "vm-youhave");
8851  if (!res) {
8852  if (vms->newmessages) {
8853  res = say_and_wait(chan, vms->newmessages, chan->language);
8854  if (!res) {
8855  if (vms->newmessages == 1)
8856  res = ast_play_and_wait(chan, "vm-INBOXs");
8857  else
8858  res = ast_play_and_wait(chan, "vm-INBOX");
8859  }
8860  if (vms->oldmessages && !res)
8861  res = ast_play_and_wait(chan, "vm-and");
8862  else if (!res) {
8863  if ((vms->newmessages == 1))
8864  res = ast_play_and_wait(chan, "vm-message");
8865  else
8866  res = ast_play_and_wait(chan, "vm-messages");
8867  }
8868 
8869  }
8870  if (!res && vms->oldmessages) {
8871  res = say_and_wait(chan, vms->oldmessages, chan->language);
8872  if (!res) {
8873  if (vms->oldmessages == 1)
8874  res = ast_play_and_wait(chan, "vm-Olds");
8875  else
8876  res = ast_play_and_wait(chan, "vm-Old");
8877  }
8878  if (!res) {
8879  if (vms->oldmessages == 1)
8880  res = ast_play_and_wait(chan, "vm-message");
8881  else
8882  res = ast_play_and_wait(chan, "vm-messages");
8883  }
8884  }
8885  if (!res) {
8886  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8887  res = ast_play_and_wait(chan, "vm-no");
8888  if (!res)
8889  res = ast_play_and_wait(chan, "vm-messages");
8890  }
8891  }
8892  }
8893  return res;
8894 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_no ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8613 {
8614  /* Introduce messages they have */
8615  int res;
8616 
8617  res = ast_play_and_wait(chan, "vm-youhave");
8618  if (res)
8619  return res;
8620 
8621  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8622  res = ast_play_and_wait(chan, "vm-no");
8623  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8624  return res;
8625  }
8626 
8627  if (vms->newmessages) {
8628  if ((vms->newmessages == 1)) {
8629  res = ast_play_and_wait(chan, "digits/1");
8630  res = res ? res : ast_play_and_wait(chan, "vm-ny");
8631  res = res ? res : ast_play_and_wait(chan, "vm-message");
8632  } else {
8633  res = say_and_wait(chan, vms->newmessages, chan->language);
8634  res = res ? res : ast_play_and_wait(chan, "vm-nye");
8635  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8636  }
8637  if (!res && vms->oldmessages)
8638  res = ast_play_and_wait(chan, "vm-and");
8639  }
8640  if (!res && vms->oldmessages) {
8641  if (vms->oldmessages == 1) {
8642  res = ast_play_and_wait(chan, "digits/1");
8643  res = res ? res : ast_play_and_wait(chan, "vm-gamel");
8644  res = res ? res : ast_play_and_wait(chan, "vm-message");
8645  } else {
8646  res = say_and_wait(chan, vms->oldmessages, chan->language);
8647  res = res ? res : ast_play_and_wait(chan, "vm-gamle");
8648  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8649  }
8650  }
8651 
8652  return res;
8653 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_pl ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8498 {
8499  /* Introduce messages they have */
8500  int res;
8501  div_t num;
8502 
8503  if (!vms->oldmessages && !vms->newmessages) {
8504  res = ast_play_and_wait(chan, "vm-no");
8505  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8506  return res;
8507  } else {
8508  res = ast_play_and_wait(chan, "vm-youhave");
8509  }
8510 
8511  if (vms->newmessages) {
8512  num = div(vms->newmessages, 10);
8513  if (vms->newmessages == 1) {
8514  res = ast_play_and_wait(chan, "digits/1-a");
8515  res = res ? res : ast_play_and_wait(chan, "vm-new-a");
8516  res = res ? res : ast_play_and_wait(chan, "vm-message");
8517  } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8518  if (num.rem == 2) {
8519  if (!num.quot) {
8520  res = ast_play_and_wait(chan, "digits/2-ie");
8521  } else {
8522  res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
8523  res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
8524  }
8525  } else {
8526  res = say_and_wait(chan, vms->newmessages, chan->language);
8527  }
8528  res = res ? res : ast_play_and_wait(chan, "vm-new-e");
8529  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8530  } else {
8531  res = say_and_wait(chan, vms->newmessages, chan->language);
8532  res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
8533  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8534  }
8535  if (!res && vms->oldmessages)
8536  res = ast_play_and_wait(chan, "vm-and");
8537  }
8538  if (!res && vms->oldmessages) {
8539  num = div(vms->oldmessages, 10);
8540  if (vms->oldmessages == 1) {
8541  res = ast_play_and_wait(chan, "digits/1-a");
8542  res = res ? res : ast_play_and_wait(chan, "vm-old-a");
8543  res = res ? res : ast_play_and_wait(chan, "vm-message");
8544  } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8545  if (num.rem == 2) {
8546  if (!num.quot) {
8547  res = ast_play_and_wait(chan, "digits/2-ie");
8548  } else {
8549  res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
8550  res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
8551  }
8552  } else {
8553  res = say_and_wait(chan, vms->oldmessages, chan->language);
8554  }
8555  res = res ? res : ast_play_and_wait(chan, "vm-old-e");
8556  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8557  } else {
8558  res = say_and_wait(chan, vms->oldmessages, chan->language);
8559  res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
8560  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8561  }
8562  }
8563 
8564  return res;
8565 }
int oldmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_pt ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8898 {
8899  /* Introduce messages they have */
8900  int res;
8901  res = ast_play_and_wait(chan, "vm-youhave");
8902  if (!res) {
8903  if (vms->newmessages) {
8904  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
8905  if (!res) {
8906  if ((vms->newmessages == 1)) {
8907  res = ast_play_and_wait(chan, "vm-message");
8908  if (!res)
8909  res = ast_play_and_wait(chan, "vm-INBOXs");
8910  } else {
8911  res = ast_play_and_wait(chan, "vm-messages");
8912  if (!res)
8913  res = ast_play_and_wait(chan, "vm-INBOX");
8914  }
8915  }
8916  if (vms->oldmessages && !res)
8917  res = ast_play_and_wait(chan, "vm-and");
8918  }
8919  if (!res && vms->oldmessages) {
8920  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
8921  if (!res) {
8922  if (vms->oldmessages == 1) {
8923  res = ast_play_and_wait(chan, "vm-message");
8924  if (!res)
8925  res = ast_play_and_wait(chan, "vm-Olds");
8926  } else {
8927  res = ast_play_and_wait(chan, "vm-messages");
8928  if (!res)
8929  res = ast_play_and_wait(chan, "vm-Old");
8930  }
8931  }
8932  }
8933  if (!res) {
8934  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8935  res = ast_play_and_wait(chan, "vm-no");
8936  if (!res)
8937  res = ast_play_and_wait(chan, "vm-messages");
8938  }
8939  }
8940  }
8941  return res;
8942 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:47
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_pt_BR ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8758  {
8759  /* Introduce messages they have */
8760  int res;
8761  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8762  res = ast_play_and_wait(chan, "vm-nomessages");
8763  return res;
8764  } else {
8765  res = ast_play_and_wait(chan, "vm-youhave");
8766  }
8767  if (vms->newmessages) {
8768  if (!res)
8769  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
8770  if ((vms->newmessages == 1)) {
8771  if (!res)
8772  res = ast_play_and_wait(chan, "vm-message");
8773  if (!res)
8774  res = ast_play_and_wait(chan, "vm-INBOXs");
8775  } else {
8776  if (!res)
8777  res = ast_play_and_wait(chan, "vm-messages");
8778  if (!res)
8779  res = ast_play_and_wait(chan, "vm-INBOX");
8780  }
8781  if (vms->oldmessages && !res)
8782  res = ast_play_and_wait(chan, "vm-and");
8783  }
8784  if (vms->oldmessages) {
8785  if (!res)
8786  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
8787  if (vms->oldmessages == 1) {
8788  if (!res)
8789  res = ast_play_and_wait(chan, "vm-message");
8790  if (!res)
8791  res = ast_play_and_wait(chan, "vm-Olds");
8792  } else {
8793  if (!res)
8794  res = ast_play_and_wait(chan, "vm-messages");
8795  if (!res)
8796  res = ast_play_and_wait(chan, "vm-Old");
8797  }
8798  }
8799  return res;
8800 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:47
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_se ( struct ast_channel chan,
struct vm_state vms 
)
static

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

8569 {
8570  /* Introduce messages they have */
8571  int res;
8572 
8573  res = ast_play_and_wait(chan, "vm-youhave");
8574  if (res)
8575  return res;
8576 
8577  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
8578  res = ast_play_and_wait(chan, "vm-no");
8579  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8580  return res;
8581  }
8582 
8583  if (vms->newmessages) {
8584  if ((vms->newmessages == 1)) {
8585  res = ast_play_and_wait(chan, "digits/ett");
8586  res = res ? res : ast_play_and_wait(chan, "vm-nytt");
8587  res = res ? res : ast_play_and_wait(chan, "vm-message");
8588  } else {
8589  res = say_and_wait(chan, vms->newmessages, chan->language);
8590  res = res ? res : ast_play_and_wait(chan, "vm-nya");
8591  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8592  }
8593  if (!res && vms->oldmessages)
8594  res = ast_play_and_wait(chan, "vm-and");
8595  }
8596  if (!res && vms->oldmessages) {
8597  if (vms->oldmessages == 1) {
8598  res = ast_play_and_wait(chan, "digits/ett");
8599  res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
8600  res = res ? res : ast_play_and_wait(chan, "vm-message");
8601  } else {
8602  res = say_and_wait(chan, vms->oldmessages, chan->language);
8603  res = res ? res : ast_play_and_wait(chan, "vm-gamla");
8604  res = res ? res : ast_play_and_wait(chan, "vm-messages");
8605  }
8606  }
8607 
8608  return res;
8609 }
int oldmessages
int urgentmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_vi ( struct ast_channel chan,
struct vm_state vms 
)
static

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

9061 {
9062  int res;
9063 
9064  /* Introduce messages they have */
9065  res = ast_play_and_wait(chan, "vm-youhave");
9066  if (!res) {
9067  if (vms->newmessages) {
9068  res = say_and_wait(chan, vms->newmessages, chan->language);
9069  if (!res)
9070  res = ast_play_and_wait(chan, "vm-INBOX");
9071  if (vms->oldmessages && !res)
9072  res = ast_play_and_wait(chan, "vm-and");
9073  }
9074  if (!res && vms->oldmessages) {
9075  res = say_and_wait(chan, vms->oldmessages, chan->language);
9076  if (!res)
9077  res = ast_play_and_wait(chan, "vm-Old");
9078  }
9079  if (!res) {
9080  if (!vms->oldmessages && !vms->newmessages) {
9081  res = ast_play_and_wait(chan, "vm-no");
9082  if (!res)
9083  res = ast_play_and_wait(chan, "vm-message");
9084  }
9085  }
9086  }
9087  return res;
9088 }
int oldmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
static int vm_intro_zh ( struct ast_channel chan,
struct vm_state vms 
)
static

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

9022 {
9023  int res;
9024  /* Introduce messages they have */
9025  res = ast_play_and_wait(chan, "vm-you");
9026 
9027  if (!res && vms->newmessages) {
9028  res = ast_play_and_wait(chan, "vm-have");
9029  if (!res)
9030  res = say_and_wait(chan, vms->newmessages, chan->language);
9031  if (!res)
9032  res = ast_play_and_wait(chan, "vm-tong");
9033  if (!res)
9034  res = ast_play_and_wait(chan, "vm-INBOX");
9035  if (vms->oldmessages && !res)
9036  res = ast_play_and_wait(chan, "vm-and");
9037  else if (!res)
9038  res = ast_play_and_wait(chan, "vm-messages");
9039  }
9040  if (!res && vms->oldmessages) {
9041  res = ast_play_and_wait(chan, "vm-have");
9042  if (!res)
9043  res = say_and_wait(chan, vms->oldmessages, chan->language);
9044  if (!res)
9045  res = ast_play_and_wait(chan, "vm-tong");
9046  if (!res)
9047  res = ast_play_and_wait(chan, "vm-Old");
9048  if (!res)
9049  res = ast_play_and_wait(chan, "vm-messages");
9050  }
9051  if (!res && !vms->oldmessages && !vms->newmessages) {
9052  res = ast_play_and_wait(chan, "vm-haveno");
9053  if (!res)
9054  res = ast_play_and_wait(chan, "vm-messages");
9055  }
9056  return res;
9057 }
int oldmessages
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
int newmessages
const ast_string_field language
Definition: channel.h:787
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 3304 of file app_voicemail.c.

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

3305 {
3306  switch (ast_lock_path(path)) {
3307  case AST_LOCK_TIMEOUT:
3308  return -1;
3309  default:
3310  return 0;
3311  }
3312 }
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: app.c:1652
static FILE* vm_mkftemp ( char *  template)
static

Definition at line 1675 of file app_voicemail.c.

References VOICEMAIL_FILE_MODE.

Referenced by sendmail(), and sendpage().

1676 {
1677  FILE *p = NULL;
1678  int pfd = mkstemp(template);
1679  chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
1680  if (pfd > -1) {
1681  p = fdopen(pfd, "w+");
1682  if (!p) {
1683  close(pfd);
1684  pfd = -1;
1685  }
1686  }
1687  return p;
1688 }
static int my_umask
#define VOICEMAIL_FILE_MODE
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 9274 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, check_password(), ast_vm_user::context, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, and VM_FORCENAME.

Referenced by vm_execmain().

9275 {
9276  int cmd = 0;
9277  int duration = 0;
9278  int tries = 0;
9279  char newpassword[80] = "";
9280  char newpassword2[80] = "";
9281  char prefile[PATH_MAX] = "";
9282  unsigned char buf[256];
9283  int bytes = 0;
9284 
9285  ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
9286  if (ast_adsi_available(chan)) {
9287  bytes += adsi_logo(buf + bytes);
9288  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
9289  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
9290  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
9291  bytes += ast_adsi_voice_mode(buf + bytes, 0);
9292  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
9293  }
9294 
9295  /* If forcename is set, have the user record their name */
9296  if (ast_test_flag(vmu, VM_FORCENAME)) {
9297  snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
9298  if (ast_fileexists(prefile, NULL, NULL) < 1) {
9299  cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9300  if (cmd < 0 || cmd == 't' || cmd == '#')
9301  return cmd;
9302  }
9303  }
9304 
9305  /* If forcegreetings is set, have the user record their greetings */
9306  if (ast_test_flag(vmu, VM_FORCEGREET)) {
9307  snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
9308  if (ast_fileexists(prefile, NULL, NULL) < 1) {
9309  cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9310  if (cmd < 0 || cmd == 't' || cmd == '#')
9311  return cmd;
9312  }
9313 
9314  snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
9315  if (ast_fileexists(prefile, NULL, NULL) < 1) {
9316  cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9317  if (cmd < 0 || cmd == 't' || cmd == '#')
9318  return cmd;
9319  }
9320  }
9321 
9322  /*
9323  * Change the password last since new users will be able to skip over any steps this one comes before
9324  * by hanging up and calling back to voicemail main since the password is used to verify new user status.
9325  */
9326  for (;;) {
9327  newpassword[1] = '\0';
9328  newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
9329  if (cmd == '#')
9330  newpassword[0] = '\0';
9331  if (cmd < 0 || cmd == 't' || cmd == '#')
9332  return cmd;
9333  cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
9334  if (cmd < 0 || cmd == 't' || cmd == '#')
9335  return cmd;
9336  cmd = check_password(vmu, newpassword); /* perform password validation */
9337  if (cmd != 0) {
9338  ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
9340  } else {
9341  newpassword2[1] = '\0';
9342  newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
9343  if (cmd == '#')
9344  newpassword2[0] = '\0';
9345  if (cmd < 0 || cmd == 't' || cmd == '#')
9346  return cmd;
9347  cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
9348  if (cmd < 0 || cmd == 't' || cmd == '#')
9349  return cmd;
9350  if (!strcmp(newpassword, newpassword2))
9351  break;
9352  ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
9353  cmd = ast_play_and_wait(chan, vm_mismatch);
9354  }
9355  if (++tries == 3)
9356  return -1;
9357  if (cmd != 0) {
9358  cmd = ast_play_and_wait(chan, vm_pls_try_again);
9359  }
9360  }
9362  vm_change_password(vmu, newpassword);
9364  vm_change_password_shell(vmu, newpassword);
9365 
9366  ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
9367  cmd = ast_play_and_wait(chan, vm_passchanged);
9368 
9369  return cmd;
9370 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
static char ext_pass_cmd[128]
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int adsi_logo(unsigned char *buf)
static int pwdchange
static int maxgreet
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define AST_LOG_NOTICE
Definition: logger.h:138
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
#define VM_FORCENAME
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char username[80]
static char vm_reenterpassword[80]
char context[AST_MAX_CONTEXT]
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
static char VM_SPOOL_DIR[PATH_MAX]
#define PWDCHANGE_INTERNAL
static char vm_mismatch[80]
static char vm_pls_try_again[80]
static char vm_invalid_password[80]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static char vm_passchanged[80]
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
#define PWDCHANGE_EXTERNAL
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:5837
static char vm_newpassword[80]
#define ADSI_JUST_CENT
Definition: adsi.h:114
#define VM_FORCEGREET
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 9372 of file app_voicemail.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_suite_event_notify, ast_waitfordigit(), check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::mailbox, ast_vm_user::password, play_record_review(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), and vm_tempgreeting().

Referenced by vm_execmain().

9373 {
9374  int cmd = 0;
9375  int retries = 0;
9376  int duration = 0;
9377  char newpassword[80] = "";
9378  char newpassword2[80] = "";
9379  char prefile[PATH_MAX] = "";
9380  unsigned char buf[256];
9381  int bytes = 0;
9382 
9383  ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
9384  if (ast_adsi_available(chan)) {
9385  bytes += adsi_logo(buf + bytes);
9386  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
9387  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
9388  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
9389  bytes += ast_adsi_voice_mode(buf + bytes, 0);
9390  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
9391  }
9392  while ((cmd >= 0) && (cmd != 't')) {
9393  if (cmd)
9394  retries = 0;
9395  switch (cmd) {
9396  case '1': /* Record your unavailable message */
9397  snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
9398  cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9399  break;
9400  case '2': /* Record your busy message */
9401  snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
9402  cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9403  break;
9404  case '3': /* Record greeting */
9405  snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
9406  cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9407  break;
9408  case '4': /* manage the temporary greeting */
9409  cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
9410  break;
9411  case '5': /* change password */
9412  if (vmu->password[0] == '-') {
9413  cmd = ast_play_and_wait(chan, "vm-no");
9414  break;
9415  }
9416  newpassword[1] = '\0';
9417  newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
9418  if (cmd == '#')
9419  newpassword[0] = '\0';
9420  else {
9421  if (cmd < 0)
9422  break;
9423  if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
9424  break;
9425  }
9426  }
9427  cmd = check_password(vmu, newpassword); /* perform password validation */
9428  if (cmd != 0) {
9429  ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
9431  if (!cmd) {
9432  cmd = ast_play_and_wait(chan, vm_pls_try_again);
9433  }
9434  break;
9435  }
9436  newpassword2[1] = '\0';
9437  newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
9438  if (cmd == '#')
9439  newpassword2[0] = '\0';
9440  else {
9441  if (cmd < 0)
9442  break;
9443 
9444  if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
9445  break;
9446  }
9447  }
9448  if (strcmp(newpassword, newpassword2)) {
9449  ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
9450  cmd = ast_play_and_wait(chan, vm_mismatch);
9451  if (!cmd) {
9452  cmd = ast_play_and_wait(chan, vm_pls_try_again);
9453  }
9454  break;
9455  }
9456 
9457  if (pwdchange & PWDCHANGE_INTERNAL) {
9458  vm_change_password(vmu, newpassword);
9459  }
9461  vm_change_password_shell(vmu, newpassword);
9462  }
9463 
9464  ast_debug(1, "User %s set password to %s of length %d\n",
9465  vms->username, newpassword, (int) strlen(newpassword));
9466  cmd = ast_play_and_wait(chan, vm_passchanged);
9467  break;
9468  case '*':
9469  cmd = 't';
9470  break;
9471  default:
9472  cmd = 0;
9473  snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
9474  RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
9475  if (ast_fileexists(prefile, NULL, NULL)) {
9476  cmd = ast_play_and_wait(chan, "vm-tmpexists");
9477  }
9478  DISPOSE(prefile, -1);
9479  if (!cmd) {
9480  cmd = ast_play_and_wait(chan, "vm-options");
9481  }
9482  if (!cmd) {
9483  cmd = ast_waitfordigit(chan, 6000);
9484  }
9485  if (!cmd) {
9486  retries++;
9487  }
9488  if (retries > 3) {
9489  cmd = 't';
9490  }
9491  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
9492  }
9493  }
9494  if (cmd == 't')
9495  cmd = 0;
9496  return cmd;
9497 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
static char ext_pass_cmd[128]
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static int adsi_logo(unsigned char *buf)
static int pwdchange
static int maxgreet
#define DISPOSE(a, b)
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define AST_LOG_NOTICE
Definition: logger.h:138
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char mailbox[AST_MAX_EXTENSION]
char username[80]
static char vm_reenterpassword[80]
char context[AST_MAX_CONTEXT]
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
static char VM_SPOOL_DIR[PATH_MAX]
#define PWDCHANGE_INTERNAL
static char vm_mismatch[80]
static char vm_pls_try_again[80]
static char vm_invalid_password[80]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static char vm_passchanged[80]
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
#define PWDCHANGE_EXTERNAL
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:5837
static char vm_newpassword[80]
#define ADSI_JUST_CENT
Definition: adsi.h:114
char password[80]
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 &#39;record a temporary greeting&#39;.
static int vm_play_folder_name ( struct ast_channel chan,
char *  mbox 
)
static

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

8168 {
8169  int cmd;
8170 
8171  if ( !strncasecmp(chan->language, "it", 2) ||
8172  !strncasecmp(chan->language, "es", 2) ||
8173  !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
8174  cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
8175  return cmd ? cmd : ast_play_and_wait(chan, box);
8176  } else if (!strncasecmp(chan->language, "gr", 2)) {
8177  return vm_play_folder_name_gr(chan, box);
8178  } else if (!strncasecmp(chan->language, "he", 2)) { /* Hebrew syntax */
8179  return ast_play_and_wait(chan, box);
8180  } else if (!strncasecmp(chan->language, "pl", 2)) {
8181  return vm_play_folder_name_pl(chan, box);
8182  } else if (!strncasecmp(chan->language, "ua", 2)) { /* Ukrainian syntax */
8183  return vm_play_folder_name_ua(chan, box);
8184  } else if (!strncasecmp(chan->language, "vi", 2)) {
8185  return ast_play_and_wait(chan, box);
8186  } else { /* Default English */
8187  cmd = ast_play_and_wait(chan, box);
8188  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
8189  }
8190 }
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua(struct ast_channel *chan, char *box)
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
const ast_string_field language
Definition: channel.h:787
static int vm_play_folder_name_gr ( struct ast_channel chan,
char *  box 
)
static

Definition at line 8120 of file app_voicemail.c.

References ast_alloca, and ast_play_and_wait().

Referenced by vm_play_folder_name().

8121 {
8122  int cmd;
8123  char *buf;
8124 
8125  buf = ast_alloca(strlen(box) + 2);
8126  strcpy(buf, box);
8127  strcat(buf, "s");
8128 
8129  if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
8130  cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
8131  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
8132  } else {
8133  cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
8134  return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
8135  }
8136 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int vm_play_folder_name_pl ( struct ast_channel chan,
char *  box 
)
static

Definition at line 8138 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

8139 {
8140  int cmd;
8141 
8142  if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
8143  if (!strcasecmp(box, "vm-INBOX"))
8144  cmd = ast_play_and_wait(chan, "vm-new-e");
8145  else
8146  cmd = ast_play_and_wait(chan, "vm-old-e");
8147  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
8148  } else {
8149  cmd = ast_play_and_wait(chan, "vm-messages");
8150  return cmd ? cmd : ast_play_and_wait(chan, box);
8151  }
8152 }
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static int vm_play_folder_name_ua ( struct ast_channel chan,
char *  box 
)
static

Definition at line 8154 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

8155 {
8156  int cmd;
8157 
8158  if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
8159  cmd = ast_play_and_wait(chan, "vm-messages");
8160  return cmd ? cmd : ast_play_and_wait(chan, box);
8161  } else {
8162  cmd = ast_play_and_wait(chan, box);
8163  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
8164  }
8165 }
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
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_gainThis 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 9515 of file app_voicemail.c.

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

Referenced by vm_options().

9516 {
9517  int cmd = 0;
9518  int retries = 0;
9519  int duration = 0;
9520  char prefile[PATH_MAX] = "";
9521  unsigned char buf[256];
9522  int bytes = 0;
9523 
9524  if (ast_adsi_available(chan)) {
9525  bytes += adsi_logo(buf + bytes);
9526  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
9527  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
9528  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
9529  bytes += ast_adsi_voice_mode(buf + bytes, 0);
9530  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
9531  }
9532 
9533  ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
9534  snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
9535  while ((cmd >= 0) && (cmd != 't')) {
9536  if (cmd)
9537  retries = 0;
9538  RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
9539  if (ast_fileexists(prefile, NULL, NULL) <= 0) {
9540  cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9541  if (cmd == -1) {
9542  break;
9543  }
9544  cmd = 't';
9545  } else {
9546  switch (cmd) {
9547  case '1':
9548  cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9549  break;
9550  case '2':
9551  DELETE(prefile, -1, prefile, vmu);
9552  ast_play_and_wait(chan, "vm-tempremoved");
9553  cmd = 't';
9554  break;
9555  case '*':
9556  cmd = 't';
9557  break;
9558  default:
9559  cmd = ast_play_and_wait(chan,
9560  ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
9561  "vm-tempgreeting2" : "vm-tempgreeting");
9562  if (!cmd) {
9563  cmd = ast_waitfordigit(chan, 6000);
9564  }
9565  if (!cmd) {
9566  retries++;
9567  }
9568  if (retries > 3) {
9569  cmd = 't';
9570  }
9571  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
9572  }
9573  }
9574  DISPOSE(prefile, -1);
9575  }
9576  if (cmd == 't')
9577  cmd = 0;
9578  return cmd;
9579 }
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static int adsi_logo(unsigned char *buf)
static int maxgreet
#define DISPOSE(a, b)
#define ADSI_COMM_PAGE
Definition: adsi.h:107
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
char mailbox[AST_MAX_EXTENSION]
char username[80]
char context[AST_MAX_CONTEXT]
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition: adsi.c:274
#define DELETE(a, b, c, d)
static char VM_SPOOL_DIR[PATH_MAX]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
#define ADSI_JUST_CENT
Definition: adsi.h:114
static int vm_users_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
)
static

Definition at line 11384 of file app_voicemail.c.

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

11386 {
11387  struct ast_vm_user *user;
11388 
11389  AST_LIST_LOCK(&users);
11390  AST_LIST_TRAVERSE(&users, user, list) {
11391  vm_users_data_provider_get_helper(search, data_root, user);
11392  }
11394 
11395  return 0;
11396 }
static char user[512]
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
list of users found in the config file
struct ast_vm_user::@65 list
static int vm_users_data_provider_get_helper(const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
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 11337 of file app_voicemail.c.

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

Referenced by vm_users_data_provider_get().

11339 {
11340  struct ast_data *data_user, *data_zone;
11341  struct ast_data *data_state;
11342  struct vm_zone *zone = NULL;
11343  int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11344  char ext_context[256] = "";
11345 
11346  data_user = ast_data_add_node(data_root, "user");
11347  if (!data_user) {
11348  return -1;
11349  }
11350 
11351  ast_data_add_structure(ast_vm_user, data_user, user);
11352 
11353  AST_LIST_LOCK(&zones);
11354  AST_LIST_TRAVERSE(&zones, zone, list) {
11355  if (!strcmp(zone->name, user->zonetag)) {
11356  break;
11357  }
11358  }
11360 
11361  /* state */
11362  data_state = ast_data_add_node(data_user, "state");
11363  if (!data_state) {
11364  return -1;
11365  }
11366  snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11367  inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11368  ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11369  ast_data_add_int(data_state, "newmsg", newmsg);
11370  ast_data_add_int(data_state, "oldmsg", oldmsg);
11371 
11372  if (zone) {
11373  data_zone = ast_data_add_node(data_user, "zone");
11374  ast_data_add_structure(vm_zone, data_zone, zone);
11375  }
11376 
11377  if (!ast_data_search_match(search, data_user)) {
11378  ast_data_remove_node(data_root, data_user);
11379  }
11380 
11381  return 0;
11382 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
The data tree to be returned by the callbacks and managed by functions local to this file...
Definition: data.c:85
char name[80]
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
Definition: data.c:2317
char mailbox[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
char zonetag[80]
#define ast_data_add_structure(structure_name, root, structure)
Definition: data.h:620
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
Definition: data.c:2486
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_data * ast_data_add_int(struct ast_data *root, const char *childname, int value)
Add an integer node type.
Definition: data.c:2322
int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
Check the current generated node to know if it matches the search condition.
Definition: data.c:1458
struct vm_zone::@66 list
static int vmauthenticate ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 11023 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_vm_user::context, ast_channel::context, pbx_builtin_setvar_helper(), strsep(), user, and vm_authenticate().

Referenced by load_module().

11024 {
11025  char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11026  struct ast_vm_user vmus;
11027  char *options = NULL;
11028  int silent = 0, skipuser = 0;
11029  int res = -1;
11030 
11031  if (data) {
11032  s = ast_strdupa(data);
11033  user = strsep(&s, ",");
11034  options = strsep(&s, ",");
11035  if (user) {
11036  s = user;
11037  user = strsep(&s, "@");
11038  context = strsep(&s, "");
11039  if (!ast_strlen_zero(user))
11040  skipuser++;
11041  ast_copy_string(mailbox, user, sizeof(mailbox));
11042  }
11043  }
11044 
11045  if (options) {
11046  silent = (strchr(options, 's')) != NULL;
11047  }
11048 
11049  if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11050  pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11051  pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11052  ast_play_and_wait(chan, "auth-thankyou");
11053  res = 0;
11054  } else if (mailbox[0] == '*') {
11055  /* user entered '*' */
11056  if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11057  res = 0; /* prevent hangup */
11058  }
11059  }
11060 
11061  return res;
11062 }
static char user[512]
char * strsep(char **str, const char *delims)
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: app.c:822
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_MAX_EXTENSION
Definition: channel.h:135
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)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:11261
structure to hold users read from users.conf
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
static int vmsayname_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 12563 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(), context, ast_channel::language, LOG_WARNING, and sayname().

Referenced by load_module().

12564 {
12565  char *context;
12566  char *args_copy;
12567  int res;
12568 
12569  if (ast_strlen_zero(data)) {
12570  ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12571  return -1;
12572  }
12573 
12574  args_copy = ast_strdupa(data);
12575  if ((context = strchr(args_copy, '@'))) {
12576  *context++ = '\0';
12577  } else {
12578  context = "default";
12579  }
12580 
12581  if ((res = sayname(chan, args_copy, context) < 0)) {
12582  ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12583  res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12584  if (!res) {
12585  res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12586  }
12587  }
12588 
12589  return res;
12590 }
#define AST_DIGIT_ANY
Definition: file.h:47
#define LOG_WARNING
Definition: logger.h:144
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
Definition: channel.c:8421
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
const ast_string_field language
Definition: channel.h:787
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 4461 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().

4462 {
4463  const struct vm_zone *z = NULL;
4464  struct timeval t = ast_tvnow();
4465 
4466  /* Does this user have a timezone specified? */
4467  if (!ast_strlen_zero(vmu->zonetag)) {
4468  /* Find the zone in the list */
4469  AST_LIST_LOCK(&zones);
4470  AST_LIST_TRAVERSE(&zones, z, list) {
4471  if (!strcmp(z->name, vmu->zonetag))
4472  break;
4473  }
4475  }
4476  ast_localtime(&t, tm, z ? z->timezone : NULL);
4477  return tm;
4478 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char name[80]
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char timezone[80]
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char zonetag[80]
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static int wait_file ( struct ast_channel chan,
struct vm_state vms,
char *  file 
)
static

Definition at line 7516 of file app_voicemail.c.

References ast_control_streamfile(), and ast_test_suite_event_notify.

Referenced by advanced_options(), and play_message().

7517 {
7518  ast_test_suite_event_notify("PLAYVOICE", "Message: Playing %s", file);
7520 }
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms)
Stream a file with fast forward, pause, reverse, restart.
Definition: app.c:683
static char listen_control_reverse_key[12]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:184
static int skipms
static char listen_control_restart_key[12]
static char listen_control_pause_key[12]
static char listen_control_forward_key[12]
static char listen_control_stop_key[12]
static int wait_file2 ( struct ast_channel chan,
struct vm_state vms,
char *  file 
)
static

Definition at line 7508 of file app_voicemail.c.

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

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

7509 {
7510  int res;
7511  if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
7512  ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file);
7513  return res;
7514 }
#define AST_DIGIT_ANY
Definition: file.h:47
#define AST_LOG_WARNING
Definition: logger.h:149
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
static int write_password_to_file ( const char *  secretfn,
const char *  password 
)
static

Definition at line 12530 of file app_voicemail.c.

References ast_category_append(), ast_category_destroy(), ast_category_new(), ast_config_destroy(), 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().

12530  {
12531  struct ast_config *conf;
12532  struct ast_category *cat;
12533  struct ast_variable *var;
12534  int res = -1;
12535 
12536  if (!(conf = ast_config_new())) {
12537  ast_log(LOG_ERROR, "Error creating new config structure\n");
12538  return res;
12539  }
12540  if (!(cat = ast_category_new("general", "", 1))) {
12541  ast_log(LOG_ERROR, "Error creating new category structure\n");
12542  ast_config_destroy(conf);
12543  return res;
12544  }
12545  if (!(var = ast_variable_new("password", password, ""))) {
12546  ast_log(LOG_ERROR, "Error creating new variable structure\n");
12547  ast_config_destroy(conf);
12548  ast_category_destroy(cat);
12549  return res;
12550  }
12551  ast_category_append(conf, cat);
12552  ast_variable_append(cat, var);
12553  if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12554  res = 0;
12555  } else {
12556  ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12557  }
12558 
12559  ast_config_destroy(conf);
12560  return res;
12561 }
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Definition: config.c:1977
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
Definition: config.c:673
void ast_category_destroy(struct ast_category *cat)
Definition: config.c:762
#define LOG_ERROR
Definition: logger.h:155
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: config.c:483
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: config.c:888
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Definition: config.c:719
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278

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

Definition at line 13643 of file app_voicemail.c.

char* addesc = "Comedian Mail"
static

Definition at line 769 of file app_voicemail.c.

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

Definition at line 896 of file app_voicemail.c.

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

Definition at line 897 of file app_voicemail.c.

int adsiver = 1
static

Definition at line 898 of file app_voicemail.c.

char* app = "VoiceMail"
static

Definition at line 772 of file app_voicemail.c.

char* app2 = "VoiceMailMain"
static

Definition at line 775 of file app_voicemail.c.

char* app3 = "MailboxExists"
static

Definition at line 777 of file app_voicemail.c.

char* app4 = "VMAuthenticate"
static

Definition at line 778 of file app_voicemail.c.

Definition at line 13643 of file app_voicemail.c.

char callcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 882 of file app_voicemail.c.

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

Definition at line 894 of file app_voicemail.c.

Referenced by tds_load_module().

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static

Definition at line 885 of file app_voicemail.c.

struct ast_cli_entry cli_voicemail[]
static
Initial value:
= {
AST_CLI_DEFINE(handle_voicemail_show_users, "List defined voicemail boxes"),
AST_CLI_DEFINE(handle_voicemail_show_zones, "List zone message formats"),
AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"),
}
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
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_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Reload voicemail configuration from 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.

Definition at line 11262 of file app_voicemail.c.

char dialcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 881 of file app_voicemail.c.

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

char* emailbody = NULL
static

Definition at line 888 of file app_voicemail.c.

Referenced by make_email_file(), and message_template_parse_emailbody().

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

Definition at line 899 of file app_voicemail.c.

char* emailsubject = NULL
static

Definition at line 889 of file app_voicemail.c.

Referenced by make_email_file().

char exitcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 883 of file app_voicemail.c.

Referenced by common_exec(), and conf_run().

char ext_pass_check_cmd[128]
static

Definition at line 749 of file app_voicemail.c.

char ext_pass_cmd[128]
static

Definition at line 748 of file app_voicemail.c.

char externnotify[160]
static

Definition at line 792 of file app_voicemail.c.

char fromstring[100]
static

Definition at line 892 of file app_voicemail.c.

struct ast_flags globalflags = {0}
static

Definition at line 877 of file app_voicemail.c.

struct ao2_container* inprocess_container

Definition at line 921 of file app_voicemail.c.

char listen_control_forward_key[12]
static

Definition at line 850 of file app_voicemail.c.

char listen_control_pause_key[12]
static

Definition at line 852 of file app_voicemail.c.

char listen_control_restart_key[12]
static

Definition at line 853 of file app_voicemail.c.

char listen_control_reverse_key[12]
static

Definition at line 851 of file app_voicemail.c.

char listen_control_stop_key[12]
static

Definition at line 854 of file app_voicemail.c.

char locale[20]
static

Definition at line 785 of file app_voicemail.c.

struct ast_custom_function mailbox_exists_acf
static
Initial value:
= {
.name = "MAILBOX_EXISTS",
}
static int acf_mailbox_exists(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)

Definition at line 11018 of file app_voicemail.c.

const char* const mailbox_folders[]
static

Definition at line 1711 of file app_voicemail.c.

char mailcmd[160]
static

Definition at line 791 of file app_voicemail.c.

int maxdeletedmsg
static

Definition at line 788 of file app_voicemail.c.

Referenced by populate_defaults().

int maxgreet
static

Definition at line 798 of file app_voicemail.c.

int maxlogins
static

Definition at line 800 of file app_voicemail.c.

int maxmsg
static

Definition at line 787 of file app_voicemail.c.

Referenced by populate_defaults().

int maxsilence
static

Definition at line 786 of file app_voicemail.c.

Referenced by ast_record_review().

int minpassword
static

Definition at line 801 of file app_voicemail.c.

struct ast_event_sub* mwi_sub_sub
static

Subscription to ... MWI event subscriptions

Definition at line 819 of file app_voicemail.c.

struct mwi_subs mwi_subs = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
static
struct ast_taskprocessor* mwi_subscription_tps
static

Definition at line 845 of file app_voicemail.c.

struct ast_event_sub* mwi_unsub_sub
static

Subscription to ... MWI event un-subscriptions

Definition at line 821 of file app_voicemail.c.

int my_umask
static

Definition at line 751 of file app_voicemail.c.

char* pagerbody = NULL
static

Definition at line 890 of file app_voicemail.c.

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

Definition at line 900 of file app_voicemail.c.

char pagerfromstring[100]
static

Definition at line 893 of file app_voicemail.c.

char* pagersubject = NULL
static

Definition at line 891 of file app_voicemail.c.

int passwordlocation
static

Definition at line 802 of file app_voicemail.c.

Referenced by populate_defaults().

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static

Definition at line 814 of file app_voicemail.c.

unsigned int poll_freq
static

Polling frequency

Definition at line 809 of file app_voicemail.c.

ast_mutex_t poll_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static

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

pthread_t poll_thread = AST_PTHREADT_NULL
static

Definition at line 815 of file app_voicemail.c.

unsigned char poll_thread_run
static

Definition at line 816 of file app_voicemail.c.

int pwdchange = PWDCHANGE_INTERNAL
static

Definition at line 755 of file app_voicemail.c.

int saydurationminfo
static

Definition at line 879 of file app_voicemail.c.

Referenced by populate_defaults().

char* sayname_app = "VMSayName"
static

Definition at line 780 of file app_voicemail.c.

char serveremail[80]
static

Definition at line 790 of file app_voicemail.c.

Referenced by forward_message(), and notify_new_message().

int silencethreshold = 128
static

Definition at line 789 of file app_voicemail.c.

Referenced by ast_record_review(), and setup_privacy_args().

int skipms
static

Definition at line 799 of file app_voicemail.c.

Referenced by controlplayback_exec(), and handle_controlstreamfile().

struct ast_smdi_interface* smdi_iface = NULL
static

Definition at line 793 of file app_voicemail.c.

struct users users = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
char userscontext[AST_MAX_EXTENSION] = "default"
static

Definition at line 767 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 532 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 11403 of file app_voicemail.c.

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

Definition at line 862 of file app_voicemail.c.

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

Definition at line 861 of file app_voicemail.c.

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

Definition at line 858 of file app_voicemail.c.

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

Definition at line 859 of file app_voicemail.c.

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

Definition at line 857 of file app_voicemail.c.

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

Definition at line 863 of file app_voicemail.c.

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

Definition at line 875 of file app_voicemail.c.

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

Definition at line 860 of file app_voicemail.c.

char VM_SPOOL_DIR[PATH_MAX]
static

Definition at line 746 of file app_voicemail.c.

struct ast_data_handler vm_users_data_provider
static
Initial value:
= {
}
#define AST_DATA_HANDLER_VERSION
The Data API structures version.
Definition: data.h:204
static int vm_users_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)

Definition at line 11398 of file app_voicemail.c.

char vmfmts[80]
static

Definition at line 794 of file app_voicemail.c.

int vmmaxsecs
static

Definition at line 797 of file app_voicemail.c.

Referenced by apply_option(), and populate_defaults().

int vmminsecs
static

Definition at line 796 of file app_voicemail.c.

Referenced by apply_option(), and populate_defaults().

double volgain
static

Definition at line 795 of file app_voicemail.c.

Referenced by populate_defaults().

struct zones zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
char zonetag[80]
static

Definition at line 784 of file app_voicemail.c.

Referenced by build_peer().