Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
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/mwi.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/strings.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj2.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"
#include "asterisk/format_cache.h"
Include dependency graph for app_voicemail.c:

Go to the source code of this file.

Data Structures

struct  alias_mailbox_mapping
 
struct  ast_vm_user
 
struct  baseio
 
struct  inprocess
 
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
 
struct  mailbox_alias_mapping
 
struct  test_files
 
struct  users
 list of users found in the config file More...
 
struct  vm_state
 
struct  vm_zone
 
struct  zones
 

Macros

#define ALIASES_OUTPUT_FORMAT   "%-32s %-32s\n"
 
#define ASTERISK_USERNAME   "asterisk"
 
#define BASELINELEN   72
 
#define BASEMAXINLINE   256
 
#define CHECK(u, attr, value)
 
#define CHUNKSIZE   65536
 
#define COMMAND_TIMEOUT   5000
 
#define COPY(a, b, c, d, e, f, g, h)   (copy_plain_file(g,h));
 
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"
 
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"
 
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"
 
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"
 
#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"
 
#define DEFAULT_POLL_FREQ   30
 
#define DELETE(a, b, c, d)   (vm_delete(c))
 
#define DISPOSE(a, b)
 
#define ENDL   "\n"
 
#define ERROR_LOCK_PATH   -100
 
#define ERROR_MAX_MSGS   -101
 
#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 MAPPING_BUCKETS   511
 
#define MAX_DATETIME_FORMAT   512
 
#define MAX_MAIL_BODY_CONTENT_SIZE   134217728L
 
#define MAX_NUM_CID_CONTEXTS   10
 
#define MAX_VM_CONTEXT_LEN   (AST_MAX_CONTEXT)
 
#define MAX_VM_MAILBOX_LEN   (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)
 
#define MAX_VM_MBOX_ID_LEN   (AST_MAX_EXTENSION)
 
#define MAXMSG   100
 
#define MAXMSGLIMIT   9999
 
#define MINPASSWORD   0
 
#define MSG_ID_LEN   256
 
#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, k)
 
#define tdesc   "Comedian Mail (Voicemail System)"
 
#define UPDATE_MSG_ID(a, b, c, d, e, f)
 
#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 = 0, OLD_FOLDER = 1, WORK_FOLDER = 2, FAMILY_FOLDER = 3,
  FRIENDS_FOLDER = 4, GREETINGS_FOLDER = -1
}
 
enum  vm_option_args {
  OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_BEEP_TONE = 3,
  OPT_ARG_ARRAY_SIZE = 4
}
 
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_EARLYM_GREETING = (1 << 10), OPT_BEEP = (1 << 11)
}
 
enum  vm_passwordlocation { OPT_PWLOC_VOICEMAILCONF = 0, OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2 }
 

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int acf_vm_info (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
 
static int actual_load_config (int reload, struct ast_config *cfg, struct ast_config *ucfg)
 
static int add_email_attachment (FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
 
static int add_message_id (struct ast_config *msg_cfg, char *dir, int msg, char *filename, char *id, size_t id_size, struct ast_vm_user *vmu, int folder)
 
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 struct alias_mailbox_mappingalias_mailbox_mapping_create (const char *alias, const char *mailbox)
 
 AO2_STRING_FIELD_CMP_FN (alias_mailbox_mapping, alias)
 
 AO2_STRING_FIELD_CMP_FN (mailbox_alias_mapping, mailbox)
 
 AO2_STRING_FIELD_HASH_FN (alias_mailbox_mapping, alias)
 
 AO2_STRING_FIELD_HASH_FN (mailbox_alias_mapping, mailbox)
 
static int append_mailbox (const char *context, const char *box, const char *data)
 
static int append_vmu_info_astman (struct mansession *s, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
 Append vmu info string into given astman with event_name. More...
 
static void apply_option (struct ast_vm_user *vmu, const char *var, const char *value)
 Sets 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...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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)
 
 AST_TEST_DEFINE (test_voicemail_vmsayname)
 
 AST_TEST_DEFINE (test_voicemail_msgcount)
 
 AST_TEST_DEFINE (test_voicemail_notify_endl)
 
 AST_TEST_DEFINE (test_voicemail_load_config)
 
 AST_TEST_DEFINE (test_voicemail_vm_info)
 
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, const char *dest_folder)
 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_framefake_read (struct ast_channel *ast)
 
static int fake_write (struct ast_channel *ast, struct ast_frame *frame)
 
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_user_final (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 void generate_msg_id (char *dst)
 Sets the destination string to a uniquely identifying msg_id string. More...
 
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 get_folder_ja (struct ast_channel *chan, int start)
 
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_aliases (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail zones in 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)
 Check the given mailbox's message count. More...
 
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 void load_aliases (struct ast_config *cfg)
 
static int load_config (int reload)
 
static int load_config_from_memory (int reload, struct ast_config *cfg, struct ast_config *ucfg)
 
static int load_module (void)
 Load the module. More...
 
static void load_users (struct ast_config *cfg)
 
static void load_zonemessages (struct ast_config *cfg)
 
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, const char *msg_id)
 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 int manager_match_mailbox (struct ast_mwi_state *mwi_state, void *data)
 
static int manager_status_voicemail_user (struct mansession *s, const struct message *m)
 
static int manager_voicemail_refresh (struct mansession *s, const struct message *m)
 
static void * mb_poll_thread (void *data)
 
static const char * mbox (struct ast_vm_user *vmu, int id)
 
static int message_range_and_existence_check (struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
 common bounds checking and existence check for Voicemail API functions. More...
 
static int messagecount (const char *mailbox_id, const char *folder)
 
static int msg_create_from_file (struct ast_vm_recording_data *recdata)
 
static void mwi_handle_subscribe (const char *id, struct ast_mwi_subscriber *sub)
 
static int mwi_handle_subscribe2 (void *data)
 
static void mwi_handle_unsubscribe (const char *id, struct ast_mwi_subscriber *sub)
 
static int mwi_handle_unsubscribe2 (void *data)
 
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 void notify_new_state (struct ast_vm_user *vmu)
 
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_by_id (struct ast_channel *chan, const char *mailbox, const char *context, const char *msg_id)
 Finds a message in a specific mailbox by msg_id and plays it to the channel. More...
 
static int play_message_by_id_helper (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)
 
static int play_message_callerid (struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
 
static int play_message_category (struct ast_channel *chan, const char *category)
 
static int play_message_datetime (struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
 
static int play_message_duration (struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
 
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag, const char *msg_id, int forwardintro)
 
static int poll_subscribed_mailbox (struct ast_mwi_state *mwi_state, void *data)
 
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 print_mappings (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void queue_mwi_event (const char *channel_id, 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 (const char *context, const char *extension, const char *flag)
 
static int save_to_folder (struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
 
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, const char *msg_id)
 
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 int separate_mailbox (char *mailbox_id, char **mailbox, char **context)
 
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_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_es (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Spanish syntax for 'You have N messages' greeting. More...
 
static int vm_browse_messages_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek syntax for 'You have N messages' greeting. 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_it (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Italian syntax for 'You have N messages' greeting. More...
 
static int vm_browse_messages_ja (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Japanese syntax for 'You have N messages' greeting. More...
 
static int vm_browse_messages_pt (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Portuguese syntax for 'You have N messages' greeting. 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 const char * vm_index_to_foldername (int id)
 
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_ja (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_is (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_ja (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 struct ast_vm_mailbox_snapshotvm_mailbox_snapshot_create (const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
 
static struct ast_vm_mailbox_snapshotvm_mailbox_snapshot_destroy (struct ast_vm_mailbox_snapshot *mailbox_snapshot)
 
static FILE * vm_mkftemp (char *template)
 
static int vm_msg_forward (const char *from_mailbox, const char *from_context, const char *from_folder, const char *to_mailbox, const char *to_context, const char *to_folder, size_t num_msgs, const char *msg_ids[], int delete_old)
 
static int vm_msg_move (const char *mailbox, const char *context, size_t num_msgs, const char *oldfolder, const char *old_msg_ids[], const char *newfolder)
 
static int vm_msg_play (struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb cb)
 
static int vm_msg_remove (const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
 
static struct ast_vm_msg_snapshotvm_msg_snapshot_alloc (void)
 
static int vm_msg_snapshot_create (struct ast_vm_user *vmu, struct vm_state *vms, struct ast_vm_mailbox_snapshot *mailbox_snapshot, int snapshot_index, int mailbox_index, int descending, enum ast_vm_snapshot_sort_val sort_val)
 Create and store off all the msgs in an open mailbox. More...
 
static struct ast_vm_msg_snapshotvm_msg_snapshot_destroy (struct ast_vm_msg_snapshot *msg_snapshot)
 
static int vm_newuser_setup (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_ja (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_playmsgexec (struct ast_channel *chan, const char *data)
 
static int vm_sayname (struct ast_channel *chan, const char *mailbox_id)
 
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_test_create_user (const char *context, const char *mailbox)
 
static int vm_test_destroy_user (const char *context, const char *mailbox)
 
static int vmauthenticate (struct ast_channel *chan, const char *data)
 
static int vmsayname_exec (struct ast_channel *chan, const char *data)
 
static const 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .optional_modules = "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 struct ao2_containeralias_mailbox_mappings
 
static char aliasescontext [MAX_VM_CONTEXT_LEN]
 
static const 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
 
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
 
static char * emailsubject
 
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 ao2_containermailbox_alias_mappings
 
static const char *const mailbox_folders []
 
static char mailcmd [160] = SENDMAIL
 
static int maxdeletedmsg
 
static int maxgreet
 
static int maxlogins = 3
 
static int maxmsg = MAXMSG
 
static int maxsilence
 
static int minpassword = MINPASSWORD
 
static int msg_id_incrementor
 
struct ast_mwi_observer mwi_observer
 
static struct ast_taskprocessormwi_subscription_tps
 
static int my_umask
 
static char * pagerbody
 
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
 
static char pagerfromstring [100]
 
static char * pagersubject
 
static int passwordlocation
 
static char * playmsg_app = "VoiceMailPlayMsg"
 
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
 
static unsigned int poll_freq = DEFAULT_POLL_FREQ
 
static ast_mutex_t poll_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
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 = 2
 
static char * sayname_app = "VMSayName"
 
static char serveremail [80] = ASTERISK_USERNAME
 
static int silencethreshold = 128
 
static int skipms = 3000
 
static struct ast_smdi_interfacesmdi_iface = NULL
 
static struct users users = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static char userscontext [AST_MAX_EXTENSION] = "default"
 
static const 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 }, [ 'e' ] = { .flag = OPT_EARLYM_GREETING }, [ 't' ] = { .flag = OPT_BEEP , .arg_index = OPT_ARG_BEEP_TONE + 1 } }
 
static const struct ast_vm_greeter_functions vm_greeter_table
 
static struct ast_custom_function vm_info_acf
 
static char vm_invalid_password [80] = "vm-invalid-password"
 
static char vm_login [80] = "vm-login"
 
static char vm_mismatch [80] = "vm-mismatch"
 
static char vm_newpassword [80] = "vm-newpassword"
 
static char vm_newuser [80] = "vm-newuser"
 
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 const struct ast_vm_functions vm_table
 
static char * vmauthenticate_app = "VMAuthenticate"
 
static char vmfmts [80] = "wav"
 
static int vmmaxsecs
 
static int vmminsecs
 
static char * voicemail_app = "VoiceMail"
 
static char * voicemailmain_app = "VoiceMailMain"
 
static double volgain
 
static struct zones zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
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 unixODBC (http://www.unixodbc.org/) A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/)
See also
  • Config_vm
Note
For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage
Todo:
This module requires res_adsi to load. This needs to be optional during compilation.
Todo:
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

◆ ALIASES_OUTPUT_FORMAT

#define ALIASES_OUTPUT_FORMAT   "%-32s %-32s\n"

◆ ASTERISK_USERNAME

#define ASTERISK_USERNAME   "asterisk"

Definition at line 512 of file app_voicemail.c.

Referenced by actual_load_config().

◆ BASELINELEN

#define BASELINELEN   72

Definition at line 537 of file app_voicemail.c.

Referenced by ochar().

◆ BASEMAXINLINE

#define BASEMAXINLINE   256

Definition at line 538 of file app_voicemail.c.

Referenced by base_encode(), and inbuf().

◆ CHECK

#define CHECK (   u,
  attr,
  value 
)
Value:
else if (strcmp(u->attr, value)) { \
ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
int value
Definition: syslog.c:37

Referenced by AST_TEST_DEFINE().

◆ CHUNKSIZE

#define CHUNKSIZE   65536

Definition at line 509 of file app_voicemail.c.

◆ COMMAND_TIMEOUT

#define COMMAND_TIMEOUT   5000

Definition at line 505 of file app_voicemail.c.

◆ COPY

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

Definition at line 872 of file app_voicemail.c.

Referenced by copy_message(), and save_to_folder().

◆ DEFAULT_LISTEN_CONTROL_FORWARD_KEY

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 517 of file app_voicemail.c.

Referenced by actual_load_config().

◆ DEFAULT_LISTEN_CONTROL_PAUSE_KEY

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 519 of file app_voicemail.c.

Referenced by actual_load_config().

◆ DEFAULT_LISTEN_CONTROL_RESTART_KEY

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 520 of file app_voicemail.c.

Referenced by actual_load_config().

◆ DEFAULT_LISTEN_CONTROL_REVERSE_KEY

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 518 of file app_voicemail.c.

Referenced by actual_load_config().

◆ DEFAULT_LISTEN_CONTROL_STOP_KEY

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 521 of file app_voicemail.c.

Referenced by actual_load_config().

◆ DEFAULT_POLL_FREQ

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 943 of file app_voicemail.c.

Referenced by actual_load_config().

◆ DELETE

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

◆ DISPOSE

#define DISPOSE (   a,
  b 
)

◆ ENDL

#define ENDL   "\n"

Definition at line 542 of file app_voicemail.c.

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

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

◆ ERROR_MAX_MSGS

#define ERROR_MAX_MSGS   -101

Definition at line 568 of file app_voicemail.c.

Referenced by close_mailbox(), and save_to_folder().

◆ EXISTS

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

Definition at line 870 of file app_voicemail.c.

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

◆ HVSU_OUTPUT_FORMAT

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

◆ HVSZ_OUTPUT_FORMAT

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

◆ INTRO

#define INTRO   "vm-intro"

Definition at line 528 of file app_voicemail.c.

Referenced by leave_voicemail(), and play_record_review().

◆ MAPPING_BUCKETS

#define MAPPING_BUCKETS   511

Definition at line 966 of file app_voicemail.c.

Referenced by load_module().

◆ MAX_DATETIME_FORMAT

#define MAX_DATETIME_FORMAT   512

Definition at line 545 of file app_voicemail.c.

◆ MAX_MAIL_BODY_CONTENT_SIZE

#define MAX_MAIL_BODY_CONTENT_SIZE   134217728L

Definition at line 530 of file app_voicemail.c.

Referenced by vm_allocate_dh().

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 546 of file app_voicemail.c.

Referenced by actual_load_config(), and play_message_callerid().

◆ MAX_VM_CONTEXT_LEN

#define MAX_VM_CONTEXT_LEN   (AST_MAX_CONTEXT)

Definition at line 749 of file app_voicemail.c.

◆ MAX_VM_MAILBOX_LEN

#define MAX_VM_MAILBOX_LEN   (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)

Definition at line 751 of file app_voicemail.c.

Referenced by __has_voicemail(), append_mailbox(), and find_user().

◆ MAX_VM_MBOX_ID_LEN

#define MAX_VM_MBOX_ID_LEN   (AST_MAX_EXTENSION)

Definition at line 748 of file app_voicemail.c.

◆ MAXMSG

#define MAXMSG   100

Definition at line 532 of file app_voicemail.c.

Referenced by actual_load_config(), and apply_option().

◆ MAXMSGLIMIT

#define MAXMSGLIMIT   9999

Definition at line 533 of file app_voicemail.c.

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

◆ MINPASSWORD

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 535 of file app_voicemail.c.

Referenced by actual_load_config().

◆ MSG_ID_LEN

#define MSG_ID_LEN   256

◆ OPERATOR_EXIT

#define OPERATOR_EXIT   300

Definition at line 569 of file app_voicemail.c.

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

◆ PWDCHANGE_EXTERNAL

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 886 of file app_voicemail.c.

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

◆ PWDCHANGE_INTERNAL

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 885 of file app_voicemail.c.

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

◆ RENAME

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

Definition at line 871 of file app_voicemail.c.

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

◆ RETRIEVE

#define RETRIEVE (   a,
  b,
  c,
  d 
)

◆ SENDMAIL

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

Definition at line 526 of file app_voicemail.c.

Referenced by actual_load_config().

◆ SMDI_MWI_WAIT_TIMEOUT

#define SMDI_MWI_WAIT_TIMEOUT   1000 /* 1 second */

Definition at line 503 of file app_voicemail.c.

Referenced by run_externnotify().

◆ STORE

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

◆ tdesc

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 895 of file app_voicemail.c.

Referenced by vm_msg_play().

◆ UPDATE_MSG_ID

#define UPDATE_MSG_ID (   a,
  b,
  c,
  d,
  e,
 
)

Definition at line 874 of file app_voicemail.c.

Referenced by add_message_id().

◆ VALID_DTMF

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

Definition at line 522 of file app_voicemail.c.

Referenced by is_valid_dtmf().

◆ VM_ALLOCED

#define VM_ALLOCED   (1 << 13)

Structure was malloc'ed, instead of placed in a return (usually static) buffer

Definition at line 561 of file app_voicemail.c.

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

◆ VM_ATTACH

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 559 of file app_voicemail.c.

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

◆ VM_DELETE

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 560 of file app_voicemail.c.

Referenced by append_vmu_info_astman(), apply_option(), AST_TEST_DEFINE(), and notify_new_message().

◆ VM_DIRECFORWARD

#define VM_DIRECFORWARD   (1 << 10)

Permit caller to use the Directory app for selecting to which mailbox to forward a VM

Definition at line 558 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

◆ VM_ENVELOPE

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 552 of file app_voicemail.c.

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

◆ VM_FORCEGREET

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 556 of file app_voicemail.c.

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

◆ VM_FORCENAME

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 555 of file app_voicemail.c.

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

◆ VM_FWDURGAUTO

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 566 of file app_voicemail.c.

Referenced by actual_load_config(), and forward_message().

◆ VM_MESSAGEWRAP

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 565 of file app_voicemail.c.

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

◆ VM_MOVEHEARD

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 564 of file app_voicemail.c.

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

◆ VM_OPERATOR

#define VM_OPERATOR   (1 << 1)

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

Definition at line 549 of file app_voicemail.c.

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

◆ VM_PBXSKIP

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 557 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

◆ VM_REVIEW

#define VM_REVIEW   (1 << 0)

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

Definition at line 548 of file app_voicemail.c.

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

◆ VM_SAYCID

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 550 of file app_voicemail.c.

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

◆ VM_SAYDURATION

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 553 of file app_voicemail.c.

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

◆ VM_SEARCH

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 562 of file app_voicemail.c.

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

◆ VM_SKIPAFTERCMD

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 554 of file app_voicemail.c.

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

◆ VM_SVMAIL

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 551 of file app_voicemail.c.

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

◆ VM_TEMPGREETWARN

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 563 of file app_voicemail.c.

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

◆ VMSTATE_MAX_MSG_ARRAY

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 803 of file app_voicemail.c.

Referenced by vm_allocate_dh().

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 511 of file app_voicemail.c.

Referenced by load_config(), and vm_change_password().

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0777

Definition at line 507 of file app_voicemail.c.

Referenced by create_dirpath(), leave_voicemail(), and msg_create_from_file().

◆ VOICEMAIL_FILE_MODE

#define VOICEMAIL_FILE_MODE   0666

Definition at line 508 of file app_voicemail.c.

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

Enumeration Type Documentation

◆ vm_box

enum vm_box
Enumerator
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 571 of file app_voicemail.c.

◆ vm_option_args

Enumerator
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_BEEP_TONE 
OPT_ARG_ARRAY_SIZE 

Definition at line 594 of file app_voicemail.c.

594  {
595  OPT_ARG_RECORDGAIN = 0,
596  OPT_ARG_PLAYFOLDER = 1,
597  OPT_ARG_DTMFEXIT = 2,
598  OPT_ARG_BEEP_TONE = 3,
599  /* This *must* be the last value in this enum! */
600  OPT_ARG_ARRAY_SIZE = 4,
601 };

◆ vm_option_flags

Enumerator
OPT_SILENT 
OPT_BUSY_GREETING 
OPT_UNAVAIL_GREETING 
OPT_RECORDGAIN 
OPT_PREPEND_MAILBOX 
OPT_AUTOPLAY 
OPT_DTMFEXIT 
OPT_MESSAGE_Urgent 
OPT_MESSAGE_PRIORITY 
OPT_EARLYM_GREETING 
OPT_BEEP 

Definition at line 580 of file app_voicemail.c.

580  {
581  OPT_SILENT = (1 << 0),
582  OPT_BUSY_GREETING = (1 << 1),
583  OPT_UNAVAIL_GREETING = (1 << 2),
584  OPT_RECORDGAIN = (1 << 3),
585  OPT_PREPEND_MAILBOX = (1 << 4),
586  OPT_AUTOPLAY = (1 << 6),
587  OPT_DTMFEXIT = (1 << 7),
588  OPT_MESSAGE_Urgent = (1 << 8),
589  OPT_MESSAGE_PRIORITY = (1 << 9),
590  OPT_EARLYM_GREETING = (1 << 10),
591  OPT_BEEP = (1 << 11)
592 };

◆ vm_passwordlocation

Enumerator
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 603 of file app_voicemail.c.

Function Documentation

◆ __has_voicemail()

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

Definition at line 6061 of file app_voicemail.c.

References ao2_find, ao2_ref, ast_strdupa, ast_strlen_zero, c, alias_mailbox_mapping::mailbox, MAX_VM_MAILBOX_LEN, OBJ_SEARCH_KEY, and separate_mailbox().

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

6062 {
6063  DIR *dir;
6064  struct dirent *de;
6065  char fn[256];
6066  int ret = 0;
6067  struct alias_mailbox_mapping *mapping;
6068  char *c;
6069  char *m;
6070 
6071  /* If no mailbox, return immediately */
6072  if (ast_strlen_zero(mailbox))
6073  return 0;
6074 
6075  if (ast_strlen_zero(folder))
6076  folder = "INBOX";
6077  if (ast_strlen_zero(context))
6078  context = "default";
6079 
6080  c = (char *)context;
6081  m = (char *)mailbox;
6082 
6084  char tmp[MAX_VM_MAILBOX_LEN];
6085 
6086  snprintf(tmp, MAX_VM_MAILBOX_LEN, "%s@%s", mailbox, context);
6088  if (mapping) {
6089  separate_mailbox(ast_strdupa(mapping->mailbox), &m, &c);
6090  ao2_ref(mapping, -1);
6091  }
6092  }
6093 
6094  snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, c, m, folder);
6095 
6096  if (!(dir = opendir(fn)))
6097  return 0;
6098 
6099  while ((de = readdir(dir))) {
6100  if (!strncasecmp(de->d_name, "msg", 3)) {
6101  if (shortcircuit) {
6102  ret = 1;
6103  break;
6104  } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
6105  ret++;
6106  }
6107  }
6108  }
6109 
6110  closedir(dir);
6111 
6112  return ret;
6113 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static struct ao2_container * alias_mailbox_mappings
static int tmp()
Definition: bt_open.c:389
static struct test_val c
static char aliasescontext[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static char VM_SPOOL_DIR[PATH_MAX]
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define MAX_VM_MAILBOX_LEN

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 16611 of file app_voicemail.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 16611 of file app_voicemail.c.

◆ acf_vm_info()

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

Definition at line 12679 of file app_voicemail.c.

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

Referenced by AST_TEST_DEFINE().

12680 {
12681  struct ast_vm_user svm;
12682  struct ast_vm_user *vmu = NULL;
12683  char *parse;
12684  char *mailbox;
12685  char *context;
12686  int res = 0;
12687 
12689  AST_APP_ARG(mailbox_context);
12690  AST_APP_ARG(attribute);
12691  AST_APP_ARG(folder);
12692  );
12693 
12694  buf[0] = '\0';
12695 
12696  if (ast_strlen_zero(args)) {
12697  ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12698  return -1;
12699  }
12700 
12701  parse = ast_strdupa(args);
12702  AST_STANDARD_APP_ARGS(arg, parse);
12703 
12704  if (ast_strlen_zero(arg.mailbox_context)
12705  || ast_strlen_zero(arg.attribute)
12706  || separate_mailbox(ast_strdupa(arg.mailbox_context), &mailbox, &context)) {
12707  ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12708  return -1;
12709  }
12710 
12711  memset(&svm, 0, sizeof(svm));
12712  vmu = find_user(&svm, context, mailbox);
12713 
12714  if (!strncasecmp(arg.attribute, "exists", 5)) {
12715  ast_copy_string(buf, vmu ? "1" : "0", len);
12716  free_user(vmu);
12717  return 0;
12718  }
12719 
12720  if (vmu) {
12721  if (!strncasecmp(arg.attribute, "password", 8)) {
12722  ast_copy_string(buf, vmu->password, len);
12723  } else if (!strncasecmp(arg.attribute, "fullname", 8)) {
12724  ast_copy_string(buf, vmu->fullname, len);
12725  } else if (!strncasecmp(arg.attribute, "email", 5)) {
12726  ast_copy_string(buf, vmu->email, len);
12727  } else if (!strncasecmp(arg.attribute, "pager", 5)) {
12728  ast_copy_string(buf, vmu->pager, len);
12729  } else if (!strncasecmp(arg.attribute, "language", 8)) {
12731  } else if (!strncasecmp(arg.attribute, "locale", 6)) {
12732  ast_copy_string(buf, vmu->locale, len);
12733  } else if (!strncasecmp(arg.attribute, "tz", 2)) {
12734  ast_copy_string(buf, vmu->zonetag, len);
12735  } else if (!strncasecmp(arg.attribute, "count", 5)) {
12736  char *mailbox_id;
12737 
12738  mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2);
12739  sprintf(mailbox_id, "%s@%s", mailbox, context);/* Safe */
12740 
12741  /* If mbxfolder is empty messagecount will default to INBOX */
12742  res = messagecount(mailbox_id, arg.folder);
12743  if (res < 0) {
12744  ast_log(LOG_ERROR, "Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
12745  free_user(vmu);
12746  return -1;
12747  }
12748  snprintf(buf, len, "%d", res);
12749  } else {
12750  ast_log(LOG_ERROR, "Unknown attribute '%s' for VM_INFO\n", arg.attribute);
12751  free_user(vmu);
12752  return -1;
12753  }
12754  free_user(vmu);
12755  }
12756 
12757  return 0;
12758 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
static int messagecount(const char *mailbox_id, const char *folder)
char pager[80]
const char * args
char password[80]
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
char locale[20]
char zonetag[80]
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void free_user(struct ast_vm_user *vmu)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:1872
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
char language[MAX_LANGUAGE]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_language(const struct ast_channel *chan)
char fullname[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ actual_load_config()

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

Definition at line 13680 of file app_voicemail.c.

References ao2_callback, 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_LOCK, AST_LIST_UNLOCK, ast_log, AST_LOG_ERROR, AST_LOG_WARNING, ast_mwi_state_callback_all(), AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero, ast_taskprocessor_alert_set_levels(), AST_TASKPROCESSOR_HIGH_WATER_LEVEL, 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(), load_aliases(), load_users(), load_zonemessages(), LOG_ERROR, ast_vm_user::mailbox, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, PATH_MAX, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), S_OR, SENDMAIL, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, tmp(), 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(), and load_config_from_memory().

13681 {
13682  struct ast_vm_user *current;
13683  char *cat;
13684  const char *val;
13685  char *q, *stringp, *tmp;
13686  int x;
13687  unsigned int tmpadsi[4];
13688  char secretfn[PATH_MAX] = "";
13689  long tps_queue_low;
13690  long tps_queue_high;
13691 
13692 #ifdef IMAP_STORAGE
13693  ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
13694 #endif
13695  /* set audio control prompts */
13701 
13702 #ifdef IMAP_STORAGE
13703  ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
13704 #endif
13705 
13706  /* Free all the users structure */
13707  free_vm_users();
13708 
13709  /* Free all the zones structure */
13710  free_vm_zones();
13711 
13712  /* Remove all aliases */
13715 
13716  AST_LIST_LOCK(&users);
13717 
13718  memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
13719  memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
13720 
13721  if (cfg) {
13722  /* General settings */
13723 
13724  if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
13725  val = "default";
13726  ast_copy_string(userscontext, val, sizeof(userscontext));
13727 
13728  aliasescontext[0] = '\0';
13729  val = ast_variable_retrieve(cfg, "general", "aliasescontext");
13730  ast_copy_string(aliasescontext, S_OR(val, ""), sizeof(aliasescontext));
13731 
13732  /* Attach voice message to mail message ? */
13733  if (!(val = ast_variable_retrieve(cfg, "general", "attach")))
13734  val = "yes";
13736 
13737  if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
13738  val = "no";
13740 
13741  volgain = 0.0;
13742  if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
13743  sscanf(val, "%30lf", &volgain);
13744 
13745 #ifdef ODBC_STORAGE
13746  strcpy(odbc_database, "asterisk");
13747  if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
13748  ast_copy_string(odbc_database, val, sizeof(odbc_database));
13749  }
13750  strcpy(odbc_table, "voicemessages");
13751  if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
13752  ast_copy_string(odbc_table, val, sizeof(odbc_table));
13753  }
13754 #endif
13755  /* Mail command */
13756  strcpy(mailcmd, SENDMAIL);
13757  if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
13758  ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
13759 
13760  maxsilence = 0;
13761  if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
13762  maxsilence = atoi(val);
13763  if (maxsilence > 0)
13764  maxsilence *= 1000;
13765  }
13766 
13767  if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
13768  maxmsg = MAXMSG;
13769  } else {
13770  maxmsg = atoi(val);
13771  if (maxmsg < 0) {
13772  ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
13773  maxmsg = MAXMSG;
13774  } else if (maxmsg > MAXMSGLIMIT) {
13775  ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
13776  maxmsg = MAXMSGLIMIT;
13777  }
13778  }
13779 
13780  if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
13781  maxdeletedmsg = 0;
13782  } else {
13783  if (sscanf(val, "%30d", &x) == 1)
13784  maxdeletedmsg = x;
13785  else if (ast_true(val))
13787  else
13788  maxdeletedmsg = 0;
13789 
13790  if (maxdeletedmsg < 0) {
13791  ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
13793  } else if (maxdeletedmsg > MAXMSGLIMIT) {
13794  ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
13796  }
13797  }
13798 
13799  /* Load date format config for voicemail mail */
13800  if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
13802  }
13803 
13804  /* Load date format config for voicemail pager mail */
13805  if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
13807  }
13808 
13809  /* External password changing command */
13810  if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
13811  ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
13813  } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
13814  ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
13816  }
13817 
13818  /* External password validation command */
13819  if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
13821  ast_debug(1, "found externpasscheck: %s\n", ext_pass_check_cmd);
13822  }
13823 
13824 #ifdef IMAP_STORAGE
13825  /* IMAP server address */
13826  if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
13827  ast_copy_string(imapserver, val, sizeof(imapserver));
13828  } else {
13829  ast_copy_string(imapserver, "localhost", sizeof(imapserver));
13830  }
13831  /* IMAP server port */
13832  if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
13833  ast_copy_string(imapport, val, sizeof(imapport));
13834  } else {
13835  ast_copy_string(imapport, "143", sizeof(imapport));
13836  }
13837  /* IMAP server flags */
13838  if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
13839  ast_copy_string(imapflags, val, sizeof(imapflags));
13840  }
13841  /* IMAP server master username */
13842  if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
13843  ast_copy_string(authuser, val, sizeof(authuser));
13844  }
13845  /* IMAP server master password */
13846  if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
13847  ast_copy_string(authpassword, val, sizeof(authpassword));
13848  }
13849  /* Expunge on exit */
13850  if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
13851  if (ast_false(val))
13852  expungeonhangup = 0;
13853  else
13854  expungeonhangup = 1;
13855  } else {
13856  expungeonhangup = 1;
13857  }
13858  /* IMAP voicemail folder */
13859  if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
13860  ast_copy_string(imapfolder, val, sizeof(imapfolder));
13861  } else {
13862  ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
13863  }
13864  if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
13865  ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
13866  }
13867  if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
13868  imapgreetings = ast_true(val);
13869  } else {
13870  imapgreetings = 0;
13871  }
13872  if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
13873  ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
13874  } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
13875  /* Also support greetingsfolder as documented in voicemail.conf.sample */
13876  ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
13877  } else {
13878  ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
13879  }
13880  if ((val = ast_variable_retrieve(cfg, "general", "imap_poll_logout"))) {
13881  imap_poll_logout = ast_true(val);
13882  } else {
13883  imap_poll_logout = 0;
13884  }
13885 
13886  /* There is some very unorthodox casting done here. This is due
13887  * to the way c-client handles the argument passed in. It expects a
13888  * void pointer and casts the pointer directly to a long without
13889  * first dereferencing it. */
13890  if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
13891  mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
13892  } else {
13893  mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
13894  }
13895 
13896  if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
13897  mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
13898  } else {
13899  mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
13900  }
13901 
13902  if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
13903  mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
13904  } else {
13905  mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
13906  }
13907 
13908  if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
13909  mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
13910  } else {
13911  mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
13912  }
13913 
13914  /* Increment configuration version */
13915  imapversion++;
13916 #endif
13917  /* External voicemail notify application */
13918  if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
13919  ast_copy_string(externnotify, val, sizeof(externnotify));
13920  ast_debug(1, "found externnotify: %s\n", externnotify);
13921  } else {
13922  externnotify[0] = '\0';
13923  }
13924 
13925  /* SMDI voicemail notification */
13926  if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
13927  ast_debug(1, "Enabled SMDI voicemail notification\n");
13928  if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
13930  } else {
13931  ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
13932  smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
13933  }
13934  if (!smdi_iface) {
13935  ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
13936  }
13937  }
13938 
13939  /* Silence treshold */
13941  if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
13942  silencethreshold = atoi(val);
13943 
13944  if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
13945  val = ASTERISK_USERNAME;
13946  ast_copy_string(serveremail, val, sizeof(serveremail));
13947 
13948  vmmaxsecs = 0;
13949  if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
13950  if (sscanf(val, "%30d", &x) == 1) {
13951  vmmaxsecs = x;
13952  } else {
13953  ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
13954  }
13955  } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
13956  static int maxmessage_deprecate = 0;
13957  if (maxmessage_deprecate == 0) {
13958  maxmessage_deprecate = 1;
13959  ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
13960  }
13961  if (sscanf(val, "%30d", &x) == 1) {
13962  vmmaxsecs = x;
13963  } else {
13964  ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
13965  }
13966  }
13967 
13968  vmminsecs = 0;
13969  if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
13970  if (sscanf(val, "%30d", &x) == 1) {
13971  vmminsecs = x;
13972  if (maxsilence / 1000 >= vmminsecs) {
13973  ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
13974  }
13975  } else {
13976  ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
13977  }
13978  } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
13979  static int maxmessage_deprecate = 0;
13980  if (maxmessage_deprecate == 0) {
13981  maxmessage_deprecate = 1;
13982  ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
13983  }
13984  if (sscanf(val, "%30d", &x) == 1) {
13985  vmminsecs = x;
13986  if (maxsilence / 1000 >= vmminsecs) {
13987  ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
13988  }
13989  } else {
13990  ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
13991  }
13992  }
13993 
13994  val = ast_variable_retrieve(cfg, "general", "format");
13995  if (!val) {
13996  val = "wav";
13997  } else {
13998  tmp = ast_strdupa(val);
13999  val = ast_format_str_reduce(tmp);
14000  if (!val) {
14001  ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
14002  val = "wav";
14003  }
14004  }
14005  ast_copy_string(vmfmts, val, sizeof(vmfmts));
14006 
14007  skipms = 3000;
14008  if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
14009  if (sscanf(val, "%30d", &x) == 1) {
14010  maxgreet = x;
14011  } else {
14012  ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
14013  }
14014  }
14015 
14016  if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
14017  if (sscanf(val, "%30d", &x) == 1) {
14018  skipms = x;
14019  } else {
14020  ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
14021  }
14022  }
14023 
14024  maxlogins = 3;
14025  if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
14026  if (sscanf(val, "%30d", &x) == 1) {
14027  maxlogins = x;
14028  } else {
14029  ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
14030  }
14031  }
14032 
14034  if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
14035  if (sscanf(val, "%30d", &x) == 1) {
14036  minpassword = x;
14037  } else {
14038  ast_log(AST_LOG_WARNING, "Invalid minimum password length. Default to %d\n", minpassword);
14039  }
14040  }
14041 
14042  /* Force new user to record name ? */
14043  if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
14044  val = "no";
14046 
14047  /* Force new user to record greetings ? */
14048  if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
14049  val = "no";
14051 
14052  if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
14053  ast_debug(1, "VM_CID Internal context string: %s\n", val);
14054  stringp = ast_strdupa(val);
14055  for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
14056  if (!ast_strlen_zero(stringp)) {
14057  q = strsep(&stringp, ",");
14058  while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
14059  q++;
14061  ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
14062  } else {
14063  cidinternalcontexts[x][0] = '\0';
14064  }
14065  }
14066  }
14067  if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
14068  ast_debug(1, "VM Review Option disabled globally\n");
14069  val = "no";
14070  }
14072 
14073  /* Temporary greeting reminder */
14074  if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
14075  ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
14076  val = "no";
14077  } else {
14078  ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
14079  }
14081  if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
14082  ast_debug(1, "VM next message wrap disabled globally\n");
14083  val = "no";
14084  }
14086 
14087  if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
14088  ast_debug(1, "VM Operator break disabled globally\n");
14089  val = "no";
14090  }
14092 
14093  if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
14094  ast_debug(1, "VM CID Info before msg disabled globally\n");
14095  val = "no";
14096  }
14098 
14099  if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
14100  ast_debug(1, "Send Voicemail msg disabled globally\n");
14101  val = "no";
14102  }
14104 
14105  if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
14106  ast_debug(1, "ENVELOPE before msg enabled globally\n");
14107  val = "yes";
14108  }
14110 
14111  if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
14112  ast_debug(1, "Move Heard enabled globally\n");
14113  val = "yes";
14114  }
14116 
14117  if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
14118  ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
14119  val = "no";
14120  }
14122 
14123  if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
14124  ast_debug(1, "Duration info before msg enabled globally\n");
14125  val = "yes";
14126  }
14128 
14129  saydurationminfo = 2;
14130  if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
14131  if (sscanf(val, "%30d", &x) == 1) {
14132  saydurationminfo = x;
14133  } else {
14134  ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
14135  }
14136  }
14137 
14138  if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
14139  ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
14140  val = "no";
14141  }
14143 
14144  if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
14145  ast_copy_string(dialcontext, val, sizeof(dialcontext));
14146  ast_debug(1, "found dialout context: %s\n", dialcontext);
14147  } else {
14148  dialcontext[0] = '\0';
14149  }
14150 
14151  if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
14152  ast_copy_string(callcontext, val, sizeof(callcontext));
14153  ast_debug(1, "found callback context: %s\n", callcontext);
14154  } else {
14155  callcontext[0] = '\0';
14156  }
14157 
14158  if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
14159  ast_copy_string(exitcontext, val, sizeof(exitcontext));
14160  ast_debug(1, "found operator context: %s\n", exitcontext);
14161  } else {
14162  exitcontext[0] = '\0';
14163  }
14164 
14165  /* load password sounds configuration */
14166  if ((val = ast_variable_retrieve(cfg, "general", "vm-login")))
14167  ast_copy_string(vm_login, val, sizeof(vm_login));
14168  if ((val = ast_variable_retrieve(cfg, "general", "vm-newuser")))
14169  ast_copy_string(vm_newuser, val, sizeof(vm_newuser));
14170  if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
14171  ast_copy_string(vm_password, val, sizeof(vm_password));
14172  if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
14174  if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
14176  if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
14178  if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
14180  if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
14181  ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
14182  if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
14184  }
14185  if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
14187  }
14188  /* load configurable audio prompts */
14189  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
14191  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
14193  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
14195  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
14197  if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
14199 
14200  if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory")))
14201  val = "no";
14203 
14204  if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
14205  val = "voicemail.conf";
14206  }
14207  if (!(strcmp(val, "spooldir"))) {
14209  } else {
14211  }
14212 
14214  if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
14215  if (sscanf(val, "%30u", &poll_freq) != 1) {
14217  ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
14218  }
14219  }
14220 
14221  poll_mailboxes = 0;
14222  if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
14223  poll_mailboxes = ast_true(val);
14224 
14225  memset(fromstring, 0, sizeof(fromstring));
14226  memset(pagerfromstring, 0, sizeof(pagerfromstring));
14227  strcpy(charset, "ISO-8859-1");
14228  if (emailbody) {
14230  emailbody = NULL;
14231  }
14232  if (emailsubject) {
14234  emailsubject = NULL;
14235  }
14236  if (pagerbody) {
14238  pagerbody = NULL;
14239  }
14240  if (pagersubject) {
14242  pagersubject = NULL;
14243  }
14244  if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
14246  if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
14247  ast_copy_string(fromstring, val, sizeof(fromstring));
14248  if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
14250  if ((val = ast_variable_retrieve(cfg, "general", "charset")))
14251  ast_copy_string(charset, val, sizeof(charset));
14252  if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
14253  sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14254  for (x = 0; x < 4; x++) {
14255  memcpy(&adsifdn[x], &tmpadsi[x], 1);
14256  }
14257  }
14258  if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
14259  sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14260  for (x = 0; x < 4; x++) {
14261  memcpy(&adsisec[x], &tmpadsi[x], 1);
14262  }
14263  }
14264  if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
14265  if (atoi(val)) {
14266  adsiver = atoi(val);
14267  }
14268  }
14269  if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
14270  ast_copy_string(zonetag, val, sizeof(zonetag));
14271  }
14272  if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
14273  ast_copy_string(locale, val, sizeof(locale));
14274  }
14275  if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
14277  }
14278  if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
14280  }
14281  if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
14283  }
14284  if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
14286  }
14287 
14288  tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
14289  if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_high"))) {
14290  if (sscanf(val, "%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
14291  ast_log(AST_LOG_WARNING, "Invalid the taskprocessor high water alert trigger level '%s'\n", val);
14292  tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
14293  }
14294  }
14295  tps_queue_low = -1;
14296  if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_low"))) {
14297  if (sscanf(val, "%30ld", &tps_queue_low) != 1 ||
14298  tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
14299  ast_log(AST_LOG_WARNING, "Invalid the taskprocessor low water clear alert level '%s'\n", val);
14300  tps_queue_low = -1;
14301  }
14302  }
14303  if (ast_taskprocessor_alert_set_levels(mwi_subscription_tps, tps_queue_low, tps_queue_high)) {
14304  ast_log(AST_LOG_WARNING, "Failed to set alert levels for voicemail taskprocessor.\n");
14305  }
14306 
14307  /* load mailboxes from users.conf */
14308  if (ucfg) {
14309  for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
14310  if (!strcasecmp(cat, "general")) {
14311  continue;
14312  }
14313  if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
14314  continue;
14315  if ((current = find_or_create(userscontext, cat))) {
14316  populate_defaults(current);
14317  apply_options_full(current, ast_variable_browse(ucfg, cat));
14318  ast_copy_string(current->context, userscontext, sizeof(current->context));
14319  if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
14321  }
14322 
14323  switch (current->passwordlocation) {
14324  case OPT_PWLOC_SPOOLDIR:
14325  snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
14326  read_password_from_file(secretfn, current->password, sizeof(current->password));
14327  }
14328  }
14329  }
14330  }
14331 
14332  /* load mailboxes from voicemail.conf */
14333 
14334  /*
14335  * Aliases must be loaded before users or the aliases won't be notified
14336  * if there's existing voicemail in the user mailbox.
14337  */
14338  load_aliases(cfg);
14339 
14340  load_zonemessages(cfg);
14341 
14342  load_users(cfg);
14343 
14345 
14349  stop_poll_thread();;
14350 
14351  return 0;
14352  } else {
14354  ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
14355  return 0;
14356  }
14357 }
#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
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
static char mailcmd[160]
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
#define MAX_NUM_CID_CONTEXTS
static char vm_newuser[80]
static unsigned char adsifdn[4]
Definition: ast_expr2.c:325
static void free_vm_users(void)
Free the users structure.
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
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
static struct ao2_container * alias_mailbox_mappings
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:63
static int pwdchange
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
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:563
static int tmp()
Definition: bt_open.c:389
#define AST_LOG_WARNING
Definition: logger.h:279
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]
static char aliasescontext[MAX_VM_CONTEXT_LEN]
static void load_aliases(struct ast_config *cfg)
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
static char externnotify[160]
char password[80]
#define NULL
Definition: resample.c:96
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]
char context[MAX_VM_CONTEXT_LEN]
#define VM_SAYCID
#define VM_SVMAIL
static void load_users(struct ast_config *cfg)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:452
#define ast_log
Definition: astobj2.c:42
#define MINPASSWORD
static void load_zonemessages(struct ast_config *cfg)
#define AST_LOG_ERROR
Definition: logger.h:290
#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:66
static int silencethreshold
int passwordlocation
static char vm_reenterpassword[80]
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define VM_MOVEHEARD
char * ast_format_str_reduce(char *fmts)
Definition: file.c:1826
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 struct ast_taskprocessor * mwi_subscription_tps
static char vm_invalid_password[80]
#define DEFAULT_POLL_FREQ
#define VM_PBXSKIP
#define VM_OPERATOR
static char callcontext[AST_MAX_CONTEXT]
static int skipms
#define LOG_ERROR
Definition: logger.h:285
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 "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static unsigned int poll_mailboxes
static char listen_control_restart_key[12]
#define VM_REVIEW
#define ast_free(a)
Definition: astmm.h:182
static char emaildateformat[32]
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
Definition: mwi.c:333
static char vm_passchanged[80]
static int maxlogins
static char listen_control_pause_key[12]
charset
Definition: chan_unistim.c:336
#define SENDMAIL
static struct ao2_container * mailbox_alias_mappings
static char listen_control_forward_key[12]
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
char * strsep(char **str, const char *delims)
static int vmmaxsecs
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static void start_poll_thread(void)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
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 "false"...
Definition: main/utils.c:1968
#define VM_SKIPAFTERCMD
static char * pagersubject
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
Definition: main/config.c:684
#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.
#define PATH_MAX
Definition: asterisk.h:40
#define VM_FWDURGAUTO
static char vm_login[80]
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:1996
static char vmfmts[80]
char mailbox[MAX_VM_MBOX_ID_LEN]
static char serveremail[80]
static char listen_control_stop_key[12]
#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]

◆ add_email_attachment()

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

References ast_copy_string(), ast_debug, ast_file_is_readable(), ast_log, AST_LOG_WARNING, ast_safe_system(), base_encode(), ast_vm_user::context, create_dirpath(), ENDL, errno, LOG_ERROR, LOG_WARNING, ast_vm_user::mailbox, mkdtemp(), NULL, PATH_MAX, and ast_vm_user::volgain.

Referenced by make_email_file().

5385 {
5386  char fname[PATH_MAX] = "";
5387  char sox_gain_tmpdir[PATH_MAX];
5388  char *file_to_delete = NULL, *dir_to_delete = NULL;
5389  int res;
5390  char altfname[PATH_MAX] = "";
5391  int altused = 0;
5392  char altformat[80] = "";
5393  char *c = NULL;
5394 
5395  /* Eww. We want formats to tell us their own MIME type */
5396  char *mime_type = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
5397 
5398  /* Users of multiple file formats need special attention. */
5399  snprintf(fname, sizeof(fname), "%s.%s", attach, format);
5400  if (!ast_file_is_readable(fname)) {
5401  ast_copy_string(altformat, vmfmts, sizeof(altformat));
5402  c = strchr(altformat, '|');
5403  if (c) {
5404  *c = '\0';
5405  }
5406  ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s - trying first/alternate format %s\n", fname, strerror(errno), altformat);
5407  snprintf(altfname, sizeof(altfname), "%s.%s", attach, altformat);
5408  if (!ast_file_is_readable(altfname)) {
5409  ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s - alternate format %s failure\n", altfname, strerror(errno), altformat);
5410  } else {
5411  altused = 1;
5412  }
5413  }
5414 
5415  /* This 'while' loop will only execute once. We use it so that we can 'break' */
5416  while (vmu->volgain < -.001 || vmu->volgain > .001 || altused) {
5417  char tmpdir[PATH_MAX];
5418 
5419  create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
5420 
5421  res = snprintf(sox_gain_tmpdir, sizeof(sox_gain_tmpdir), "%s/vm-gain-XXXXXX", tmpdir);
5422  if (res >= sizeof(sox_gain_tmpdir)) {
5423  ast_log(LOG_ERROR, "Failed to create temporary directory path %s: Out of buffer space\n", tmpdir);
5424  break;
5425  }
5426 
5427  if (mkdtemp(sox_gain_tmpdir)) {
5428  int soxstatus = 0;
5429  char sox_gain_cmd[PATH_MAX];
5430 
5431  ast_debug(3, "sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
5432 
5433  /* Save for later */
5434  dir_to_delete = sox_gain_tmpdir;
5435 
5436  res = snprintf(fname, sizeof(fname), "%s/output.%s", sox_gain_tmpdir, format);
5437  if (res >= sizeof(fname)) {
5438  ast_log(LOG_ERROR, "Failed to create filename buffer for %s/output.%s: Too long\n", sox_gain_tmpdir, format);
5439  break;
5440  }
5441 
5442  if (!altused) {
5443  res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
5444  vmu->volgain, attach, format, fname);
5445  } else {
5446  if (!strcasecmp(format, "wav")) {
5447  if (vmu->volgain < -.001 || vmu->volgain > .001) {
5448  res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s -e signed-integer -b 16 %s",
5449  vmu->volgain, attach, altformat, fname);
5450  } else {
5451  res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox %s.%s -e signed-integer -b 16 %s",
5452  attach, altformat, fname);
5453  }
5454  } else {
5455  if (vmu->volgain < -.001 || vmu->volgain > .001) {
5456  res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
5457  vmu->volgain, attach, altformat, fname);
5458  } else {
5459  res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox %s.%s %s",
5460  attach, altformat, fname);
5461  }
5462  }
5463  }
5464 
5465  if (res >= sizeof(sox_gain_cmd)) {
5466  ast_log(LOG_ERROR, "Failed to generate sox command, out of buffer space\n");
5467  break;
5468  }
5469 
5470  soxstatus = ast_safe_system(sox_gain_cmd);
5471  if (!soxstatus) {
5472  /* Save for later */
5473  file_to_delete = fname;
5474  ast_debug(3, "VOLGAIN: Stored at: %s - Level: %.4f - Mailbox: %s\n", fname, vmu->volgain, mailbox);
5475  } else {
5476  ast_log(LOG_WARNING, "Sox failed to re-encode %s: %s (have you installed support for all sox file formats?)\n",
5477  fname,
5478  soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
5479  ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
5480  }
5481  }
5482 
5483  break;
5484  }
5485 
5486  if (!file_to_delete) {
5487  res = snprintf(fname, sizeof(fname), "%s.%s", attach, format);
5488  if (res >= sizeof(fname)) {
5489  ast_log(LOG_ERROR, "Failed to create filename buffer for %s.%s: Too long\n", attach, format);
5490  return -1;
5491  }
5492  }
5493 
5494  fprintf(p, "--%s" ENDL, bound);
5495  if (msgnum > -1)
5496  fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, mime_type, format, filename);
5497  else
5498  fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, mime_type, format, greeting_attachment, format);
5499  fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
5500  fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
5501  if (msgnum > -1)
5502  fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
5503  else
5504  fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
5505  base_encode(fname, p);
5506  if (last)
5507  fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
5508 
5509  if (file_to_delete) {
5510  unlink(file_to_delete);
5511  }
5512 
5513  if (dir_to_delete) {
5514  rmdir(dir_to_delete);
5515  }
5516 
5517  return 0;
5518 }
double volgain
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:274
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: main/utils.c:2855
#define AST_LOG_WARNING
Definition: logger.h:279
static struct test_val c
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define ENDL
#define LOG_ERROR
Definition: logger.h:285
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
char * mkdtemp(char *template_s)
int errno
static int base_encode(char *filename, FILE *so)
Performs a base 64 encode algorithm on the contents of a File.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define PATH_MAX
Definition: asterisk.h:40
static char vmfmts[80]
static snd_pcm_format_t format
Definition: chan_alsa.c:102
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ add_message_id()

static int add_message_id ( struct ast_config msg_cfg,
char *  dir,
int  msg,
char *  filename,
char *  id,
size_t  id_size,
struct ast_vm_user vmu,
int  folder 
)
static

Definition at line 12356 of file app_voicemail.c.

References ast_category_get(), ast_config_text_file_save(), ast_log, ast_variable_append(), ast_variable_new, ast_variables_destroy(), generate_msg_id(), LOG_ERROR, LOG_WARNING, NULL, UPDATE_MSG_ID, and var.

Referenced by vm_msg_snapshot_create().

12357 {
12358  struct ast_variable *var;
12359  struct ast_category *cat;
12360  generate_msg_id(id);
12361 
12362  var = ast_variable_new("msg_id", id, "");
12363  if (!var) {
12364  return -1;
12365  }
12366 
12367  cat = ast_category_get(msg_cfg, "message", NULL);
12368  if (!cat) {
12369  ast_log(LOG_ERROR, "Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
12370  ast_variables_destroy(var);
12371  return -1;
12372  }
12373 
12374  ast_variable_append(cat, var);
12375 
12376  if (ast_config_text_file_save(filename, msg_cfg, "app_voicemail")) {
12377  ast_log(LOG_WARNING, "Unable to update %s to have a message ID\n", filename);
12378  return -1;
12379  }
12380 
12381  UPDATE_MSG_ID(dir, msg, id, vmu, msg_cfg, folder);
12382  return 0;
12383 }
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
Definition: main/config.c:2531
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
#define LOG_WARNING
Definition: logger.h:274
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
#define ast_variable_new(name, value, filename)
#define LOG_ERROR
Definition: logger.h:285
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
#define UPDATE_MSG_ID(a, b, c, d, e, f)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1022

◆ adsi_begin()

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

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

7449 {
7450  int x;
7451  if (!ast_adsi_available(chan))
7452  return;
7453  x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
7454  if (x < 0)
7455  return;
7456  if (!x) {
7457  if (adsi_load_vmail(chan, useadsi)) {
7458  ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
7459  return;
7460  }
7461  } else
7462  *useadsi = 1;
7463 }
static unsigned char adsifdn[4]
static int adsiver
#define AST_LOG_WARNING
Definition: logger.h:279
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
#define ast_log
Definition: astobj2.c:42
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)

◆ adsi_delete()

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

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

7645 {
7646  int bytes = 0;
7647  unsigned char buf[256];
7648  unsigned char keys[8];
7649 
7650  int x;
7651 
7652  if (!ast_adsi_available(chan))
7653  return;
7654 
7655  /* New meaning for keys */
7656  for (x = 0; x < 5; x++)
7657  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
7658 
7659  keys[6] = 0x0;
7660  keys[7] = 0x0;
7661 
7662  if (!vms->curmsg) {
7663  /* No prev key, provide "Folder" instead */
7664  keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7665  }
7666  if (vms->curmsg >= vms->lastmsg) {
7667  /* If last message ... */
7668  if (vms->curmsg) {
7669  /* but not only message, provide "Folder" instead */
7670  keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7671  } else {
7672  /* Otherwise if only message, leave blank */
7673  keys[3] = 1;
7674  }
7675  }
7676 
7677  /* If deleted, show "undeleted" */
7678 #ifdef IMAP_STORAGE
7679  ast_mutex_lock(&vms->lock);
7680 #endif
7681  if (vms->deleted[vms->curmsg]) {
7682  keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
7683  }
7684 #ifdef IMAP_STORAGE
7685  ast_mutex_unlock(&vms->lock);
7686 #endif
7687 
7688  /* Except "Exit" */
7689  keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
7690  bytes += ast_adsi_set_keys(buf + bytes, keys);
7691  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7692 
7693  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7694 }
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 * deleted
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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:187
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_KEY_APPS
Definition: adsi.h:109
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ adsi_folders()

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

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

7514 {
7515  unsigned char buf[256];
7516  int bytes = 0;
7517  unsigned char keys[8];
7518  int x, y;
7519 
7520  if (!ast_adsi_available(chan))
7521  return;
7522 
7523  for (x = 0; x < 5; x++) {
7524  y = ADSI_KEY_APPS + 12 + start + x;
7525  if (y > ADSI_KEY_APPS + 12 + 4)
7526  y = 0;
7527  keys[x] = ADSI_KEY_SKT | y;
7528  }
7529  keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
7530  keys[6] = 0;
7531  keys[7] = 0;
7532 
7533  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
7534  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
7535  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7536  bytes += ast_adsi_set_keys(buf + bytes, keys);
7537  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7538 
7539  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7540 }
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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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

◆ adsi_goodbye()

static void adsi_goodbye ( struct ast_channel chan)
static

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

7800 {
7801  unsigned char buf[256];
7802  int bytes = 0;
7803 
7804  if (!ast_adsi_available(chan))
7805  return;
7806  bytes += adsi_logo(buf + bytes);
7807  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
7808  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
7809  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7810  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7811 
7812  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7813 }
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)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#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

◆ adsi_load_vmail()

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

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

Referenced by adsi_begin().

7320 {
7321  unsigned char buf[256];
7322  int bytes = 0;
7323  int x;
7324  char num[5];
7325 
7326  *useadsi = 0;
7327  bytes += ast_adsi_data_mode(buf + bytes);
7328  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7329 
7330  bytes = 0;
7331  bytes += adsi_logo(buf);
7332  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
7333 #ifdef DISPLAY
7334  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
7335 #endif
7336  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7337  bytes += ast_adsi_data_mode(buf + bytes);
7338  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7339 
7341  bytes = 0;
7342  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
7343  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
7344  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7345  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7346  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7347  return 0;
7348  }
7349 
7350 #ifdef DISPLAY
7351  /* Add a dot */
7352  bytes = 0;
7353  bytes += ast_adsi_logo(buf);
7354  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
7355  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
7356  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7357  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7358 #endif
7359  bytes = 0;
7360  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
7361  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
7362  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
7363  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
7364  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
7365  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
7366  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
7367 
7368 #ifdef DISPLAY
7369  /* Add another dot */
7370  bytes = 0;
7371  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
7372  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7373 
7374  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7375  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7376 #endif
7377 
7378  bytes = 0;
7379  /* These buttons we load but don't use yet */
7380  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
7381  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
7382  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
7383  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
7384  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
7385  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
7386  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
7387 
7388 #ifdef DISPLAY
7389  /* Add another dot */
7390  bytes = 0;
7391  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
7392  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7393  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7394 #endif
7395 
7396  bytes = 0;
7397  for (x = 0; x < 5; x++) {
7398  snprintf(num, sizeof(num), "%d", x);
7399  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
7400  }
7401  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
7402  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
7403 
7404 #ifdef DISPLAY
7405  /* Add another dot */
7406  bytes = 0;
7407  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
7408  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7409  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7410 #endif
7411 
7412  if (ast_adsi_end_download(chan)) {
7413  bytes = 0;
7414  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
7415  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
7416  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7417  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7418  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7419  return 0;
7420  }
7421  bytes = 0;
7422  bytes += ast_adsi_download_disconnect(buf + bytes);
7423  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7424  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
7425 
7426  ast_debug(1, "Done downloading scripts...\n");
7427 
7428 #ifdef DISPLAY
7429  /* Add last dot */
7430  bytes = 0;
7431  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
7432  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7433 #endif
7434  ast_debug(1, "Restarting session...\n");
7435 
7436  bytes = 0;
7437  /* Load the session now */
7438  if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
7439  *useadsi = 1;
7440  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
7441  } else
7442  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
7443 
7444  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7445  return 0;
7446 }
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)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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 NULL
Definition: resample.c:96
#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:452
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 "load soft key" 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

◆ adsi_login()

static void adsi_login ( struct ast_channel chan)
static

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

7466 {
7467  unsigned char buf[256];
7468  int bytes = 0;
7469  unsigned char keys[8];
7470  int x;
7471  if (!ast_adsi_available(chan))
7472  return;
7473 
7474  for (x = 0; x < 8; x++)
7475  keys[x] = 0;
7476  /* Set one key for next */
7477  keys[3] = ADSI_KEY_APPS + 3;
7478 
7479  bytes += adsi_logo(buf + bytes);
7480  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
7481  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
7482  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7483  bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
7484  bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
7485  bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
7486  bytes += ast_adsi_set_keys(buf + bytes, keys);
7487  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7488  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7489 }
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)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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 "load soft key" 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

◆ adsi_logo()

static int adsi_logo ( unsigned char *  buf)
static

Definition at line 7311 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_setup(), vm_options(), and vm_tempgreeting().

7312 {
7313  int bytes = 0;
7314  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
7315  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
7316  return bytes;
7317 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#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

◆ adsi_message()

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

Definition at line 7542 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, vm_state::fn, vm_state::lastmsg, name, NULL, PATH_MAX, and strsep().

Referenced by play_message(), and vm_execmain().

7543 {
7544  int bytes = 0;
7545  unsigned char buf[256];
7546  char buf1[256], buf2[256];
7547  char fn2[PATH_MAX];
7548 
7549  char cid[256] = "";
7550  char *val;
7551  char *name, *num;
7552  char datetime[21] = "";
7553  FILE *f;
7554 
7555  unsigned char keys[8];
7556 
7557  int x;
7558 
7559  if (!ast_adsi_available(chan))
7560  return;
7561 
7562  /* Retrieve important info */
7563  snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
7564  f = fopen(fn2, "r");
7565  if (f) {
7566  while (!feof(f)) {
7567  if (!fgets((char *) buf, sizeof(buf), f)) {
7568  continue;
7569  }
7570  if (!feof(f)) {
7571  char *stringp = NULL;
7572  stringp = (char *) buf;
7573  strsep(&stringp, "=");
7574  val = strsep(&stringp, "=");
7575  if (!ast_strlen_zero(val)) {
7576  if (!strcmp((char *) buf, "callerid"))
7577  ast_copy_string(cid, val, sizeof(cid));
7578  if (!strcmp((char *) buf, "origdate"))
7579  ast_copy_string(datetime, val, sizeof(datetime));
7580  }
7581  }
7582  }
7583  fclose(f);
7584  }
7585  /* New meaning for keys */
7586  for (x = 0; x < 5; x++)
7587  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
7588  keys[6] = 0x0;
7589  keys[7] = 0x0;
7590 
7591  if (!vms->curmsg) {
7592  /* No prev key, provide "Folder" instead */
7593  keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7594  }
7595  if (vms->curmsg >= vms->lastmsg) {
7596  /* If last message ... */
7597  if (vms->curmsg) {
7598  /* but not only message, provide "Folder" instead */
7599  keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7600  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7601 
7602  } else {
7603  /* Otherwise if only message, leave blank */
7604  keys[3] = 1;
7605  }
7606  }
7607 
7608  if (!ast_strlen_zero(cid)) {
7609  ast_callerid_parse(cid, &name, &num);
7610  if (!name)
7611  name = num;
7612  } else {
7613  name = "Unknown Caller";
7614  }
7615 
7616  /* If deleted, show "undeleted" */
7617 #ifdef IMAP_STORAGE
7618  ast_mutex_lock(&vms->lock);
7619 #endif
7620  if (vms->deleted[vms->curmsg]) {
7621  keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
7622  }
7623 #ifdef IMAP_STORAGE
7624  ast_mutex_unlock(&vms->lock);
7625 #endif
7626 
7627  /* Except "Exit" */
7628  keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
7629  snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
7630  strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
7631  snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
7632 
7633  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
7634  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
7635  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
7636  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
7637  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7638  bytes += ast_adsi_set_keys(buf + bytes, keys);
7639  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7640 
7641  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7642 }
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
Definition: ast_expr2.c:325
int * deleted
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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:187
#define NULL
Definition: resample.c:96
char fn[PATH_MAX]
char curbox[80]
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define ast_strlen_zero(foo)
Definition: strings.h:52
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
static const char name[]
Definition: cdr_mysql.c:74
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define PATH_MAX
Definition: asterisk.h:40
#define ADSI_KEY_APPS
Definition: adsi.h:109
#define ast_mutex_unlock(a)
Definition: lock.h:188
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1008

◆ adsi_password()

static void adsi_password ( struct ast_channel chan)
static

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

7492 {
7493  unsigned char buf[256];
7494  int bytes = 0;
7495  unsigned char keys[8];
7496  int x;
7497  if (!ast_adsi_available(chan))
7498  return;
7499 
7500  for (x = 0; x < 8; x++)
7501  keys[x] = 0;
7502  /* Set one key for next */
7503  keys[3] = ADSI_KEY_APPS + 3;
7504 
7505  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7506  bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
7507  bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
7508  bytes += ast_adsi_set_keys(buf + bytes, keys);
7509  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7510  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7511 }
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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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

◆ adsi_status()

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

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

7697 {
7698  unsigned char buf[256] = "";
7699  char buf1[256] = "", buf2[256] = "";
7700  int bytes = 0;
7701  unsigned char keys[8];
7702  int x;
7703 
7704  char *newm = (vms->newmessages == 1) ? "message" : "messages";
7705  char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
7706  if (!ast_adsi_available(chan))
7707  return;
7708  if (vms->newmessages) {
7709  snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
7710  if (vms->oldmessages) {
7711  strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
7712  snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
7713  } else {
7714  snprintf(buf2, sizeof(buf2), "%s.", newm);
7715  }
7716  } else if (vms->oldmessages) {
7717  snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
7718  snprintf(buf2, sizeof(buf2), "%s.", oldm);
7719  } else {
7720  strcpy(buf1, "You have no messages.");
7721  buf2[0] = ' ';
7722  buf2[1] = '\0';
7723  }
7724  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
7725  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
7726  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7727 
7728  for (x = 0; x < 6; x++)
7729  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
7730  keys[6] = 0;
7731  keys[7] = 0;
7732 
7733  /* Don't let them listen if there are none */
7734  if (vms->lastmsg < 0)
7735  keys[0] = 1;
7736  bytes += ast_adsi_set_keys(buf + bytes, keys);
7737 
7738  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7739 
7740  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7741 }
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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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

◆ adsi_status2()

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

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

7744 {
7745  unsigned char buf[256] = "";
7746  char buf1[256] = "", buf2[256] = "";
7747  int bytes = 0;
7748  unsigned char keys[8];
7749  int x;
7750 
7751  char *mess = (vms->lastmsg == 0) ? "message" : "messages";
7752 
7753  if (!ast_adsi_available(chan))
7754  return;
7755 
7756  /* Original command keys */
7757  for (x = 0; x < 6; x++)
7758  keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
7759 
7760  keys[6] = 0;
7761  keys[7] = 0;
7762 
7763  if ((vms->lastmsg + 1) < 1)
7764  keys[0] = 0;
7765 
7766  snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
7767  strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
7768 
7769  if (vms->lastmsg + 1)
7770  snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
7771  else
7772  strcpy(buf2, "no messages.");
7773  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
7774  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
7775  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
7776  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7777  bytes += ast_adsi_set_keys(buf + bytes, keys);
7778 
7779  bytes += ast_adsi_voice_mode(buf + bytes, 0);
7780 
7781  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
7782 
7783 }
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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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
char curbox[80]
#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
#define ADSI_KEY_APPS
Definition: adsi.h:109

◆ advanced_options()

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 15305 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(), leave_vm_options::beeptone, 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, free_user(), vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), name, NULL, PATH_MAX, play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, valid_config(), and wait_file().

Referenced by vm_execmain().

15306 {
15307  int res = 0;
15308  char filename[PATH_MAX];
15309  struct ast_config *msg_cfg = NULL;
15310  const char *origtime, *context;
15311  char *name, *num;
15312  int retries = 0;
15313  char *cid;
15314  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
15315 
15316  vms->starting = 0;
15317 
15318  make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
15319 
15320  /* Retrieve info from VM attribute file */
15321  snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
15322  RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
15323  msg_cfg = ast_config_load(filename, config_flags);
15324  DISPOSE(vms->curdir, vms->curmsg);
15325  if (!valid_config(msg_cfg)) {
15326  ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
15327  return 0;
15328  }
15329 
15330  if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
15331  ast_config_destroy(msg_cfg);
15332  return 0;
15333  }
15334 
15335  cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
15336 
15337  context = ast_variable_retrieve(msg_cfg, "message", "context");
15338  if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
15339  context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
15340  switch (option) {
15341  case 3: /* Play message envelope */
15342  if (!res) {
15343  res = play_message_datetime(chan, vmu, origtime, filename);
15344  }
15345  if (!res) {
15346  res = play_message_callerid(chan, vms, cid, context, 0, 1);
15347  }
15348 
15349  res = 't';
15350  break;
15351 
15352  case 2: /* Call back */
15353 
15354  if (ast_strlen_zero(cid))
15355  break;
15356 
15357  ast_callerid_parse(cid, &name, &num);
15358  while ((res > -1) && (res != 't')) {
15359  switch (res) {
15360  case '1':
15361  if (num) {
15362  /* Dial the CID number */
15363  res = dialout(chan, vmu, num, vmu->callback);
15364  if (res) {
15365  ast_config_destroy(msg_cfg);
15366  return 9;
15367  }
15368  } else {
15369  res = '2';
15370  }
15371  break;
15372 
15373  case '2':
15374  /* Want to enter a different number, can only do this if there's a dialout context for this user */
15375  if (!ast_strlen_zero(vmu->dialout)) {
15376  res = dialout(chan, vmu, NULL, vmu->dialout);
15377  if (res) {
15378  ast_config_destroy(msg_cfg);
15379  return 9;
15380  }
15381  } else {
15382  ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
15383  res = ast_play_and_wait(chan, "vm-sorry");
15384  }
15385  ast_config_destroy(msg_cfg);
15386  return res;
15387  case '*':
15388  res = 't';
15389  break;
15390  case '3':
15391  case '4':
15392  case '5':
15393  case '6':
15394  case '7':
15395  case '8':
15396  case '9':
15397  case '0':
15398 
15399  res = ast_play_and_wait(chan, "vm-sorry");
15400  retries++;
15401  break;
15402  default:
15403  if (num) {
15404  ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
15405  res = ast_play_and_wait(chan, "vm-num-i-have");
15406  if (!res)
15407  res = play_message_callerid(chan, vms, num, vmu->context, 1, 1);
15408  if (!res)
15409  res = ast_play_and_wait(chan, "vm-tocallnum");
15410  /* Only prompt for a caller-specified number if there is a dialout context specified */
15411  if (!ast_strlen_zero(vmu->dialout)) {
15412  if (!res)
15413  res = ast_play_and_wait(chan, "vm-calldiffnum");
15414  }
15415  } else {
15416  res = ast_play_and_wait(chan, "vm-nonumber");
15417  if (!ast_strlen_zero(vmu->dialout)) {
15418  if (!res)
15419  res = ast_play_and_wait(chan, "vm-toenternumber");
15420  }
15421  }
15422  if (!res) {
15423  res = ast_play_and_wait(chan, "vm-star-cancel");
15424  }
15425  if (!res) {
15426  res = ast_waitfordigit(chan, 6000);
15427  }
15428  if (!res) {
15429  retries++;
15430  if (retries > 3) {
15431  res = 't';
15432  }
15433  }
15434  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
15435  isprint(res) ? res : '?', isprint(res) ? res : '?');
15436  break;
15437 
15438  }
15439  if (res == 't')
15440  res = 0;
15441  else if (res == '*')
15442  res = -1;
15443  }
15444  break;
15445 
15446  case 1: /* Reply */
15447  /* Send reply directly to sender */
15448  if (ast_strlen_zero(cid))
15449  break;
15450 
15451  ast_callerid_parse(cid, &name, &num);
15452  if (!num) {
15453  ast_verb(3, "No CID number available, no reply sent\n");
15454  if (!res)
15455  res = ast_play_and_wait(chan, "vm-nonumber");
15456  ast_config_destroy(msg_cfg);
15457  return res;
15458  } else {
15459  struct ast_vm_user vmu2, *vmu3;
15460  memset(&vmu2, 0, sizeof(vmu2));
15461  vmu3 = find_user(&vmu2, vmu->context, num);
15462  if (vmu3) {
15463  struct leave_vm_options leave_options;
15464  char mailbox[AST_MAX_EXTENSION * 2 + 2];
15465  snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
15466 
15467  ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
15468 
15469  memset(&leave_options, 0, sizeof(leave_options));
15470  leave_options.record_gain = record_gain;
15471  leave_options.beeptone = "beep";
15472  res = leave_voicemail(chan, mailbox, &leave_options);
15473  if (!res)
15474  res = 't';
15475  ast_config_destroy(msg_cfg);
15476  free_user(vmu3);
15477  return res;
15478  } else {
15479  /* Sender has no mailbox, can't reply */
15480  ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
15481  ast_play_and_wait(chan, "vm-nobox");
15482  res = 't';
15483  ast_config_destroy(msg_cfg);
15484  return res;
15485  }
15486  }
15487  res = 0;
15488 
15489  break;
15490  }
15491 
15492  ast_config_destroy(msg_cfg);
15493 
15494 #ifndef IMAP_STORAGE
15495  if (!res) {
15496  make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
15497  vms->heard[msg] = 1;
15498  res = wait_file(chan, vms, vms->fn);
15499  }
15500 #endif
15501  return res;
15502 }
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
#define AST_LOG_WARNING
Definition: logger.h:279
char curdir[PATH_MAX]
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char fn[PATH_MAX]
#define ast_verb(level,...)
Definition: logger.h:463
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
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 mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
char dialout[80]
int * heard
#define AST_MAX_EXTENSION
Definition: channel.h:135
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: main/app.c:1470
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void free_user(struct ast_vm_user *vmu)
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
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[]
Definition: cdr_mysql.c:74
Structure used to handle boolean flags.
Definition: utils.h:199
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:650
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
signed char record_gain
Definition: app_minivm.c:652
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
char callback[80]
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1008
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)

◆ alias_mailbox_mapping_create()

static struct alias_mailbox_mapping* alias_mailbox_mapping_create ( const char *  alias,
const char *  mailbox 
)
static

Definition at line 13588 of file app_voicemail.c.

References alias_mailbox_mapping::alias, ao2_alloc, ast_copy_string(), alias_mailbox_mapping::buf, alias_mailbox_mapping::mailbox, and NULL.

Referenced by load_aliases().

13589 {
13590  struct alias_mailbox_mapping *mapping;
13591  size_t from_len = strlen(alias) + 1;
13592  size_t to_len = strlen(mailbox) + 1;
13593 
13594  mapping = ao2_alloc(sizeof(*mapping) + from_len + to_len, NULL);
13595  if (!mapping) {
13596  return NULL;
13597  }
13598  mapping->alias = mapping->buf;
13599  mapping->mailbox = mapping->buf + from_len;
13600  ast_copy_string(mapping->alias, alias, from_len); /* Safe */
13601  ast_copy_string(mapping->mailbox, mailbox, to_len); /* Safe */
13602 
13603  return mapping;
13604 }
#define NULL
Definition: resample.c:96
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ AO2_STRING_FIELD_CMP_FN() [1/2]

AO2_STRING_FIELD_CMP_FN ( alias_mailbox_mapping  ,
alias   
)

◆ AO2_STRING_FIELD_CMP_FN() [2/2]

AO2_STRING_FIELD_CMP_FN ( mailbox_alias_mapping  ,
mailbox   
)

◆ AO2_STRING_FIELD_HASH_FN() [1/2]

AO2_STRING_FIELD_HASH_FN ( alias_mailbox_mapping  ,
alias   
)

◆ AO2_STRING_FIELD_HASH_FN() [2/2]

AO2_STRING_FIELD_HASH_FN ( mailbox_alias_mapping  ,
mailbox   
)

◆ append_mailbox()

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

Definition at line 12425 of file app_voicemail.c.

References apply_options(), ast_copy_string(), ast_log, ast_strdup, 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, MAX_VM_MAILBOX_LEN, NULL, OPT_PWLOC_SPOOLDIR, ast_vm_user::pager, ast_vm_user::password, ast_vm_user::passwordlocation, PATH_MAX, populate_defaults(), queue_mwi_event(), read_password_from_file(), strsep(), and tmp().

Referenced by load_users().

12426 {
12427  /* Assumes lock is already held */
12428  char *tmp;
12429  char *stringp;
12430  char *s;
12431  struct ast_vm_user *vmu;
12432  char mailbox_full[MAX_VM_MAILBOX_LEN];
12433  int new = 0, old = 0, urgent = 0;
12434  char secretfn[PATH_MAX] = "";
12435 
12436  tmp = ast_strdupa(data);
12437 
12438  if (!(vmu = find_or_create(context, box)))
12439  return -1;
12440 
12441  populate_defaults(vmu);
12442 
12443  stringp = tmp;
12444  if ((s = strsep(&stringp, ","))) {
12445  if (!ast_strlen_zero(s) && s[0] == '*') {
12446  ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
12447  "\n\tmust be reset in voicemail.conf.\n", box);
12448  }
12449  /* assign password regardless of validity to prevent NULL password from being assigned */
12450  ast_copy_string(vmu->password, s, sizeof(vmu->password));
12451  }
12452  if (stringp && (s = strsep(&stringp, ","))) {
12453  ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
12454  }
12455  if (stringp && (s = strsep(&stringp, ","))) {
12456  vmu->email = ast_strdup(s);
12457  }
12458  if (stringp && (s = strsep(&stringp, ","))) {
12459  ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
12460  }
12461  if (stringp) {
12462  apply_options(vmu, stringp);
12463  }
12464 
12465  switch (vmu->passwordlocation) {
12466  case OPT_PWLOC_SPOOLDIR:
12467  snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
12468  read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
12469  }
12470 
12471  snprintf(mailbox_full, MAX_VM_MAILBOX_LEN, "%s%s%s",
12472  box,
12473  ast_strlen_zero(context) ? "" : "@",
12474  context);
12475 
12476  inboxcount2(mailbox_full, &urgent, &new, &old);
12477 #ifdef IMAP_STORAGE
12478  imap_logout(mailbox_full);
12479 #endif
12480  queue_mwi_event(NULL, mailbox_full, urgent, new, old);
12481 
12482  return 0;
12483 }
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
char pager[80]
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
char password[80]
#define NULL
Definition: resample.c:96
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox&#39;s message count.
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
int passwordlocation
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
static char VM_SPOOL_DIR[PATH_MAX]
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static struct ast_vm_user * find_or_create(const char *context, const char *box)
#define PATH_MAX
Definition: asterisk.h:40
char fullname[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]
#define MAX_VM_MAILBOX_LEN
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ append_vmu_info_astman()

static int append_vmu_info_astman ( struct mansession s,
struct ast_vm_user vmu,
const char *  event_name,
const char *  actionid 
)
static

Append vmu info string into given astman with event_name.

Returns
0 failed. 1 otherwise.

Definition at line 13227 of file app_voicemail.c.

References ast_asprintf, ast_free, ast_log, ast_strlen_zero, ast_test_flag, astman_append(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::context, ast_vm_user::dialout, ast_vm_user::email, errno, ast_vm_user::exit, ast_vm_user::fromstring, ast_vm_user::fullname, inboxcount(), ast_vm_user::language, LOG_ERROR, mailbox, ast_vm_user::mailbox, ast_vm_user::maxmsg, ast_vm_user::maxsecs, NULL, ast_vm_user::pager, 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 manager_list_voicemail_users(), and manager_status_voicemail_user().

13233 {
13234  int new;
13235  int old;
13236  char *mailbox;
13237  int ret;
13238 
13239  if((s == NULL) || (vmu == NULL) || (event_name == NULL) || (actionid == NULL)) {
13240  ast_log(LOG_ERROR, "Wrong input parameter.");
13241  return 0;
13242  }
13243 
13244  /* create mailbox string */
13245  if (!ast_strlen_zero(vmu->context)) {
13246  ret = ast_asprintf(&mailbox, "%s@%s", vmu->mailbox, vmu->context);
13247  } else {
13248  ret = ast_asprintf(&mailbox, "%s", vmu->mailbox);
13249  }
13250  if (ret == -1) {
13251  ast_log(LOG_ERROR, "Could not create mailbox string. err[%s]\n", strerror(errno));
13252  return 0;
13253  }
13254 
13255  /* get mailbox count */
13256  ret = inboxcount(mailbox, &new, &old);
13257  ast_free(mailbox);
13258  if (ret == -1) {
13259  ast_log(LOG_ERROR, "Could not get mailbox count. user[%s], context[%s]\n",
13260  vmu->mailbox ?: "", vmu->context ?: "");
13261  return 0;
13262  }
13263 
13264  astman_append(s,
13265  "Event: %s\r\n"
13266  "%s"
13267  "VMContext: %s\r\n"
13268  "VoiceMailbox: %s\r\n"
13269  "Fullname: %s\r\n"
13270  "Email: %s\r\n"
13271  "Pager: %s\r\n"
13272  "ServerEmail: %s\r\n"
13273  "FromString: %s\r\n"
13274  "MailCommand: %s\r\n"
13275  "Language: %s\r\n"
13276  "TimeZone: %s\r\n"
13277  "Callback: %s\r\n"
13278  "Dialout: %s\r\n"
13279  "UniqueID: %s\r\n"
13280  "ExitContext: %s\r\n"
13281  "SayDurationMinimum: %d\r\n"
13282  "SayEnvelope: %s\r\n"
13283  "SayCID: %s\r\n"
13284  "AttachMessage: %s\r\n"
13285  "AttachmentFormat: %s\r\n"
13286  "DeleteMessage: %s\r\n"
13287  "VolumeGain: %.2f\r\n"
13288  "CanReview: %s\r\n"
13289  "CallOperator: %s\r\n"
13290  "MaxMessageCount: %d\r\n"
13291  "MaxMessageLength: %d\r\n"
13292  "NewMessageCount: %d\r\n"
13293  "OldMessageCount: %d\r\n"
13294 #ifdef IMAP_STORAGE
13295  "IMAPUser: %s\r\n"
13296  "IMAPServer: %s\r\n"
13297  "IMAPPort: %s\r\n"
13298  "IMAPFlags: %s\r\n"
13299 #endif
13300  "\r\n",
13301 
13302  event_name,
13303  actionid,
13304  vmu->context,
13305  vmu->mailbox,
13306  vmu->fullname,
13307  vmu->email,
13308  vmu->pager,
13311  mailcmd,
13312  vmu->language,
13313  vmu->zonetag,
13314  vmu->callback,
13315  vmu->dialout,
13316  vmu->uniqueid,
13317  vmu->exit,
13318  vmu->saydurationm,
13319  ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
13320  ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
13321  ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
13322  vmu->attachfmt,
13323  ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
13324  vmu->volgain,
13325  ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
13326  ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
13327  vmu->maxmsg,
13328  vmu->maxsecs,
13329  new,
13330  old
13331 #ifdef IMAP_STORAGE
13332  ,
13333  vmu->imapuser,
13334  vmu->imapserver,
13335  vmu->imapport,
13336  vmu->imapflags
13337 #endif
13338  );
13339 
13340  return 1;
13341 
13342 }
double volgain
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
static char mailcmd[160]
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define VM_ATTACH
char pager[80]
#define NULL
Definition: resample.c:96
static char fromstring[100]
char context[MAX_VM_CONTEXT_LEN]
char exit[80]
#define VM_SAYCID
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define VM_ENVELOPE
#define ast_log
Definition: astobj2.c:42
char dialout[80]
#define VM_DELETE
char zonetag[80]
char fromstring[100]
#define VM_OPERATOR
#define LOG_ERROR
Definition: logger.h:285
#define VM_REVIEW
int errno
#define ast_free(a)
Definition: astmm.h:182
char language[MAX_LANGUAGE]
char serveremail[80]
char attachfmt[20]
char uniqueid[80]
char callback[80]
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
char fullname[80]
char mailbox[MAX_VM_MBOX_ID_LEN]
static char serveremail[80]

◆ apply_option()

static void apply_option ( struct ast_vm_user vmu,
const char *  var,
const char *  value 
)
static

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

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

1253 {
1254  int x;
1255  if (!strcasecmp(var, "attach")) {
1257  } else if (!strcasecmp(var, "attachfmt")) {
1258  ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
1259  } else if (!strcasecmp(var, "serveremail")) {
1260  ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
1261  } else if (!strcasecmp(var, "fromstring")) {
1262  ast_copy_string(vmu->fromstring, value, sizeof(vmu->fromstring));
1263  } else if (!strcasecmp(var, "emailbody")) {
1264  ast_free(vmu->emailbody);
1266  } else if (!strcasecmp(var, "emailsubject")) {
1267  ast_free(vmu->emailsubject);
1269  } else if (!strcasecmp(var, "language")) {
1270  ast_copy_string(vmu->language, value, sizeof(vmu->language));
1271  } else if (!strcasecmp(var, "tz")) {
1272  ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
1273  } else if (!strcasecmp(var, "locale")) {
1274  ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
1275 #ifdef IMAP_STORAGE
1276  } else if (!strcasecmp(var, "imapuser")) {
1277  ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
1278  vmu->imapversion = imapversion;
1279  } else if (!strcasecmp(var, "imapserver")) {
1280  ast_copy_string(vmu->imapserver, value, sizeof(vmu->imapserver));
1281  vmu->imapversion = imapversion;
1282  } else if (!strcasecmp(var, "imapport")) {
1283  ast_copy_string(vmu->imapport, value, sizeof(vmu->imapport));
1284  vmu->imapversion = imapversion;
1285  } else if (!strcasecmp(var, "imapflags")) {
1286  ast_copy_string(vmu->imapflags, value, sizeof(vmu->imapflags));
1287  vmu->imapversion = imapversion;
1288  } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
1289  ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
1290  vmu->imapversion = imapversion;
1291  } else if (!strcasecmp(var, "imapfolder")) {
1292  ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
1293  vmu->imapversion = imapversion;
1294  } else if (!strcasecmp(var, "imapvmshareid")) {
1295  ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
1296  vmu->imapversion = imapversion;
1297 #endif
1298  } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
1300  } else if (!strcasecmp(var, "saycid")){
1302  } else if (!strcasecmp(var, "sendvoicemail")){
1304  } else if (!strcasecmp(var, "review")){
1306  } else if (!strcasecmp(var, "tempgreetwarn")){
1308  } else if (!strcasecmp(var, "messagewrap")){
1310  } else if (!strcasecmp(var, "operator")) {
1312  } else if (!strcasecmp(var, "envelope")){
1314  } else if (!strcasecmp(var, "moveheard")){
1316  } else if (!strcasecmp(var, "sayduration")){
1318  } else if (!strcasecmp(var, "saydurationm")){
1319  if (sscanf(value, "%30d", &x) == 1) {
1320  vmu->saydurationm = x;
1321  } else {
1322  ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
1323  }
1324  } else if (!strcasecmp(var, "forcename")){
1326  } else if (!strcasecmp(var, "forcegreetings")){
1328  } else if (!strcasecmp(var, "callback")) {
1329  ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
1330  } else if (!strcasecmp(var, "dialout")) {
1331  ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
1332  } else if (!strcasecmp(var, "exitcontext")) {
1333  ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
1334  } else if (!strcasecmp(var, "minsecs")) {
1335  if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
1336  vmu->minsecs = x;
1337  } else {
1338  ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1339  vmu->minsecs = vmminsecs;
1340  }
1341  } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
1342  vmu->maxsecs = atoi(value);
1343  if (vmu->maxsecs <= 0) {
1344  ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
1345  vmu->maxsecs = vmmaxsecs;
1346  } else {
1347  vmu->maxsecs = atoi(value);
1348  }
1349  if (!strcasecmp(var, "maxmessage"))
1350  ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1351  } else if (!strcasecmp(var, "maxmsg")) {
1352  vmu->maxmsg = atoi(value);
1353  /* Accept maxmsg=0 (Greetings only voicemail) */
1354  if (vmu->maxmsg < 0) {
1355  ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
1356  vmu->maxmsg = MAXMSG;
1357  } else if (vmu->maxmsg > MAXMSGLIMIT) {
1358  ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
1359  vmu->maxmsg = MAXMSGLIMIT;
1360  }
1361  } else if (!strcasecmp(var, "nextaftercmd")) {
1363  } else if (!strcasecmp(var, "backupdeleted")) {
1364  if (sscanf(value, "%30d", &x) == 1)
1365  vmu->maxdeletedmsg = x;
1366  else if (ast_true(value))
1367  vmu->maxdeletedmsg = MAXMSG;
1368  else
1369  vmu->maxdeletedmsg = 0;
1370 
1371  if (vmu->maxdeletedmsg < 0) {
1372  ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
1373  vmu->maxdeletedmsg = MAXMSG;
1374  } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
1375  ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
1376  vmu->maxdeletedmsg = MAXMSGLIMIT;
1377  }
1378  } else if (!strcasecmp(var, "volgain")) {
1379  sscanf(value, "%30lf", &vmu->volgain);
1380  } else if (!strcasecmp(var, "passwordlocation")) {
1381  if (!strcasecmp(value, "spooldir")) {
1383  } else {
1385  }
1386  } else if (!strcasecmp(var, "options")) {
1387  apply_options(vmu, value);
1388  }
1389 }
double volgain
#define VM_TEMPGREETWARN
static const char * substitute_escapes(const char *value)
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define VM_SAYDURATION
#define LOG_WARNING
Definition: logger.h:274
#define AST_LOG_WARNING
Definition: logger.h:279
#define var
Definition: ast_expr2f.c:614
#define VM_MESSAGEWRAP
#define VM_ATTACH
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static int vmminsecs
int value
Definition: syslog.c:37
char exit[80]
#define VM_SAYCID
#define VM_SVMAIL
#define VM_ENVELOPE
#define ast_log
Definition: astobj2.c:42
char locale[20]
char dialout[80]
#define MAXMSG
#define VM_FORCENAME
#define VM_DELETE
char zonetag[80]
int passwordlocation
#define VM_MOVEHEARD
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
char fromstring[100]
#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 "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
char * emailbody
#define VM_REVIEW
#define ast_free(a)
Definition: astmm.h:182
char language[MAX_LANGUAGE]
char serveremail[80]
char attachfmt[20]
static int vmmaxsecs
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char callback[80]
#define VM_SKIPAFTERCMD
char * emailsubject
#define MAXMSGLIMIT
#define VM_FORCEGREET

◆ apply_options()

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

Destructively Parse options and apply.

Definition at line 1507 of file app_voicemail.c.

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

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

1508 {
1509  char *stringp;
1510  char *s;
1511  char *var, *value;
1512  stringp = ast_strdupa(options);
1513  while ((s = strsep(&stringp, "|"))) {
1514  value = s;
1515  if ((var = strsep(&value, "=")) && value) {
1516  apply_option(vmu, var, value);
1517  }
1518  }
1519 }
#define var
Definition: ast_expr2f.c:614
int value
Definition: syslog.c:37
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a specific property value.
char * strsep(char **str, const char *delims)
static struct test_options options

◆ apply_options_full()

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 1526 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(), find_user_realtime(), and vm_allocate_dh().

1527 {
1528  for (; var; var = var->next) {
1529  if (!strcasecmp(var->name, "vmsecret")) {
1530  ast_copy_string(retval->password, var->value, sizeof(retval->password));
1531  } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
1532  if (ast_strlen_zero(retval->password)) {
1533  if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
1534  ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
1535  "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
1536  } else {
1537  ast_copy_string(retval->password, var->value, sizeof(retval->password));
1538  }
1539  }
1540  } else if (!strcasecmp(var->name, "uniqueid")) {
1541  ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
1542  } else if (!strcasecmp(var->name, "pager")) {
1543  ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
1544  } else if (!strcasecmp(var->name, "email")) {
1545  ast_free(retval->email);
1546  retval->email = ast_strdup(var->value);
1547  } else if (!strcasecmp(var->name, "fullname")) {
1548  ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
1549  } else if (!strcasecmp(var->name, "context")) {
1550  ast_copy_string(retval->context, var->value, sizeof(retval->context));
1551  } else if (!strcasecmp(var->name, "emailsubject")) {
1552  ast_free(retval->emailsubject);
1554  } else if (!strcasecmp(var->name, "emailbody")) {
1555  ast_free(retval->emailbody);
1556  retval->emailbody = ast_strdup(substitute_escapes(var->value));
1557 #ifdef IMAP_STORAGE
1558  } else if (!strcasecmp(var->name, "imapuser")) {
1559  ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
1560  retval->imapversion = imapversion;
1561  } else if (!strcasecmp(var->name, "imapserver")) {
1562  ast_copy_string(retval->imapserver, var->value, sizeof(retval->imapserver));
1563  retval->imapversion = imapversion;
1564  } else if (!strcasecmp(var->name, "imapport")) {
1565  ast_copy_string(retval->imapport, var->value, sizeof(retval->imapport));
1566  retval->imapversion = imapversion;
1567  } else if (!strcasecmp(var->name, "imapflags")) {
1568  ast_copy_string(retval->imapflags, var->value, sizeof(retval->imapflags));
1569  retval->imapversion = imapversion;
1570  } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
1571  ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
1572  retval->imapversion = imapversion;
1573  } else if (!strcasecmp(var->name, "imapfolder")) {
1574  ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
1575  retval->imapversion = imapversion;
1576  } else if (!strcasecmp(var->name, "imapvmshareid")) {
1577  ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
1578  retval->imapversion = imapversion;
1579 #endif
1580  } else
1581  apply_option(retval, var->name, var->value);
1582  }
1583 }
struct ast_variable * next
static const char * substitute_escapes(const char *value)
#define LOG_WARNING
Definition: logger.h:274
#define var
Definition: ast_expr2f.c:614
char pager[80]
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
char password[80]
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a specific property value.
char * emailbody
#define ast_free(a)
Definition: astmm.h:182
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char uniqueid[80]
char * emailsubject
char fullname[80]
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 16611 of file app_voicemail.c.

◆ ast_str_encode_mime()

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

5030 {
5031  struct ast_str *tmp = ast_str_alloca(80);
5032  int first_section = 1;
5033 
5034  ast_str_reset(*end);
5035  ast_str_set(&tmp, -1, "=?%s?Q?", charset);
5036  for (; *start; start++) {
5037  int need_encoding = 0;
5038  if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
5039  need_encoding = 1;
5040  }
5041  if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
5042  (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
5043  (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
5044  (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
5045  /* Start new line */
5046  ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
5047  ast_str_set(&tmp, -1, "=?%s?Q?", charset);
5048  first_section = 0;
5049  }
5050  if (need_encoding && *start == ' ') {
5051  ast_str_append(&tmp, -1, "_");
5052  } else if (need_encoding) {
5053  ast_str_append(&tmp, -1, "=%hhX", *start);
5054  } else {
5055  ast_str_append(&tmp, -1, "%c", *start);
5056  }
5057  }
5058  ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
5059  return ast_str_buffer(*end);
5060 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
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:1091
#define ast_str_alloca(init_len)
Definition: strings.h:800
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:1065
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
charset
Definition: chan_unistim.c:336
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:653
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688

◆ ast_str_quote()

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

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

Referenced by make_email_file(), and sendpage().

4958 {
4959  const char *ptr;
4960 
4961  /* We're only ever passing 0 to maxlen, so short output isn't possible */
4962  ast_str_set(buf, maxlen, "\"");
4963  for (ptr = from; *ptr; ptr++) {
4964  if (*ptr == '"' || *ptr == '\\') {
4965  ast_str_append(buf, maxlen, "\\%c", *ptr);
4966  } else {
4967  ast_str_append(buf, maxlen, "%c", *ptr);
4968  }
4969  }
4970  ast_str_append(buf, maxlen, "\"");
4971 
4972  return ast_str_buffer(*buf);
4973 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1091
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:1065

◆ AST_TEST_DEFINE() [1/6]

AST_TEST_DEFINE ( test_voicemail_vmuser  )

Definition at line 12486 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::fromstring, sip_to_pjsip::info(), 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.

12487 {
12488  int res = 0;
12489  struct ast_vm_user *vmu;
12490  /* language parameter seems to only be used for display in manager action */
12491  static const char options_string[] = "attach=yes|attachfmt=wav49|"
12492  "[email protected]|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|"
12493  "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
12494  "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
12495  "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
12496  "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
12497  "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
12498  "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
12499  "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
12500 #ifdef IMAP_STORAGE
12501  static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
12502  "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
12503 #endif
12504 
12505  switch (cmd) {
12506  case TEST_INIT:
12507  info->name = "vmuser";
12508  info->category = "/apps/app_voicemail/";
12509  info->summary = "Vmuser unit test";
12510  info->description =
12511  "This tests passing all supported parameters to apply_options, the voicemail user config parser";
12512  return AST_TEST_NOT_RUN;
12513  case TEST_EXECUTE:
12514  break;
12515  }
12516 
12517  if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
12518  return AST_TEST_NOT_RUN;
12519  }
12520  populate_defaults(vmu);
12521  ast_set_flag(vmu, VM_ALLOCED);
12522 
12523  apply_options(vmu, options_string);
12524 
12525  if (!ast_test_flag(vmu, VM_ATTACH)) {
12526  ast_test_status_update(test, "Parse failure for attach option\n");
12527  res = 1;
12528  }
12529  if (strcasecmp(vmu->attachfmt, "wav49")) {
12530  ast_test_status_update(test, "Parse failure for attachftm option\n");
12531  res = 1;
12532  }
12533  if (strcasecmp(vmu->fromstring, "Voicemail System")) {
12534  ast_test_status_update(test, "Parse failure for fromstring option\n");
12535  res = 1;
12536  }
12537  if (strcasecmp(vmu->serveremail, "[email protected]")) {
12538  ast_test_status_update(test, "Parse failure for serveremail option\n");
12539  res = 1;
12540  }
12541  if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
12542  ast_test_status_update(test, "Parse failure for emailsubject option\n");
12543  res = 1;
12544  }
12545  if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
12546  ast_test_status_update(test, "Parse failure for emailbody option\n");
12547  res = 1;
12548  }
12549  if (strcasecmp(vmu->zonetag, "central")) {
12550  ast_test_status_update(test, "Parse failure for tz option\n");
12551  res = 1;
12552  }
12553  if (!ast_test_flag(vmu, VM_DELETE)) {
12554  ast_test_status_update(test, "Parse failure for delete option\n");
12555  res = 1;
12556  }
12557  if (!ast_test_flag(vmu, VM_SAYCID)) {
12558  ast_test_status_update(test, "Parse failure for saycid option\n");
12559  res = 1;
12560  }
12561  if (!ast_test_flag(vmu, VM_SVMAIL)) {
12562  ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
12563  res = 1;
12564  }
12565  if (!ast_test_flag(vmu, VM_REVIEW)) {
12566  ast_test_status_update(test, "Parse failure for review option\n");
12567  res = 1;
12568  }
12569  if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
12570  ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
12571  res = 1;
12572  }
12573  if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
12574  ast_test_status_update(test, "Parse failure for messagewrap option\n");
12575  res = 1;
12576  }
12577  if (!ast_test_flag(vmu, VM_OPERATOR)) {
12578  ast_test_status_update(test, "Parse failure for operator option\n");
12579  res = 1;
12580  }
12581  if (!ast_test_flag(vmu, VM_ENVELOPE)) {
12582  ast_test_status_update(test, "Parse failure for envelope option\n");
12583  res = 1;
12584  }
12585  if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
12586  ast_test_status_update(test, "Parse failure for moveheard option\n");
12587  res = 1;
12588  }
12589  if (!ast_test_flag(vmu, VM_SAYDURATION)) {
12590  ast_test_status_update(test, "Parse failure for sayduration option\n");
12591  res = 1;
12592  }
12593  if (vmu->saydurationm != 5) {
12594  ast_test_status_update(test, "Parse failure for saydurationm option\n");
12595  res = 1;
12596  }
12597  if (!ast_test_flag(vmu, VM_FORCENAME)) {
12598  ast_test_status_update(test, "Parse failure for forcename option\n");
12599  res = 1;
12600  }
12601  if (!ast_test_flag(vmu, VM_FORCEGREET)) {
12602  ast_test_status_update(test, "Parse failure for forcegreetings option\n");
12603  res = 1;
12604  }
12605  if (strcasecmp(vmu->callback, "somecontext")) {
12606  ast_test_status_update(test, "Parse failure for callbacks option\n");
12607  res = 1;
12608  }
12609  if (strcasecmp(vmu->dialout, "somecontext2")) {
12610  ast_test_status_update(test, "Parse failure for dialout option\n");
12611  res = 1;
12612  }
12613  if (strcasecmp(vmu->exit, "somecontext3")) {
12614  ast_test_status_update(test, "Parse failure for exitcontext option\n");
12615  res = 1;
12616  }
12617  if (vmu->minsecs != 10) {
12618  ast_test_status_update(test, "Parse failure for minsecs option\n");
12619  res = 1;
12620  }
12621  if (vmu->maxsecs != 100) {
12622  ast_test_status_update(test, "Parse failure for maxsecs option\n");
12623  res = 1;
12624  }
12625  if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
12626  ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
12627  res = 1;
12628  }
12629  if (vmu->maxdeletedmsg != 50) {
12630  ast_test_status_update(test, "Parse failure for backupdeleted option\n");
12631  res = 1;
12632  }
12633  if (vmu->volgain != 1.3) {
12634  ast_test_status_update(test, "Parse failure for volgain option\n");
12635  res = 1;
12636  }
12637  if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
12638  ast_test_status_update(test, "Parse failure for passwordlocation option\n");
12639  res = 1;
12640  }
12641 #ifdef IMAP_STORAGE
12642  apply_options(vmu, option_string2);
12643 
12644  if (strcasecmp(vmu->imapuser, "imapuser")) {
12645  ast_test_status_update(test, "Parse failure for imapuser option\n");
12646  res = 1;
12647  }
12648  if (strcasecmp(vmu->imappassword, "imappasswd")) {
12649  ast_test_status_update(test, "Parse failure for imappasswd option\n");
12650  res = 1;
12651  }
12652  if (strcasecmp(vmu->imapfolder, "INBOX")) {
12653  ast_test_status_update(test, "Parse failure for imapfolder option\n");
12654  res = 1;
12655  }
12656  if (strcasecmp(vmu->imapvmshareid, "6000")) {
12657  ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
12658  res = 1;
12659  }
12660  if (strcasecmp(vmu->imapserver, "imapserver")) {
12661  ast_test_status_update(test, "Parse failure for imapserver option\n");
12662  res = 1;
12663  }
12664  if (strcasecmp(vmu->imapport, "1234")) {
12665  ast_test_status_update(test, "Parse failure for imapport option\n");
12666  res = 1;
12667  }
12668  if (strcasecmp(vmu->imapflags, "flagged")) {
12669  ast_test_status_update(test, "Parse failure for imapflags option\n");
12670  res = 1;
12671  }
12672 #endif
12673 
12674  free_user(vmu);
12675  return res ? AST_TEST_FAIL : AST_TEST_PASS;
12676 }
double volgain
#define VM_TEMPGREETWARN
#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 exit[80]
#define VM_SAYCID
#define VM_SVMAIL
#define VM_ENVELOPE
char dialout[80]
#define VM_FORCENAME
#define VM_DELETE
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
char zonetag[80]
int passwordlocation
#define VM_MOVEHEARD
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.
char fromstring[100]
#define VM_OPERATOR
char * emailbody
def info(msg)
#define VM_REVIEW
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char serveremail[80]
char attachfmt[20]
char callback[80]
#define VM_SKIPAFTERCMD
char * emailsubject
#define VM_ALLOCED
#define VM_FORCEGREET
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ AST_TEST_DEFINE() [2/6]

AST_TEST_DEFINE ( test_voicemail_vmsayname  )

Definition at line 14480 of file app_voicemail.c.

References ao2_ref, ast_channel_alloc, ast_channel_nativeformats_set(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_tech_set(), ast_channel_unlock, ast_config_AST_DATA_DIR, ast_fileexists(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_gsm, ast_hangup(), ast_log, AST_LOG_WARNING, AST_STATE_DOWN, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, create_dirpath(), errno, fake_read(), fake_write(), sip_to_pjsip::info(), LOG_WARNING, NULL, PATH_MAX, TEST_CONTEXT, TEST_EXECUTE, TEST_EXTENSION, TEST_INIT, vmsayname_exec(), and ast_channel_tech::write.

14481 {
14482  char dir[PATH_MAX];
14483  char dir2[PATH_MAX];
14484  static const char TEST_CONTEXT[] = "very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
14485  static const char TEST_EXTENSION[] = "1234";
14486 
14487  struct ast_channel *test_channel1 = NULL;
14488  int res = -1;
14489  struct ast_format_cap *capabilities;
14490 
14491  static const struct ast_channel_tech fake_tech = {
14492  .write = fake_write,
14493  .read = fake_read,
14494  };
14495 
14496  switch (cmd) {
14497  case TEST_INIT:
14498  info->name = "vmsayname_exec";
14499  info->category = "/apps/app_voicemail/";
14500  info->summary = "Vmsayname unit test";
14501  info->description =
14502  "This tests passing various parameters to vmsayname";
14503  return AST_TEST_NOT_RUN;
14504  case TEST_EXECUTE:
14505  break;
14506  }
14507 
14508  if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL,
14509  NULL, NULL, 0, 0, "TestChannel1"))) {
14510  goto exit_vmsayname_test;
14511  }
14512 
14513  /* normally this is done in the channel driver */
14515  if (!capabilities) {
14516  goto exit_vmsayname_test;
14517  }
14518  ast_format_cap_append(capabilities, ast_format_gsm, 0);
14519  ast_channel_nativeformats_set(test_channel1, capabilities);
14520  ao2_ref(capabilities, -1);
14525  ast_channel_tech_set(test_channel1, &fake_tech);
14526 
14527  ast_channel_unlock(test_channel1);
14528 
14529  ast_test_status_update(test, "Test playing of extension when greeting is not available...\n");
14530  snprintf(dir, sizeof(dir), "%s@%s", TEST_EXTENSION, TEST_CONTEXT); /* not a dir, don't get confused */
14531  if (!(res = vmsayname_exec(test_channel1, dir))) {
14532  snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
14533  if (ast_fileexists(dir, NULL, NULL)) {
14534  ast_test_status_update(test, "This should not happen, most likely means clean up from previous test failed\n");
14535  res = -1;
14536  goto exit_vmsayname_test;
14537  } else {
14538  /* no greeting already exists as expected, let's create one to fully test sayname */
14539  if ((res = create_dirpath(dir, sizeof(dir), TEST_CONTEXT, TEST_EXTENSION, ""))) {
14540  ast_log(AST_LOG_WARNING, "Failed to make test directory\n");
14541  goto exit_vmsayname_test;
14542  }
14543  snprintf(dir, sizeof(dir), "%s/sounds/beep.gsm", ast_config_AST_DATA_DIR);
14544  snprintf(dir2, sizeof(dir2), "%s%s/%s/greet.gsm", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
14545  /* we're not going to hear the sound anyway, just use a valid gsm audio file */
14546  if ((res = symlink(dir, dir2))) {
14547  ast_log(LOG_WARNING, "Symlink reported %s\n", strerror(errno));
14548  goto exit_vmsayname_test;
14549  }
14550  ast_test_status_update(test, "Test playing created mailbox greeting...\n");
14551  snprintf(dir, sizeof(dir), "%s@%s", TEST_EXTENSION, TEST_CONTEXT); /* not a dir, don't get confused */
14552  res = vmsayname_exec(test_channel1, dir);
14553 
14554  /* TODO: there may be a better way to do this */
14555  unlink(dir2);
14556  snprintf(dir2, sizeof(dir2), "%s%s/%s", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
14557  rmdir(dir2);
14558  snprintf(dir2, sizeof(dir2), "%s%s", VM_SPOOL_DIR, TEST_CONTEXT);
14559  rmdir(dir2);
14560  }
14561  }
14562 
14563 exit_vmsayname_test:
14564 
14565  ast_hangup(test_channel1);
14566 
14567  return res ? AST_TEST_FAIL : AST_TEST_PASS;
14568 }
Main Channel structure associated with a channel.
#define TEST_EXTENSION
Definition: test_message.c:47
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
Definition: channel.h:751
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#define LOG_WARNING
Definition: logger.h:274
#define AST_LOG_WARNING
Definition: logger.h:279
#define NULL
Definition: resample.c:96
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
#define TEST_CONTEXT
Definition: test_message.c:46
static int vmsayname_exec(struct ast_channel *chan, const char *data)
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
struct ast_format * ast_format_gsm
Built-in cached gsm format.
Definition: format_cache.c:101
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
static char VM_SPOOL_DIR[PATH_MAX]
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
def info(msg)
int errno
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int fake_write(struct ast_channel *ast, struct ast_frame *frame)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
#define PATH_MAX
Definition: asterisk.h:40
static struct ast_frame * fake_read(struct ast_channel *ast)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259

◆ AST_TEST_DEFINE() [3/6]

AST_TEST_DEFINE ( test_voicemail_msgcount  )

Definition at line 14576 of file app_voicemail.c.

References ast_alloca, ast_app_has_voicemail(), ast_app_inboxcount(), ast_app_inboxcount2(), ast_app_messagecount(), ast_channel_unref, ast_config_AST_DATA_DIR, ast_dummy_channel_alloc, ast_fileexists(), ast_free, ast_safe_system(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_unreplace_sigchld(), create_dirpath(), DELETE, vm_state::deleted, DISPOSE, find_or_create(), find_user(), free_user(), vm_state::heard, sip_to_pjsip::info(), make_file(), NULL, open_mailbox(), populate_defaults(), STORE, TEST_EXECUTE, TEST_INIT, and test_files::txtfile.

14577 {
14578  int i, j, res = AST_TEST_PASS, syserr;
14579  struct ast_vm_user *vmu;
14580  struct ast_vm_user svm;
14581  struct vm_state vms;
14582 #ifdef IMAP_STORAGE
14583  struct ast_channel *chan = NULL;
14584 #endif
14585  /* Using ast_alloca instead of just declaring tmp as an array is a workaround for a GCC 10 issue with -Wrestrict */
14586  struct test_files *tmp = ast_alloca(sizeof(struct test_files) * 3);
14587  char syscmd[256];
14588  const char origweasels[] = "tt-weasels";
14589  const char testcontext[] = "test";
14590  const char testmailbox[] = "00000000";
14591  const char testspec[] = "00000000@test";
14592  FILE *txt;
14593  int new, old, urgent;
14594  const char *folders[3] = { "Old", "Urgent", "INBOX" };
14595  const int folder2mbox[3] = { 1, 11, 0 };
14596  const int expected_results[3][12] = {
14597  /* hasvm-old, hasvm-urgent, hasvm-new, ic-old, ic-urgent, ic-new, ic2-old, ic2-urgent, ic2-new, mc-old, mc-urgent, mc-new */
14598  { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
14599  { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
14600  { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
14601  };
14602 
14603  switch (cmd) {
14604  case TEST_INIT:
14605  info->name = "test_voicemail_msgcount";
14606  info->category = "/apps/app_voicemail/";
14607  info->summary = "Test Voicemail status checks";
14608  info->description =
14609  "Verify that message counts are correct when retrieved through the public API";
14610  return AST_TEST_NOT_RUN;
14611  case TEST_EXECUTE:
14612  break;
14613  }
14614 
14615  /* Make sure the original path was completely empty */
14616  snprintf(syscmd, sizeof(syscmd), "rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
14617  if ((syserr = ast_safe_system(syscmd))) {
14618  ast_test_status_update(test, "Unable to clear test directory: %s\n",
14619  syserr > 0 ? strerror(syserr) : "unable to fork()");
14620  return AST_TEST_FAIL;
14621  }
14622 
14623 #ifdef IMAP_STORAGE
14624  if (!(chan = ast_dummy_channel_alloc())) {
14625  ast_test_status_update(test, "Unable to create dummy channel\n");
14626  return AST_TEST_FAIL;
14627  }
14628 #endif
14629 
14630  memset(&svm, 0, sizeof(svm));
14631  if (!(vmu = find_user(&svm, testcontext, testmailbox)) &&
14632  !(vmu = find_or_create(testcontext, testmailbox))) {
14633  ast_test_status_update(test, "Cannot create vmu structure\n");
14635 #ifdef IMAP_STORAGE
14636  chan = ast_channel_unref(chan);
14637 #endif
14638  return AST_TEST_FAIL;
14639  }
14640 
14641  populate_defaults(vmu);
14642  memset(&vms, 0, sizeof(vms));
14643 
14644  /* Create temporary voicemail */
14645  for (i = 0; i < 3; i++) {
14646  create_dirpath(tmp[i].dir, sizeof(tmp[i].dir), testcontext, testmailbox, folders[i]);
14647  make_file(tmp[i].file, sizeof(tmp[i].file), tmp[i].dir, 0);
14648  snprintf(tmp[i].txtfile, sizeof(tmp[i].txtfile), "%s.txt", tmp[i].file);
14649 
14650  if (ast_fileexists(origweasels, "gsm", "en") > 0) {
14651  snprintf(syscmd, sizeof(syscmd), "cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"", ast_config_AST_DATA_DIR, origweasels,
14652  VM_SPOOL_DIR, testcontext, testmailbox, folders[i]);
14653  if ((syserr = ast_safe_system(syscmd))) {
14654  ast_test_status_update(test, "Unable to create test voicemail: %s\n",
14655  syserr > 0 ? strerror(syserr) : "unable to fork()");
14657 #ifdef IMAP_STORAGE
14658  chan = ast_channel_unref(chan);
14659 #endif
14660  free_user(vmu);
14661  return AST_TEST_FAIL;
14662  }
14663  }
14664 
14665  if ((txt = fopen(tmp[i].txtfile, "w+"))) {
14666  fprintf(txt, "; just a stub\n[message]\nflag=%s\n", strcmp(folders[i], "Urgent") ? "" : "Urgent");
14667  fclose(txt);
14668  } else {
14669  ast_test_status_update(test, "Unable to write message file '%s'\n", tmp[i].txtfile);
14670  res = AST_TEST_FAIL;
14671  break;
14672  }
14673  open_mailbox(&vms, vmu, folder2mbox[i]);
14674  STORE(tmp[i].dir, testmailbox, testcontext, 0, chan, vmu, "gsm", 600, &vms, strcmp(folders[i], "Urgent") ? "" : "Urgent", NULL);
14675 
14676  /* hasvm-old, hasvm-urgent, hasvm-new, ic-old, ic-urgent, ic-new, ic2-old, ic2-urgent, ic2-new, mc-old, mc-urgent, mc-new */
14677  for (j = 0; j < 3; j++) {
14678  /* folder[2] is INBOX, __has_voicemail will default back to INBOX */
14679  if (ast_app_has_voicemail(testspec, (j==2 ? NULL : folders[j])) != expected_results[i][0 + j]) {
14680  ast_test_status_update(test, "has_voicemail(%s, %s) returned %d and we expected %d\n",
14681  testspec, folders[j], ast_app_has_voicemail(testspec, folders[j]), expected_results[i][0 + j]);
14682  res = AST_TEST_FAIL;
14683  }
14684  }
14685 
14686  new = old = urgent = 0;
14687  if (ast_app_inboxcount(testspec, &new, &old)) {
14688  ast_test_status_update(test, "inboxcount returned failure\n");
14689  res = AST_TEST_FAIL;
14690  } else if (old != expected_results[i][3 + 0] || new != expected_results[i][3 + 2]) {
14691  ast_test_status_update(test, "inboxcount(%s) returned old=%d (expected %d) and new=%d (expected %d)\n",
14692  testspec, old, expected_results[i][3 + 0], new, expected_results[i][3 + 2]);
14693  res = AST_TEST_FAIL;
14694  }
14695 
14696  new = old = urgent = 0;
14697  if (ast_app_inboxcount2(testspec, &urgent, &new, &old)) {
14698  ast_test_status_update(test, "inboxcount2 returned failure\n");
14699  res = AST_TEST_FAIL;
14700  } else if (old != expected_results[i][6 + 0] ||
14701  urgent != expected_results[i][6 + 1] ||
14702  new != expected_results[i][6 + 2] ) {
14703  ast_test_status_update(test, "inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
14704  testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1], new, expected_results[i][6 + 2]);
14705  res = AST_TEST_FAIL;
14706  }
14707 
14708  new = old = urgent = 0;
14709  for (j = 0; j < 3; j++) {
14710  if (ast_app_messagecount(testspec, folders[j]) != expected_results[i][9 + j]) {
14711  ast_test_status_update(test, "messagecount(%s, %s) returned %d and we expected %d\n",
14712  testspec, folders[j], ast_app_messagecount(testspec, folders[j]), expected_results[i][9 + j]);
14713  res = AST_TEST_FAIL;
14714  }
14715  }
14716  }
14717 
14718  for (i = 0; i < 3; i++) {
14719  /* This is necessary if the voicemails are stored on an ODBC/IMAP
14720  * server, in which case, the rm below will not affect the
14721  * voicemails. */
14722  DELETE(tmp[i].dir, 0, tmp[i].file, vmu);
14723  DISPOSE(tmp[i].dir, 0);
14724  }
14725 
14726  if (vms.deleted) {
14727  ast_free(vms.deleted);
14728  }
14729  if (vms.heard) {
14730  ast_free(vms.heard);
14731  }
14732 
14733 #ifdef IMAP_STORAGE
14734  chan = ast_channel_unref(chan);
14735 #endif
14736 
14737  /* And remove test directory */
14738  snprintf(syscmd, sizeof(syscmd), "rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
14739  if ((syserr = ast_safe_system(syscmd))) {
14740  ast_test_status_update(test, "Unable to clear test directory: %s\n",
14741  syserr > 0 ? strerror(syserr) : "unable to fork()");
14742  }
14743 
14744  free_user(vmu);
14745  return res;
14746 }
Main Channel structure associated with a channel.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Definition: extconf.c:815
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
char dir[256]
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
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_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: main/app.c:692
char txtfile[256]
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
#define DELETE(a, b, c, d)
static char VM_SPOOL_DIR[PATH_MAX]
static void free_user(struct ast_vm_user *vmu)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
def info(msg)
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.
#define ast_free(a)
Definition: astmm.h:182
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:655
int ast_app_messagecount(const char *mailbox_id, const char *folder)
Get the number of messages in a given mailbox folder.
Definition: main/app.c:718
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
static struct ast_vm_user * find_or_create(const char *context, const char *box)
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
Determine number of new/old messages in a mailbox.
Definition: main/app.c:677
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ AST_TEST_DEFINE() [4/6]

AST_TEST_DEFINE ( test_voicemail_notify_endl  )

Definition at line 14748 of file app_voicemail.c.

References ARRAY_LEN, ast_clear_flag, ast_config_AST_DATA_DIR, ast_set_flag, ast_strdup, AST_TEST_FAIL, ast_test_flag, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, errno, make_ari_stubs::file, find_or_create(), find_user(), ast_vm_user::flags, free_user(), sip_to_pjsip::info(), make_email_file(), name, NULL, ast_vm_user::password, populate_defaults(), ast_vm_user::serveremail, TEST_EXECUTE, TEST_INIT, type, and VM_ATTACH.

14749 {
14750  int res = AST_TEST_PASS;
14751  char testcontext[] = "test";
14752  char testmailbox[] = "00000000";
14753  char from[] = "[email protected]", cidnum[] = "1234", cidname[] = "Mark Spencer", format[] = "gsm";
14754  char attach[256], attach2[256];
14755  char buf[256] = ""; /* No line should actually be longer than 80 */
14756  struct ast_channel *chan = NULL;
14757  struct ast_vm_user *vmu, vmus = {
14758  .flags = 0,
14759  };
14760  FILE *file;
14761  struct {
14762  char *name;
14763  enum { INT, FLAGVAL, STATIC, STRPTR } type;
14764  void *location;
14765  union {
14766  int intval;
14767  char *strval;
14768  } u;
14769  } test_items[] = {
14770  { "plain jane config", STATIC, vmus.password, .u.strval = "1234" }, /* No, this doesn't change this test any. */
14771  { "emailsubject", STRPTR, vmus.emailsubject, .u.strval = "Oogly boogly\xf8koogly with what appears to be UTF-8" },
14772  { "emailbody", STRPTR, vmus.emailbody, .u.strval = "This is a test\n\twith multiple\nlines\nwithin\n" },
14773  { "serveremail", STATIC, vmus.serveremail, .u.strval = "\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <[email protected]>" },
14774  { "attachment flag", FLAGVAL, &vmus.flags, .u.intval = VM_ATTACH },
14775  { "attach2", STRPTR, attach2, .u.strval = "" },
14776  { "attach", STRPTR, attach, .u.strval = "" },
14777  };
14778  int which;
14779 
14780  switch (cmd) {
14781  case TEST_INIT:
14782  info->name = "test_voicemail_notify_endl";
14783  info->category = "/apps/app_voicemail/";
14784  info->summary = "Test Voicemail notification end-of-line";
14785  info->description =
14786  "Verify that notification emails use a consistent end-of-line character";
14787  return AST_TEST_NOT_RUN;
14788  case TEST_EXECUTE:
14789  break;
14790  }
14791 
14792  snprintf(attach, sizeof(attach), "%s/sounds/en/tt-weasels", ast_config_AST_DATA_DIR);
14793  snprintf(attach2, sizeof(attach2), "%s/sounds/en/tt-somethingwrong", ast_config_AST_DATA_DIR);
14794 
14795  if (!(vmu = find_user(&vmus, testcontext, testmailbox)) &&
14796  !(vmu = find_or_create(testcontext, testmailbox))) {
14797  ast_test_status_update(test, "Cannot create vmu structure\n");
14798  return AST_TEST_NOT_RUN;
14799  }
14800 
14801  if (vmu != &vmus && !(vmu = find_user(&vmus, testcontext, testmailbox))) {
14802  ast_test_status_update(test, "Cannot find vmu structure?!!\n");
14803  return AST_TEST_NOT_RUN;
14804  }
14805 
14806  populate_defaults(vmu);
14808 #ifdef IMAP_STORAGE
14809  /* TODO When we set up the IMAP server test, we'll need to have credentials for the VMU structure added here */
14810 #endif
14811 
14812  file = tmpfile();
14813  for (which = 0; which < ARRAY_LEN(test_items); which++) {
14814  /* Kill previous test, if any */
14815  rewind(file);
14816  if (ftruncate(fileno(file), 0)) {
14817  ast_test_status_update(test, "Cannot truncate test output file: %s\n", strerror(errno));
14818  res = AST_TEST_FAIL;
14819  break;
14820  }
14821 
14822  /* Make each change, in order, to the test mailbox */
14823  if (test_items[which].type == INT) {
14824  *((int *) test_items[which].location) = test_items[which].u.intval;
14825  } else if (test_items[which].type == FLAGVAL) {
14826  if (ast_test_flag(vmu, test_items[which].u.intval)) {
14827  ast_clear_flag(vmu, test_items[which].u.intval);
14828  } else {
14829  ast_set_flag(vmu, test_items[which].u.intval);
14830  }
14831  } else if (test_items[which].type == STATIC) {
14832  strcpy(test_items[which].location, test_items[which].u.strval);
14833  } else if (test_items[which].type == STRPTR) {
14834  test_items[which].location = test_items[which].u.strval;
14835  }
14836 
14837  make_email_file(file, from, vmu, 0, testcontext, testmailbox, "INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan, NULL, 0, NULL, NULL);
14838  rewind(file);
14839  while (fgets(buf, sizeof(buf), file)) {
14840  if (
14841  (strlen(buf) > 1 &&
14842 #ifdef IMAP_STORAGE
14843  buf[strlen(buf) - 2] != '\r'
14844 #else
14845  buf[strlen(buf) - 2] == '\r'
14846 #endif
14847  )
14848  || buf[strlen(buf) - 1] != '\n') {
14849  res = AST_TEST_FAIL;
14850  }
14851  }
14852  }
14853  fclose(file);
14854  free_user(vmu);
14855  return res;
14856 }
static const char type[]
Definition: chan_ooh323.c:109
Main Channel structure associated with a channel.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_test_flag(p, flag)
Definition: utils.h:63
unsigned int flags
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define VM_ATTACH
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
char password[80]
#define NULL
Definition: resample.c:96
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static void free_user(struct ast_vm_user *vmu)
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
char * emailbody
def info(msg)
int errno
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[]
Definition: cdr_mysql.c:74
#define ast_clear_flag(p, flag)
Definition: utils.h:77
char serveremail[80]
static struct ast_vm_user * find_or_create(const char *context, const char *box)
char * emailsubject
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, const char *msg_id)
Creates the email file to be sent to indicate a new voicemail exists for a user.
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ AST_TEST_DEFINE() [5/6]

AST_TEST_DEFINE ( test_voicemail_load_config  )

Definition at line 14858 of file app_voicemail.c.

References ast_config_destroy(), ast_config_load, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, CHECK, cleanup(), config_filename, CONFIG_FLAG_NOCACHE, make_ari_stubs::file, sip_to_pjsip::info(), load_config(), load_config_from_memory(), ast_vm_user::mailbox, NULL, TEST_EXECUTE, TEST_INIT, and valid_config().

14859 {
14860  int res = AST_TEST_PASS;
14861  struct ast_vm_user *vmu;
14862  struct ast_config *cfg;
14863  char config_filename[32] = "/tmp/voicemail.conf.XXXXXX";
14864  int fd;
14865  FILE *file;
14866  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
14867 
14868  switch (cmd) {
14869  case TEST_INIT:
14870  info->name = "test_voicemail_load_config";
14871  info->category = "/apps/app_voicemail/";
14872  info->summary = "Test loading Voicemail config";
14873  info->description =
14874  "Verify that configuration is loaded consistently. "
14875  "This is to test regressions of ASTERISK-18838 where it was noticed that "
14876  "some options were loaded after the mailboxes were instantiated, causing "
14877  "those options not to be set correctly.";
14878  return AST_TEST_NOT_RUN;
14879  case TEST_EXECUTE:
14880  break;
14881  }
14882 
14883  /* build a config file by hand... */
14884  if ((fd = mkstemp(config_filename)) < 0) {
14885  return AST_TEST_FAIL;
14886  }
14887  if (!(file = fdopen(fd, "w"))) {
14888  close(fd);
14889  unlink(config_filename);
14890  return AST_TEST_FAIL;
14891  }
14892  fputs("[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]", file);
14893  fputs("00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n", file);
14894  fputs("00000002 => 9999,Mrs. Test\n", file);
14895  fclose(file);
14896 
14897  if (!(cfg = ast_config_load(config_filename, config_flags)) || !valid_config(cfg)) {
14898  res = AST_TEST_FAIL;
14899  goto cleanup;
14900  }
14901 
14902  load_config_from_memory(1, cfg, NULL);
14903  ast_config_destroy(cfg);
14904 
14905 #define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
14906  ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
14907  u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
14908 
14909  AST_LIST_LOCK(&users);
14910  AST_LIST_TRAVERSE(&users, vmu, list) {
14911  if (!strcmp(vmu->mailbox, "00000001")) {
14912  if (0); /* trick to get CHECK to work */
14913  CHECK(vmu, callback, "othercontext")
14914  CHECK(vmu, locale, "nl_NL.UTF-8")
14915  CHECK(vmu, zonetag, "central")
14916  } else if (!strcmp(vmu->mailbox, "00000002")) {
14917  if (0); /* trick to get CHECK to work */
14918  CHECK(vmu, callback, "somecontext")
14919  CHECK(vmu, locale, "de_DE.UTF-8")
14920  CHECK(vmu, zonetag, "european")
14921  }
14922  }
14924 
14925 #undef CHECK
14926 
14927  /* restore config */
14928  load_config(1); /* this might say "Failed to load configuration file." */
14929 
14930 cleanup:
14931  unlink(config_filename);
14932  return res;
14933 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int load_config(int reload)
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
static char locale[20]
#define NULL
Definition: resample.c:96
list of users found in the config file
#define CHECK(u, attr, value)
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_config_load(filename, flags)
Load a config file.
static char * config_filename
Definition: extconf.c:2121
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static char zonetag[80]
def info(msg)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static int load_config_from_memory(int reload, struct ast_config *cfg, struct ast_config *ucfg)
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
Structure used to handle boolean flags.
Definition: utils.h:199
char mailbox[MAX_VM_MBOX_ID_LEN]
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.

◆ AST_TEST_DEFINE() [6/6]

AST_TEST_DEFINE ( test_voicemail_vm_info  )

Definition at line 14935 of file app_voicemail.c.

References acf_vm_info(), ARRAY_LEN, ast_channel_unref, ast_copy_string(), ast_dummy_channel_alloc, ast_strdup, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_vm_user::email, find_or_create(), find_user(), free_user(), ast_vm_user::fullname, sip_to_pjsip::info(), ast_vm_user::language, ast_vm_user::locale, NULL, ast_vm_user::pager, ast_vm_user::password, populate_defaults(), TEST_EXECUTE, TEST_INIT, and ast_vm_user::zonetag.

14936 {
14937  struct ast_vm_user *vmu;
14938  struct ast_channel *chan = NULL;
14939  const char testcontext[] = "test";
14940  const char testmailbox[] = "00000000";
14941  const char vminfo_cmd[] = "VM_INFO";
14942  char vminfo_buf[256], vminfo_args[256];
14943  int res = AST_TEST_PASS;
14944  int test_ret = 0;
14945  int test_counter = 0;
14946 
14947  struct {
14948  char *vminfo_test_args;
14949  char *vminfo_expected;
14950  int vminfo_ret;
14951  } test_items[] = {
14952  { "", "", -1 }, /* Missing argument */
14953  { "00000000@test,badparam", "", -1 }, /* Wrong argument */
14954  { "00000000@test", "", -1 }, /* Missing argument */
14955  { "00000000@test,exists", "1", 0 },
14956  { "11111111@test,exists", "0", 0 }, /* Invalid mailbox */
14957  { "00000000@test,email", "[email protected]", 0 },
14958  { "11111111@test,email", "", 0 }, /* Invalid mailbox */
14959  { "00000000@test,fullname", "Test Framework Mailbox", 0 },
14960  { "00000000@test,pager", "[email protected]", 0 },
14961  { "00000000@test,locale", "en_US", 0 },
14962  { "00000000@test,tz", "central", 0 },
14963  { "00000000@test,language", "en", 0 },
14964  { "00000000@test,password", "9876", 0 },
14965  };
14966 
14967  switch (cmd) {
14968  case TEST_INIT:
14969  info->name = "test_voicemail_vm_info";
14970  info->category = "/apps/app_voicemail/";
14971  info->summary = "VM_INFO unit test";
14972  info->description =
14973  "This tests passing various parameters to VM_INFO";
14974  return AST_TEST_NOT_RUN;
14975  case TEST_EXECUTE:
14976  break;
14977  }
14978 
14979  if (!(chan = ast_dummy_channel_alloc())) {
14980  ast_test_status_update(test, "Unable to create dummy channel\n");
14981  return AST_TEST_FAIL;
14982  }
14983 
14984  if (!(vmu = find_user(NULL, testcontext, testmailbox)) &&
14985  !(vmu = find_or_create(testcontext, testmailbox))) {
14986  ast_test_status_update(test, "Cannot create vmu structure\n");
14987  chan = ast_channel_unref(chan);
14988  return AST_TEST_FAIL;
14989  }
14990 
14991  populate_defaults(vmu);
14992 
14994  ast_copy_string(vmu->fullname, "Test Framework Mailbox", sizeof(vmu->fullname));
14995  ast_copy_string(vmu->pager, "[email protected]", sizeof(vmu->pager));
14996  ast_copy_string(vmu->language, "en", sizeof(vmu->language));
14997  ast_copy_string(vmu->zonetag, "central", sizeof(vmu->zonetag));
14998  ast_copy_string(vmu->locale, "en_US", sizeof(vmu->zonetag));
14999  ast_copy_string(vmu->password, "9876", sizeof(vmu->password));
15000 
15001  for (test_counter = 0; test_counter < ARRAY_LEN(test_items); test_counter++) {
15002  ast_copy_string(vminfo_args, test_items[test_counter].vminfo_test_args, sizeof(vminfo_args));
15003  test_ret = acf_vm_info(chan, vminfo_cmd, vminfo_args, vminfo_buf, sizeof(vminfo_buf));
15004  if (strcmp(vminfo_buf, test_items[test_counter].vminfo_expected)) {
15005  ast_test_status_update(test, "VM_INFO respose was: '%s', but expected: '%s'\n", vminfo_buf, test_items[test_counter].vminfo_expected);
15006  res = AST_TEST_FAIL;
15007  }
15008  if (!(test_ret == test_items[test_counter].vminfo_ret)) {
15009  ast_test_status_update(test, "VM_INFO return code was: '%i', but expected '%i'\n", test_ret, test_items[test_counter].vminfo_ret);
15010  res = AST_TEST_FAIL;
15011  }
15012  }
15013 
15014  chan = ast_channel_unref(chan);
15015  free_user(vmu);
15016  return res;
15017 }
Main Channel structure associated with a channel.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
char pager[80]
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
char password[80]
#define NULL
Definition: resample.c:96
char locale[20]
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
char zonetag[80]
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
static void free_user(struct ast_vm_user *vmu)
def info(msg)
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.
char language[MAX_LANGUAGE]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static struct ast_vm_user * find_or_create(const char *context, const char *box)
char fullname[80]
static int acf_vm_info(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ base_encode()

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

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

Referenced by add_email_attachment().

4836 {
4837  static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
4838  'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
4839  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
4840  '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
4841  int i, hiteof = 0;
4842  FILE *fi;
4843  struct baseio bio;
4844 
4845  memset(&bio, 0, sizeof(bio));
4846  bio.iocp = BASEMAXINLINE;
4847 
4848  if (!(fi = fopen(filename, "rb"))) {
4849  ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
4850  return -1;
4851  }
4852 
4853  while (!hiteof){
4854  unsigned char igroup[3], ogroup[4];
4855  int c, n;
4856 
4857  memset(igroup, 0, sizeof(igroup));
4858 
4859  for (n = 0; n < 3; n++) {
4860  if ((c = inchar(&bio, fi)) == EOF) {
4861  hiteof = 1;
4862  break;
4863  }
4864 
4865  igroup[n] = (unsigned char) c;
4866  }
4867 
4868  if (n > 0) {
4869  ogroup[0]= dtable[igroup[0] >> 2];
4870  ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
4871  ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
4872  ogroup[3]= dtable[igroup[2] & 0x3F];
4873 
4874  if (n < 3) {
4875  ogroup[3] = '=';
4876 
4877  if (n < 2)
4878  ogroup[2] = '=';
4879  }
4880 
4881  for (i = 0; i < 4; i++)
4882  ochar(&bio, ogroup[i], so);
4883  }
4884  }
4885 
4886  fclose(fi);
4887 
4888  if (fputs(ENDL, so) == EOF) {
4889  return 0;
4890  }
4891 
4892  return 1;
4893 }
#define AST_LOG_WARNING
Definition: logger.h:279
static struct test_val c
#define ast_log
Definition: astobj2.c:42
#define ENDL
int errno
static int ochar(struct baseio *bio, int c, FILE *so)
utility used by base_encode()
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
#define BASEMAXINLINE

◆ change_password_realtime()

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

1486 {
1487  int res = -1;
1488  if (!strcmp(vmu->password, password)) {
1489  /* No change (but an update would return 0 rows updated, so we opt out here) */
1490  return 0;
1491  }
1492 
1493  if (strlen(password) > 10) {
1494  ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
1495  }
1496  if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
1497  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
1498  ast_copy_string(vmu->password, password, sizeof(vmu->password));
1499  res = 0;
1500  }
1501  return res;
1502 }
char password[80]
static struct ast_str * password
Definition: cdr_mysql.c:77
char context[MAX_VM_CONTEXT_LEN]
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3525
#define SENTINEL
Definition: compiler.h:87
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: main/config.c:3382
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ check_mime()

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

References str.

Referenced by make_email_file(), and sendpage().

5003 {
5004  for (; *str; str++) {
5005  if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
5006  return 1;
5007  }
5008  }
5009  return 0;
5010 }
const char * str
Definition: app_jack.c:147

◆ check_password()

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

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

Referenced by vm_newuser_setup(), and vm_options().

1445 {
1446  /* check minimum length */
1447  if (strlen(password) < minpassword)
1448  return 1;
1449  /* check that password does not contain '*' character */
1450  if (!ast_strlen_zero(password) && password[0] == '*')
1451  return 1;
1453  char cmd[255], buf[255];
1454 
1455  ast_debug(1, "Verify password policies for %s\n", password);
1456 
1457  snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
1458  if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
1459  ast_debug(5, "Result: %s\n", buf);
1460  if (!strncasecmp(buf, "VALID", 5)) {
1461  ast_debug(3, "Passed password check: '%s'\n", buf);
1462  return 0;
1463  } else if (!strncasecmp(buf, "FAILURE", 7)) {
1464  ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
1465  return 0;
1466  } else {
1467  ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
1468  return 1;
1469  }
1470  }
1471  }
1472  return 0;
1473 }
static char * vm_check_password_shell(char *command, char *buf, size_t len)
static int minpassword
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_LOG_WARNING
Definition: logger.h:279
char password[80]
static struct ast_str * password
Definition: cdr_mysql.c:77
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_LOG_NOTICE
Definition: logger.h:268
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static char ext_pass_check_cmd[128]
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ close_mailbox()

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

Definition at line 9152 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, done, ERROR_LOCK_PATH, ERROR_MAX_MSGS, EXISTS, vm_state::fn, vm_state::heard, last_message_index(), vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, NULL, PATH_MAX, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

Referenced by play_message_by_id(), vm_allocate_dh(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

9153 {
9154  int x = 0;
9155  int last_msg_idx = 0;
9156 
9157 #ifndef IMAP_STORAGE
9158  int res = 0, nummsg;
9159  char fn2[PATH_MAX];
9160 #endif
9161 
9162  if (vms->lastmsg <= -1) {
9163  goto done;
9164  }
9165 
9166  vms->curmsg = -1;
9167 #ifndef IMAP_STORAGE
9168  /* Get the deleted messages fixed */
9169  if (vm_lock_path(vms->curdir)) {
9170  return ERROR_LOCK_PATH;
9171  }
9172 
9173  /* update count as message may have arrived while we've got mailbox open */
9174  last_msg_idx = last_message_index(vmu, vms->curdir);
9175  if (last_msg_idx != vms->lastmsg) {
9176  ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
9177  }
9178 
9179  /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
9180  for (x = 0; x < last_msg_idx + 1; x++) {
9181  if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
9182  /* Save this message. It's not in INBOX or hasn't been heard */
9183  make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
9184  if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
9185  break;
9186  }
9187  vms->curmsg++;
9188  make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
9189  if (strcmp(vms->fn, fn2)) {
9190  RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
9191  }
9192  } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
9193  /* Move to old folder before deleting */
9194  res = save_to_folder(vmu, vms, x, 1, NULL, 0);
9195  if (res == ERROR_LOCK_PATH || res == ERROR_MAX_MSGS) {
9196  /* If save failed do not delete the message */
9197  ast_log(AST_LOG_WARNING, "Save failed. Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
9198  vms->deleted[x] = 0;
9199  vms->heard[x] = 0;
9200  --x;
9201  }
9202  } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
9203  /* Move to deleted folder */
9204  res = save_to_folder(vmu, vms, x, 10, NULL, 0);
9205  if (res == ERROR_LOCK_PATH) {
9206  /* If save failed do not delete the message */
9207  vms->deleted[x] = 0;
9208  vms->heard[x] = 0;
9209  --x;
9210  }
9211  } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
9212  /* If realtime storage enabled - we should explicitly delete this message,
9213  cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
9214  make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
9215  if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
9216  DELETE(vms->curdir, x, vms->fn, vmu);
9217  }
9218  }
9219  }
9220 
9221  /* Delete ALL remaining messages */
9222  nummsg = x - 1;
9223  for (x = vms->curmsg + 1; x <= nummsg; x++) {
9224  make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
9225  if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
9226  DELETE(vms->curdir, x, vms->fn, vmu);
9227  }
9228  }
9229  ast_unlock_path(vms->curdir);
9230 #else /* defined(IMAP_STORAGE) */
9231  ast_mutex_lock(&vms->lock);
9232  if (vms->deleted) {
9233  /* Since we now expunge after each delete, deleting in reverse order
9234  * ensures that no reordering occurs between each step. */
9235  last_msg_idx = vms->dh_arraysize;
9236  for (x = last_msg_idx - 1; x >= 0; x--) {
9237  if (vms->deleted[x]) {
9238  ast_debug(3, "IMAP delete of %d\n", x);
9239  DELETE(vms->curdir, x, vms->fn, vmu);
9240  }
9241  }
9242  }
9243 #endif
9244 
9245 done:
9246  if (vms->deleted) {
9247  ast_free(vms->deleted);
9248  vms->deleted = NULL;
9249  }
9250  if (vms->heard) {
9251  ast_free(vms->heard);
9252  vms->heard = NULL;
9253  }
9254  vms->dh_arraysize = 0;
9255 #ifdef IMAP_STORAGE
9256  ast_mutex_unlock(&vms->lock);
9257 #endif
9258 
9259  return 0;
9260 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
int * deleted
#define ERROR_LOCK_PATH
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
#define AST_LOG_WARNING
Definition: logger.h:279
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:187
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
char fn[PATH_MAX]
char curbox[80]
char context[MAX_VM_CONTEXT_LEN]
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...
int done
Definition: test_amihooks.c:48
#define AST_LOG_NOTICE
Definition: logger.h:268
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int * heard
#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. ...
#define RENAME(a, b, c, d, e, f, g, h)
#define ast_free(a)
Definition: astmm.h:182
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
#define ERROR_MAX_MSGS
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)
#define PATH_MAX
Definition: asterisk.h:40
char mailbox[MAX_VM_MBOX_ID_LEN]
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ complete_voicemail_show_users()

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

Definition at line 12845 of file app_voicemail.c.

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

Referenced by handle_voicemail_show_users().

12846 {
12847  int which = 0;
12848  int wordlen;
12849  struct ast_vm_user *vmu;
12850  const char *context = "";
12851 
12852  /* 0 - voicemail; 1 - show; 2 - users; 3 - for; 4 - <context> */
12853  if (pos > 4)
12854  return NULL;
12855  wordlen = strlen(word);
12856  AST_LIST_TRAVERSE(&users, vmu, list) {
12857  if (!strncasecmp(word, vmu->context, wordlen)) {
12858  if (context && strcmp(context, vmu->context) && ++which > state)
12859  return ast_strdup(vmu->context);
12860  /* ignore repeated contexts ? */
12861  context = vmu->context;
12862  }
12863  }
12864  return NULL;
12865 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
list of users found in the config file
char context[MAX_VM_CONTEXT_LEN]
struct ast_vm_user::@82 list
#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:116
short word

◆ copy()

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

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

Referenced by __bt_ret(), ast_ari_asterisk_update_object(), ast_bucket_file_copy(), ast_dns_test_write_domain(), ast_func_read(), ast_func_read2(), ast_func_write(), ast_sip_for_each_aor(), ast_sip_sanitize_xml(), ast_sip_session_add_supplements(), ast_sorcery_copy(), ast_sorcery_object_set_copy_handler(), AST_TEST_DEFINE(), authenticate_api_key(), check_nonce(), config_hook_exec(), copy_plain_file(), crypto_get_attrib(), handle_updates(), iax2_register(), module_load_error(), parse_hint_device(), parse_hint_presence(), play_message(), process_dahdi(), reload_followme(), vm_allocate_dh(), and vm_forwardoptions().

4630 {
4631  int ifd;
4632  int ofd;
4633  int res = -1;
4634  int len;
4635  char buf[4096];
4636 
4637 #ifdef HARDLINK_WHEN_POSSIBLE
4638  /* Hard link if possible; saves disk space & is faster */
4639  if (!link(infile, outfile)) {
4640  return 0;
4641  }
4642 #endif
4643 
4644  if ((ifd = open(infile, O_RDONLY)) < 0) {
4645  ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
4646  return -1;
4647  }
4648 
4649  if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
4650  ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
4651  close(ifd);
4652  return -1;
4653  }
4654 
4655  for (;;) {
4656  int wrlen;
4657 
4658  len = read(ifd, buf, sizeof(buf));
4659  if (!len) {
4660  res = 0;
4661  break;
4662  }
4663 
4664  if (len < 0) {
4665  ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
4666  break;
4667  }
4668 
4669  wrlen = write(ofd, buf, len);
4670  if (errno == ENOMEM || errno == ENOSPC || wrlen != len) {
4671  ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, wrlen, len, strerror(errno));
4672  break;
4673  }
4674  }
4675 
4676  close(ifd);
4677  close(ofd);
4678  if (res) {
4679  unlink(outfile);
4680  }
4681 
4682  return res;
4683 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_LOG_WARNING
Definition: logger.h:279
#define ast_log
Definition: astobj2.c:42
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
#define VOICEMAIL_FILE_MODE

◆ copy_message()

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,
const char *  dest_folder 
)
static

Copies a message from one mailbox to another.

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

Definition at line 5982 of file app_voicemail.c.

References ast_channel_caller(), ast_channel_language(), ast_copy_string(), ast_log, AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero, ast_unlock_path(), ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), mbox(), ast_party_id::name, notify_new_message(), NULL, ast_party_id::number, PATH_MAX, 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(), leave_voicemail(), vm_allocate_dh(), and vm_msg_forward().

5983 {
5984  char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
5985  const char *frombox = mbox(vmu, imbox);
5986  const char *userfolder;
5987  int recipmsgnum;
5988  int res = 0;
5989 
5990  ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
5991 
5992  if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
5993  userfolder = "Urgent";
5994  } else if (!ast_strlen_zero(dest_folder)) {
5995  userfolder = dest_folder;
5996  } else {
5997  userfolder = "INBOX";
5998  }
5999 
6000  create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
6001 
6002  if (!dir)
6003  make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
6004  else
6005  ast_copy_string(fromdir, dir, sizeof(fromdir));
6006 
6007  make_file(frompath, sizeof(frompath), fromdir, msgnum);
6008  make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
6009 
6010  if (vm_lock_path(todir))
6011  return ERROR_LOCK_PATH;
6012 
6013  recipmsgnum = last_message_index(recip, todir) + 1;
6014  if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
6015  make_file(topath, sizeof(topath), todir, recipmsgnum);
6016 #ifndef ODBC_STORAGE
6017  if (EXISTS(fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : "")) {
6018  COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
6019  } else {
6020 #endif
6021  /* If we are prepending a message for ODBC, then the message already
6022  * exists in the database, but we want to force copying from the
6023  * filesystem (since only the FS contains the prepend). */
6024  copy_plain_file(frompath, topath);
6025  STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL);
6026  vm_delete(topath);
6027 #ifndef ODBC_STORAGE
6028  }
6029 #endif
6030  } else {
6031  ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
6032  res = -1;
6033  }
6034  ast_unlock_path(todir);
6035  if (chan) {
6036  struct ast_party_caller *caller = ast_channel_caller(chan);
6037  notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
6038  S_COR(caller->id.number.valid, caller->id.number.str, NULL),
6039  S_COR(caller->id.name.valid, caller->id.name.str, NULL),
6040  flag);
6041  }
6042 
6043  return res;
6044 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
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:341
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.
char * str
Subscriber name (Malloced)
Definition: channel.h:265
static int inprocess_count(const char *context, const char *mailbox, int delta)
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:421
#define AST_LOG_NOTICE
Definition: logger.h:268
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
Caller Party information.
Definition: channel.h:419
#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:85
#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.
long int flag
Definition: f2c.h:83
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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)
const char * ast_channel_language(const struct ast_channel *chan)
#define PATH_MAX
Definition: asterisk.h:40
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
static int maxmsg
char mailbox[MAX_VM_MBOX_ID_LEN]
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ copy_plain_file()

static void copy_plain_file ( char *  frompath,
char *  topath 
)
static

Copies a voicemail information (envelope) file.

Parameters
frompath
topathEvery 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 4694 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, NULL, PATH_MAX, priority, SENTINEL, tmp(), ast_variable::value, and var.

Referenced by copy_message().

4695 {
4696  char frompath2[PATH_MAX], topath2[PATH_MAX];
4697  struct ast_variable *tmp, *var = NULL;
4698  const char *origmailbox = "", *context = "", *macrocontext = "", *exten = "";
4699  const char *priority = "", *callerchan = "", *callerid = "", *origdate = "";
4700  const char *origtime = "", *category = "", *duration = "";
4701 
4702  ast_filecopy(frompath, topath, NULL);
4703  snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
4704  snprintf(topath2, sizeof(topath2), "%s.txt", topath);
4705 
4706  if (ast_check_realtime("voicemail_data")) {
4707  var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
4708  /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
4709  for (tmp = var; tmp; tmp = tmp->next) {
4710  if (!strcasecmp(tmp->name, "origmailbox")) {
4711  origmailbox = tmp->value;
4712  } else if (!strcasecmp(tmp->name, "context")) {
4713  context = tmp->value;
4714  } else if (!strcasecmp(tmp->name, "macrocontext")) {
4715  macrocontext = tmp->value;
4716  } else if (!strcasecmp(tmp->name, "exten")) {
4717  exten = tmp->value;
4718  } else if (!strcasecmp(tmp->name, "priority")) {
4719  priority = tmp->value;
4720  } else if (!strcasecmp(tmp->name, "callerchan")) {
4721  callerchan = tmp->value;
4722  } else if (!strcasecmp(tmp->name, "callerid")) {
4723  callerid = tmp->value;
4724  } else if (!strcasecmp(tmp->name, "origdate")) {
4725  origdate = tmp->value;
4726  } else if (!strcasecmp(tmp->name, "origtime")) {
4727  origtime = tmp->value;
4728  } else if (!strcasecmp(tmp->name, "category")) {
4729  category = tmp->value;
4730  } else if (!strcasecmp(tmp->name, "duration")) {
4731  duration = tmp->value;
4732  }
4733  }
4734  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);
4735  }
4736  copy(frompath2, topath2);
4737  ast_variables_destroy(var);
4738 }
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:1108
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3339
struct ast_variable * next
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
static int tmp()
Definition: bt_open.c:389
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define NULL
Definition: resample.c:96
static int priority
#define SENTINEL
Definition: compiler.h:87
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
Definition: main/config.c:3570
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ count_messages()

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

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

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

4525 {
4526 
4527  int vmcount = 0;
4528  DIR *vmdir = NULL;
4529  struct dirent *vment = NULL;
4530 
4531  if (vm_lock_path(dir))
4532  return ERROR_LOCK_PATH;
4533 
4534  if ((vmdir = opendir(dir))) {
4535  while ((vment = readdir(vmdir))) {
4536  if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
4537  vmcount++;
4538  }
4539  }
4540  closedir(vmdir);
4541  }
4542  ast_unlock_path(dir);
4543 
4544  return vmcount;
4545 }
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
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...

◆ create_dirpath()

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

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

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

1949 {
1950  mode_t mode = VOICEMAIL_DIR_MODE;
1951  int res;
1952 
1953  make_dir(dest, len, context, ext, folder);
1954  if ((res = ast_mkdir(dest, mode))) {
1955  ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
1956  return -1;
1957  }
1958  return 0;
1959 }
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:279
const char * ext
Definition: http.c:147
#define ast_log
Definition: astobj2.c:42
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define VOICEMAIL_DIR_MODE
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2231

◆ dialout()

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

Definition at line 15233 of file app_voicemail.c.

References ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_priority_set(), ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero, ast_test_suite_event_notify, ast_verb, and ast_waitfordigit().

Referenced by advanced_options(), and vm_execmain().

15234 {
15235  int cmd = 0;
15236  char destination[80] = "";
15237  int retries = 0;
15238 
15239  if (!num) {
15240  ast_verb(3, "Destination number will be entered manually\n");
15241  while (retries < 3 && cmd != 't') {
15242  destination[1] = '\0';
15243  destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
15244  if (!cmd)
15245  destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
15246  if (!cmd)
15247  destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
15248  if (!cmd) {
15249  cmd = ast_waitfordigit(chan, 6000);
15250  if (cmd)
15251  destination[0] = cmd;
15252  }
15253  if (!cmd) {
15254  retries++;
15255  } else {
15256 
15257  if (cmd < 0)
15258  return 0;
15259  if (cmd == '*') {
15260  ast_verb(3, "User hit '*' to cancel outgoing call\n");
15261  return 0;
15262  }
15263  if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0)
15264  retries++;
15265  else
15266  cmd = 't';
15267  }
15268  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
15269  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
15270  }
15271  if (retries >= 3) {
15272  return 0;
15273  }
15274 
15275  } else {
15276  ast_verb(3, "Destination number is CID number '%s'\n", num);
15277  ast_copy_string(destination, num, sizeof(destination));
15278  }
15279 
15280  if (!ast_strlen_zero(destination)) {
15281  if (destination[strlen(destination) -1 ] == '*')
15282  return 0;
15283  ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, ast_channel_context(chan));
15284  ast_channel_exten_set(chan, destination);
15285  ast_channel_context_set(chan, outgoing_context);
15286  ast_channel_priority_set(chan, 0);
15287  return 9;
15288  }
15289  return 0;
15290 }
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
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: main/app.c:1470
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_context(const struct ast_channel *chan)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6655
void ast_channel_priority_set(struct ast_channel *chan, int value)

◆ fake_read()

static struct ast_frame* fake_read ( struct ast_channel ast)
static

Definition at line 14475 of file app_voicemail.c.

References ast_null_frame.

Referenced by AST_TEST_DEFINE().

14476 {
14477  return &ast_null_frame;
14478 }
struct ast_frame ast_null_frame
Definition: main/frame.c:79

◆ fake_write()

static int fake_write ( struct ast_channel ast,
struct ast_frame frame 
)
static

Definition at line 14470 of file app_voicemail.c.

Referenced by AST_TEST_DEFINE().

14471 {
14472  return 0;
14473 }

◆ find_or_create()

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

Definition at line 12385 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, ast_vm_user::list, LOG_WARNING, ast_vm_user::mailbox, NULL, and VM_SEARCH.

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

12386 {
12387  struct ast_vm_user *vmu;
12388 
12389  if (!ast_strlen_zero(box) && box[0] == '*') {
12390  ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character. The '*' character,"
12391  "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
12392  "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
12393  "\n\tand will be ignored.\n", box, context);
12394  return NULL;
12395  }
12396 
12397  AST_LIST_TRAVERSE(&users, vmu, list) {
12398  if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
12399  if (strcasecmp(vmu->context, context)) {
12400  ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
12401  \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
12402  \n\tconfiguration creates an ambiguity that you likely do not want. Please\
12403  \n\tamend your voicemail.conf file to avoid this situation.\n", box);
12404  }
12405  ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
12406  return NULL;
12407  }
12408  if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
12409  ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
12410  return NULL;
12411  }
12412  }
12413 
12414  if (!(vmu = ast_calloc(1, sizeof(*vmu))))
12415  return NULL;
12416 
12417  ast_copy_string(vmu->context, context, sizeof(vmu->context));
12418  ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
12419 
12421 
12422  return vmu;
12423 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
list of users found in the config file
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_vm_user::@82 list
#define VM_SEARCH
#define ast_log
Definition: astobj2.c:42
static struct ast_flags globalflags
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ find_user()

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

References ao2_find, ao2_ref, ast_alloca, ast_calloc, ast_free, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set2_flag, ast_strdup, ast_strdupa, ast_strlen_zero, ast_test_flag, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, find_user_realtime(), ast_vm_user::list, alias_mailbox_mapping::mailbox, MAX_VM_MAILBOX_LEN, NULL, OBJ_SEARCH_KEY, S_OR, separate_mailbox(), VM_ALLOCED, and VM_SEARCH.

Referenced by acf_vm_info(), advanced_options(), AST_TEST_DEFINE(), forward_message(), leave_voicemail(), manager_status_voicemail_user(), mb_poll_thread(), msg_create_from_file(), play_message_by_id(), vm_allocate_dh(), vm_authenticate(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

1659 {
1660  /* This function could be made to generate one from a database, too */
1661  struct ast_vm_user *vmu = NULL, *cur;
1662  AST_LIST_LOCK(&users);
1663 
1665  context = "default";
1666 
1667  AST_LIST_TRAVERSE(&users, cur, list) {
1668 #ifdef IMAP_STORAGE
1669  if (cur->imapversion != imapversion) {
1670  continue;
1671  }
1672 #endif
1673  if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
1674  break;
1675  if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1676  break;
1677  }
1678  if (cur) {
1679  /* Make a copy, so that on a reload, we have no race */
1680  if ((vmu = (ivm ? ivm : ast_calloc(1, sizeof(*vmu))))) {
1681  ast_free(vmu->email);
1682  ast_free(vmu->emailbody);
1683  ast_free(vmu->emailsubject);
1684  *vmu = *cur;
1685  vmu->email = ast_strdup(cur->email);
1686  vmu->emailbody = ast_strdup(cur->emailbody);
1687  vmu->emailsubject = ast_strdup(cur->emailsubject);
1688  ast_set2_flag(vmu, !ivm, VM_ALLOCED);
1689  AST_LIST_NEXT(vmu, list) = NULL;
1690  }
1691  }
1693  if (!vmu) {
1694  vmu = find_user_realtime(ivm, context, mailbox);
1695  }
1696  if (!vmu && !ast_strlen_zero(aliasescontext)) {
1697  struct alias_mailbox_mapping *mapping;
1698  char *search_string = ast_alloca(MAX_VM_MAILBOX_LEN);
1699 
1700  snprintf(search_string, MAX_VM_MAILBOX_LEN, "%s%s%s",
1701  mailbox,
1702  ast_strlen_zero(context) ? "" : "@",
1703  S_OR(context, ""));
1704 
1705  mapping = ao2_find(alias_mailbox_mappings, search_string, OBJ_SEARCH_KEY);
1706  if (mapping) {
1707  char *search_mailbox = NULL;
1708  char *search_context = NULL;
1709 
1710  separate_mailbox(ast_strdupa(mapping->mailbox), &search_mailbox, &search_context);
1711  ao2_ref(mapping, -1);
1712  vmu = find_user(ivm, search_mailbox, search_context);
1713  }
1714  }
1715 
1716  return vmu;
1717 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#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
static struct ao2_container * alias_mailbox_mappings
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
static char aliasescontext[MAX_VM_CONTEXT_LEN]
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
list of users found in the config file
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_vm_user::@82 list
#define VM_SEARCH
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static struct ast_flags globalflags
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
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
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.
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char * emailsubject
#define VM_ALLOCED
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define MAX_VM_MAILBOX_LEN

◆ find_user_realtime()

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

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

Referenced by find_user().

1618 {
1619  struct ast_variable *var;
1620  struct ast_vm_user *retval;
1621 
1622  if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
1623  if (ivm) {
1624  memset(retval, 0, sizeof(*retval));
1625  }
1626  populate_defaults(retval);
1627  if (!ivm) {
1628  ast_set_flag(retval, VM_ALLOCED);
1629  }
1630  if (mailbox) {
1631  ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
1632  }
1633  if (!context && ast_test_flag((&globalflags), VM_SEARCH)) {
1634  var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
1635  } else {
1636  var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
1637  }
1638  if (var) {
1639  apply_options_full(retval, var);
1640  ast_variables_destroy(var);
1641  } else {
1642  if (!ivm)
1643  ast_free(retval);
1644  retval = NULL;
1645  }
1646  }
1647  return retval;
1648 }
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3339
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
#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.
#define var
Definition: ast_expr2f.c:614
#define NULL
Definition: resample.c:96
#define VM_SEARCH
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define SENTINEL
Definition: compiler.h:87
static struct ast_flags globalflags
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static ENTRY retval
Definition: hsearch.c:50
#define VM_ALLOCED
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ forward_message()

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 mailbox, and then invoke leave_message() function to record and store the message.

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

  • retrieves 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 8269 of file app_voicemail.c.

References ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_language(), ast_channel_priority(), ast_channel_priority_set(), ast_clear_flag, ast_config_destroy(), ast_config_load, 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_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero, ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), ast_waitfordigit(), leave_vm_options::beeptone, CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, done, find_user(), vm_state::fn, free_user(), inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, name, NULL, PATH_MAX, pbx_exec(), pbx_findapp(), leave_vm_options::record_gain, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), serveremail, STORE, strsep(), vm_state::username, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), and VM_FWDURGAUTO.

Referenced by vm_execmain().

8270 {
8271 #ifdef IMAP_STORAGE
8272  int todircount = 0;
8273  struct vm_state *dstvms;
8274 #endif
8275  char username[70]="";
8276  char fn[PATH_MAX]; /* for playback of name greeting */
8277  char ecodes[16] = "#";
8278  int res = 0, cmd = 0;
8279  struct ast_vm_user *receiver = NULL, *vmtmp;
8281  char *stringp;
8282  const char *s;
8283  const char mailbox_context[256];
8284  int saved_messages = 0;
8285  int valid_extensions = 0;
8286  char *dir;
8287  int curmsg;
8288  char urgent_str[7] = "";
8289  int prompt_played = 0;
8290 #ifndef IMAP_STORAGE
8291  char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
8292 #endif
8294  ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
8295  }
8296 
8297  if (vms == NULL) return -1;
8298  dir = vms->curdir;
8299  curmsg = vms->curmsg;
8300 
8301  ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
8302  while (!res && !valid_extensions) {
8303  int use_directory = 0;
8305  int done = 0;
8306  int retries = 0;
8307  cmd = 0;
8308  while ((cmd >= 0) && !done ){
8309  if (cmd)
8310  retries = 0;
8311  switch (cmd) {
8312  case '1':
8313  use_directory = 0;
8314  done = 1;
8315  break;
8316  case '2':
8317  use_directory = 1;
8318  done = 1;
8319  break;
8320  case '*':
8321  cmd = 't';
8322  done = 1;
8323  break;
8324  default:
8325  /* Press 1 to enter an extension press 2 to use the directory */
8326  cmd = ast_play_and_wait(chan, "vm-forward");
8327  if (!cmd) {
8328  cmd = ast_waitfordigit(chan, 3000);
8329  }
8330  if (!cmd) {
8331  retries++;
8332  }
8333  if (retries > 3) {
8334  cmd = 't';
8335  done = 1;
8336  }
8337  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
8338  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
8339  }
8340  }
8341  if (cmd < 0 || cmd == 't')
8342  break;
8343  }
8344 
8345  if (use_directory) {
8346  /* use app_directory */
8347 
8348  struct ast_app* directory_app;
8349 
8350  directory_app = pbx_findapp("Directory");
8351  if (directory_app) {
8352  char vmcontext[256];
8353  char old_context[strlen(ast_channel_context(chan)) + 1];
8354  char old_exten[strlen(ast_channel_exten(chan)) + 1];
8355  int old_priority;
8356  /* make backup copies */
8357  strcpy(old_context, ast_channel_context(chan)); /* safe */
8358  strcpy(old_exten, ast_channel_exten(chan)); /* safe */
8359  old_priority = ast_channel_priority(chan);
8360 
8361  /* call the Directory, changes the channel */
8362  snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
8363  res = pbx_exec(chan, directory_app, vmcontext);
8364 
8365  ast_copy_string(username, ast_channel_exten(chan), sizeof(username));
8366 
8367  /* restore the old context, exten, and priority */
8368  ast_channel_context_set(chan, old_context);
8369  ast_channel_exten_set(chan, old_exten);
8370  ast_channel_priority_set(chan, old_priority);
8371  } else {
8372  ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
8374  }
8375  } else {
8376  /* Ask for an extension */
8377  res = ast_streamfile(chan, "vm-extension", ast_channel_language(chan)); /* "extension" */
8378  prompt_played++;
8379  if (res || prompt_played > 4)
8380  break;
8381  if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#")) < 0)
8382  break;
8383  }
8384 
8385  /* start all over if no username */
8386  if (ast_strlen_zero(username))
8387  continue;
8388  stringp = username;
8389  s = strsep(&stringp, "*");
8390  /* start optimistic */
8391  valid_extensions = 1;
8392  while (s) {
8393  snprintf((char*)mailbox_context, sizeof(mailbox_context), "%s@%s", s, context ? context : "default");
8394  if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
8395  int oldmsgs;
8396  int newmsgs;
8397  int capacity;
8398 
8399  if (inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
8400  ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
8401  /* Shouldn't happen, but allow trying another extension if it does */
8402  res = ast_play_and_wait(chan, "pbx-invalid");
8403  valid_extensions = 0;
8404  break;
8405  }
8406 #ifdef IMAP_STORAGE
8407  if (!(dstvms = get_vm_state_by_mailbox(s, context, 0))) {
8408  if (!(dstvms = create_vm_state_from_user(receiver))) {
8409  ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
8410  /* Shouldn't happen, but allow trying another extension if it does */
8411  res = ast_play_and_wait(chan, "pbx-invalid");
8412  valid_extensions = 0;
8413  break;
8414  }
8415  }
8416  check_quota(dstvms, imapfolder);
8417  if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
8418  ast_log(LOG_NOTICE, "Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
8419  res = ast_play_and_wait(chan, "vm-mailboxfull");
8420  valid_extensions = 0;
8421  while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8422  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8423  free_user(vmtmp);
8424  }
8425  break;
8426  }
8427 #endif
8428  capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
8429  if ((newmsgs + oldmsgs) >= capacity) {
8430  ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
8431  res = ast_play_and_wait(chan, "vm-mailboxfull");
8432  valid_extensions = 0;
8433  while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8434  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8435  free_user(vmtmp);
8436  }
8437  inprocess_count(receiver->mailbox, receiver->context, -1);
8438  break;
8439  }
8440  AST_LIST_INSERT_HEAD(&extensions, receiver, list);
8441  } else {
8442  /* XXX Optimization for the future. When we encounter a single bad extension,
8443  * bailing out on all of the extensions may not be the way to go. We should
8444  * probably just bail on that single extension, then allow the user to enter
8445  * several more. XXX
8446  */
8447  while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8448  free_user(receiver);
8449  }
8450  ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", mailbox_context);
8451  /* "I am sorry, that's not a valid extension. Please try again." */
8452  res = ast_play_and_wait(chan, "pbx-invalid");
8453  valid_extensions = 0;
8454  break;
8455  }
8456 
8457  /* play name if available, else play extension number */
8458  snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
8459  RETRIEVE(fn, -1, s, receiver->context);
8460  if (ast_fileexists(fn, NULL, NULL) > 0) {
8461  res = ast_stream_and_wait(chan, fn, ecodes);
8462  if (res) {
8463  DISPOSE(fn, -1);
8464  return res;
8465  }
8466  } else {
8467  res = ast_say_digit_str(chan, s, ecodes, ast_channel_language(chan));
8468  }
8469  DISPOSE(fn, -1);
8470 
8471  s = strsep(&stringp, "*");
8472  }
8473  /* break from the loop of reading the extensions */
8474  if (valid_extensions)
8475  break;
8476  }
8477  /* check if we're clear to proceed */
8478  if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
8479  return res;
8480  if (is_new_message == 1) {
8481  struct leave_vm_options leave_options;
8482  char mailbox[AST_MAX_EXTENSION * 2 + 2];
8483  snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
8484 
8485  /* Send VoiceMail */
8486  memset(&leave_options, 0, sizeof(leave_options));
8487  leave_options.record_gain = record_gain;
8488  leave_options.beeptone = "beep";
8489  cmd = leave_voicemail(chan, mailbox, &leave_options);
8490  } else {
8491  /* Forward VoiceMail */
8492  long duration = 0;
8493  struct vm_state vmstmp;
8494  int copy_msg_result = 0;
8495 #ifdef IMAP_STORAGE
8496  char filename[PATH_MAX];
8497  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8498  const char *msg_id = NULL;
8499  struct ast_config *msg_cfg;
8500 #endif
8501  memcpy(&vmstmp, vms, sizeof(vmstmp));
8502 
8503  RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
8504 #ifdef IMAP_STORAGE
8505  make_file(filename, sizeof(filename), dir, curmsg);
8506  strncat(filename, ".txt", sizeof(filename) - strlen(filename) - 1);
8507  msg_cfg = ast_config_load(filename, config_flags);
8508  if (msg_cfg && msg_cfg == CONFIG_STATUS_FILEINVALID) {
8509  msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
8510  ast_config_destroy(msg_cfg);
8511  }
8512 #endif
8513 
8514  cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
8515  if (!cmd) {
8516  AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
8517 #ifdef IMAP_STORAGE
8518  int attach_user_voicemail;
8519  char *myserveremail = serveremail;
8520 
8521  /* get destination mailbox */
8522  dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
8523  if (!dstvms) {
8524  dstvms = create_vm_state_from_user(vmtmp);
8525  }
8526  if (dstvms) {
8527  init_mailstream(dstvms, 0);
8528  if (!dstvms->mailstream) {
8529  ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
8530  } else {
8531  copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
8532  run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str);
8533  }
8534  } else {
8535  ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
8536  }
8537  if (!ast_strlen_zero(vmtmp->serveremail))
8538  myserveremail = vmtmp->serveremail;
8539  attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
8540  /* NULL category for IMAP storage */
8541  sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
8542  dstvms->curbox,
8543  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
8544  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
8545  vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
8546  NULL, urgent_str, msg_id);
8547 #else
8548  copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL);
8549 #endif
8550  saved_messages++;
8552  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8553  free_user(vmtmp);
8554  if (res)
8555  break;
8556  }
8558  if (saved_messages > 0 && !copy_msg_result) {
8559  /* give confirmation that the message was saved */
8560  /* commented out since we can't forward batches yet
8561  if (saved_messages == 1)
8562  res = ast_play_and_wait(chan, "vm-message");
8563  else
8564  res = ast_play_and_wait(chan, "vm-messages");
8565  if (!res)
8566  res = ast_play_and_wait(chan, "vm-saved"); */
8567  res = ast_play_and_wait(chan, "vm-msgforwarded");
8568  }
8569 #ifndef IMAP_STORAGE
8570  else {
8571  /* with IMAP, mailbox full warning played by imap_check_limits */
8572  res = ast_play_and_wait(chan, "vm-mailboxfull");
8573  }
8574  /* Restore original message without prepended message if backup exists */
8575  make_file(msgfile, sizeof(msgfile), dir, curmsg);
8576  strcpy(textfile, msgfile);
8577  strcpy(backup, msgfile);
8578  strcpy(backup_textfile, msgfile);
8579  strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
8580  strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
8581  strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8582  if (ast_fileexists(backup, NULL, NULL) > 0) {
8583  ast_filerename(backup, msgfile, NULL);
8584  rename(backup_textfile, textfile);
8585  }
8586 #endif
8587  }
8588  DISPOSE(dir, curmsg);
8589 #ifndef IMAP_STORAGE
8590  if (cmd) { /* assuming hangup, cleanup backup file */
8591  make_file(msgfile, sizeof(msgfile), dir, curmsg);
8592  strcpy(textfile, msgfile);
8593  strcpy(backup_textfile, msgfile);
8594  strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
8595  strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8596  rename(backup_textfile, textfile);
8597  }
8598 #endif
8599  }
8600 
8601  /* If anything failed above, we still have this list to free */
8602  while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8603  inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8604  free_user(vmtmp);
8605  }
8606  return res ? res : cmd;
8607 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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, const char *dest_folder)
Copies a message from one mailbox to another.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
char username[80]
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define CONFIG_STATUS_FILEINVALID
#define AST_LOG_WARNING
Definition: logger.h:279
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:8355
char curdir[PATH_MAX]
#define VM_ATTACH
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
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, const char *msg_id)
static int inprocess_count(const char *context, const char *mailbox, int delta)
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char fn[PATH_MAX]
char curbox[80]
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
int ast_channel_priority(const struct ast_channel *chan)
char context[MAX_VM_CONTEXT_LEN]
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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 done
Definition: test_amihooks.c:48
Number structure.
Definition: app_followme.c:154
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define AST_LOG_ERROR
Definition: logger.h:290
static struct ast_flags globalflags
#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:556
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: main/app.c:1470
#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:85
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static char VM_SPOOL_DIR[PATH_MAX]
static void free_user(struct ast_vm_user *vmu)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
static void run_externnotify(const char *context, const char *extension, const char *flag)
#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:285
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:263
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
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[]
Definition: cdr_mysql.c:74
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:1814
Structure used to handle boolean flags.
Definition: utils.h:199
#define ast_clear_flag(p, flag)
Definition: utils.h:77
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:650
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
signed char record_gain
Definition: app_minivm.c:652
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
char * strsep(char **str, const char *delims)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
ast_app: A registered application
Definition: pbx_app.c:45
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
const char * ast_channel_language(const struct ast_channel *chan)
#define VM_DIRECFORWARD
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
const char * ast_channel_context(const struct ast_channel *chan)
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
#define PATH_MAX
Definition: asterisk.h:40
#define VM_FWDURGAUTO
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6655
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
void ast_channel_priority_set(struct ast_channel *chan, int value)
static char vmfmts[80]
char mailbox[MAX_VM_MBOX_ID_LEN]
static char serveremail[80]

◆ free_user()

static void free_user ( struct ast_vm_user vmu)
static

Definition at line 1990 of file app_voicemail.c.

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

Referenced by acf_vm_info(), advanced_options(), AST_TEST_DEFINE(), forward_message(), free_user_final(), leave_voicemail(), manager_status_voicemail_user(), mb_poll_thread(), msg_create_from_file(), play_message_by_id(), vm_allocate_dh(), vm_authenticate(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

1991 {
1992  if (!vmu) {
1993  return;
1994  }
1995 
1996  ast_free(vmu->email);
1997  vmu->email = NULL;
1998  ast_free(vmu->emailbody);
1999  vmu->emailbody = NULL;
2000  ast_free(vmu->emailsubject);
2001  vmu->emailsubject = NULL;
2002 
2003  if (ast_test_flag(vmu, VM_ALLOCED)) {
2004  ast_free(vmu);
2005  }
2006 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define NULL
Definition: resample.c:96
char * emailbody
#define ast_free(a)
Definition: astmm.h:182
char * emailsubject
#define VM_ALLOCED

◆ free_user_final()

static void free_user_final ( struct ast_vm_user vmu)
static

Definition at line 2008 of file app_voicemail.c.

References ast_delete_mwi_state_full(), ast_strlen_zero, ast_vm_user::context, free_user(), ast_vm_user::mailbox, and NULL.

Referenced by free_vm_users().

2009 {
2010  if (!vmu) {
2011  return;
2012  }
2013 
2014  if (!ast_strlen_zero(vmu->mailbox)) {
2016  }
2017 
2018  free_user(vmu);
2019 }
int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)
Delete MWI state cached by stasis with all parameters.
Definition: mwi.c:399
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
static void free_user(struct ast_vm_user *vmu)
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ free_vm_users()

static void free_vm_users ( void  )
static

Free the users structure.

Definition at line 13470 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

13471 {
13472  struct ast_vm_user *current;
13473  AST_LIST_LOCK(&users);
13474  while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
13475  ast_set_flag(current, VM_ALLOCED);
13476  free_user_final(current);
13477  }
13479 }
#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::@82 list
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static void free_user_final(struct ast_vm_user *vmu)
#define VM_ALLOCED

◆ free_vm_zones()

static void free_vm_zones ( void  )
static

Free the zones structure.

Definition at line 13482 of file app_voicemail.c.

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

Referenced by actual_load_config(), and unload_module().

13483 {
13484  struct vm_zone *zcur;
13485  AST_LIST_LOCK(&zones);
13486  while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
13487  free_zone(zcur);
13489 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct vm_zone::@83 list
#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:832

◆ free_zone()

static void free_zone ( struct vm_zone z)
static

◆ generate_msg_id()

static void generate_msg_id ( char *  dst)
static

Sets the destination string to a uniquely identifying msg_id string.

Parameters
dstpointer to a character buffer that should contain MSG_ID_LEN characters.

Definition at line 6291 of file app_voicemail.c.

References ast_atomic_fetchadd_int(), MSG_ID_LEN, and NULL.

Referenced by add_message_id(), leave_voicemail(), and msg_create_from_file().

6292 {
6293  /* msg id is time of msg_id generation plus an incrementing value
6294  * called each time a new msg_id is generated. This should achieve uniqueness,
6295  * but only in single system solutions.
6296  */
6297  unsigned int unique_counter = ast_atomic_fetchadd_int(&msg_id_incrementor, +1);
6298  snprintf(dst, MSG_ID_LEN, "%ld-%08x", (long) time(NULL), unique_counter);
6299 }
#define MSG_ID_LEN
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static int msg_id_incrementor

◆ get_date()

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

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

Referenced by leave_voicemail(), and msg_create_from_file().

5727 {
5728  struct ast_tm tm;
5729  struct timeval t = ast_tvnow();
5730 
5731  ast_localtime(&t, &tm, "UTC");
5732 
5733  return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
5734 }
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:1739
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
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:2524

◆ get_folder()

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

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

Referenced by get_folder2().

7820 {
7821  int x;
7822  int d;
7823  char fn[PATH_MAX];
7824  d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
7825  if (d)
7826  return d;
7827  for (x = start; x < 5; x++) { /* For all folders */
7828  if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
7829  return d;
7830  d = ast_play_and_wait(chan, "vm-for"); /* "for" */
7831  if (d)
7832  return d;
7833  snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
7834 
7835  /* The inbox folder can have its name changed under certain conditions
7836  * so this checks if the sound file exists for the inbox folder name and
7837  * if it doesn't, plays the default name instead. */
7838  if (x == 0) {
7839  if (ast_fileexists(fn, NULL, NULL)) {
7840  d = vm_play_folder_name(chan, fn);
7841  } else {
7842  ast_verb(4, "Failed to find file %s; falling back to INBOX\n", fn);
7843  d = vm_play_folder_name(chan, "vm-INBOX");
7844  }
7845  } else {
7846  ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
7847  d = vm_play_folder_name(chan, fn);
7848  }
7849 
7850  if (d)
7851  return d;
7852  d = ast_waitfordigit(chan, 500);
7853  if (d)
7854  return d;
7855  }
7856 
7857  d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
7858  if (d)
7859  return d;
7860  d = ast_waitfordigit(chan, 4000);
7861  return d;
7862 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define AST_DIGIT_ANY
Definition: file.h:48
static struct test_val d
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
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: main/app.c:1470
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
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:8337
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
const char * ast_channel_language(const struct ast_channel *chan)
#define PATH_MAX
Definition: asterisk.h:40

◆ get_folder2()

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

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

Referenced by vm_execmain().

7905 {
7906  int res = 0;
7907  int loops = 0;
7908 
7909  res = ast_play_and_wait(chan, fn); /* Folder name */
7910  while (((res < '0') || (res > '9')) &&
7911  (res != '#') && (res >= 0) &&
7912  loops < 4) {
7913  /* res = get_folder(chan, 0); */
7914  if (!strcasecmp(ast_channel_language(chan), "ja")) { /* Japanese syntax */
7915  res = get_folder_ja(chan, 0);
7916  } else { /* Default syntax */
7917  res = get_folder(chan, 0);
7918  }
7919  loops++;
7920  }
7921  if (loops == 4) { /* give up */
7922  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
7923  return '#';
7924  }
7925  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
7926  isprint(res) ? res : '?', isprint(res) ? res : '?');
7927  return res;
7928 }
static int get_folder_ja(struct ast_channel *chan, int start)
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 ...
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: main/app.c:1470
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
const char * ast_channel_language(const struct ast_channel *chan)

◆ get_folder_by_name()

static int get_folder_by_name ( const char *  name)
static

Definition at line 1977 of file app_voicemail.c.

References ARRAY_LEN.

Referenced by play_message(), save_to_folder(), vm_allocate_dh(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

1978 {
1979  size_t i;
1980 
1981  for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
1982  if (strcasecmp(name, mailbox_folders[i]) == 0) {
1983  return i;
1984  }
1985  }
1986 
1987  return -1;
1988 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char *const mailbox_folders[]
static const char name[]
Definition: cdr_mysql.c:74

◆ get_folder_ja()

static int get_folder_ja ( struct ast_channel chan,
int  start 
)
static

Definition at line 7865 of file app_voicemail.c.

References ast_channel_language(), AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_waitfordigit(), d, mbox(), NULL, and vm_play_folder_name().

Referenced by get_folder2().

7866 {
7867  int x;
7868  int d;
7869  char fn[256];
7870  for (x = start; x < 5; x++) { /* For all folders */
7871  if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL))) {
7872  return d;
7873  }
7874  snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
7875  d = vm_play_folder_name(chan, fn);
7876  if (d) {
7877  return d;
7878  }
7879  d = ast_waitfordigit(chan, 500);
7880  if (d) {
7881  return d;
7882  }
7883  }
7884  d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
7885  if (d) {
7886  return d;
7887  }
7888  d = ast_waitfordigit(chan, 4000);
7889  return d;
7890 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define AST_DIGIT_ANY
Definition: file.h:48
static struct test_val d
#define NULL
Definition: resample.c:96
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: main/app.c:1470
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
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:8337
const char * ast_channel_language(const struct ast_channel *chan)

◆ handle_voicemail_reload()

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 13020 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(), NULL, and ast_cli_entry::usage.

13021 {
13022  switch (cmd) {
13023  case CLI_INIT:
13024  e->command = "voicemail reload";
13025  e->usage =
13026  "Usage: voicemail reload\n"
13027  " Reload voicemail configuration\n";
13028  return NULL;
13029  case CLI_GENERATE:
13030  return NULL;
13031  }
13032 
13033  if (a->argc != 2)
13034  return CLI_SHOWUSAGE;
13035 
13036  ast_cli(a->fd, "Reloading voicemail configuration...\n");
13037  load_config(1);
13038 
13039  return CLI_SUCCESS;
13040 }
static int load_config(int reload)
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ handle_voicemail_show_aliases()

static char* handle_voicemail_show_aliases ( 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 12980 of file app_voicemail.c.

References alias_mailbox_mapping::alias, ALIASES_OUTPUT_FORMAT, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_args::argc, ast_cli(), ast_strlen_zero, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, alias_mailbox_mapping::mailbox, NULL, and ast_cli_entry::usage.

12981 {
12982  struct ao2_iterator aliases;
12983  struct alias_mailbox_mapping *mapping;
12984 #define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"
12985  char *res = CLI_SUCCESS;
12986 
12987  switch (cmd) {
12988  case CLI_INIT:
12989  e->command = "voicemail show aliases";
12990  e->usage =
12991  "Usage: voicemail show aliases\n"
12992  " Lists mailbox aliases\n";
12993  return NULL;
12994  case CLI_GENERATE:
12995  return NULL;
12996  }
12997 
12998  if (a->argc != 3)
12999  return CLI_SHOWUSAGE;
13000 
13002  ast_cli(a->fd, "Aliases are not enabled\n");
13003  return res;
13004  }
13005 
13006  ast_cli(a->fd, "Aliases context: %s\n", aliasescontext);
13007  ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, "Alias", "Mailbox");
13008 
13010  while ((mapping = ao2_iterator_next(&aliases))) {
13011  ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, mapping->alias, mapping->mailbox);
13012  ao2_ref(mapping, -1);
13013  }
13015 
13016  return res;
13017 }
const int argc
Definition: cli.h:160
static struct ao2_container * alias_mailbox_mappings
Definition: cli.h:152
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static char aliasescontext[MAX_VM_CONTEXT_LEN]
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ALIASES_OUTPUT_FORMAT
const int fd
Definition: cli.h:159
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define CLI_SHOWUSAGE
Definition: cli.h:45
static const struct cfalias aliases[]
Definition: chan_sip.c:8510
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ handle_voicemail_show_users()

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

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

12869 {
12870  struct ast_vm_user *vmu;
12871 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
12872  const char *context = NULL;
12873  int users_counter = 0;
12874 
12875  switch (cmd) {
12876  case CLI_INIT:
12877  e->command = "voicemail show users [for]";
12878  e->usage =
12879  "Usage: voicemail show users [for <context>]\n"
12880  " Lists all mailboxes currently set up\n";
12881  return NULL;
12882  case CLI_GENERATE:
12883  return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
12884  }
12885 
12886  if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
12887  return CLI_SHOWUSAGE;
12888  if (a->argc == 5) {
12889  if (strcmp(a->argv[3],"for"))
12890  return CLI_SHOWUSAGE;
12891  context = a->argv[4];
12892  }
12893 
12894  if (ast_check_realtime("voicemail")) {
12895  if (!context) {
12896  ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
12897  return CLI_SHOWUSAGE;
12898  }
12899  return show_users_realtime(a->fd, context);
12900  }
12901 
12902  AST_LIST_LOCK(&users);
12903  if (AST_LIST_EMPTY(&users)) {
12904  ast_cli(a->fd, "There are no voicemail users currently defined\n");
12906  return CLI_FAILURE;
12907  }
12908  if (!context) {
12909  ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
12910  } else {
12911  int count = 0;
12912  AST_LIST_TRAVERSE(&users, vmu, list) {
12913  if (!strcmp(context, vmu->context)) {
12914  count++;
12915  break;
12916  }
12917  }
12918  if (count) {
12919  ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
12920  } else {
12921  ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
12923  return CLI_FAILURE;
12924  }
12925  }
12926  AST_LIST_TRAVERSE(&users, vmu, list) {
12927  int newmsgs = 0, oldmsgs = 0;
12928  char count[12], tmp[256] = "";
12929 
12930  if (!context || !strcmp(context, vmu->context)) {
12931  snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
12932  inboxcount(tmp, &newmsgs, &oldmsgs);
12933  snprintf(count, sizeof(count), "%d", newmsgs);
12934  ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
12935  users_counter++;
12936  }
12937  }
12939  ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
12940  return CLI_SUCCESS;
12941 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int tmp()
Definition: bt_open.c:389
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
Definition: cli.h:152
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
list of users found in the config file
char context[MAX_VM_CONTEXT_LEN]
const char * line
Definition: cli.h:162
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_vm_user::@82 list
static char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
const int fd
Definition: cli.h:159
char zonetag[80]
const int n
Definition: cli.h:165
const char *const * argv
Definition: cli.h:161
#define HVSU_OUTPUT_FORMAT
#define CLI_SHOWUSAGE
Definition: cli.h:45
#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:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164
static char * show_users_realtime(int fd, const char *context)
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
char fullname[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ handle_voicemail_show_zones()

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

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

12945 {
12946  struct vm_zone *zone;
12947 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
12948  char *res = CLI_SUCCESS;
12949 
12950  switch (cmd) {
12951  case CLI_INIT:
12952  e->command = "voicemail show zones";
12953  e->usage =
12954  "Usage: voicemail show zones\n"
12955  " Lists zone message formats\n";
12956  return NULL;
12957  case CLI_GENERATE:
12958  return NULL;
12959  }
12960 
12961  if (a->argc != 3)
12962  return CLI_SHOWUSAGE;
12963 
12964  AST_LIST_LOCK(&zones);
12965  if (!AST_LIST_EMPTY(&zones)) {
12966  ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
12967  AST_LIST_TRAVERSE(&zones, zone, list) {
12968  ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
12969  }
12970  } else {
12971  ast_cli(a->fd, "There are no voicemail zones currently defined\n");
12972  res = CLI_FAILURE;
12973  }
12975 
12976  return res;
12977 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct vm_zone::@83 list
char timezone[80]
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:152
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
char msg_format[512]
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
char name[80]
#define CLI_SHOWUSAGE
Definition: cli.h:45
#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:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define HVSZ_OUTPUT_FORMAT

◆ has_voicemail()

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

Determines if the given folder has messages.

Parameters
mailboxThe @ delimited string for user@context. 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.
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 6124 of file app_voicemail.c.

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

Referenced by ast_app_has_voicemail(), free_zone(), and vm_allocate_dh().

6125 {
6126  char tmp[256], *tmp2 = tmp, *box, *context;
6127  ast_copy_string(tmp, mailbox, sizeof(tmp));
6128  if (ast_strlen_zero(folder)) {
6129  folder = "INBOX";
6130  }
6131  while ((box = strsep(&tmp2, ",&"))) {
6132  if ((context = strchr(box, '@')))
6133  *context++ = '\0';
6134  else
6135  context = "default";
6136  if (__has_voicemail(context, box, folder, 1))
6137  return 1;
6138  /* If we are checking INBOX, we should check Urgent as well */
6139  if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
6140  return 1;
6141  }
6142  }
6143  return 0;
6144 }
static int tmp()
Definition: bt_open.c:389
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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:116

◆ inboxcount()

static int inboxcount ( const char *  mailbox,
int *  newmsgs,
int *  oldmsgs 
)
static
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 6224 of file app_voicemail.c.

References inboxcount2().

Referenced by append_vmu_info_astman(), ast_app_inboxcount(), forward_message(), handle_voicemail_show_users(), leave_voicemail(), and msg_create_from_file().

6225 {
6226  int urgentmsgs = 0;
6227  int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
6228  if (newmsgs) {
6229  *newmsgs += urgentmsgs;
6230  }
6231  return res;
6232 }
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox&#39;s message count.
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204

◆ inboxcount2()

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

Check the given mailbox's message count.

Parameters
mailboxThe @ delimited string for user. If no context is found, uses 'default' for the context.
urgentmsgsurgent message count.
newmsgsnew message count.
oldmsgsold message count pointer
Returns
-1 if error occurred, 0 otherwise.
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 6154 of file app_voicemail.c.

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

Referenced by append_mailbox(), ast_app_inboxcount2(), free_zone(), inboxcount(), poll_subscribed_mailbox(), run_externnotify(), and vm_allocate_dh().

6155 {
6156  char tmp[256];
6157  char *context;
6158 
6159  /* If no mailbox, return immediately */
6160  if (ast_strlen_zero(mailbox)) {
6161  return 0;
6162  }
6163 
6164  if (newmsgs) {
6165  *newmsgs = 0;
6166  }
6167  if (oldmsgs) {
6168  *oldmsgs = 0;
6169  }
6170  if (urgentmsgs) {
6171  *urgentmsgs = 0;
6172  }
6173 
6174  if (strchr(mailbox, ',')) {
6175  int tmpnew, tmpold, tmpurgent;
6176  char *mb, *cur;
6177 
6178  ast_copy_string(tmp, mailbox, sizeof(tmp));
6179  mb = tmp;
6180  while ((cur = strsep(&mb, ", "))) {
6181  if (!ast_strlen_zero(cur)) {
6182  if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL)) {
6183  return -1;
6184  } else {
6185  if (newmsgs) {
6186  *newmsgs += tmpnew;
6187  }
6188  if (oldmsgs) {
6189  *oldmsgs += tmpold;
6190  }
6191  if (urgentmsgs) {
6192  *urgentmsgs += tmpurgent;
6193  }
6194  }
6195  }
6196  }
6197  return 0;
6198  }
6199 
6200  ast_copy_string(tmp, mailbox, sizeof(tmp));
6201 
6202  if ((context = strchr(tmp, '@'))) {
6203  *context++ = '\0';
6204  } else {
6205  context = "default";
6206  }
6207 
6208  if (newmsgs) {
6209  *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
6210  }
6211  if (oldmsgs) {
6212  *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
6213  }
6214  if (urgentmsgs) {
6215  *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
6216  }
6217 
6218  return 0;
6219 }
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox&#39;s message count.
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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:116

◆ inbuf()

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

utility used by inchar(), for base_encode()

Definition at line 4770 of file app_voicemail.c.

References baseio::ateof, BASEMAXINLINE, baseio::iobuf, baseio::iocp, and baseio::iolen.

Referenced by analys_(), ast_eivr_getvariable(), ast_eivr_setvariable(), inchar(), lpfilt_(), netconsole(), preemp_(), sip_addheader(), sip_removeheader(), and term_strip().

4771 {
4772  int l;
4773 
4774  if (bio->ateof)
4775  return 0;
4776 
4777  if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) != BASEMAXINLINE) {
4778  bio->ateof = 1;
4779  if (l == 0) {
4780  /* Assume EOF */
4781  return 0;
4782  }
4783  }
4784 
4785  bio->iolen = l;
4786  bio->iocp = 0;
4787 
4788  return 1;
4789 }
unsigned char iobuf[BASEMAXINLINE]
#define BASEMAXINLINE

◆ inchar()

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

utility used by base_encode()

Definition at line 4794 of file app_voicemail.c.

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

Referenced by base_encode().

4795 {
4796  if (bio->iocp>=bio->iolen) {
4797  if (!inbuf(bio, fi))
4798  return EOF;
4799  }
4800 
4801  return bio->iobuf[bio->iocp++];
4802 }
unsigned char iobuf[BASEMAXINLINE]
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()

◆ inprocess_cmp_fn()

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

Definition at line 1124 of file app_voicemail.c.

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

Referenced by load_module().

1125 {
1126  struct inprocess *i = obj, *j = arg;
1127  if (strcmp(i->mailbox, j->mailbox)) {
1128  return 0;
1129  }
1130  return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
1131 }
char * context
char mailbox[0]

◆ inprocess_count()

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

Definition at line 1133 of file app_voicemail.c.

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

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

1134 {
1135  int context_len = strlen(context) + 1;
1136  int mailbox_len = strlen(mailbox) + 1;
1137  struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + context_len + mailbox_len);
1138  arg->context = arg->mailbox + mailbox_len;
1139  ast_copy_string(arg->mailbox, mailbox, mailbox_len); /* SAFE */
1140  ast_copy_string(arg->context, context, context_len); /* SAFE */
1142  if ((i = ao2_find(inprocess_container, arg, 0))) {
1143  int ret = ast_atomic_fetchadd_int(&i->count, delta);
1145  ao2_ref(i, -1);
1146  return ret;
1147  }
1148  if (delta < 0) {
1149  ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
1150  }
1151  if (!(i = ao2_alloc(sizeof(*i) + context_len + mailbox_len, NULL))) {
1153  return 0;
1154  }
1155  i->context = i->mailbox + mailbox_len;
1156  ast_copy_string(i->mailbox, mailbox, mailbox_len); /* SAFE */
1157  ast_copy_string(i->context, context, context_len); /* SAFE */
1158  i->count = delta;
1161  ao2_ref(i, -1);
1162  return 0;
1163 }
#define LOG_WARNING
Definition: logger.h:274
char * context
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
char mailbox[0]
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ao2_container * inprocess_container
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ inprocess_hash_fn()

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

Definition at line 1118 of file app_voicemail.c.

References inprocess::mailbox.

Referenced by load_module().

1119 {
1120  const struct inprocess *i = obj;
1121  return atoi(i->mailbox);
1122 }
char mailbox[0]

◆ invent_message()

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

Definition at line 5736 of file app_voicemail.c.

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

Referenced by leave_voicemail().

5737 {
5738  int res;
5739  char fn[PATH_MAX];
5740  char dest[PATH_MAX];
5741 
5742  snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
5743 
5744  if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
5745  ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
5746  return -1;
5747  }
5748 
5749  RETRIEVE(fn, -1, ext, context);
5750  if (ast_fileexists(fn, NULL, NULL) > 0) {
5751  res = ast_stream_and_wait(chan, fn, ecodes);
5752  if (res) {
5753  DISPOSE(fn, -1);
5754  return res;
5755  }
5756  } else {
5757  /* Dispose just in case */
5758  DISPOSE(fn, -1);
5759  res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
5760  if (res)
5761  return res;
5762  res = ast_say_digit_str(chan, ext, ecodes, ast_channel_language(chan));
5763  if (res)
5764  return res;
5765  }
5766  res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
5767  return res;
5768 }
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:279
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:8355
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
const char * ext
Definition: http.c:147
#define ast_log
Definition: astobj2.c:42
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:1814
#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:1086
const char * ast_channel_language(const struct ast_channel *chan)
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ is_valid_dtmf()

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

References ast_log, AST_LOG_WARNING, ast_strdupa, and VALID_DTMF.

Referenced by actual_load_config().

1593 {
1594  int i;
1595  char *local_key = ast_strdupa(key);
1596 
1597  for (i = 0; i < strlen(key); ++i) {
1598  if (!strchr(VALID_DTMF, *local_key)) {
1599  ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
1600  return 0;
1601  }
1602  local_key++;
1603  }
1604  return 1;
1605 }
#define AST_LOG_WARNING
Definition: logger.h:279
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define VALID_DTMF

◆ last_message_index()

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

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

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

4579 {
4580  int x;
4581  unsigned char map[MAXMSGLIMIT] = "";
4582  DIR *msgdir;
4583  struct dirent *msgdirent;
4584  int msgdirint;
4585  char extension[4];
4586  int stopcount = 0;
4587 
4588  /* Reading the entire directory into a file map scales better than
4589  * doing a stat repeatedly on a predicted sequence. I suspect this
4590  * is partially due to stat(2) internally doing a readdir(2) itself to
4591  * find each file. */
4592  if (!(msgdir = opendir(dir))) {
4593  return -1;
4594  }
4595 
4596  while ((msgdirent = readdir(msgdir))) {
4597  if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
4598  map[msgdirint] = 1;
4599  stopcount++;
4600  ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4601  }
4602  }
4603  closedir(msgdir);
4604 
4605  for (x = 0; x < vmu->maxmsg; x++) {
4606  if (map[x] == 1) {
4607  stopcount--;
4608  } else if (map[x] == 0 && !stopcount) {
4609  break;
4610  }
4611  }
4612 
4613  return x - 1;
4614 }
static int * map
Definition: misdn_config.c:438
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
structure to hold extensions
#define MAXMSGLIMIT

◆ leave_voicemail()

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

References ast_answer(), ast_callerid_merge(), ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_language(), ast_channel_lock, ast_channel_macrocontext(), ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_redirecting(), 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_STATE_UP, 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(), leave_vm_options::beeptone, context, ast_vm_user::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, leave_vm_options::exitcontext, exten, find_user(), free_user(), generate_msg_id(), get_date(), inboxcount(), inprocess_count(), INTRO, invent_message(), last_message_index(), LOG_WARNING, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, MSG_ID_LEN, name, vm_state::newmessages, notify_new_message(), NULL, OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_UNAVAIL_GREETING, PATH_MAX, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), priority, leave_vm_options::record_gain, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, strsep(), transfer, vm_lock_path(), VM_OPERATOR, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

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

6602 {
6603 #ifdef IMAP_STORAGE
6604  int newmsgs, oldmsgs;
6605 #endif
6606  char txtfile[PATH_MAX];
6607  char tmptxtfile[PATH_MAX];
6608  struct vm_state *vms = NULL;
6609  char callerid[256];
6610  FILE *txt;
6611  char date[256];
6612  int txtdes;
6613  int res = 0;
6614  int msgnum;
6615  int duration = 0;
6616  int sound_duration = 0;
6617  int ausemacro = 0;
6618  int ousemacro = 0;
6619  int ouseexten = 0;
6620  int greeting_only = 0;
6621  char tmpdur[16];
6622  char priority[16];
6623  char origtime[16];
6624  char dir[PATH_MAX];
6625  char tmpdir[PATH_MAX];
6626  char fn[PATH_MAX];
6627  char prefile[PATH_MAX] = "";
6628  char tempfile[PATH_MAX] = "";
6629  char ext_context[256] = "";
6630  char fmt[80];
6631  char *context;
6632  char ecodes[17] = "#";
6633  struct ast_str *tmp = ast_str_create(16);
6634  char *tmpptr;
6635  struct ast_vm_user *vmu;
6636  struct ast_vm_user svm;
6637  const char *category = NULL;
6638  const char *code;
6639  const char *alldtmf = "0123456789ABCD*#";
6640  char flag[80];
6641 
6642  if (!tmp) {
6643  return -1;
6644  }
6645 
6646  ast_str_set(&tmp, 0, "%s", ext);
6647  ext = ast_str_buffer(tmp);
6648  if ((context = strchr(ext, '@'))) {
6649  *context++ = '\0';
6650  tmpptr = strchr(context, '&');
6651  } else {
6652  tmpptr = strchr(ext, '&');
6653  }
6654 
6655  if (tmpptr)
6656  *tmpptr++ = '\0';
6657 
6658  ast_channel_lock(chan);
6659  if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
6660  category = ast_strdupa(category);
6661  }
6662  ast_channel_unlock(chan);
6663 
6664  if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
6665  ast_copy_string(flag, "Urgent", sizeof(flag));
6666  } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
6667  ast_copy_string(flag, "PRIORITY", sizeof(flag));
6668  } else {
6669  flag[0] = '\0';
6670  }
6671 
6672  ast_debug(3, "Before find_user\n");
6673  memset(&svm, 0, sizeof(svm));
6674  if (!(vmu = find_user(&svm, context, ext))) {
6675  ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
6676  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
6677  ast_free(tmp);
6678  return res;
6679  }
6680 
6681  /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
6682  if (vmu->maxmsg == 0) {
6683  greeting_only = 1;
6684  ast_set_flag(options, OPT_SILENT);
6685  }
6686 
6687  /* Setup pre-file if appropriate */
6688  if (strcmp(vmu->context, "default"))
6689  snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
6690  else
6691  ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
6692 
6693  /* Set the path to the prefile. Will be one of
6694  VM_SPOOL_DIRcontext/ext/busy
6695  VM_SPOOL_DIRcontext/ext/unavail
6696  Depending on the flag set in options.
6697  */
6698  if (ast_test_flag(options, OPT_BUSY_GREETING)) {
6699  snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
6700  } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
6701  snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
6702  }
6703  /* Set the path to the tmpfile as
6704  VM_SPOOL_DIR/context/ext/temp
6705  and attempt to create the folder structure.
6706  */
6707  snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
6708  if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
6709  ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
6710  free_user(vmu);
6711  ast_free(tmp);
6712  return -1;
6713  }
6714  RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
6715  if (ast_fileexists(tempfile, NULL, NULL) > 0)
6716  ast_copy_string(prefile, tempfile, sizeof(prefile));
6717 
6718  DISPOSE(tempfile, -1);
6719  /* It's easier just to try to make it than to check for its existence */
6720 #ifndef IMAP_STORAGE
6721  create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
6722 #else
6723  snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
6724  if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
6725  ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
6726  }
6727 #endif
6728 
6729  /* Check current or macro-calling context for special extensions */
6730  if (ast_test_flag(vmu, VM_OPERATOR)) {
6731  if (!ast_strlen_zero(vmu->exit)) {
6732  if (ast_exists_extension(chan, vmu->exit, "o", 1,
6733  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6734  strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
6735  ouseexten = 1;
6736  }
6737  } else if (ast_exists_extension(chan, ast_channel_context(chan), "o", 1,
6738  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6739  strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
6740  ouseexten = 1;
6741  } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))
6742  && ast_exists_extension(chan, ast_channel_macrocontext(chan), "o", 1,
6743  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6744  strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
6745  ousemacro = 1;
6746  }
6747  }
6748 
6749  if (!ast_strlen_zero(vmu->exit)) {
6750  if (ast_exists_extension(chan, vmu->exit, "a", 1,
6751  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6752  strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
6753  }
6754  } else if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
6755  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6756  strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
6757  } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))
6758  && ast_exists_extension(chan, ast_channel_macrocontext(chan), "a", 1,
6759  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6760  strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
6761  ausemacro = 1;
6762  }
6763 
6764  if (ast_test_flag(options, OPT_DTMFEXIT)) {
6765  for (code = alldtmf; *code; code++) {
6766  char e[2] = "";
6767  e[0] = *code;
6768  if (strchr(ecodes, e[0]) == NULL
6769  && ast_canmatch_extension(chan,
6770  (!ast_strlen_zero(options->exitcontext) ? options->exitcontext : ast_channel_context(chan)),
6771  e, 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
6772  strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
6773  }
6774  }
6775  }
6776 
6777  /* Play the beginning intro if desired */
6778  if (!ast_strlen_zero(prefile)) {
6779 #ifdef ODBC_STORAGE
6780  int success =
6781 #endif
6782  RETRIEVE(prefile, -1, ext, context);
6783  if (ast_fileexists(prefile, NULL, NULL) > 0) {
6784  if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1)
6785  res = ast_waitstream(chan, ecodes);
6786 #ifdef ODBC_STORAGE
6787  if (success == -1) {
6788  /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
6789  ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
6790  store_file(prefile, vmu->mailbox, vmu->context, -1);
6791  }
6792 #endif
6793  } else {
6794  ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
6795  res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
6796  }
6797  DISPOSE(prefile, -1);
6798  if (res < 0) {
6799  ast_debug(1, "Hang up during prefile playback\n");
6800  free_user(vmu);
6801  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
6802  ast_free(tmp);
6803  return -1;
6804  }
6805  }
6806  if (res == '#') {
6807  /* On a '#' we skip the instructions */
6808  ast_set_flag(options, OPT_SILENT);
6809  res = 0;
6810  }
6811  if (!res && !ast_test_flag(options, OPT_SILENT)) {
6812  res = ast_stream_and_wait(chan, INTRO, ecodes);
6813  if (res == '#') {
6814  ast_set_flag(options, OPT_SILENT);
6815  res = 0;
6816  }
6817  }
6818  if (res > 0)
6819  ast_stopstream(chan);
6820  /* Check for a '*' here in case the caller wants to escape from voicemail to something
6821  other than the operator -- an automated attendant or mailbox login for example */
6822  if (res == '*') {
6823  ast_channel_exten_set(chan, "a");
6824  if (!ast_strlen_zero(vmu->exit)) {
6825  ast_channel_context_set(chan, vmu->exit);
6826  } else if (ausemacro && !ast_strlen_zero(ast_channel_macrocontext(chan))) {
6828  }
6829  ast_channel_priority_set(chan, 0);
6830  free_user(vmu);
6831  pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
6832  ast_free(tmp);
6833  return 0;
6834  }
6835 
6836  /* Check for a '0' here */
6837  if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
6838  transfer:
6839  if (ouseexten || ousemacro) {
6840  ast_channel_exten_set(chan, "o");
6841  if (!ast_strlen_zero(vmu->exit)) {
6842  ast_channel_context_set(chan, vmu->exit);
6843  } else if (ousemacro && !ast_strlen_zero(ast_channel_macrocontext(chan))) {
6845  }
6846  ast_play_and_wait(chan, "transfer");
6847  ast_channel_priority_set(chan, 0);
6848  pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
6849  }
6850  free_user(vmu);
6851  ast_free(tmp);
6852  return OPERATOR_EXIT;
6853  }
6854 
6855  /* Allow all other digits to exit Voicemail and return to the dialplan */
6856  if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
6857  if (!ast_strlen_zero(options->exitcontext)) {
6858  ast_channel_context_set(chan, options->exitcontext);
6859  }
6860  free_user(vmu);
6861  ast_free(tmp);
6862  pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
6863  return res;
6864  }
6865 
6866  if (greeting_only) {
6867  ast_debug(3, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
6868  pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
6869  res = 0;
6870  goto leave_vm_out;
6871  }
6872 
6873  if (res < 0) {
6874  free_user(vmu);
6875  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
6876  ast_free(tmp);
6877  return -1;
6878  }
6879  /* The meat of recording the message... All the announcements and beeps have been played*/
6880  if (ast_channel_state(chan) != AST_STATE_UP) {
6881  ast_answer(chan);
6882  }
6883  ast_copy_string(fmt, vmfmts, sizeof(fmt));
6884  if (!ast_strlen_zero(fmt)) {
6885  char msg_id[MSG_ID_LEN] = "";
6886  msgnum = 0;
6887 
6888 #ifdef IMAP_STORAGE
6889  /* Is ext a mailbox? */
6890  /* must open stream for this user to get info! */
6891  res = inboxcount(ext_context, &newmsgs, &oldmsgs);
6892  if (res < 0) {
6893  ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
6894  free_user(vmu);
6895  ast_free(tmp);
6896  return -1;
6897  }
6898  if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
6899  /* It is possible under certain circumstances that inboxcount did not
6900  * create a vm_state when it was needed. This is a catchall which will
6901  * rarely be used.
6902  */
6903  if (!(vms = create_vm_state_from_user(vmu))) {
6904  ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
6905  free_user(vmu);
6906  ast_free(tmp);
6907  return -1;
6908  }
6909  }
6910  vms->newmessages++;
6911 
6912  /* here is a big difference! We add one to it later */
6913  msgnum = newmsgs + oldmsgs;
6914  ast_debug(3, "Messagecount set to %d\n", msgnum);
6915  snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
6916  /* set variable for compatibility */
6917  pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
6918 
6919  if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
6920  goto leave_vm_out;
6921  }
6922 #else
6923  if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
6924  res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
6925  if (!res)
6926  res = ast_waitstream(chan, "");
6927  ast_log(AST_LOG_WARNING, "No more messages possible\n");
6928  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
6929  inprocess_count(vmu->mailbox, vmu->context, -1);
6930  goto leave_vm_out;
6931  }
6932 
6933 #endif
6934  snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
6935  txtdes = mkstemp(tmptxtfile);
6936  chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
6937  if (txtdes < 0) {
6938  res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
6939  if (!res)
6940  res = ast_waitstream(chan, "");
6941  ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
6942  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
6943  inprocess_count(vmu->mailbox, vmu->context, -1);
6944  goto leave_vm_out;
6945  }
6946 
6947  /* Now play the beep once we have the message number for our next message. */
6948  if (res >= 0) {
6949  /* Unless we're *really* silent, try to send the beep */
6950  /* Play default or custom beep, unless no beep desired */
6951  if (!ast_strlen_zero(options->beeptone)) {
6952  res = ast_stream_and_wait(chan, options->beeptone, "");
6953  }
6954  }
6955 
6956  /* Store information in real-time storage */
6957  if (ast_check_realtime("voicemail_data")) {
6958  snprintf(priority, sizeof(priority), "%d", ast_channel_priority(chan));
6959  snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
6960  get_date(date, sizeof(date));
6961  ast_callerid_merge(callerid, sizeof(callerid),
6962  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
6963  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
6964  "Unknown");
6965  ast_store_realtime("voicemail_data",
6966  "origmailbox", ext,
6967  "context", ast_channel_context(chan),
6968  "macrocontext", ast_channel_macrocontext(chan),
6969  "exten", ast_channel_exten(chan),
6970  "priority", priority,
6971  "callerchan", ast_channel_name(chan),
6972  "callerid", callerid,
6973  "origdate", date,
6974  "origtime", origtime,
6975  "category", S_OR(category, ""),
6976  "filename", tmptxtfile,
6977  SENTINEL);
6978  }
6979 
6980  /* Store information */
6981  txt = fdopen(txtdes, "w+");
6982  if (txt) {
6983  generate_msg_id(msg_id);
6984  get_date(date, sizeof(date));
6985  ast_callerid_merge(callerid, sizeof(callerid),
6986  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
6987  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
6988  "Unknown");
6989  fprintf(txt,
6990  ";\n"
6991  "; Message Information file\n"
6992  ";\n"
6993  "[message]\n"
6994  "origmailbox=%s\n"
6995  "context=%s\n"
6996  "macrocontext=%s\n"
6997  "exten=%s\n"
6998  "rdnis=%s\n"
6999  "priority=%d\n"
7000  "callerchan=%s\n"
7001  "callerid=%s\n"
7002  "origdate=%s\n"
7003  "origtime=%ld\n"
7004  "category=%s\n"
7005  "msg_id=%s\n",
7006  ext,
7007  ast_channel_context(chan),
7009  ast_channel_exten(chan),
7010  S_COR(ast_channel_redirecting(chan)->from.number.valid,
7011  ast_channel_redirecting(chan)->from.number.str, "unknown"),
7012  ast_channel_priority(chan),
7013  ast_channel_name(chan),
7014  callerid,
7015  date, (long) time(NULL),
7016  category ? category : "",
7017  msg_id);
7018  } else {
7019  ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
7020  inprocess_count(vmu->mailbox, vmu->context, -1);
7021  if (ast_check_realtime("voicemail_data")) {
7022  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
7023  }
7024  res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
7025  goto leave_vm_out;
7026  }
7027  res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id, 0);
7028 
7029  /* At this point, either we were instructed to make the message Urgent
7030  by arguments to VoiceMail or during the review process by the person
7031  leaving the message. So we update the directory where we want this
7032  message to go. */
7033  if (!strcmp(flag, "Urgent")) {
7034  create_dirpath(dir, sizeof(dir), vmu->context, ext, "Urgent");
7035  }
7036 
7037  if (txt) {
7038  fprintf(txt, "flag=%s\n", flag);
7039  if (sound_duration < vmu->minsecs) {
7040  fclose(txt);
7041  ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->minsecs);
7042  ast_filedelete(tmptxtfile, NULL);
7043  unlink(tmptxtfile);
7044  if (ast_check_realtime("voicemail_data")) {
7045  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
7046  }
7047  inprocess_count(vmu->mailbox, vmu->context, -1);
7048  } else {
7049  fprintf(txt, "duration=%d\n", duration);
7050  fclose(txt);
7051  if (vm_lock_path(dir)) {
7052  ast_log(AST_LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
7053  /* Delete files */
7054  ast_filedelete(tmptxtfile, NULL);
7055  unlink(tmptxtfile);
7056  inprocess_count(vmu->mailbox, vmu->context, -1);
7057  } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
7058  ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
7059  unlink(tmptxtfile);
7060  ast_unlock_path(dir);
7061  inprocess_count(vmu->mailbox, vmu->context, -1);
7062  if (ast_check_realtime("voicemail_data")) {
7063  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
7064  }
7065  } else {
7066 #ifndef IMAP_STORAGE
7067  msgnum = last_message_index(vmu, dir) + 1;
7068 #endif
7069  make_file(fn, sizeof(fn), dir, msgnum);
7070 
7071  /* assign a variable with the name of the voicemail file */
7072 #ifndef IMAP_STORAGE
7073  pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
7074 #else
7075  pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
7076 #endif
7077 
7078  snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
7079  ast_filerename(tmptxtfile, fn, NULL);
7080  rename(tmptxtfile, txtfile);
7081  inprocess_count(vmu->mailbox, vmu->context, -1);
7082 
7083  /* Properly set permissions on voicemail text descriptor file.
7084  Unfortunately mkstemp() makes this file 0600 on most unix systems. */
7085  if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
7086  ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
7087 
7088  ast_unlock_path(dir);
7089  if (ast_check_realtime("voicemail_data")) {
7090  snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
7091  ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
7092  }
7093  /* We must store the file first, before copying the message, because
7094  * ODBC storage does the entire copy with SQL.
7095  */
7096  if (ast_fileexists(fn, NULL, NULL) > 0) {
7097  STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag, msg_id);
7098  }
7099 
7100  /* Are there to be more recipients of this message? */
7101  while (tmpptr) {
7102  struct ast_vm_user recipu, *recip;
7103  char *exten, *cntx;
7104 
7105  exten = strsep(&tmpptr, "&");
7106  cntx = strchr(exten, '@');
7107  if (cntx) {
7108  *cntx = '\0';
7109  cntx++;
7110  }
7111  memset(&recipu, 0, sizeof(recipu));
7112  if ((recip = find_user(&recipu, cntx, exten))) {
7113  copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag, NULL);
7114  free_user(recip);
7115  }
7116  }
7117 
7118  /* Notification needs to happen after the copy, though. */
7119  if (ast_fileexists(fn, NULL, NULL)) {
7120 #ifdef IMAP_STORAGE
7121  notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
7122  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
7123  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
7124  flag);
7125 #else
7126  notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
7127  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
7128  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
7129  flag);
7130 #endif
7131  }
7132 
7133  /* Disposal needs to happen after the optional move and copy */
7134  if (ast_fileexists(fn, NULL, NULL)) {
7135  DISPOSE(dir, msgnum);
7136  }
7137  }
7138  }
7139  } else {
7140  inprocess_count(vmu->mailbox, vmu->context, -1);
7141  }
7142  if (res == '0') {
7143  goto transfer;
7144  } else if (res > 0 && res != 't')
7145  res = 0;
7146 
7147  if (sound_duration < vmu->minsecs)
7148  /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
7149  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7150  else
7151  pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
7152  } else
7153  ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
7154 leave_vm_out:
7155  free_user(vmu);
7156 
7157 #ifdef IMAP_STORAGE
7158  /* expunge message - use UID Expunge if supported on IMAP server*/
7159  ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
7160  if (expungeonhangup == 1 && vms->mailstream != NULL) {
7161  ast_mutex_lock(&vms->lock);
7162 #ifdef HAVE_IMAP_TK2006
7163  if (LEVELUIDPLUS (vms->mailstream)) {
7164  mail_expunge_full(vms->mailstream, NIL, EX_UID);
7165  } else
7166 #endif
7167  mail_expunge(vms->mailstream);
7168  ast_mutex_unlock(&vms->lock);
7169  }
7170 #endif
7171 
7172  ast_free(tmp);
7173  return res;
7174 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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, const char *dest_folder)
Copies a message from one mailbox to another.
#define MSG_ID_LEN
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
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
#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:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
#define AST_LOG_WARNING
Definition: logger.h:279
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define INTRO
#define ast_mutex_lock(a)
Definition: lock.h:187
static int inprocess_count(const char *context, const char *mailbox, int delta)
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
#define DISPOSE(a, b)
char fn[PATH_MAX]
static int priority
const char * ext
Definition: http.c:147
int ast_channel_priority(const struct ast_channel *chan)
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3489
#define ast_verb(level,...)
Definition: logger.h:463
static int transfer
Definition: chan_mgcp.c:194
char context[MAX_VM_CONTEXT_LEN]
char exit[80]
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:4194
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.
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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...
Number structure.
Definition: app_followme.c:154
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:1065
#define AST_LOG_NOTICE
Definition: logger.h:268
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define SENTINEL
Definition: compiler.h:87
#define AST_LOG_ERROR
Definition: logger.h:290
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
Definition: main/config.c:3570
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
static int my_umask
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: main/app.c:1470
#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:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
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:4179
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)
const char * ast_channel_exten(const struct ast_channel *chan)
#define VM_OPERATOR
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, const char *msg_id, int forwardintro)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define OPERATOR_EXIT
int errno
#define VOICEMAIL_DIR_MODE
long int flag
Definition: f2c.h:83
#define ast_channel_unlock(chan)
Definition: channel.h:2946
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[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
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:1814
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
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...
#define RETRIEVE(a, b, c, d)
signed char record_gain
Definition: app_minivm.c:652
char * strsep(char **str, const char *delims)
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
Definition: main/config.c:3606
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
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:1776
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
const char * ast_channel_language(const struct ast_channel *chan)
#define VOICEMAIL_FILE_MODE
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
const char * ast_channel_context(const struct ast_channel *chan)
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
const char * ast_channel_macrocontext(const struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
static char vmfmts[80]
char mailbox[MAX_VM_MBOX_ID_LEN]
int newmessages
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ load_aliases()

static void load_aliases ( struct ast_config cfg)
static

Definition at line 13606 of file app_voicemail.c.

References alias_mailbox_mapping_create(), ao2_link, ao2_ref, ast_strlen_zero, ast_variable_browse(), ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by actual_load_config().

13607 {
13608  struct ast_variable *var;
13609 
13611  return;
13612  }
13613  var = ast_variable_browse(cfg, aliasescontext);
13614  while (var) {
13615  struct alias_mailbox_mapping *mapping = alias_mailbox_mapping_create(var->name, var->value);
13616  if (mapping) {
13617  ao2_link(alias_mailbox_mappings, mapping);
13618  ao2_link(mailbox_alias_mappings, mapping);
13619  ao2_ref(mapping, -1);
13620  }
13621  var = var->next;
13622  }
13623 }
struct ast_variable * next
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
static struct ao2_container * alias_mailbox_mappings
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
static char aliasescontext[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ao2_container * mailbox_alias_mappings
static struct alias_mailbox_mapping * alias_mailbox_mapping_create(const char *alias, const char *mailbox)
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ load_config()

static int load_config ( int  reload)
static

Definition at line 13538 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, NULL, and VOICEMAIL_CONFIG.

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

13539 {
13540  struct ast_config *cfg, *ucfg;
13541  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
13542  int res;
13543 
13544  ast_unload_realtime("voicemail");
13545  ast_unload_realtime("voicemail_data");
13546 
13547  if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
13548  if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
13549  return 0;
13550  } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
13551  ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
13552  ucfg = NULL;
13553  }
13554  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
13555  if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
13556  ast_config_destroy(ucfg);
13557  ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
13558  return 0;
13559  }
13560  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
13561  ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
13562  return 0;
13563  } else {
13564  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
13565  if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
13566  ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
13567  ucfg = NULL;
13568  }
13569  }
13570 
13571  res = actual_load_config(reload, cfg, ucfg);
13572 
13573  ast_config_destroy(cfg);
13574  ast_config_destroy(ucfg);
13575 
13576  return res;
13577 }
static int reload(void)
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: main/config.c:3406
#define CONFIG_STATUS_FILEINVALID
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define VOICEMAIL_CONFIG
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define CONFIG_STATUS_FILEUNCHANGED
#define LOG_ERROR
Definition: logger.h:285
Structure used to handle boolean flags.
Definition: utils.h:199
#define ast_clear_flag(p, flag)
Definition: utils.h:77

◆ load_config_from_memory()

static int load_config_from_memory ( int  reload,
struct ast_config cfg,
struct ast_config ucfg 
)
static

Definition at line 13580 of file app_voicemail.c.

References actual_load_config(), and ast_unload_realtime().

Referenced by AST_TEST_DEFINE().

13581 {
13582  ast_unload_realtime("voicemail");
13583  ast_unload_realtime("voicemail_data");
13584  return actual_load_config(reload, cfg, ucfg);
13585 }
static int reload(void)
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: main/config.c:3406
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS.

If a dependency, allocation or environment variable fails tests, return AST_MODULE_LOAD_FAILURE.

If the module can't load the configuration file, can't register as a provider or has another issue not fatal to Asterisk itself, return AST_MODULE_LOAD_DECLINE.

On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 15123 of file app_voicemail.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_cleanup, ao2_container_alloc_hash, ao2_container_register(), ao2_container_unregister(), ARRAY_LEN, ast_cli_register_multiple, ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_install_vm_test_functions(), ast_log, AST_LOG_WARNING, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_realtime_require_field(), ast_register_application_xml, ast_taskprocessor_get(), AST_TEST_REGISTER, ast_vm_greeter_register, ast_vm_register, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, EVENT_FLAG_USER, inprocess_cmp_fn(), inprocess_hash_fn(), load_config(), LOG_ERROR, manager_list_voicemail_users(), manager_status_voicemail_user(), manager_voicemail_refresh(), MAPPING_BUCKETS, NULL, print_mappings(), RQ_CHAR, RQ_UINTEGER3, SENTINEL, unload_module(), vm_exec(), vm_execmain(), vm_playmsgexec(), vm_test_create_user(), vm_test_destroy_user(), vmauthenticate(), and vmsayname_exec().

Referenced by vm_msg_play().

15124 {
15125  int res;
15126  my_umask = umask(0);
15127  umask(my_umask);
15128 
15131  if (!inprocess_container) {
15132  return AST_MODULE_LOAD_DECLINE;
15133  }
15134 
15136  alias_mailbox_mapping_hash_fn, NULL, alias_mailbox_mapping_cmp_fn);
15137  if (!alias_mailbox_mappings) {
15138  ast_log(LOG_ERROR, "Unable to create alias_mailbox_mappings container\n");
15140  return AST_MODULE_LOAD_DECLINE;
15141  }
15142  res = ao2_container_register("voicemail_alias_mailbox_mappings", alias_mailbox_mappings, print_mappings);
15143  if (res) {
15144  ast_log(LOG_ERROR, "Unable to register alias_mailbox_mappings container\n");
15147  return AST_MODULE_LOAD_DECLINE;
15148  }
15149 
15151  mailbox_alias_mapping_hash_fn, NULL, mailbox_alias_mapping_cmp_fn);
15152  if (!mailbox_alias_mappings) {
15153  ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");
15155  ao2_container_unregister("voicemail_alias_mailbox_mappings");
15157  return AST_MODULE_LOAD_DECLINE;
15158  }
15159  res = ao2_container_register("voicemail_mailbox_alias_mappings", mailbox_alias_mappings, print_mappings);
15160  if (res) {
15161  ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");
15163  ao2_container_unregister("voicemail_alias_mailbox_mappings");
15166  return AST_MODULE_LOAD_DECLINE;
15167  }
15168 
15169  /* compute the location of the voicemail spool directory */
15170  snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
15171 
15172  if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
15173  ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor. MWI will not work\n");
15174  }
15175 
15176  if ((res = load_config(0))) {
15177  unload_module();
15178  return AST_MODULE_LOAD_DECLINE;
15179  }
15180 
15190 #ifdef TEST_FRAMEWORK
15191  res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
15192  res |= AST_TEST_REGISTER(test_voicemail_msgcount);
15193  res |= AST_TEST_REGISTER(test_voicemail_vmuser);
15194  res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
15195  res |= AST_TEST_REGISTER(test_voicemail_load_config);
15196  res |= AST_TEST_REGISTER(test_voicemail_vm_info);
15197 #endif
15198 
15199  if (res) {
15200  ast_log(LOG_ERROR, "Failure registering applications, functions or tests\n");
15201  unload_module();
15202  return AST_MODULE_LOAD_DECLINE;
15203  }
15204 
15205  /* ast_vm_register may return DECLINE if another module registered for vm */
15206  res = ast_vm_register(&vm_table);
15207  if (res) {
15208  ast_log(LOG_ERROR, "Failure registering as a voicemail provider\n");
15209  unload_module();
15210  return AST_MODULE_LOAD_DECLINE;
15211  }
15212 
15213  /* ast_vm_greeter_register may return DECLINE if another module registered as a greeter */
15215  if (res) {
15216  ast_log(LOG_ERROR, "Failure registering as a greeter provider\n");
15217  unload_module();
15218  return AST_MODULE_LOAD_DECLINE;
15219  }
15220 
15222 
15223 #ifdef TEST_FRAMEWORK
15225 #endif
15226 
15227  ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
15228  ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
15229 
15230  return AST_MODULE_LOAD_SUCCESS;
15231 }
static struct ast_custom_function vm_info_acf
static const struct ast_vm_functions vm_table
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 char * voicemailmain_app
static int manager_status_voicemail_user(struct mansession *s, const struct message *m)
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
void ast_install_vm_test_functions(ast_vm_test_create_user_fn *vm_test_create_user_func, ast_vm_test_destroy_user_fn *vm_test_destroy_user_func)
Definition: main/app.c:599
static struct ao2_container * alias_mailbox_mappings
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...
static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)
#define AST_LOG_WARNING
Definition: logger.h:279
#define MAPPING_BUCKETS
static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
static const struct ast_vm_greeter_functions vm_greeter_table
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int unload_module(void)
#define NULL
Definition: resample.c:96
static char * playmsg_app
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
static char * sayname_app
#define ast_log
Definition: astobj2.c:42
static int inprocess_hash_fn(const void *obj, const int flags)
#define SENTINEL
Definition: compiler.h:87
static int vmsayname_exec(struct ast_channel *chan, const char *data)
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: main/config.c:3382
static char * vmauthenticate_app
static int vm_execmain(struct ast_channel *chan, const char *data)
static int my_umask
static char VM_SPOOL_DIR[PATH_MAX]
static struct ast_taskprocessor * mwi_subscription_tps
#define ast_vm_register(vm_table)
See __ast_vm_register()
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static int vm_test_destroy_user(const char *context, const char *mailbox)
#define EVENT_FLAG_USER
Definition: manager.h:77
static int vm_playmsgexec(struct ast_channel *chan, const char *data)
static char * voicemail_app
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_cli_entry cli_voicemail[]
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
static struct ao2_container * mailbox_alias_mappings
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int vm_exec(struct ast_channel *chan, const char *data)
static int vm_test_create_user(const char *context, const char *mailbox)
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
static int vmauthenticate(struct ast_channel *chan, const char *data)
#define ast_vm_greeter_register(vm_table)
See __ast_vm_greeter_register()
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
struct ao2_container * inprocess_container

◆ load_users()

static void load_users ( struct ast_config cfg)
static

Definition at line 13660 of file app_voicemail.c.

References append_mailbox(), ast_category_browse(), ast_variable_browse(), ast_variable::name, ast_variable::next, NULL, ast_variable::value, and var.

Referenced by actual_load_config().

13661 {
13662  struct ast_variable *var;
13663  char *cat = NULL;
13664 
13665  while ((cat = ast_category_browse(cfg, cat))) {
13666  if (strcasecmp(cat, "general") == 0
13667  || strcasecmp(cat, aliasescontext) == 0
13668  || strcasecmp(cat, "zonemessages") == 0) {
13669  continue;
13670  }
13671 
13672  var = ast_variable_browse(cfg, cat);
13673  while (var) {
13674  append_mailbox(cat, var->name, var->value);
13675  var = var->next;
13676  }
13677  }
13678 }
struct ast_variable * next
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
static char aliasescontext[MAX_VM_CONTEXT_LEN]
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
static int append_mailbox(const char *context, const char *box, const char *data)

◆ load_zonemessages()

static void load_zonemessages ( struct ast_config cfg)
static

Definition at line 13625 of file app_voicemail.c.

References ast_copy_string(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, AST_LOG_WARNING, ast_malloc, ast_variable_browse(), ast_variable::lineno, vm_zone::list, vm_zone::msg_format, ast_variable::name, vm_zone::name, ast_variable::next, strsep(), vm_zone::timezone, ast_variable::value, and var.

Referenced by actual_load_config().

13626 {
13627  struct ast_variable *var;
13628 
13629  var = ast_variable_browse(cfg, "zonemessages");
13630  while (var) {
13631  if (var->value) {
13632  struct vm_zone *z;
13633  char *msg_format, *tzone;
13634  char storage[strlen(var->value) + 1];
13635 
13636  z = ast_malloc(sizeof(*z));
13637  if (!z) {
13638  return;
13639  }
13640 
13641  strcpy(storage, var->value); /* safe */
13642  msg_format = storage;
13643  tzone = strsep(&msg_format, "|,");
13644  if (msg_format) {
13645  ast_copy_string(z->name, var->name, sizeof(z->name));
13646  ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
13647  ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
13648  AST_LIST_LOCK(&zones);
13651  } else {
13652  ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
13653  ast_free(z);
13654  }
13655  }
13656  var = var->next;
13657  }
13658 }
struct ast_variable * next
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct vm_zone::@83 list
char timezone[80]
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for variables, used for configurations and for channel variables.
#define AST_LOG_WARNING
Definition: logger.h:279
#define var
Definition: ast_expr2f.c:614
char msg_format[512]
#define ast_log
Definition: astobj2.c:42
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
char name[80]
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_free(a)
Definition: astmm.h:182
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ make_dir()

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
folderThe path is constructed as VM_SPOOL_DIRcontext/ext/folder
Returns
zero on success, -1 on error.

Definition at line 1902 of file app_voicemail.c.

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

1903 {
1904  return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
1905 }
const char * ext
Definition: http.c:147
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:116

◆ make_email_file()

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,
const char *  msg_id 
)
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.
flag,msg_idThe 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 5085 of file app_voicemail.c.

References add_email_attachment(), ast_channel_priority(), 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, email, ast_vm_user::email, ast_vm_user::emailbody, emailbody, ast_vm_user::emailsubject, emailsubject, ENDL, ast_vm_user::fromstring, fromstring, ast_vm_user::fullname, host, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, NULL, prep_email_sub_vars(), S_OR, strip_control_and_high(), strsep(), valid_config(), VM_PBXSKIP, and vmu_tm().

Referenced by AST_TEST_DEFINE(), sendmail(), and vm_allocate_dh().

5104 {
5105  char date[256];
5106  char host[MAXHOSTNAMELEN] = "";
5107  char who[256];
5108  char bound[256];
5109  char dur[256];
5110  struct ast_tm tm;
5111  char enc_cidnum[256] = "", enc_cidname[256] = "";
5112  struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
5113  char *greeting_attachment;
5114  char filename[256];
5115  int first_line;
5116  char *emailsbuf;
5117  char *email;
5118 
5119  if (!str1 || !str2) {
5120  ast_free(str1);
5121  ast_free(str2);
5122  return;
5123  }
5124 
5125  if (cidnum) {
5126  strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
5127  }
5128  if (cidname) {
5129  strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
5130  }
5131  gethostname(host, sizeof(host) - 1);
5132 
5133  if (strchr(srcemail, '@')) {
5134  ast_copy_string(who, srcemail, sizeof(who));
5135  } else {
5136  snprintf(who, sizeof(who), "%s@%s", srcemail, host);
5137  }
5138 
5139  greeting_attachment = strrchr(ast_strdupa(attach), '/');
5140  if (greeting_attachment) {
5141  *greeting_attachment++ = '\0';
5142  }
5143 
5144  snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
5145  ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
5146  fprintf(p, "Date: %s" ENDL, date);
5147 
5148  /* Set date format for voicemail mail */
5149  ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
5150 
5152  struct ast_channel *ast;
5153  char *e_fromstring = !ast_strlen_zero(vmu->fromstring) ? vmu->fromstring : fromstring;
5154  if ((ast = ast_dummy_channel_alloc())) {
5155  char *ptr;
5156  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5157  ast_str_substitute_variables(&str1, 0, ast, e_fromstring);
5158 
5159  if (check_mime(ast_str_buffer(str1))) {
5160  first_line = 1;
5161  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
5162  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5163  *ptr = '\0';
5164  fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
5165  first_line = 0;
5166  /* Substring is smaller, so this will never grow */
5167  ast_str_set(&str2, 0, "%s", ptr + 1);
5168  }
5169  fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
5170  } else {
5171  fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
5172  }
5173  ast = ast_channel_unref(ast);
5174  } else {
5175  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5176  }
5177  } else {
5178  fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
5179  }
5180 
5181  emailsbuf = ast_strdupa(vmu->email);
5182  fprintf(p, "To:");
5183  first_line = 1;
5184  while ((email = strsep(&emailsbuf, "|"))) {
5185  char *next = emailsbuf;
5186  if (check_mime(vmu->fullname)) {
5187  char *ptr;
5188  ast_str_encode_mime(&str2, 0, vmu->fullname, first_line ? strlen("To: ") : 0, strlen(email) + 3 + (next ? strlen(",") : 0));
5189  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5190  *ptr = '\0';
5191  fprintf(p, " %s" ENDL, ast_str_buffer(str2));
5192  /* Substring is smaller, so this will never grow */
5193  ast_str_set(&str2, 0, "%s", ptr + 1);
5194  }
5195  fprintf(p, " %s <%s>%s" ENDL, ast_str_buffer(str2), email, next ? "," : "");
5196  } else {
5197  fprintf(p, " %s <%s>%s" ENDL, ast_str_quote(&str2, 0, vmu->fullname), email, next ? "," : "");
5198  }
5199  first_line = 0;
5200  }
5201 
5202  if (msgnum <= -1) {
5203  fprintf(p, "Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
5204  } else if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
5205  char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
5206  struct ast_channel *ast;
5207  if ((ast = ast_dummy_channel_alloc())) {
5208  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5209  ast_str_substitute_variables(&str1, 0, ast, e_subj);
5210  if (check_mime(ast_str_buffer(str1))) {
5211  char *ptr;
5212  first_line = 1;
5213  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
5214  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5215  *ptr = '\0';
5216  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5217  first_line = 0;
5218  /* Substring is smaller, so this will never grow */
5219  ast_str_set(&str2, 0, "%s", ptr + 1);
5220  }
5221  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5222  } else {
5223  fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
5224  }
5225  ast = ast_channel_unref(ast);
5226  } else {
5227  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5228  }
5229  } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
5230  if (ast_strlen_zero(flag)) {
5231  fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5232  } else {
5233  fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
5234  }
5235  } else {
5236  if (ast_strlen_zero(flag)) {
5237  fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5238  } else {
5239  fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
5240  }
5241  }
5242 
5243  fprintf(p, "Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
5244  (unsigned int) ast_random(), mailbox, (int) getpid(), host);
5245  if (imap) {
5246  /* additional information needed for IMAP searching */
5247  fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
5248  /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
5249  fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
5250  fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
5251 #ifdef IMAP_STORAGE
5252  fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
5253 #else
5254  fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
5255 #endif
5256  /* flag added for Urgent */
5257  fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, S_OR(flag, ""));
5258  fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan ? ast_channel_priority(chan) : 0);
5259  fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
5260  fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
5261  fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
5262  if (!ast_strlen_zero(category)) {
5263  fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
5264  } else {
5265  fprintf(p, "X-Asterisk-VM-Category: " ENDL);
5266  }
5267  fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
5268  fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
5269  fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
5270  fprintf(p, "X-Asterisk-VM-Message-ID: %s" ENDL, msg_id);
5271  }
5272  if (!ast_strlen_zero(cidnum)) {
5273  fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
5274  }
5275  if (!ast_strlen_zero(cidname)) {
5276  fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
5277  }
5278  fprintf(p, "MIME-Version: 1.0" ENDL);
5279  if (attach_user_voicemail) {
5280  /* Something unique. */
5281  snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%u", msgnum + 1, mailbox,
5282  (int) getpid(), (unsigned int) ast_random());
5283 
5284  fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
5285  fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
5286  fprintf(p, "--%s" ENDL, bound);
5287  }
5288  fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
5289  if (msgnum <= -1) {
5290  fprintf(p, "This message is to let you know that your greeting '%s' was changed on %s." ENDL
5291  "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
5292  greeting_attachment, date);
5293  } else if (emailbody || vmu->emailbody) {
5294  char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
5295  struct ast_channel *ast;
5296  if ((ast = ast_dummy_channel_alloc())) {
5297  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5298  ast_str_substitute_variables(&str1, 0, ast, e_body);
5299 #ifdef IMAP_STORAGE
5300  {
5301  /* Convert body to native line terminators for IMAP backend */
5302  char *line = ast_str_buffer(str1), *next;
5303  do {
5304  /* Terminate line before outputting it to the file */
5305  if ((next = strchr(line, '\n'))) {
5306  *next++ = '\0';
5307  }
5308  fprintf(p, "%s" ENDL, line);
5309  line = next;
5310  } while (!ast_strlen_zero(line));
5311  }
5312 #else
5313  fprintf(p, "%s" ENDL, ast_str_buffer(str1));
5314 #endif
5315  ast = ast_channel_unref(ast);
5316  } else {
5317  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5318  }
5319  } else {
5320  if (strcmp(vmu->mailbox, mailbox)) {
5321  /* Forwarded type */
5322  struct ast_config *msg_cfg;
5323  const char *v;
5324  int inttime;
5325  char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
5326  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
5327  /* Retrieve info from VM attribute file */
5328  make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
5329  make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
5330  if (strlen(fromfile) < sizeof(fromfile) - 5) {
5331  strcat(fromfile, ".txt");
5332  }
5333  if ((msg_cfg = ast_config_load(fromfile, config_flags)) && valid_config(msg_cfg)) {
5334  if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
5335  ast_copy_string(origcallerid, v, sizeof(origcallerid));
5336  }
5337 
5338  /* You might be tempted to do origdate, except that a) it's in the wrong
5339  * format, and b) it's missing for IMAP recordings. */
5340  if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
5341  struct timeval tv = { inttime, };
5342  struct ast_tm tm;
5343  ast_localtime(&tv, &tm, NULL);
5344  ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
5345  }
5346  fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
5347  " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
5348  "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
5349  " chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
5350  msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
5351  date, origcallerid, origdate);
5352  ast_config_destroy(msg_cfg);
5353  } else {
5354  goto plain_message;
5355  }
5356  } else {
5357 plain_message:
5358  fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
5359  "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
5360  "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
5361  ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
5362  (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
5363  }
5364  }
5365 
5366  if (imap || attach_user_voicemail) {
5367  if (!ast_strlen_zero(attach2)) {
5368  snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
5369  ast_debug(5, "creating second attachment filename %s\n", filename);
5370  add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
5371  snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
5372  ast_debug(5, "creating attachment filename %s\n", filename);
5373  add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5374  } else {
5375  snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
5376  ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
5377  add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5378  }
5379  }
5380  ast_free(str1);
5381  ast_free(str2);
5382 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#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...
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1739
static char email[80]
Definition: pbx_dundi.c:206
#define AST_LOG_WARNING
Definition: logger.h:279
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#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...
#define NULL
Definition: resample.c:96
static char * emailsubject
int ast_channel_priority(const struct ast_channel *chan)
static char fromstring[100]
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1065
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char locale[20]
#define ast_config_load(filename, flags)
Load a config file.
static char host[256]
Definition: muted.c:77
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 struct ast_flags globalflags
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
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)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
long int ast_random(void)
Definition: main/utils.c:2064
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2452
#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
char fromstring[100]
char * emailbody
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
long int flag
Definition: f2c.h:83
#define ast_free(a)
Definition: astmm.h:182
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:2524
charset
Definition: chan_unistim.c:336
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char * emailsubject
char fullname[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static const 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.
static snd_pcm_format_t format
Definition: chan_alsa.c:102
char mailbox[MAX_VM_MBOX_ID_LEN]
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)
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ make_file()

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
numThe path is constructed as VM_SPOOL_DIRcontext/ext/folder
Returns
zero on success, -1 on error.

Definition at line 1919 of file app_voicemail.c.

Referenced by advanced_options(), AST_TEST_DEFINE(), close_mailbox(), copy_message(), forward_message(), leave_voicemail(), make_email_file(), message_range_and_existence_check(), msg_create_from_file(), notify_new_message(), play_message(), play_message_by_id_helper(), prep_email_sub_vars(), resequence_mailbox(), save_to_folder(), vm_allocate_dh(), vm_execmain(), vm_forwardoptions(), vm_msg_forward(), vm_msg_play(), and vm_msg_snapshot_create().

1920 {
1921  return snprintf(dest, len, "%s/msg%04d", dir, num);
1922 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ manager_list_voicemail_users()

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

Manager list voicemail users command.

Definition at line 13428 of file app_voicemail.c.

References append_vmu_info_astman(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), ast_vm_user::list, LOG_ERROR, NULL, and RESULT_SUCCESS.

Referenced by load_module().

13429 {
13430  struct ast_vm_user *vmu = NULL;
13431  const char *id = astman_get_header(m, "ActionID");
13432  char actionid[128];
13433  int num_users = 0;
13434  int ret;
13435 
13436  actionid[0] = '\0';
13437  if (!ast_strlen_zero(id)) {
13438  snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
13439  }
13440 
13441  AST_LIST_LOCK(&users);
13442 
13443  if (AST_LIST_EMPTY(&users)) {
13444  astman_send_ack(s, m, "There are no voicemail users currently defined.");
13446  return RESULT_SUCCESS;
13447  }
13448 
13449  astman_send_listack(s, m, "Voicemail user list will follow", "start");
13450 
13451  AST_LIST_TRAVERSE(&users, vmu, list) {
13452  /* append vmu info event */
13453  ret = append_vmu_info_astman(s, vmu, "VoicemailUserEntry", actionid);
13454  if(ret == 0) {
13455  ast_log(LOG_ERROR, "Could not append voicemail user info.");
13456  continue;
13457  }
13458  ++num_users;
13459  }
13460 
13461  astman_send_list_complete_start(s, m, "VoicemailUserEntryComplete", num_users);
13463 
13465 
13466  return RESULT_SUCCESS;
13467 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmu info string into given astman with event_name.
#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:3191
#define NULL
Definition: resample.c:96
list of users found in the config file
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_vm_user::@82 list
#define ast_log
Definition: astobj2.c:42
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define RESULT_SUCCESS
Definition: cli.h:40
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201

◆ manager_match_mailbox()

static int manager_match_mailbox ( struct ast_mwi_state mwi_state,
void *  data 
)
static

Definition at line 13344 of file app_voicemail.c.

References ast_strlen_zero, astman_get_header(), NULL, poll_subscribed_mailbox(), and ast_mwi_state::uniqueid.

Referenced by manager_voicemail_refresh().

13345 {
13346  const char *context = astman_get_header(data, "Context");
13347  const char *mailbox = astman_get_header(data, "Mailbox");
13348  const char *at;
13349 
13350  if (!ast_strlen_zero(mwi_state->uniqueid)) {
13351  if (
13352  /* First case: everything matches */
13353  (ast_strlen_zero(context) && ast_strlen_zero(mailbox)) ||
13354  /* Second case: match the mailbox only */
13355  (ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&
13356  (at = strchr(mwi_state->uniqueid, '@')) &&
13357  strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0) ||
13358  /* Third case: match the context only */
13359  (!ast_strlen_zero(context) && ast_strlen_zero(mailbox) &&
13360  (at = strchr(mwi_state->uniqueid, '@')) &&
13361  strcmp(context, at + 1) == 0) ||
13362  /* Final case: match an exact specified mailbox */
13363  (!ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&
13364  (at = strchr(mwi_state->uniqueid, '@')) &&
13365  strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0 &&
13366  strcmp(context, at + 1) == 0)
13367  ) {
13368  poll_subscribed_mailbox(mwi_state, NULL);
13369  }
13370  }
13371 
13372  return 0;
13373 }
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)
const ast_string_field uniqueid
Definition: mwi.h:460
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ manager_status_voicemail_user()

static int manager_status_voicemail_user ( struct mansession s,
const struct message m 
)
static

Definition at line 13382 of file app_voicemail.c.

References append_vmu_info_astman(), ast_log, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), find_user(), free_user(), LOG_ERROR, NULL, and RESULT_SUCCESS.

Referenced by load_module().

13383 {
13384  struct ast_vm_user *vmu = NULL;
13385  const char *id = astman_get_header(m, "ActionID");
13386  char actionid[128];
13387  struct ast_vm_user svm;
13388  int ret;
13389 
13390  const char *context = astman_get_header(m, "Context");
13391  const char *mailbox = astman_get_header(m, "Mailbox");
13392 
13393  if ((ast_strlen_zero(context) || ast_strlen_zero(mailbox))) {
13394  astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters.");
13395  return RESULT_SUCCESS;
13396  }
13397 
13398  actionid[0] = '\0';
13399  if (!ast_strlen_zero(id)) {
13400  snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
13401  }
13402 
13403  /* find user */
13404  memset(&svm, 0, sizeof(svm));
13405  vmu = find_user(&svm, context, mailbox);
13406  if (!vmu) {
13407  /* could not find it */
13408  astman_send_ack(s, m, "There is no voicemail user of the given info.");
13409  return RESULT_SUCCESS;
13410  }
13411 
13412  astman_send_listack(s, m, "Voicemail user detail will follow", "start");
13413 
13414  /* append vmu info event */
13415  ret = append_vmu_info_astman(s, vmu, "VoicemailUserDetail", actionid);
13416  free_user(vmu);
13417  if(ret == 0) {
13418  ast_log(LOG_ERROR, "Could not append voicemail user info.");
13419  }
13420 
13421  astman_send_list_complete_start(s, m, "VoicemailUserDetailComplete", 1);
13423 
13424  return RESULT_SUCCESS;
13425 }
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmu info string into given astman with event_name.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
static void free_user(struct ast_vm_user *vmu)
#define LOG_ERROR
Definition: logger.h:285
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 char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define RESULT_SUCCESS
Definition: cli.h:40
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201

◆ manager_voicemail_refresh()

static int manager_voicemail_refresh ( struct mansession s,
const struct message m 
)
static

Definition at line 13375 of file app_voicemail.c.

References ast_mwi_state_callback_all(), astman_send_ack(), manager_match_mailbox(), and RESULT_SUCCESS.

Referenced by load_module().

13376 {
13378  astman_send_ack(s, m, "Refresh sent");
13379  return RESULT_SUCCESS;
13380 }
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data)
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
Definition: mwi.c:333
#define RESULT_SUCCESS
Definition: cli.h:40

◆ mb_poll_thread()

static void* mb_poll_thread ( void *  data)
static

Definition at line 13074 of file app_voicemail.c.

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_mwi_state_callback_subscribed(), ast_samp2tv(), ast_strdupa, ast_strlen_zero, ast_tvadd(), ast_tvnow(), context, find_user(), free_user(), mailbox, NULL, poll_lock, poll_subscribed_mailbox(), RAII_VAR, separate_mailbox(), and ast_mwi_state::uniqueid.

Referenced by start_poll_thread().

13075 {
13076  while (poll_thread_run) {
13077  struct timespec ts = { 0, };
13078  struct timeval wait;
13079 
13081 
13082  if (!poll_thread_run) {
13083  break;
13084  }
13085 
13086  wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
13087  ts.tv_sec = wait.tv_sec;
13088  ts.tv_nsec = wait.tv_usec * 1000;
13089 
13093  }
13094 
13095  return NULL;
13096 }
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
void ast_mwi_state_callback_subscribed(on_mwi_state handler, void *data)
For each managed mailbox that has a subscriber call the given handler.
Definition: mwi.c:343
static ast_cond_t poll_cond
#define NULL
Definition: resample.c:96
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:238
static ast_mutex_t poll_lock
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
static unsigned char poll_thread_run
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
static unsigned int poll_freq
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mbox()

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

Definition at line 1961 of file app_voicemail.c.

References ARRAY_LEN, and id.

Referenced by add_peer_mailboxes(), adsi_load_vmail(), copy_message(), get_folder(), get_folder_ja(), notify_new_message(), open_mailbox(), save_to_folder(), vm_allocate_dh(), vm_execmain(), and vm_index_to_foldername().

1962 {
1963 #ifdef IMAP_STORAGE
1964  if (vmu && id == 0) {
1965  return vmu->imapfolder;
1966  }
1967 #endif
1968  return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
1969 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char *const mailbox_folders[]
enum queue_result id
Definition: app_queue.c:1507

◆ message_range_and_existence_check()

static int message_range_and_existence_check ( struct vm_state vms,
const char *  msg_ids[],
size_t  num_msgs,
int *  msg_nums,
struct ast_vm_user vmu 
)
static

common bounds checking and existence check for Voicemail API functions.

This is called by vm_msg_move, vm_msg_remove, and vm_msg_forward to ensure that data passed in are valid. This ensures that given the desired message IDs, they can be found.

Parameters
vmsThe voicemail state corresponding to an open mailbox
msg_idsAn array of message identifiers
num_msgsThe number of identifiers in msg_ids
msg_nums[out] The message indexes corresponding to the given
vmumessage IDs
Precondition
vms must have open_mailbox() called on it prior to this function.
Return values
-1Failure
0Success

Definition at line 16082 of file app_voicemail.c.

References ast_config_destroy(), ast_config_load, ast_strlen_zero, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, done, vm_state::fn, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), PATH_MAX, and RETRIEVE.

Referenced by play_message_by_id_helper(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

16083 {
16084  int i;
16085  int res = 0;
16086  for (i = 0; i < num_msgs; ++i) {
16087  const char *msg_id = msg_ids[i];
16088  int found = 0;
16089  for (vms->curmsg = 0; vms->curmsg <= vms->lastmsg; vms->curmsg++) {
16090  const char *other_msg_id;
16091  char filename[PATH_MAX];
16092  struct ast_config *msg_cfg;
16093  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
16094 
16095  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
16096  snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
16097  RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
16098  msg_cfg = ast_config_load(filename, config_flags);
16099  if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
16100  DISPOSE(vms->curdir, vms->curmsg);
16101  res = -1;
16102  goto done;
16103  }
16104 
16105  other_msg_id = ast_variable_retrieve(msg_cfg, "message", "msg_id");
16106 
16107  if (!ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
16108  /* Message found. We can get out of this inner loop
16109  * and move on to the next message to find
16110  */
16111  found = 1;
16112  msg_nums[i] = vms->curmsg;
16113  ast_config_destroy(msg_cfg);
16114  DISPOSE(vms->curdir, vms->curmsg);
16115  break;
16116  }
16117  ast_config_destroy(msg_cfg);
16118  DISPOSE(vms->curdir, vms->curmsg);
16119  }
16120  if (!found) {
16121  /* If we can't find one of the message IDs requested, then OH NO! */
16122  res = -1;
16123  goto done;
16124  }
16125  }
16126 
16127 done:
16128  return res;
16129 }
#define CONFIG_STATUS_FILEINVALID
char curdir[PATH_MAX]
#define DISPOSE(a, b)
char fn[PATH_MAX]
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
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 done
Definition: test_amihooks.c:48
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
Structure used to handle boolean flags.
Definition: utils.h:199
#define RETRIEVE(a, b, c, d)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define PATH_MAX
Definition: asterisk.h:40
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ messagecount()

static int messagecount ( const char *  mailbox_id,
const char *  folder 
)
static
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 6048 of file app_voicemail.c.

References __has_voicemail(), ast_strdupa, ast_strlen_zero, context, mailbox, and separate_mailbox().

Referenced by acf_vm_info(), ast_app_messagecount(), free_zone(), and vm_allocate_dh().

6049 {
6050  char *context;
6051  char *mailbox;
6052 
6053  if (ast_strlen_zero(mailbox_id)
6054  || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
6055  return 0;
6056  }
6057 
6058  return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
6059 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
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:116

◆ msg_create_from_file()

static int msg_create_from_file ( struct ast_vm_recording_data recdata)
static

Definition at line 6315 of file app_voicemail.c.

References ast_check_realtime(), ast_closestream(), ast_debug, ast_destroy_realtime(), ast_filecopy(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_log, AST_LOG_ERROR, AST_LOG_WARNING, ast_ratestream(), ast_readfile(), ast_seekstream(), ast_store_realtime(), ast_strdupa, ast_tellstream(), ast_unlock_path(), ast_vm_recording_data::call_callerchan, ast_vm_recording_data::call_callerid, ast_vm_recording_data::call_context, ast_vm_recording_data::call_extension, ast_vm_recording_data::call_macrocontext, ast_vm_recording_data::call_priority, ast_vm_recording_data::context, ast_vm_user::context, count_messages(), create_dirpath(), errno, find_user(), ast_vm_recording_data::folder, free_user(), generate_msg_id(), get_date(), inboxcount(), inprocess_count(), last_message_index(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_vm_recording_data::mailbox, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, MSG_ID_LEN, vm_state::newmessages, notify_new_state(), NULL, PATH_MAX, ast_vm_recording_data::recording_ext, ast_vm_recording_data::recording_file, S_OR, SENTINEL, STORE, vm_lock_path(), VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

6316 {
6317  /* voicemail recipient structure */
6318  struct ast_vm_user *recipient; /* points to svm once it's been created */
6319  struct ast_vm_user svm; /* struct storing the voicemail recipient */
6320 
6321  /* File paths */
6322  char tmpdir[PATH_MAX]; /* directory temp files are stored in */
6323  char tmptxtfile[PATH_MAX]; /* tmp file for voicemail txt file */
6324  char desttxtfile[PATH_MAX]; /* final destination for txt file */
6325  char tmpaudiofile[PATH_MAX]; /* tmp file where audio is stored */
6326  char dir[PATH_MAX]; /* destination for tmp files on completion */
6327  char destination[PATH_MAX]; /* destination with msgXXXX. Basically <dir>/msgXXXX */
6328 
6329  /* stuff that only seems to be needed for IMAP */
6330  #ifdef IMAP_STORAGE
6331  struct vm_state *vms = NULL;
6332  char ext_context[256] = "";
6333  char *fmt = ast_strdupa(recdata->recording_ext);
6334  int newmsgs = 0;
6335  int oldmsgs = 0;
6336  #endif
6337 
6338  /* miscellaneous operational variables */
6339  int res = 0; /* Used to store error codes from functions */
6340  int txtdes /* File descriptor for the text file used to write the voicemail info */;
6341  FILE *txt; /* FILE pointer to text file used to write the voicemail info */
6342  char date[256]; /* string used to hold date of the voicemail (only used for ODBC) */
6343  int msgnum; /* the 4 digit number designated to the voicemail */
6344  int duration = 0; /* Length of the audio being recorded in seconds */
6345  struct ast_filestream *recording_fs; /*used to read the recording to get duration data */
6346 
6347  /* We aren't currently doing anything with category, since it comes from a channel variable and
6348  * this function doesn't use channels, but this function could add that as an argument later. */
6349  const char *category = NULL; /* pointless for now */
6350  char msg_id[MSG_ID_LEN];
6351 
6352  /* Start by checking to see if the file actually exists... */
6353  if (!(ast_fileexists(recdata->recording_file, recdata->recording_ext, NULL))) {
6354  ast_log(LOG_ERROR, "File: %s not found.\n", recdata->recording_file);
6355  return -1;
6356  }
6357 
6358  memset(&svm, 0, sizeof(svm));
6359  if (!(recipient = find_user(&svm, recdata->context, recdata->mailbox))) {
6360  ast_log(LOG_ERROR, "No entry in voicemail config file for '%s@%s'\n", recdata->mailbox, recdata->context);
6361  return -1;
6362  }
6363 
6364  /* determine duration in seconds */
6365  if ((recording_fs = ast_readfile(recdata->recording_file, recdata->recording_ext, NULL, 0, 0, VOICEMAIL_DIR_MODE))) {
6366  if (!ast_seekstream(recording_fs, 0, SEEK_END)) {
6367  long framelength = ast_tellstream(recording_fs);
6368  int sample_rate = ast_ratestream(recording_fs);
6369  if (sample_rate) {
6370  duration = (int) (framelength / sample_rate);
6371  } else {
6372  ast_log(LOG_ERROR,"Unable to determine sample rate of recording %s\n", recdata->recording_file);
6373  }
6374  }
6375  ast_closestream(recording_fs);
6376  }
6377 
6378  /* If the duration was below the minimum duration for the user, let's just drop the whole thing now */
6379  if (duration < recipient->minsecs) {
6380  ast_log(LOG_NOTICE, "Copying recording to voicemail %s@%s skipped because duration was shorter than "
6381  "minmessage of recipient\n", recdata->mailbox, recdata->context);
6382  return -1;
6383  }
6384 
6385  /* Note that this number must be dropped back to a net sum of zero before returning from this function */
6386 
6387  if ((res = create_dirpath(tmpdir, sizeof(tmpdir), recipient->context, recdata->mailbox, "tmp"))) {
6388  ast_log(LOG_ERROR, "Failed to make directory.\n");
6389  }
6390 
6391  snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
6392  txtdes = mkstemp(tmptxtfile);
6393  if (txtdes < 0) {
6394  chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
6395  /* Something screwed up. Abort. */
6396  ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
6397  free_user(recipient);
6398  return -1;
6399  }
6400 
6401  /* Store information */
6402  txt = fdopen(txtdes, "w+");
6403  if (txt) {
6404  generate_msg_id(msg_id);
6405  get_date(date, sizeof(date));
6406  fprintf(txt,
6407  ";\n"
6408  "; Message Information file\n"
6409  ";\n"
6410  "[message]\n"
6411  "origmailbox=%s\n"
6412  "context=%s\n"
6413  "macrocontext=%s\n"
6414  "exten=%s\n"
6415  "rdnis=Unknown\n"
6416  "priority=%d\n"
6417  "callerchan=%s\n"
6418  "callerid=%s\n"
6419  "origdate=%s\n"
6420  "origtime=%ld\n"
6421  "category=%s\n"
6422  "msg_id=%s\n"
6423  "flag=\n" /* flags not supported in copy from file yet */
6424  "duration=%d\n", /* Don't have any reliable way to get duration of file. */
6425 
6426  recdata->mailbox,
6427  S_OR(recdata->call_context, ""),
6428  S_OR(recdata->call_macrocontext, ""),
6429  S_OR(recdata->call_extension, ""),
6430  recdata->call_priority,
6431  S_OR(recdata->call_callerchan, "Unknown"),
6432  S_OR(recdata->call_callerid, "Unknown"),
6433  date, (long) time(NULL),
6434  S_OR(category, ""),
6435  msg_id,
6436  duration);
6437 
6438  /* Since we are recording from a file, we shouldn't need to do anything else with
6439  * this txt file */
6440  fclose(txt);
6441 
6442  } else {
6443  ast_log(LOG_WARNING, "Error opening text file for output\n");
6444  if (ast_check_realtime("voicemail_data")) {
6445  ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
6446  }
6447  free_user(recipient);
6448  return -1;
6449  }
6450 
6451  /* At this point, the actual creation of a voicemail message should be finished.
6452  * Now we just need to copy the files being recorded into the receiving folder. */
6453 
6454  create_dirpath(dir, sizeof(dir), recipient->context, recipient->mailbox, recdata->folder);
6455 
6456 #ifdef IMAP_STORAGE
6457  /* make recipient info into an inboxcount friendly string */
6458  snprintf(ext_context, sizeof(ext_context), "%s@%s", recipient->mailbox, recipient->context);
6459 
6460  /* Is ext a mailbox? */
6461  /* must open stream for this user to get info! */
6462  res = inboxcount(ext_context, &newmsgs, &oldmsgs);
6463  if (res < 0) {
6464  ast_log(LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
6465  free_user(recipient);
6466  unlink(tmptxtfile);
6467  return -1;
6468  }
6469  if (!(vms = get_vm_state_by_mailbox(recipient->mailbox, recipient->context, 0))) {
6470  /* It is possible under certain circumstances that inboxcount did not
6471  * create a vm_state when it was needed. This is a catchall which will
6472  * rarely be used.
6473  */
6474  if (!(vms = create_vm_state_from_user(recipient))) {
6475  ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
6476  free_user(recipient);
6477  unlink(tmptxtfile);
6478  return -1;
6479  }
6480  }
6481  vms->newmessages++;
6482 
6483  /* here is a big difference! We add one to it later */
6484  msgnum = newmsgs + oldmsgs;
6485  ast_debug(3, "Messagecount set to %d\n", msgnum);
6486  snprintf(destination, sizeof(destination), "%simap/msg%s%04d", VM_SPOOL_DIR, recipient->mailbox, msgnum);
6487 
6488  /* Check to see if we have enough room in the mailbox. If not, spit out an error and end
6489  * Note that imap_check_limits raises inprocess_count if successful */
6490  if ((res = imap_check_limits(NULL, vms, recipient, msgnum))) {
6491  ast_log(LOG_NOTICE, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context);
6492  inprocess_count(recipient->mailbox, recipient->context, -1);
6493  free_user(recipient);
6494  unlink(tmptxtfile);
6495  return -1;
6496  }
6497 
6498 #else
6499 
6500  /* Check to see if the mailbox is full for ODBC/File storage */
6501  ast_debug(3, "mailbox = %d : inprocess = %d\n", count_messages(recipient, dir),
6502  inprocess_count(recipient->mailbox, recipient->context, 0));
6503  if (count_messages(recipient, dir) > recipient->maxmsg - inprocess_count(recipient->mailbox, recipient->context, +1)) {
6504  ast_log(AST_LOG_WARNING, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context);
6505  inprocess_count(recipient->mailbox, recipient->context, -1);
6506  free_user(recipient);
6507  unlink(tmptxtfile);
6508  return -1;
6509  }
6510 
6511  msgnum = last_message_index(recipient, dir) + 1;
6512 #endif
6513 
6514  /* Lock the directory receiving the voicemail since we want it to still exist when we attempt to copy the voicemail.
6515  * We need to unlock it before we return. */
6516  if (vm_lock_path(dir)) {
6517  ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6518  /* Delete files */
6519  ast_filedelete(tmptxtfile, NULL);
6520  unlink(tmptxtfile);
6521  free_user(recipient);
6522  return -1;
6523  }
6524 
6525  make_file(destination, sizeof(destination), dir, msgnum);
6526 
6527  make_file(tmpaudiofile, sizeof(tmpaudiofile), tmpdir, msgnum);
6528 
6529  if (ast_filecopy(recdata->recording_file, tmpaudiofile, recdata->recording_ext)) {
6530  ast_log(LOG_ERROR, "Audio file failed to copy to tmp dir. Probably low disk space.\n");
6531 
6532  inprocess_count(recipient->mailbox, recipient->context, -1);
6533  ast_unlock_path(dir);
6534  free_user(recipient);
6535  unlink(tmptxtfile);
6536  return -1;
6537  }
6538 
6539  /* Alright, try to copy to the destination folder now. */
6540  if (ast_filerename(tmpaudiofile, destination, recdata->recording_ext)) {
6541  ast_log(LOG_ERROR, "Audio file failed to move to destination directory. Permissions/Overlap?\n");
6542  inprocess_count(recipient->mailbox, recipient->context, -1);
6543  ast_unlock_path(dir);
6544  free_user(recipient);
6545  unlink(tmptxtfile);
6546  return -1;
6547  }
6548 
6549  snprintf(desttxtfile, sizeof(desttxtfile), "%s.txt", destination);
6550  rename(tmptxtfile, desttxtfile);
6551 
6552  if (chmod(desttxtfile, VOICEMAIL_FILE_MODE) < 0) {
6553  ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", desttxtfile, strerror(errno));
6554  }
6555 
6556 
6557  ast_unlock_path(dir);
6558  inprocess_count(recipient->mailbox, recipient->context, -1);
6559 
6560  /* If we copied something, we should store it either to ODBC or IMAP if we are using those. The STORE macro allows us
6561  * to do both with one line and is also safe to use with file storage mode. Also, if we are using ODBC, now is a good
6562  * time to create the voicemail database entry. */
6563  if (ast_fileexists(destination, NULL, NULL) > 0) {
6564  if (ast_check_realtime("voicemail_data")) {
6565  get_date(date, sizeof(date));
6566  ast_store_realtime("voicemail_data",
6567  "origmailbox", recdata->mailbox,
6568  "context", S_OR(recdata->context, ""),
6569  "macrocontext", S_OR(recdata->call_macrocontext, ""),
6570  "exten", S_OR(recdata->call_extension, ""),
6571  "priority", recdata->call_priority,
6572  "callerchan", S_OR(recdata->call_callerchan, "Unknown"),
6573  "callerid", S_OR(recdata->call_callerid, "Unknown"),
6574  "origdate", date,
6575  "origtime", time(NULL),
6576  "category", S_OR(category, ""),
6577  "filename", tmptxtfile,
6578  "duration", duration,
6579  SENTINEL);
6580  }
6581 
6582  STORE(dir, recipient->mailbox, recipient->context, msgnum, NULL, recipient, fmt, 0, vms, "", msg_id);
6583  notify_new_state(recipient);
6584  }
6585 
6586  free_user(recipient);
6587  unlink(tmptxtfile);
6588  return 0;
6589 }
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:1108
#define MSG_ID_LEN
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
const ast_string_field recording_file
const ast_string_field mailbox
#define LOG_WARNING
Definition: logger.h:274
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
#define AST_LOG_WARNING
Definition: logger.h:279
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
static int inprocess_count(const char *context, const char *mailbox, int delta)
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
const ast_string_field folder
char context[MAX_VM_CONTEXT_LEN]
static int get_date(char *s, int len)
Gets the current date and time, as formatted string.
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
const ast_string_field recording_ext
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1048
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_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define SENTINEL
Definition: compiler.h:87
#define AST_LOG_ERROR
Definition: logger.h:290
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
Definition: main/config.c:3570
const ast_string_field call_macrocontext
static void notify_new_state(struct ast_vm_user *vmu)
static int my_umask
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
static char VM_SPOOL_DIR[PATH_MAX]
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)
int ast_ratestream(struct ast_filestream *fs)
Return the sample rate of the stream&#39;s format.
Definition: file.c:1053
const ast_string_field call_callerid
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field context
int errno
#define LOG_NOTICE
Definition: logger.h:263
const ast_string_field call_callerchan
#define VOICEMAIL_DIR_MODE
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1038
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_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1068
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
Definition: main/config.c:3606
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
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_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
struct ast_filestream * ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts reading from a file.
Definition: file.c:1309
#define VOICEMAIL_FILE_MODE
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
#define PATH_MAX
Definition: asterisk.h:40
const ast_string_field call_context
char mailbox[MAX_VM_MBOX_ID_LEN]
int newmessages
const ast_string_field call_extension

◆ mwi_handle_subscribe()

static void mwi_handle_subscribe ( const char *  id,
struct ast_mwi_subscriber sub 
)
static

Definition at line 13181 of file app_voicemail.c.

References ao2_ref, ast_mwi_subscriber_data(), ast_taskprocessor_push(), and mwi_handle_subscribe2().

13182 {
13183  void *data = ast_mwi_subscriber_data(sub);
13184 
13185  /* Don't bump data's reference. We'll just use the one returned above */
13187  /* A reference was returned for data when retrieving, so remove it on error */
13188  ao2_ref(data, -1);
13189  }
13190 }
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
Definition: mwi.c:264
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_taskprocessor * mwi_subscription_tps
static int mwi_handle_subscribe2(void *data)
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.

◆ mwi_handle_subscribe2()

static int mwi_handle_subscribe2 ( void *  data)
static

Definition at line 13174 of file app_voicemail.c.

References ao2_ref, NULL, and poll_subscribed_mailbox().

Referenced by mwi_handle_subscribe().

13175 {
13177  ao2_ref(data, -1);
13178  return 0;
13179 }
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)

◆ mwi_handle_unsubscribe()

static void mwi_handle_unsubscribe ( const char *  id,
struct ast_mwi_subscriber sub 
)
static

Definition at line 13163 of file app_voicemail.c.

References ao2_ref, ast_mwi_subscriber_data(), ast_taskprocessor_push(), and mwi_handle_unsubscribe2().

13164 {
13165  void *data = ast_mwi_subscriber_data(sub);
13166 
13167  /* Don't bump data's reference. We'll just use the one returned above */
13169  /* A reference was returned for data when retrieving, so remove it on error */
13170  ao2_ref(data, -1);
13171  }
13172 }
static int mwi_handle_unsubscribe2(void *data)
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
Definition: mwi.c:264
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_taskprocessor * mwi_subscription_tps
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.

◆ mwi_handle_unsubscribe2()

static int mwi_handle_unsubscribe2 ( void *  data)
static

Definition at line 13144 of file app_voicemail.c.

References ao2_ref, ast_delete_mwi_state_full(), NULL, and ast_mwi_state::uniqueid.

Referenced by mwi_handle_unsubscribe().

13145 {
13146  struct ast_mwi_state *mwi_state = data;
13147 
13148  /*
13149  * Go ahead and clear the implicit MWI publisher here to avoid a leak. If a backing
13150  * configuration is available it'll re-initialize (reset the cached state) on its
13151  * next publish.
13152  */
13154 
13155 #ifdef IMAP_STORAGE
13156  imap_close_subscribed_mailbox(mwi_state, NULL);
13157 #endif
13158 
13159  ao2_ref(mwi_state, -1);
13160  return 0;
13161 }
int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)
Delete MWI state cached by stasis with all parameters.
Definition: mwi.c:399
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const ast_string_field uniqueid
Definition: mwi.h:460
The structure that contains MWI state.
Definition: mwi.h:457

◆ notify_new_message()

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

References ast_app_has_voicemail(), ast_app_inboxcount2(), ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, ast_config_destroy(), ast_config_load, ast_log, AST_LOG_WARNING, ast_strdupa, ast_strlen_zero, ast_test_flag, ast_variable_retrieve(), ast_vm_user::attachfmt, CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curmsg, DELETE, DISPOSE, ast_vm_user::email, ast_vm_user::mailbox, make_dir(), make_file(), mbox(), vm_state::newmessages, NULL, ast_vm_user::pager, PATH_MAX, 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().

8156 {
8157  char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
8158  int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8159  const char *category;
8160  char *myserveremail = serveremail;
8161 
8162  ast_channel_lock(chan);
8163  if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
8164  category = ast_strdupa(category);
8165  }
8166  ast_channel_unlock(chan);
8167 
8168 #ifndef IMAP_STORAGE
8169  make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
8170 #else
8171  snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
8172 #endif
8173  make_file(fn, sizeof(fn), todir, msgnum);
8174  snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
8175 
8176  if (!ast_strlen_zero(vmu->attachfmt)) {
8177  if (strstr(fmt, vmu->attachfmt))
8178  fmt = vmu->attachfmt;
8179  else
8180  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);
8181  }
8182 
8183  /* Attach only the first format */
8184  fmt = ast_strdupa(fmt);
8185  stringp = fmt;
8186  strsep(&stringp, "|");
8187 
8188  if (!ast_strlen_zero(vmu->serveremail))
8189  myserveremail = vmu->serveremail;
8190 
8191  if (!ast_strlen_zero(vmu->email)) {
8192  int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
8193  char *msg_id = NULL;
8194 #ifdef IMAP_STORAGE
8195  struct ast_config *msg_cfg;
8196  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8197  char filename[PATH_MAX];
8198 
8199  snprintf(filename, sizeof(filename), "%s.txt", fn);
8200  msg_cfg = ast_config_load(filename, config_flags);
8201  if (msg_cfg && msg_cfg != CONFIG_STATUS_FILEINVALID) {
8202  msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
8203  ast_config_destroy(msg_cfg);
8204  }
8205 #endif
8206 
8207  if (attach_user_voicemail)
8208  RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
8209 
8210  /* XXX possible imap issue, should category be NULL XXX */
8211  sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag, msg_id);
8212 
8213  if (attach_user_voicemail)
8214  DISPOSE(todir, msgnum);
8215  }
8216 
8217  if (!ast_strlen_zero(vmu->pager)) {
8218  sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
8219  }
8220 
8221  if (ast_test_flag(vmu, VM_DELETE))
8222  DELETE(todir, msgnum, fn, vmu);
8223 
8224  /* Leave voicemail for someone */
8225  if (ast_app_has_voicemail(ext_context, NULL))
8226  ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
8227 
8228  queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgentmsgs, newmsgs, oldmsgs);
8229  run_externnotify(vmu->context, vmu->mailbox, flag);
8230 
8231 #ifdef IMAP_STORAGE
8232  vm_delete(fn); /* Delete the file, but not the IMAP message */
8233  if (ast_test_flag(vmu, VM_DELETE)) { /* Delete the IMAP message if delete = yes */
8234  vm_imap_delete(NULL, vms->curmsg, vmu);
8235  vms->newmessages--; /* Fix new message count */
8236  }
8237 #endif
8238 
8239  return 0;
8240 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#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 CONFIG_STATUS_FILEINVALID
#define AST_LOG_WARNING
Definition: logger.h:279
#define VM_ATTACH
char pager[80]
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, const char *msg_id)
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char context[MAX_VM_CONTEXT_LEN]
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
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...
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: main/app.c:692
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define VM_DELETE
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
#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.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static void run_externnotify(const char *context, const char *extension, const char *flag)
long int flag
Definition: f2c.h:83
#define ast_channel_unlock(chan)
Definition: channel.h:2946
Structure used to handle boolean flags.
Definition: utils.h:199
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:655
#define RETRIEVE(a, b, c, d)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
char * strsep(char **str, const char *delims)
char serveremail[80]
char attachfmt[20]
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)
#define PATH_MAX
Definition: asterisk.h:40
char mailbox[MAX_VM_MBOX_ID_LEN]
static char serveremail[80]
int newmessages

◆ notify_new_state()

static void notify_new_state ( struct ast_vm_user vmu)
static

Definition at line 16131 of file app_voicemail.c.

References ast_app_inboxcount2(), ast_vm_user::context, ast_vm_user::mailbox, NULL, queue_mwi_event(), and run_externnotify().

Referenced by msg_create_from_file(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

16132 {
16133  int new = 0, old = 0, urgent = 0;
16134  char ext_context[1024];
16135 
16136  snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
16137  run_externnotify(vmu->context, vmu->mailbox, NULL);
16138  ast_app_inboxcount2(ext_context, &urgent, &new, &old);
16139  queue_mwi_event(NULL, ext_context, urgent, new, old);
16140 }
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: main/app.c:692
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
static void run_externnotify(const char *context, const char *extension, const char *flag)
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ ochar()

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

utility used by base_encode()

Definition at line 4807 of file app_voicemail.c.

References BASELINELEN, ENDL, and baseio::linelength.

Referenced by base_encode().

4808 {
4809  if (bio->linelength >= BASELINELEN) {
4810  if (fputs(ENDL, so) == EOF) {
4811  return -1;
4812  }
4813 
4814  bio->linelength = 0;
4815  }
4816 
4817  if (putc(((unsigned char) c), so) == EOF) {
4818  return -1;
4819  }
4820 
4821  bio->linelength++;
4822 
4823  return 1;
4824 }
static struct test_val c
#define ENDL
int linelength
#define BASELINELEN

◆ open_mailbox()

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

Definition at line 9099 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 AST_TEST_DEFINE(), play_message_by_id(), vm_allocate_dh(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

9100 {
9101  int count_msg, last_msg;
9102 
9103  ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
9104 
9105  /* Rename the member vmbox HERE so that we don't try to return before
9106  * we know what's going on.
9107  */
9108  snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
9109 
9110  /* Faster to make the directory than to check if it exists. */
9111  create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
9112 
9113  /* traverses directory using readdir (or select query for ODBC) */
9114  count_msg = count_messages(vmu, vms->curdir);
9115  if (count_msg < 0) {
9116  return count_msg;
9117  } else {
9118  vms->lastmsg = count_msg - 1;
9119  }
9120 
9121  if (vm_allocate_dh(vms, vmu, count_msg)) {
9122  return -1;
9123  }
9124 
9125  /*
9126  The following test is needed in case sequencing gets messed up.
9127  There appears to be more than one way to mess up sequence, so
9128  we will not try to find all of the root causes--just fix it when
9129  detected.
9130  */
9131 
9132  if (vm_lock_path(vms->curdir)) {
9133  ast_log(AST_LOG_ERROR, "Could not open mailbox %s: mailbox is locked\n", vms->curdir);
9134  return ERROR_LOCK_PATH;
9135  }
9136 
9137  /* for local storage, checks directory for messages up to maxmsg limit */
9138  last_msg = last_message_index(vmu, vms->curdir);
9139  ast_unlock_path(vms->curdir);
9140 
9141  if (last_msg < -1) {
9142  return last_msg;
9143  } else if (vms->lastmsg != last_msg) {
9144  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);
9145  resequence_mailbox(vmu, vms->curdir, count_msg);
9146  }
9147 
9148  return 0;
9149 }
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
char username[80]
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
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)
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
char curbox[80]
char context[MAX_VM_CONTEXT_LEN]
static const char * mbox(struct ast_vm_user *vmu, int id)
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
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 LOG_NOTICE
Definition: logger.h:263
char vmbox[PATH_MAX]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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...

◆ play_message()

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

Definition at line 8843 of file app_voicemail.c.

References adsi_message(), ast_channel_language(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_DIGIT_ANY, ast_filedelete(), ast_fileexists(), ast_log, AST_LOG_ERROR, 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, copy(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, make_ari_stubs::file, vm_state::fn, get_folder_by_name(), GREETINGS_FOLDER, vm_state::heard, intro, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), NULL, PATH_MAX, play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, strsep(), valid_config(), VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

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

8844 {
8845  int res = 0;
8846  char filename[PATH_MAX], *cid;
8847  const char *origtime, *context, *category, *duration, *flag;
8848  struct ast_config *msg_cfg;
8849  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8850 
8851  vms->starting = 0;
8852  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
8853  adsi_message(chan, vms);
8854  if (!vms->curmsg) {
8855  res = wait_file2(chan, vms, "vm-first"); /* "First" */
8856  } else if (vms->curmsg == vms->lastmsg) {
8857  res = wait_file2(chan, vms, "vm-last"); /* "last" */
8858  }
8859 
8860  snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
8861  RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
8862  msg_cfg = ast_config_load(filename, config_flags);
8863  if (!valid_config(msg_cfg)) {
8864  ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
8865  return 0;
8866  }
8867  flag = ast_variable_retrieve(msg_cfg, "message", "flag");
8868 
8869  /* Play the word urgent if we are listening to urgent messages */
8870  if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
8871  res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
8872  }
8873 
8874  if (!res) {
8875  /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
8876  /* POLISH syntax */
8877  if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
8878  if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
8879  int ten, one;
8880  char nextmsg[256];
8881  ten = (vms->curmsg + 1) / 10;
8882  one = (vms->curmsg + 1) % 10;
8883 
8884  if (vms->curmsg < 20) {
8885  snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
8886  res = wait_file2(chan, vms, nextmsg);
8887  } else {
8888  snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
8889  res = wait_file2(chan, vms, nextmsg);
8890  if (one > 0) {
8891  if (!res) {
8892  snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
8893  res = wait_file2(chan, vms, nextmsg);
8894  }
8895  }
8896  }
8897  }
8898  if (!res)
8899  res = wait_file2(chan, vms, "vm-message");
8900  /* HEBREW syntax */
8901  } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
8902  if (!vms->curmsg) {
8903  res = wait_file2(chan, vms, "vm-message");
8904  res = wait_file2(chan, vms, "vm-first");
8905  } else if (vms->curmsg == vms->lastmsg) {
8906  res = wait_file2(chan, vms, "vm-message");
8907  res = wait_file2(chan, vms, "vm-last");
8908  } else {
8909  res = wait_file2(chan, vms, "vm-message");
8910  res = wait_file2(chan, vms, "vm-number");
8911  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "f");
8912  }
8913  /* ICELANDIC syntax */
8914  } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) {
8915  res = wait_file2(chan, vms, "vm-message");
8916  if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
8917  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "n");
8918  }
8919  /* VIETNAMESE syntax */
8920  } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
8921  if (!vms->curmsg) {
8922  res = wait_file2(chan, vms, "vm-message");
8923  res = wait_file2(chan, vms, "vm-first");
8924  } else if (vms->curmsg == vms->lastmsg) {
8925  res = wait_file2(chan, vms, "vm-message");
8926  res = wait_file2(chan, vms, "vm-last");
8927  } else {
8928  res = wait_file2(chan, vms, "vm-message");
8929  res = wait_file2(chan, vms, "vm-number");
8930  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "f");
8931  }
8932  } else {
8933  if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
8934  res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
8935  } else { /* DEFAULT syntax */
8936  res = wait_file2(chan, vms, "vm-message");
8937  }
8938  if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
8939  if (!res) {
8940  ast_test_suite_event_notify("PLAYBACK", "Message: message number");
8941  res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
8942  }
8943  }
8944  }
8945  }
8946 
8947  if (!valid_config(msg_cfg)) {
8948  ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
8949  return 0;
8950  }
8951 
8952  if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
8953  ast_log(AST_LOG_WARNING, "No origtime?!\n");
8954  DISPOSE(vms->curdir, vms->curmsg);
8955  ast_config_destroy(msg_cfg);
8956  return 0;
8957  }
8958 
8959  cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
8960  duration = ast_variable_retrieve(msg_cfg, "message", "duration");
8961  category = ast_variable_retrieve(msg_cfg, "message", "category");
8962 
8963  context = ast_variable_retrieve(msg_cfg, "message", "context");
8964  if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
8965  context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
8966  if (!res) {
8967  res = play_message_category(chan, category);
8968  }
8969  if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
8970  res = play_message_datetime(chan, vmu, origtime, filename);
8971  }
8972  if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
8973  res = play_message_callerid(chan, vms, cid, context, 0, 0);
8974  }
8975  if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
8976  res = play_message_duration(chan, vms, duration, vmu->saydurationm);
8977  }
8978  /* Allow pressing '1' to skip envelope / callerid */
8979  if (res == '1') {
8980  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
8981  res = 0;
8982  }
8983  ast_config_destroy(msg_cfg);
8984 
8985  if (!res) {
8986  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
8987 #ifdef IMAP_STORAGE
8988  ast_mutex_lock(&vms->lock);
8989 #endif
8990  vms->heard[vms->curmsg] = 1;
8991 #ifdef IMAP_STORAGE
8992  ast_mutex_unlock(&vms->lock);
8993  /*IMAP storage stores any prepended message from a forward
8994  * as a separate file from the rest of the message
8995  */
8996  if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
8997  wait_file(chan, vms, vms->introfn);
8998  }
8999 #endif
9000  if ((res = wait_file(chan, vms, vms->fn)) < 0) {
9001  ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
9002  res = 0;
9003  }
9004  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
9005  isprint(res) ? res : '?', isprint(res) ? res : '?');
9006  }
9007  DISPOSE(vms->curdir, vms->curmsg);
9008  return res;
9009 }
#define AST_DIGIT_ANY
Definition: file.h:48
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
#define VM_SAYDURATION
#define LOG_WARNING
Definition: logger.h:274
#define AST_LOG_WARNING
Definition: logger.h:279
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char fn[PATH_MAX]
char context[MAX_VM_CONTEXT_LEN]
#define VM_SAYCID
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
int * heard
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
long int flag
Definition: f2c.h:83
Structure used to handle boolean flags.
Definition: utils.h:199
#define RETRIEVE(a, b, c, d)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
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:8337
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
const char * ast_channel_language(const struct ast_channel *chan)
static int play_message_category(struct ast_channel *chan, const char *category)
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
#define ast_mutex_unlock(a)
Definition: lock.h:188
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)

◆ play_message_by_id()

static int play_message_by_id ( struct ast_channel chan,
const char *  mailbox,
const char *  context,
const char *  msg_id 
)
static

Finds a message in a specific mailbox by msg_id and plays it to the channel.

Return values
0Success
-1Failure

Definition at line 11402 of file app_voicemail.c.

References ARRAY_LEN, ast_copy_string(), ast_log, close_mailbox(), ERROR_LOCK_PATH, find_user(), free_user(), vm_state::lastmsg, LOG_WARNING, NULL, open_mailbox(), play_message_by_id_helper(), and vm_state::username.

Referenced by vm_playmsgexec().

11403 {
11404  struct vm_state vms;
11405  struct ast_vm_user *vmu = NULL, vmus;
11406  int res = 0;
11407  int open = 0;
11408  int played = 0;
11409  int i;
11410 
11411  memset(&vmus, 0, sizeof(vmus));
11412  memset(&vms, 0, sizeof(vms));
11413 
11414  if (!(vmu = find_user(&vmus, context, mailbox))) {
11415  goto play_msg_cleanup;
11416  }
11417 
11418  /* Iterate through every folder, find the msg, and play it */
11419  for (i = 0; i < ARRAY_LEN(mailbox_folders) && !played; i++) {
11420  ast_copy_string(vms.username, mailbox, sizeof(vms.username));
11421  vms.lastmsg = -1;
11422 
11423  /* open the mailbox state */
11424  if ((res = open_mailbox(&vms, vmu, i)) < 0) {
11425  ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
11426  res = -1;
11427  goto play_msg_cleanup;
11428  }
11429  open = 1;
11430 
11431  /* play msg if it exists in this mailbox */
11432  if ((vms.lastmsg != -1) && !(play_message_by_id_helper(chan, vmu, &vms, msg_id))) {
11433  played = 1;
11434  }
11435 
11436  /* close mailbox */
11437  if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
11438  res = -1;
11439  goto play_msg_cleanup;
11440  }
11441  open = 0;
11442  }
11443 
11444 play_msg_cleanup:
11445  if (!played) {
11446  res = -1;
11447  }
11448 
11449  if (vmu && open) {
11450  close_mailbox(&vms, vmu);
11451  }
11452 
11453 #ifdef IMAP_STORAGE
11454  if (vmu) {
11455  vmstate_delete(&vms);
11456  }
11457 #endif
11458 
11459  free_user(vmu);
11460 
11461  return res;
11462 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ERROR_LOCK_PATH
#define LOG_WARNING
Definition: logger.h:274
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int play_message_by_id_helper(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)
#define NULL
Definition: resample.c:96
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
static const char *const mailbox_folders[]
static void free_user(struct ast_vm_user *vmu)
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 int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ play_message_by_id_helper()

static int play_message_by_id_helper ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
const char *  msg_id 
)
static

Definition at line 11359 of file app_voicemail.c.

References ast_fileexists(), ast_log, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, ast_vm_user::mailbox, make_file(), message_range_and_existence_check(), NULL, RETRIEVE, and wait_file().

Referenced by play_message_by_id().

11363 {
11364  if (message_range_and_existence_check(vms, &msg_id, 1, &vms->curmsg, vmu)) {
11365  return -1;
11366  }
11367  /* Found the msg, so play it back */
11368 
11369  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
11370 
11371 #ifdef IMAP_STORAGE
11372  /*IMAP storage stores any prepended message from a forward
11373  * as a separate file from the rest of the message
11374  */
11375  if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
11376  wait_file(chan, vms, vms->introfn);
11377  }
11378 #endif
11379  RETRIEVE(vms->curdir,vms->curmsg,vmu->mailbox, vmu->context);
11380 
11381  if ((wait_file(chan, vms, vms->fn)) < 0) {
11382  ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
11383  } else {
11384 #ifdef IMAP_STORAGE
11385  ast_mutex_lock(&vms->lock);
11386 #endif
11387  vms->heard[vms->curmsg] = 1;
11388 #ifdef IMAP_STORAGE
11389  ast_mutex_unlock(&vms->lock);
11390 #endif
11391  }
11392  DISPOSE(vms->curdir, vms->curmsg);
11393  return 0;
11394 }
#define AST_LOG_WARNING
Definition: logger.h:279
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char fn[PATH_MAX]
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
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
Definition: astobj2.c:42
int * heard
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
#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:1086
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.
char mailbox[MAX_VM_MBOX_ID_LEN]
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ play_message_callerid()

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

Definition at line 8716 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

8717 {
8718  int res = 0;
8719  int i;
8720  char *callerid, *name;
8721  char prefile[PATH_MAX] = "";
8722 
8723  /* If voicemail cid is not enabled, or we didn't get cid or context from
8724  * the attribute file, leave now.
8725  *
8726  * TODO Still need to change this so that if this function is called by the
8727  * message envelope (and someone is explicitly requesting to hear the CID),
8728  * it does not check to see if CID is enabled in the config file.
8729  */
8730  if ((cid == NULL)||(context == NULL))
8731  return res;
8732 
8733  /* Strip off caller ID number from name */
8734  ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
8735  ast_callerid_parse(cid, &name, &callerid);
8736  if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
8737  /* Check for internal contexts and only */
8738  /* say extension when the call didn't come from an internal context in the list */
8739  for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
8740  ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
8741  if ((strcmp(cidinternalcontexts[i], context) == 0))
8742  break;
8743  }
8744  if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
8745  if (!res) {
8746  snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
8747  if (!ast_strlen_zero(prefile)) {
8748  /* See if we can find a recorded name for this callerid
8749  * and if found, use that instead of saying number. */
8750  if (ast_fileexists(prefile, NULL, NULL) > 0) {
8751  ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
8752  if (!callback)
8753  res = wait_file2(chan, vms, "vm-from");
8754  res = ast_stream_and_wait(chan, prefile, "");
8755  } else {
8756  ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
8757  /* Say "from extension" as one saying to sound smoother */
8758  if (!callback)
8759  res = wait_file2(chan, vms, "vm-from-extension");
8760  res = ast_say_digit_str(chan, callerid, "", ast_channel_language(chan));
8761  }
8762  }
8763  }
8764  } else if (!res) {
8765  ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
8766  /* If there is a recording for this numeric callerid then play that */
8767  if (!callback) {
8768  /* See if we can find a recorded name for this person instead of their extension number */
8769  snprintf(prefile, sizeof(prefile), "%s/recordings/callerids/%s", ast_config_AST_SPOOL_DIR, callerid);
8770  if (!saycidnumber && ast_fileexists(prefile, NULL, NULL) > 0) {
8771  ast_verb(3, "Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
8772  wait_file2(chan, vms, "vm-from");
8773  res = ast_stream_and_wait(chan, prefile, "");
8774  ast_verb(3, "Played recorded name result '%d'\n", res);
8775  } else {
8776  /* Since this is all nicely figured out, why not say "from phone number" in this case" */
8777  wait_file2(chan, vms, "vm-from-phonenumber");
8778  res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
8779  }
8780  } else {
8781  res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
8782  }
8783  }
8784  } else {
8785  /* Number unknown */
8786  ast_debug(1, "VM-CID: From an unknown number\n");
8787  /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
8788  res = wait_file2(chan, vms, "vm-unknown-caller");
8789  }
8790  return res;
8791 }
#define MAX_NUM_CID_CONTEXTS
#define AST_DIGIT_ANY
Definition: file.h:48
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:8355
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:452
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static char VM_SPOOL_DIR[PATH_MAX]
static const char name[]
Definition: cdr_mysql.c:74
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:1814
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
char callback[80]
const char * ast_channel_language(const struct ast_channel *chan)
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1008

◆ play_message_category()

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

Definition at line 8623 of file app_voicemail.c.

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

Referenced by play_message().

8624 {
8625  int res = 0;
8626 
8627  if (!ast_strlen_zero(category))
8628  res = ast_play_and_wait(chan, category);
8629 
8630  if (res) {
8631  ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
8632  res = 0;
8633  }
8634 
8635  return res;
8636 }
#define AST_LOG_WARNING
Definition: logger.h:279
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
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: main/app.c:1470

◆ play_message_datetime()

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

Definition at line 8638 of file app_voicemail.c.

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

Referenced by advanced_options(), and play_message().

8639 {
8640  int res = 0;
8641  struct vm_zone *the_zone = NULL;
8642  time_t t;
8643 
8644  if (ast_get_time_t(origtime, &t, 0, NULL)) {
8645  ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
8646  return 0;
8647  }
8648 
8649  /* Does this user have a timezone specified? */
8650  if (!ast_strlen_zero(vmu->zonetag)) {
8651  /* Find the zone in the list */
8652  struct vm_zone *z;
8653  AST_LIST_LOCK(&zones);
8654  AST_LIST_TRAVERSE(&zones, z, list) {
8655  if (!strcmp(z->name, vmu->zonetag)) {
8656  the_zone = z;
8657  break;
8658  }
8659  }
8661  }
8662 
8663 /* No internal variable parsing for now, so we'll comment it out for the time being */
8664 #if 0
8665  /* Set the DIFF_* variables */
8666  ast_localtime(&t, &time_now, NULL);
8667  tv_now = ast_tvnow();
8668  ast_localtime(&tv_now, &time_then, NULL);
8669 
8670  /* Day difference */
8671  if (time_now.tm_year == time_then.tm_year)
8672  snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
8673  else
8674  snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
8675  pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
8676 
8677  /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
8678 #endif
8679  if (the_zone) {
8680  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), the_zone->msg_format, the_zone->timezone);
8681  } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */
8682  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
8683  } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */
8684  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q H 'digits/kai' M ", NULL);
8685  } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC syntax */
8686  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
8687  } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */
8688  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
8689  } else if (!strcasecmp(ast_channel_language(chan),"ja")) { /* Japanese syntax */
8690  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "PHM q 'jp-ni' 'vm-received'", NULL);
8691  } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */
8692  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/nl-om' HM", NULL);
8693  } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
8694  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
8695  } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
8696  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q HM", NULL);
8697  } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* Brazillian PORTUGUESE syntax */
8698  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
8699  } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
8700  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' dB 'digits/at' k 'and' M", NULL);
8701  } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
8702  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "qR 'vm-received'", NULL);
8703  } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
8704  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL);
8705  } else {
8706  res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' IMp", NULL);
8707  }
8708 #if 0
8709  pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
8710 #endif
8711  return res;
8712 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct vm_zone::@83 list
char timezone[80]
#define AST_DIGIT_ANY
Definition: file.h:48
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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:1739
#define AST_LOG_WARNING
Definition: logger.h:279
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
char msg_format[512]
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: main/utils.c:2198
#define ast_log
Definition: astobj2.c:42
char zonetag[80]
char name[80]
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:189
#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...
const char * ast_channel_language(const struct ast_channel *chan)

◆ play_message_duration()

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

Definition at line 8793 of file app_voicemail.c.

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

Referenced by play_message().

8794 {
8795  int res = 0;
8796  int durationm;
8797  int durations;
8798  /* Verify that we have a duration for the message */
8799  if (duration == NULL)
8800  return res;
8801 
8802  /* Convert from seconds to minutes */
8803  durations = atoi(duration);
8804  durationm = (durations / 60);
8805 
8806  ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
8807 
8808  if ((!res) && (durationm >= minduration)) {
8809  res = wait_file2(chan, vms, "vm-duration");
8810 
8811  /* POLISH syntax */
8812  if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
8813  div_t num = div(durationm, 10);
8814 
8815  if (durationm == 1) {
8816  res = ast_play_and_wait(chan, "digits/1z");
8817  res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
8818  } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8819  if (num.rem == 2) {
8820  if (!num.quot) {
8821  res = ast_play_and_wait(chan, "digits/2-ie");
8822  } else {
8823  res = say_and_wait(chan, durationm - 2 , ast_channel_language(chan));
8824  res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
8825  }
8826  } else {
8827  res = say_and_wait(chan, durationm, ast_channel_language(chan));
8828  }
8829  res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
8830  } else {
8831  res = say_and_wait(chan, durationm, ast_channel_language(chan));
8832  res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
8833  }
8834  /* DEFAULT syntax */
8835  } else {
8836  res = ast_say_number(chan, durationm, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
8837  res = wait_file2(chan, vms, "vm-minutes");
8838  }
8839  }
8840  return res;
8841 }
#define AST_DIGIT_ANY
Definition: file.h:48
#define NULL
Definition: resample.c:96
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:452
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: main/app.c:1470
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:8337
const char * ast_channel_language(const struct ast_channel *chan)

◆ play_record_review()

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,
const char *  msg_id,
int  forwardintro 
)
static

Definition at line 15504 of file app_voicemail.c.

References 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_RECORD_IF_EXISTS_OVERWRITE, ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, ast_verb, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, INTRO, ast_vm_user::mailbox, NULL, PATH_MAX, STORE, vm_exec(), VM_OPERATOR, and VM_REVIEW.

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

15507 {
15508  /* Record message & let caller review or re-record it, or set options if applicable */
15509  int res = 0;
15510  int cmd = 0;
15511  int max_attempts = 3;
15512  int attempts = 0;
15513  int recorded = 0;
15514  int msg_exists = 0;
15515  signed char zero_gain = 0;
15516  char tempfile[PATH_MAX];
15517  char *acceptdtmf = "#";
15518  char *canceldtmf = "";
15519  int canceleddtmf = 0;
15520 
15521  /* Note that urgent and private are for flagging messages as such in the future */
15522 
15523  /* barf if no pointer passed to store duration in */
15524  if (duration == NULL) {
15525  ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
15526  return -1;
15527  }
15528 
15529  if (!outsidecaller)
15530  snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
15531  else
15532  ast_copy_string(tempfile, recordfile, sizeof(tempfile));
15533 
15534  cmd = '3'; /* Want to start by recording */
15535 
15536  while ((cmd >= 0) && (cmd != 't')) {
15537  switch (cmd) {
15538  case '1':
15539  if (!msg_exists) {
15540  /* In this case, 1 is to record a message */
15541  cmd = '3';
15542  break;
15543  } else {
15544  /* Otherwise 1 is to save the existing message */
15545  ast_verb(3, "Saving message as is\n");
15546  if (!outsidecaller)
15547  ast_filerename(tempfile, recordfile, NULL);
15548  if (!forwardintro) {
15549  ast_stream_and_wait(chan, "vm-msgsaved", "");
15550  }
15551  if (!outsidecaller) {
15552  /* Saves to IMAP server only if imapgreeting=yes */
15553  STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id);
15554  DISPOSE(recordfile, -1);
15555  }
15556  cmd = 't';
15557  return res;
15558  }
15559  case '2':
15560  /* Review */
15561  ast_verb(3, "Reviewing the message\n");
15562  cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
15563  break;
15564  case '3':
15565  msg_exists = 0;
15566  /* Record */
15567  if (recorded == 1)
15568  ast_verb(3, "Re-recording the message\n");
15569  else
15570  ast_verb(3, "Recording the message\n");
15571 
15572  if (recorded && outsidecaller) {
15573  if (forwardintro) {
15574  cmd = ast_play_and_wait(chan, "vm-record-prepend");
15575  } else {
15576  cmd = ast_play_and_wait(chan, INTRO);
15577  }
15578  cmd = ast_play_and_wait(chan, "beep");
15579  }
15580  recorded = 1;
15581  /* 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 */
15582  if (record_gain)
15583  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
15584  if (ast_test_flag(vmu, VM_OPERATOR))
15585  canceldtmf = "0";
15586  cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf, 0, AST_RECORD_IF_EXISTS_OVERWRITE);
15587  if (strchr(canceldtmf, cmd)) {
15588  /* need this flag here to distinguish between pressing '0' during message recording or after */
15589  canceleddtmf = 1;
15590  }
15591  if (record_gain)
15592  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
15593  if (cmd == -1) {
15594  /* User has hung up, no options to give */
15595  if (!outsidecaller) {
15596  /* user was recording a greeting and they hung up, so let's delete the recording. */
15597  ast_filedelete(tempfile, NULL);
15598  }
15599  return cmd;
15600  }
15601  if (cmd == '0') {
15602  break;
15603  } else if (cmd == '*') {
15604  break;
15605 #if 0
15606  } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
15607  /* Message is too short */
15608  ast_verb(3, "Message too short\n");
15609  cmd = ast_play_and_wait(chan, "vm-tooshort");
15610  cmd = ast_filedelete(tempfile, NULL);
15611  break;
15612  } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
15613  /* Message is all silence */
15614  ast_verb(3, "Nothing recorded\n");
15615  cmd = ast_filedelete(tempfile, NULL);
15616  cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
15617  if (!cmd)
15618  cmd = ast_play_and_wait(chan, "vm-speakup");
15619  break;
15620 #endif
15621  } else {
15622  /* If all is well, a message exists */
15623  msg_exists = 1;
15624  cmd = 0;
15625  }
15626  break;
15627  case '4':
15628  if (outsidecaller) { /* only mark vm messages */
15629  /* Mark Urgent */
15630  if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
15631  ast_verb(3, "marking message as Urgent\n");
15632  res = ast_play_and_wait(chan, "vm-marked-urgent");
15633  strcpy(flag, "Urgent");
15634  } else if (flag) {
15635  ast_verb(3, "UNmarking message as Urgent\n");
15636  res = ast_play_and_wait(chan, "vm-marked-nonurgent");
15637  strcpy(flag, "");
15638  } else {
15639  ast_play_and_wait(chan, "vm-sorry");
15640  }
15641  cmd = 0;
15642  } else {
15643  cmd = ast_play_and_wait(chan, "vm-sorry");
15644  }
15645  break;
15646  case '5':
15647  case '6':
15648  case '7':
15649  case '8':
15650  case '9':
15651  case '*':
15652  case '#':
15653  cmd = ast_play_and_wait(chan, "vm-sorry");
15654  break;
15655 #if 0
15656 /* XXX Commented out for the moment because of the dangers of deleting
15657  a message while recording (can put the message numbers out of sync) */
15658  case '*':
15659  /* Cancel recording, delete message, offer to take another message*/
15660  cmd = ast_play_and_wait(chan, "vm-deleted");
15661  cmd = ast_filedelete(tempfile, NULL);
15662  if (outsidecaller) {
15663  res = vm_exec(chan, NULL);
15664  return res;
15665  }
15666  else
15667  return 1;
15668 #endif
15669  case '0':
15670  if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
15671  cmd = ast_play_and_wait(chan, "vm-sorry");
15672  break;
15673  }
15674  if (msg_exists || recorded) {
15675  cmd = ast_play_and_wait(chan, "vm-saveoper");
15676  if (!cmd)
15677  cmd = ast_waitfordigit(chan, 3000);
15678  if (cmd == '1') {
15679  ast_filerename(tempfile, recordfile, NULL);
15680  ast_play_and_wait(chan, "vm-msgsaved");
15681  cmd = '0';
15682  } else if (cmd == '4') {
15683  if (flag) {
15684  ast_play_and_wait(chan, "vm-marked-urgent");
15685  strcpy(flag, "Urgent");
15686  }
15687  ast_play_and_wait(chan, "vm-msgsaved");
15688  cmd = '0';
15689  } else {
15690  ast_play_and_wait(chan, "vm-deleted");
15691  DELETE(tempfile, -1, tempfile, vmu);
15692  DISPOSE(tempfile, -1);
15693  cmd = '0';
15694  }
15695  }
15696  return cmd;
15697  default:
15698  /* If the caller is an ouside caller and the review option is enabled or it's forward intro
15699  allow them to review the message, but let the owner of the box review
15700  their OGM's */
15701  if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro)
15702  return cmd;
15703  if (msg_exists) {
15704  cmd = ast_play_and_wait(chan, "vm-review");
15705  if (!cmd && outsidecaller) {
15706  if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
15707  cmd = ast_play_and_wait(chan, "vm-review-urgent");
15708  } else if (flag) {
15709  cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
15710  }
15711  }
15712  } else {
15713  cmd = ast_play_and_wait(chan, "vm-torerecord");
15714  if (!cmd)
15715  cmd = ast_waitfordigit(chan, 600);
15716  }
15717 
15718  if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
15719  cmd = ast_play_and_wait(chan, "vm-reachoper");
15720  if (!cmd)
15721  cmd = ast_waitfordigit(chan, 600);
15722  }
15723 #if 0
15724  if (!cmd)
15725  cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
15726 #endif
15727  if (!cmd)
15728  cmd = ast_waitfordigit(chan, 6000);
15729  if (!cmd) {
15730  attempts++;
15731  }
15732  if (attempts > max_attempts) {
15733  cmd = 't';
15734  }
15735  }
15736  }
15737  if (!outsidecaller && (cmd == -1 || cmd == 't')) {
15738  /* Hang up or timeout, so delete the recording. */
15739  ast_filedelete(tempfile, NULL);
15740  }
15741 
15742  if (cmd != 't' && outsidecaller)
15743  ast_play_and_wait(chan, "vm-goodbye");
15744 
15745  return cmd;
15746 }
#define AST_DIGIT_ANY
Definition: file.h:48
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int maxsilence
#define AST_LOG_WARNING
Definition: logger.h:279
#define INTRO
#define NULL
Definition: resample.c:96
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
#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:7522
#define ast_verb(level,...)
Definition: logger.h:463
char context[MAX_VM_CONTEXT_LEN]
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
static int silencethreshold
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: main/app.c:1470
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 beep, int silencethreshold, int maxsilence_ms, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
Record a file based on input from a channel This function will play "auth-thankyou" upon successful r...
Definition: main/app.c:1992
#define DELETE(a, b, c, d)
#define VM_OPERATOR
#define AST_OPTION_RXGAIN
#define VM_REVIEW
long int flag
Definition: f2c.h:83
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:1814
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
#define PATH_MAX
Definition: asterisk.h:40
static int vm_exec(struct ast_channel *chan, const char *data)
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ poll_subscribed_mailbox()

static int poll_subscribed_mailbox ( struct ast_mwi_state mwi_state,
void *  data 
)
static

Definition at line 13049 of file app_voicemail.c.

References inboxcount2(), ast_mwi_state::new_msgs, NULL, ast_mwi_state::old_msgs, queue_mwi_event(), run_externnotify(), ast_mwi_state::uniqueid, and ast_mwi_state::urgent_msgs.

Referenced by manager_match_mailbox(), mb_poll_thread(), and mwi_handle_subscribe2().

13050 {
13051  int new = 0, old = 0, urgent = 0;
13052 
13053  if (!mwi_state) {
13054  /* This should only occur due to allocation failure of a default mwi state object */
13055  return 0;
13056  }
13057 
13058  inboxcount2(mwi_state->uniqueid, &urgent, &new, &old);
13059 
13060 #ifdef IMAP_STORAGE
13061  if (imap_poll_logout) {
13062  imap_logout(mwi_state->uniqueid);
13063  }
13064 #endif
13065 
13066  if (urgent != mwi_state->urgent_msgs || new != mwi_state->new_msgs || old != mwi_state->old_msgs) {
13067  queue_mwi_event(NULL, mwi_state->uniqueid, urgent, new, old);
13068  run_externnotify(NULL, mwi_state->uniqueid, NULL);
13069  }
13070 
13071  return 0;
13072 }
#define NULL
Definition: resample.c:96
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox&#39;s message count.
int old_msgs
Definition: mwi.h:462
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
static void run_externnotify(const char *context, const char *extension, const char *flag)
int urgent_msgs
Definition: mwi.h:466
int new_msgs
Definition: mwi.h:461
const ast_string_field uniqueid
Definition: mwi.h:460

◆ populate_defaults()

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 1205 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::email, 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, NULL, 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(), find_user_realtime(), vm_allocate_dh(), and vm_test_create_user().

1206 {
1209  if (saydurationminfo) {
1211  }
1212  ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
1213  ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
1214  ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
1215  ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
1216  ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
1217  if (vmminsecs) {
1218  vmu->minsecs = vmminsecs;
1219  }
1220  if (vmmaxsecs) {
1221  vmu->maxsecs = vmmaxsecs;
1222  }
1223  if (maxmsg) {
1224  vmu->maxmsg = maxmsg;
1225  }
1226  if (maxdeletedmsg) {
1228  }
1229  vmu->volgain = volgain;
1230  ast_free(vmu->email);
1231  vmu->email = NULL;
1232  ast_free(vmu->emailsubject);
1233  vmu->emailsubject = NULL;
1234  ast_free(vmu->emailbody);
1235  vmu->emailbody = NULL;
1236 #ifdef IMAP_STORAGE
1237  ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
1238  ast_copy_string(vmu->imapserver, imapserver, sizeof(vmu->imapserver));
1239  ast_copy_string(vmu->imapport, imapport, sizeof(vmu->imapport));
1240  ast_copy_string(vmu->imapflags, imapflags, sizeof(vmu->imapflags));
1241 #endif
1242 }
double volgain
static int saydurationminfo
static int maxdeletedmsg
static char locale[20]
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define NULL
Definition: resample.c:96
static int vmminsecs
char exit[80]
static int passwordlocation
static char exitcontext[AST_MAX_CONTEXT]
char locale[20]
char dialout[80]
static char dialcontext[AST_MAX_CONTEXT]
static struct ast_flags globalflags
char zonetag[80]
int passwordlocation
static char zonetag[80]
static double volgain
static char callcontext[AST_MAX_CONTEXT]
char * emailbody
#define ast_free(a)
Definition: astmm.h:182
#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:401
char callback[80]
char * emailsubject
static int maxmsg

◆ prep_email_sub_vars()

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

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

Referenced by make_email_file(), and sendpage().

4896 {
4897  char callerid[256];
4898  char num[12];
4899  char fromdir[256], fromfile[256];
4900  struct ast_config *msg_cfg;
4901  const char *origcallerid, *origtime;
4902  char origcidname[80], origcidnum[80], origdate[80];
4903  int inttime;
4904  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
4905 
4906  /* Prepare variables for substitution in email body and subject */
4907  pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
4908  pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
4909  snprintf(num, sizeof(num), "%d", msgnum);
4910  pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
4911  pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
4912  pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
4913  pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
4914  ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
4915  pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
4916  pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
4917  pbx_builtin_setvar_helper(ast, "VM_DATE", date);
4918  pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
4919  pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
4920 
4921  /* Retrieve info from VM attribute file */
4922  make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
4923  make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
4924  if (strlen(fromfile) < sizeof(fromfile) - 5) {
4925  strcat(fromfile, ".txt");
4926  }
4927  if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
4928  ast_debug(1, "Config load for message text file '%s' failed\n", fromfile);
4929  return;
4930  }
4931 
4932  if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
4933  pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
4934  ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
4935  pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
4936  pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
4937  }
4938 
4939  if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
4940  struct timeval tv = { inttime, };
4941  struct ast_tm tm;
4942  ast_localtime(&tv, &tm, NULL);
4943  ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
4944  pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
4945  }
4946  ast_config_destroy(msg_cfg);
4947 }
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1092
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:1739
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
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 mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char locale[20]
#define ast_config_load(filename, flags)
Load a config file.
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2452
long int flag
Definition: f2c.h:83
static char emaildateformat[32]
Structure used to handle boolean flags.
Definition: utils.h:199
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...
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char fullname[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.

◆ print_mappings()

static void print_mappings ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 15099 of file app_voicemail.c.

References alias_mailbox_mapping::alias, and alias_mailbox_mapping::mailbox.

Referenced by load_module().

15100 {
15101  struct alias_mailbox_mapping *mapping = v_obj;
15102 
15103  if (!mapping) {
15104  return;
15105  }
15106  prnt(where, "Alias: %s Mailbox: %s", mapping->alias, mapping->mailbox);
15107 }

◆ queue_mwi_event()

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

Definition at line 8110 of file app_voicemail.c.

References mailbox_alias_mapping::alias, aliases, ao2_find, ao2_iterator_destroy(), ao2_iterator_next, ao2_ref, ast_debug, ast_publish_mwi_state_channel, ast_strdupa, ast_strlen_zero, context, mailbox, NULL, OBJ_MULTIPLE, OBJ_SEARCH_KEY, and separate_mailbox().

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

8111 {
8112  char *mailbox;
8113  char *context;
8114 
8115  if (separate_mailbox(ast_strdupa(box), &mailbox, &context)) {
8116  return;
8117  }
8118 
8119  ast_debug(3, "Queueing event for mailbox %s New: %d Old: %d\n", box, new + urgent, old);
8120  ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8121 
8123  struct ao2_iterator *aliases;
8124  struct mailbox_alias_mapping *mapping;
8125 
8127  while ((mapping = ao2_iterator_next(aliases))) {
8128  char alias[strlen(mapping->alias) + 1];
8129  strcpy(alias, mapping->alias); /* safe */
8130  mailbox = NULL;
8131  context = NULL;
8132  ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);
8133  separate_mailbox(alias, &mailbox, &context);
8134  ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8135  ao2_ref(mapping, -1);
8136  }
8137  ao2_iterator_destroy(aliases);
8138  }
8139 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static char aliasescontext[MAX_VM_CONTEXT_LEN]
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static const struct cfalias aliases[]
Definition: chan_sip.c:8510
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id)
Publish a MWI state update associated with some channel.
Definition: mwi.h:397
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * mailbox_alias_mappings
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ read_password_from_file()

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

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

14396  {
14397  struct ast_config *pwconf;
14398  struct ast_flags config_flags = { 0 };
14399 
14400  pwconf = ast_config_load(secretfn, config_flags);
14401  if (valid_config(pwconf)) {
14402  const char *val = ast_variable_retrieve(pwconf, "general", "password");
14403  if (val) {
14404  ast_copy_string(password, val, passwordlen);
14405  ast_config_destroy(pwconf);
14406  return;
14407  }
14408  ast_config_destroy(pwconf);
14409  }
14410  ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
14411 }
Definition: ast_expr2.c:325
static struct ast_str * password
Definition: cdr_mysql.c:77
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define LOG_NOTICE
Definition: logger.h:263
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.

◆ reload()

static int reload ( void  )
static

Definition at line 15045 of file app_voicemail.c.

References load_config().

15046 {
15047  return load_config(1);
15048 }
static int load_config(int reload)

◆ rename_file()

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

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

4555 {
4556  char stxt[PATH_MAX];
4557  char dtxt[PATH_MAX];
4558  ast_filerename(sfn, dfn, NULL);
4559  snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
4560  snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
4561  if (ast_check_realtime("voicemail_data")) {
4562  ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
4563  }
4564  rename(stxt, dtxt);
4565 }
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
#define NULL
Definition: resample.c:96
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3489
#define SENTINEL
Definition: compiler.h:87
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
#define PATH_MAX
Definition: asterisk.h:40

◆ resequence_mailbox()

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

Definition at line 7177 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, NULL, PATH_MAX, RENAME, and vm_lock_path().

Referenced by open_mailbox().

7178 {
7179  /* we know the actual number of messages, so stop process when number is hit */
7180 
7181  int x, dest;
7182  char sfn[PATH_MAX];
7183  char dfn[PATH_MAX];
7184 
7185  if (vm_lock_path(dir)) {
7186  return ERROR_LOCK_PATH;
7187  }
7188 
7189  for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
7190  make_file(sfn, sizeof(sfn), dir, x);
7191  if (EXISTS(dir, x, sfn, NULL)) {
7192 
7193  if (x != dest) {
7194  make_file(dfn, sizeof(dfn), dir, dest);
7195  RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
7196  }
7197 
7198  dest++;
7199  }
7200  }
7201  ast_unlock_path(dir);
7202 
7203  return dest;
7204 }
#define ERROR_LOCK_PATH
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
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 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)
#define PATH_MAX
Definition: asterisk.h:40
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ reset_user_pw()

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

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

Referenced by vm_change_password(), and vm_change_password_shell().

1730 {
1731  /* This function could be made to generate one from a database, too */
1732  struct ast_vm_user *cur;
1733  int res = -1;
1734  AST_LIST_LOCK(&users);
1735  AST_LIST_TRAVERSE(&users, cur, list) {
1736  if ((!context || !strcasecmp(context, cur->context)) &&
1737  (!strcasecmp(mailbox, cur->mailbox)))
1738  break;
1739  }
1740  if (cur) {
1741  ast_copy_string(cur->password, newpass, sizeof(cur->password));
1742  res = 0;
1743  }
1745  return res;
1746 }
#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
char password[80]
list of users found in the config file
char context[MAX_VM_CONTEXT_LEN]
struct ast_vm_user::@82 list
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#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:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ run_externnotify()

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

Definition at line 6234 of file app_voicemail.c.

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

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

6235 {
6236  char arguments[255];
6237  char ext_context[256] = "";
6238  int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6239  struct ast_smdi_mwi_message *mwi_msg;
6240 
6241  if (!ast_strlen_zero(context))
6242  snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
6243  else
6244  ast_copy_string(ext_context, extension, sizeof(ext_context));
6245 
6246  if (smdi_iface) {
6247  if (ast_app_has_voicemail(ext_context, NULL))
6249  else
6251 
6253  ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
6254  if (!strncmp(mwi_msg->cause, "INV", 3))
6255  ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
6256  else if (!strncmp(mwi_msg->cause, "BLK", 3))
6257  ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
6258  ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
6259  ao2_ref(mwi_msg, -1);
6260  } else {
6261  ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
6262  }
6263  }
6264 
6265  if (!ast_strlen_zero(externnotify)) {
6266  if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6267  ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
6268  } else {
6269  snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
6270  externnotify, S_OR(context, "\"\""),
6271  extension, newvoicemails,
6272  oldvoicemails, urgentvoicemails);
6273  ast_debug(1, "Executing %s\n", arguments);
6274  ast_safe_system(arguments);
6275  }
6276  }
6277 }
#define SMDI_MWI_WAIT_TIMEOUT
#define AST_LOG_WARNING
Definition: logger.h:279
static char externnotify[160]
#define NULL
Definition: resample.c:96
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox&#39;s message count.
static struct ast_smdi_interface * smdi_iface
#define ast_strlen_zero(foo)
Definition: strings.h:52
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
Definition: smdi.h:54
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
Definition: res_smdi.c:309
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
structure to hold extensions
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:53
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:655
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
Definition: res_smdi.c:314
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
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:556
An SMDI message waiting indicator message.
Definition: smdi.h:51

◆ save_to_folder()

static int save_to_folder ( struct ast_vm_user vmu,
struct vm_state vms,
int  msg,
int  box,
int *  newmsg,
int  move 
)
static

Place a message in the indicated folder

Parameters
vmuVoicemail user
vmsCurrent voicemail state for the user
msgThe message number to save
boxThe folder into which the message should be saved
[out]newmsgThe new message number of the saved message
moveTells whether to copy or to move the message
Note
the "move" parameter is only honored for IMAP voicemail presently
Return values
0Success
otherFailure

Definition at line 7214 of file app_voicemail.c.

References ast_debug, ast_log, AST_LOG_ERROR, 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, ERROR_MAX_MSGS, EXISTS, get_folder_by_name(), last_message_index(), ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, NULL, OLD_FOLDER, PATH_MAX, RENAME, vm_state::username, and vm_lock_path().

Referenced by close_mailbox(), vm_allocate_dh(), vm_execmain(), and vm_msg_move().

7215 {
7216 #ifdef IMAP_STORAGE
7217  /* we must use mbox(x) folder names, and copy the message there */
7218  /* simple. huh? */
7219  char sequence[10];
7220  char mailbox[256];
7221  int res;
7222  int curr_mbox;
7223 
7224  /* get the real IMAP message number for this message */
7225  snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
7226 
7227  ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
7228  ast_mutex_lock(&vms->lock);
7229  /* if save to Old folder, put in INBOX as read */
7230  if (box == OLD_FOLDER) {
7231  mail_setflag(vms->mailstream, sequence, "\\Seen");
7232  } else if (box == NEW_FOLDER) {
7233  mail_clearflag(vms->mailstream, sequence, "\\Seen");
7234  }
7235  if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
7236  ast_mutex_unlock(&vms->lock);
7237  return 0;
7238  }
7239 
7240  /* get the current mailbox so that we can point the mailstream back to it later */
7241  curr_mbox = get_folder_by_name(vms->curbox);
7242 
7243  /* Create the folder if it dosn't exist */
7244  imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
7245  if (vms->mailstream && !mail_status(vms->mailstream, mailbox, SA_UIDNEXT)) {
7246  if (mail_create(vms->mailstream, mailbox) != NIL) {
7247  ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
7248  }
7249  }
7250 
7251  /* restore previous mbox stream */
7252  if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
7253  ast_log(AST_LOG_ERROR, "IMAP mailstream is NULL or can't init_mailstream\n");
7254  res = -1;
7255  } else {
7256  if (move) {
7257  res = !mail_move(vms->mailstream, sequence, (char *) mbox(vmu, box));
7258  } else {
7259  res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
7260  }
7261  }
7262  ast_mutex_unlock(&vms->lock);
7263  return res;
7264 #else
7265  char *dir = vms->curdir;
7266  char *username = vms->username;
7267  char *context = vmu->context;
7268  char sfn[PATH_MAX];
7269  char dfn[PATH_MAX];
7270  char ddir[PATH_MAX];
7271  const char *dbox = mbox(vmu, box);
7272  int x, i;
7273  create_dirpath(ddir, sizeof(ddir), context, username, dbox);
7274 
7275  if (vm_lock_path(ddir))
7276  return ERROR_LOCK_PATH;
7277 
7278  x = last_message_index(vmu, ddir) + 1;
7279 
7280  if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
7281  x--;
7282  for (i = 1; i <= x; i++) {
7283  /* Push files down a "slot". The oldest file (msg0000) will be deleted. */
7284  make_file(sfn, sizeof(sfn), ddir, i);
7285  make_file(dfn, sizeof(dfn), ddir, i - 1);
7286  if (EXISTS(ddir, i, sfn, NULL)) {
7287  RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
7288  } else
7289  break;
7290  }
7291  } else {
7292  if (x >= vmu->maxmsg) {
7293  ast_unlock_path(ddir);
7294  return ERROR_MAX_MSGS;
7295  }
7296  }
7297  make_file(sfn, sizeof(sfn), dir, msg);
7298  make_file(dfn, sizeof(dfn), ddir, x);
7299  if (strcmp(sfn, dfn)) {
7300  COPY(dir, msg, ddir, x, username, context, sfn, dfn);
7301  }
7302  ast_unlock_path(ddir);
7303 
7304  if (newmsg) {
7305  *newmsg = x;
7306  }
7307  return 0;
7308 #endif
7309 }
char username[80]
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
char curdir[PATH_MAX]
#define ast_mutex_lock(a)
Definition: lock.h:187
static int get_folder_by_name(const char *name)
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
char curbox[80]
char context[MAX_VM_CONTEXT_LEN]
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:268
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
#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)
#define ERROR_MAX_MSGS
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)
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ say_and_wait()

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

Definition at line 7207 of file app_voicemail.c.

References AST_DIGIT_ANY, ast_say_number(), d, and NULL.

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

7208 {
7209  int d;
7210  d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
7211  return d;
7212 }
#define AST_DIGIT_ANY
Definition: file.h:48
static struct test_val d
#define NULL
Definition: resample.c:96
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:117
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:8337

◆ sayname()

static int sayname ( struct ast_channel chan,
const char *  mailbox,
const char *  context 
)
static
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 14359 of file app_voicemail.c.

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

Referenced by ast_app_sayname(), vm_sayname(), and vmsayname_exec().

14360 {
14361  int res = -1;
14362  char dir[PATH_MAX];
14363  snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
14364  ast_debug(2, "About to try retrieving name file %s\n", dir);
14365  RETRIEVE(dir, -1, mailbox, context);
14366  if (ast_fileexists(dir, NULL, NULL)) {
14367  res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
14368  }
14369  DISPOSE(dir, -1);
14370  return res;
14371 }
#define AST_DIGIT_ANY
Definition: file.h:48
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
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:1814
#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:1086
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ sendmail()

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,
const char *  msg_id 
)
static

Definition at line 5520 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(), NULL, strsep(), VM_ATTACH, and vm_mkftemp().

Referenced by forward_message(), and notify_new_message().

5537 {
5538  FILE *p = NULL;
5539  char tmp[80] = "/tmp/astmail-XXXXXX";
5540  char tmp2[256];
5541  char *stringp;
5542 
5543  if (vmu && ast_strlen_zero(vmu->email)) {
5544  ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
5545  return(0);
5546  }
5547 
5548  /* Mail only the first format */
5550  stringp = format;
5551  strsep(&stringp, "|");
5552 
5553  if (!strcmp(format, "wav49"))
5554  format = "WAV";
5555  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));
5556  /* Make a temporary file instead of piping directly to sendmail, in case the mail
5557  command hangs */
5558  if ((p = vm_mkftemp(tmp)) == NULL) {
5559  ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
5560  return -1;
5561  } else {
5562  make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag, msg_id);
5563  fclose(p);
5564  snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5565  ast_safe_system(tmp2);
5566  ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
5567  }
5568  return 0;
5569 }
static char mailcmd[160]
static FILE * vm_mkftemp(char *template)
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int tmp()
Definition: bt_open.c:389
#define AST_LOG_WARNING
Definition: logger.h:279
#define VM_ATTACH
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static struct ast_flags globalflags
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
long int flag
Definition: f2c.h:83
char * strsep(char **str, const char *delims)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
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, const char *msg_id)
Creates the email file to be sent to indicate a new voicemail exists for a user.
static snd_pcm_format_t format
Definition: chan_alsa.c:102
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ sendpage()

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 5571 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, ast_vm_user::fullname, host, ast_vm_user::locale, MAXHOSTNAMELEN, NULL, PATH_MAX, prep_email_sub_vars(), S_OR, strip_control_and_high(), vm_mkftemp(), and vmu_tm().

Referenced by notify_new_message().

5572 {
5573  char enc_cidnum[256], enc_cidname[256];
5574  char date[256];
5575  char host[MAXHOSTNAMELEN] = "";
5576  char who[256];
5577  char dur[PATH_MAX];
5578  char tmp[80] = "/tmp/astmail-XXXXXX";
5579  char tmp2[PATH_MAX];
5580  struct ast_tm tm;
5581  FILE *p;
5582  struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
5583 
5584  if (!str1 || !str2) {
5585  ast_free(str1);
5586  ast_free(str2);
5587  return -1;
5588  }
5589 
5590  if (cidnum) {
5591  strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
5592  }
5593  if (cidname) {
5594  strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
5595  }
5596 
5597  if ((p = vm_mkftemp(tmp)) == NULL) {
5598  ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
5599  ast_free(str1);
5600  ast_free(str2);
5601  return -1;
5602  }
5603  gethostname(host, sizeof(host)-1);
5604  if (strchr(srcemail, '@')) {
5605  ast_copy_string(who, srcemail, sizeof(who));
5606  } else {
5607  snprintf(who, sizeof(who), "%s@%s", srcemail, host);
5608  }
5609  snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
5610  ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
5611  fprintf(p, "Date: %s\n", date);
5612 
5613  /* Reformat for custom pager format */
5614  ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
5615 
5617  struct ast_channel *ast;
5618  if ((ast = ast_dummy_channel_alloc())) {
5619  char *ptr;
5620  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5622 
5623  if (check_mime(ast_str_buffer(str1))) {
5624  int first_line = 1;
5625  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
5626  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5627  *ptr = '\0';
5628  fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
5629  first_line = 0;
5630  /* Substring is smaller, so this will never grow */
5631  ast_str_set(&str2, 0, "%s", ptr + 1);
5632  }
5633  fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
5634  } else {
5635  fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
5636  }
5637  ast = ast_channel_unref(ast);
5638  } else {
5639  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5640  }
5641  } else {
5642  fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
5643  }
5644 
5645  if (check_mime(vmu->fullname)) {
5646  int first_line = 1;
5647  char *ptr;
5648  ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
5649  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5650  *ptr = '\0';
5651  fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
5652  first_line = 0;
5653  /* Substring is smaller, so this will never grow */
5654  ast_str_set(&str2, 0, "%s", ptr + 1);
5655  }
5656  fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
5657  } else {
5658  fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
5659  }
5660 
5661  if (!ast_strlen_zero(pagersubject)) {
5662  struct ast_channel *ast;
5663  if ((ast = ast_dummy_channel_alloc())) {
5664  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5666  if (check_mime(ast_str_buffer(str1))) {
5667  int first_line = 1;
5668  char *ptr;
5669  ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
5670  while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5671  *ptr = '\0';
5672  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5673  first_line = 0;
5674  /* Substring is smaller, so this will never grow */
5675  ast_str_set(&str2, 0, "%s", ptr + 1);
5676  }
5677  fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5678  } else {
5679  fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
5680  }
5681  ast = ast_channel_unref(ast);
5682  } else {
5683  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5684  }
5685  } else {
5686  if (ast_strlen_zero(flag)) {
5687  fprintf(p, "Subject: New VM\n\n");
5688  } else {
5689  fprintf(p, "Subject: New %s VM\n\n", flag);
5690  }
5691  }
5692 
5693  if (pagerbody) {
5694  struct ast_channel *ast;
5695  if ((ast = ast_dummy_channel_alloc())) {
5696  prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5697  ast_str_substitute_variables(&str1, 0, ast, pagerbody);
5698  fprintf(p, "%s" ENDL, ast_str_buffer(str1));
5699  ast = ast_channel_unref(ast);
5700  } else {
5701  ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5702  }
5703  } else {
5704  fprintf(p, "New %s long %s msg in box %s\n"
5705  "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
5706  }
5707 
5708  fclose(p);
5709  snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5710  ast_safe_system(tmp2);
5711  ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
5712  ast_free(str1);
5713  ast_free(str2);
5714  return 0;
5715 }
Main Channel structure associated with a channel.
static char mailcmd[160]
static FILE * vm_mkftemp(char *template)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static char pagerdateformat[32]
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
#define AST_LOG_WARNING
Definition: logger.h:279
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#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...
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1065
static char pagerfromstring[100]
static char * pagerbody
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char locale[20]
static char host[256]
Definition: muted.c:77
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_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
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:2452
#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:584
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
long int flag
Definition: f2c.h:83
#define ast_free(a)
Definition: astmm.h:182
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:2524
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static char * pagersubject
#define PATH_MAX
Definition: asterisk.h:40
char fullname[80]
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static const 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.
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 ...
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ separate_mailbox()

static int separate_mailbox ( char *  mailbox_id,
char **  mailbox,
char **  context 
)
static

Definition at line 1094 of file app_voicemail.c.

References ast_strlen_zero, and strsep().

Referenced by __has_voicemail(), acf_vm_info(), find_user(), free_zone(), mb_poll_thread(), messagecount(), queue_mwi_event(), vm_allocate_dh(), vm_sayname(), and vmsayname_exec().

1095 {
1096  if (ast_strlen_zero(mailbox_id) || !mailbox || !context) {
1097  return -1;
1098  }
1099  *context = mailbox_id;
1100  *mailbox = strsep(context, "@");
1101  if (ast_strlen_zero(*mailbox)) {
1102  return -1;
1103  }
1104  if (ast_strlen_zero(*context)) {
1105  *context = "default";
1106  }
1107  return 0;
1108 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
char * strsep(char **str, const char *delims)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ show_users_realtime()

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

Definition at line 12806 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, NULL, SENTINEL, ast_variable::value, and var.

Referenced by handle_voicemail_show_users().

12807 {
12808  struct ast_config *cfg;
12809  const char *cat = NULL;
12810 
12811  if (!(cfg = ast_load_realtime_multientry("voicemail",
12812  "context", context, SENTINEL))) {
12813  return CLI_FAILURE;
12814  }
12815 
12816  ast_cli(fd,
12817  "\n"
12818  "=============================================================\n"
12819  "=== Configured Voicemail Users ==============================\n"
12820  "=============================================================\n"
12821  "===\n");
12822 
12823  while ((cat = ast_category_browse(cfg, cat))) {
12824  struct ast_variable *var = NULL;
12825  ast_cli(fd,
12826  "=== Mailbox ...\n"
12827  "===\n");
12828  for (var = ast_variable_browse(cfg, cat); var; var = var->next)
12829  ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
12830  ast_cli(fd,
12831  "===\n"
12832  "=== ---------------------------------------------------------\n"
12833  "===\n");
12834  }
12835 
12836  ast_cli(fd,
12837  "=============================================================\n"
12838  "\n");
12839 
12840  ast_config_destroy(cfg);
12841 
12842  return CLI_SUCCESS;
12843 }
struct ast_variable * next
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define SENTINEL
Definition: compiler.h:87
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3452
#define CLI_FAILURE
Definition: cli.h:46
#define CLI_SUCCESS
Definition: cli.h:44
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ start_poll_thread()

static void start_poll_thread ( void  )
static

Definition at line 13197 of file app_voicemail.c.

References ast_log, ast_mwi_add_observer(), ast_pthread_create, LOG_ERROR, mb_poll_thread(), and NULL.

Referenced by actual_load_config().

13198 {
13199  int errcode;
13201 
13202  poll_thread_run = 1;
13203 
13204  if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
13205  ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
13206  }
13207 }
static pthread_t poll_thread
#define NULL
Definition: resample.c:96
int ast_mwi_add_observer(struct ast_mwi_observer *observer)
Add an observer to receive MWI state related events.
Definition: mwi.c:296
#define ast_log
Definition: astobj2.c:42
static void * mb_poll_thread(void *data)
#define LOG_ERROR
Definition: logger.h:285
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:559
struct ast_mwi_observer mwi_observer
static unsigned char poll_thread_run

◆ stop_poll_thread()

static void stop_poll_thread ( void  )
static

Definition at line 13209 of file app_voicemail.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_mwi_remove_observer(), AST_PTHREADT_NULL, NULL, and poll_lock.

Referenced by actual_load_config(), and unload_module().

13210 {
13211  poll_thread_run = 0;
13212 
13216 
13217  pthread_join(poll_thread, NULL);
13219 
13221 }
static pthread_t poll_thread
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_cond_t poll_cond
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
#define AST_PTHREADT_NULL
Definition: lock.h:66
static ast_mutex_t poll_lock
void ast_mwi_remove_observer(struct ast_mwi_observer *observer)
Remove an MWI state observer.
Definition: mwi.c:302
struct ast_mwi_observer mwi_observer
static unsigned char poll_thread_run
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ strip_control_and_high()

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

References buf, and input().

Referenced by make_email_file(), and sendpage().

1176 {
1177  char *bufptr = buf;
1178  for (; *input; input++) {
1179  if (*input < 32) {
1180  continue;
1181  }
1182  *bufptr++ = *input;
1183  if (bufptr == buf + buflen - 1) {
1184  break;
1185  }
1186  }
1187  *bufptr = '\0';
1188  return buf;
1189 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584

◆ substitute_escapes()

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

Definition at line 13491 of file app_voicemail.c.

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

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

13492 {
13493  char *current;
13494 
13495  /* Add 16 for fudge factor */
13496  struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
13497 
13498  ast_str_reset(str);
13499 
13500  /* Substitute strings \r, \n, and \t into the appropriate characters */
13501  for (current = (char *) value; *current; current++) {
13502  if (*current == '\\') {
13503  current++;
13504  if (!*current) {
13505  ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
13506  break;
13507  }
13508  switch (*current) {
13509  case '\\':
13510  ast_str_append(&str, 0, "\\");
13511  break;
13512  case 'r':
13513  ast_str_append(&str, 0, "\r");
13514  break;
13515  case 'n':
13516 #ifdef IMAP_STORAGE
13517  if (!str->used || str->str[str->used - 1] != '\r') {
13518  ast_str_append(&str, 0, "\r");
13519  }
13520 #endif
13521  ast_str_append(&str, 0, "\n");
13522  break;
13523  case 't':
13524  ast_str_append(&str, 0, "\t");
13525  break;
13526  default:
13527  ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
13528  break;
13529  }
13530  } else {
13531  ast_str_append(&str, 0, "%c", *current);
13532  }
13533  }
13534 
13535  return ast_str_buffer(str);
13536 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1091
const char * str
Definition: app_jack.c:147
int value
Definition: syslog.c:37
#define AST_LOG_NOTICE
Definition: logger.h:268
#define ast_log
Definition: astobj2.c:42
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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:653
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:861

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 15050 of file app_voicemail.c.

References ao2_cleanup, ao2_container_unregister(), ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), ast_mwi_state_callback_all(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), AST_TEST_UNREGISTER, ast_uninstall_vm_test_functions(), ast_unload_realtime(), ast_unregister_application(), ast_vm_greeter_unregister(), ast_vm_unregister(), free_vm_users(), free_vm_zones(), ast_vm_functions::module_name, ast_vm_greeter_functions::module_name, NULL, and stop_poll_thread().

Referenced by load_module(), and vm_msg_play().

15051 {
15052  int res;
15053 
15060  res |= ast_manager_unregister("VoicemailUsersList");
15061  res |= ast_manager_unregister("VoicemailUserStatus");
15062  res |= ast_manager_unregister("VoicemailRefresh");
15063 #ifdef TEST_FRAMEWORK
15064  res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
15065  res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
15066  res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
15067  res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
15068  res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
15069  res |= AST_TEST_UNREGISTER(test_voicemail_vm_info);
15070 #endif
15074 #ifdef TEST_FRAMEWORK
15076 #endif
15078 
15079  ao2_container_unregister("voicemail_alias_mailbox_mappings");
15081  ao2_container_unregister("voicemail_mailbox_alias_mappings");
15083 
15085  stop_poll_thread();
15086 
15088  ast_unload_realtime("voicemail");
15089  ast_unload_realtime("voicemail_data");
15090 
15091 #ifdef IMAP_STORAGE
15092  ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
15093 #endif
15094  free_vm_users();
15095  free_vm_zones();
15096  return res;
15097 }
static void free_vm_zones(void)
Free the zones structure.
static struct ast_custom_function vm_info_acf
static const struct ast_vm_functions vm_table
#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: clicompat.c:30
static char * voicemailmain_app
void ast_uninstall_vm_test_functions(void)
Definition: main/app.c:606
static struct ao2_container * alias_mailbox_mappings
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: main/config.c:3406
static pthread_t poll_thread
static const struct ast_vm_greeter_functions vm_greeter_table
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
Definition: main/app.c:473
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * playmsg_app
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
static char * sayname_app
static char * vmauthenticate_app
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_vm_greeter_unregister(const char *module_name)
Unregister the specified voicemail greeter provider.
Definition: main/app.c:584
static struct ast_taskprocessor * mwi_subscription_tps
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
const char * module_name
The name of the module that provides the voicemail greeter functionality.
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
Definition: mwi.c:333
static char * voicemail_app
static struct ast_cli_entry cli_voicemail[]
static struct ao2_container * mailbox_alias_mappings
const char * module_name
The name of the module that provides the voicemail functionality.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
struct ao2_container * inprocess_container
static void stop_poll_thread(void)

◆ valid_config()

static int valid_config ( const struct ast_config cfg)
inlinestatic

Check if configuration file is valid.

Definition at line 1751 of file app_voicemail.c.

References CONFIG_STATUS_FILEINVALID.

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

1752 {
1753  return cfg && cfg != CONFIG_STATUS_FILEINVALID;
1754 }
#define CONFIG_STATUS_FILEINVALID

◆ vm_allocate_dh()

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

Definition at line 2021 of file app_voicemail.c.

References apply_options_full(), ast_build_string(), ast_callerid_parse(), ast_calloc, ast_channel_caller(), ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_filedelete(), ast_fileexists(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_load_realtime(), ast_log, AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_malloc, ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_party_caller_init(), ast_play_and_wait(), ast_realloc, ast_set_flag, ast_str_append(), ast_str_buffer(), ast_str_create, ast_strdup, ast_strdupa, ast_strlen_zero, ast_variable_retrieve(), ast_variables_destroy(), buf, cid_name, cid_num, close_mailbox(), context, ast_vm_user::context, vm_state::context, copy(), copy_message(), create_dirpath(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, debug, DEBUG_ATLEAST, vm_state::deleted, vm_state::dh_arraysize, ast_vm_user::email, errno, ERROR, ast_vm_user::exit, make_ari_stubs::file, find_user(), vm_state::fn, format, free_user(), get_folder_by_name(), GREETINGS_FOLDER, has_voicemail(), vm_state::heard, ast_party_caller::id, inboxcount2(), inprocess_count(), vm_state::lastmsg, len(), ast_vm_user::list, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mailbox, ast_vm_user::mailbox, make_email_file(), make_file(), MAX_MAIL_BODY_CONTENT_SIZE, ast_vm_user::maxmsg, mbox(), messagecount(), name, ast_party_id::name, NEW_FOLDER, vm_state::newmessages, NULL, ast_party_id::number, OLD_FOLDER, vm_state::oldmessages, open_mailbox(), PATH_MAX, pbx_builtin_setvar_helper(), populate_defaults(), quote(), S_COR, S_OR, save_to_folder(), separate_mailbox(), ast_vm_user::serveremail, serveremail, status, str, ast_party_name::str, ast_party_number::str, strcasestr(), strsep(), tmp(), vm_state::urgentmessages, usage, user, vm_state::username, ast_party_name::valid, ast_party_number::valid, var, VM_ALLOCED, vm_mkftemp(), vm_state::vmbox, and VMSTATE_MAX_MSG_ARRAY.

Referenced by open_mailbox().

2021  {
2022 
2023  int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
2024 
2025  /* remove old allocation */
2026  if (vms->deleted) {
2027  ast_free(vms->deleted);
2028  vms->deleted = NULL;
2029  }
2030  if (vms->heard) {
2031  ast_free(vms->heard);
2032  vms->heard = NULL;
2033  }
2034  vms->dh_arraysize = 0;
2035 
2036  if (arraysize > 0) {
2037  if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
2038  return -1;
2039  }
2040  if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
2041  ast_free(vms->deleted);
2042  vms->deleted = NULL;
2043  return -1;
2044  }
2045  vms->dh_arraysize = arraysize;
2046  }
2047 
2048  return 0;
2049 }
int * deleted
#define NULL
Definition: resample.c:96
int dh_arraysize
int * heard
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ vm_authenticate()

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

References adsi_begin(), adsi_login(), adsi_password(), ast_channel_caller(), ast_channel_context(), ast_channel_language(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero, ast_verb, ast_waitstream(), find_user(), free_user(), NULL, password, ast_vm_user::password, and S_COR.

Referenced by vm_execmain(), and vmauthenticate().

11229 {
11230  int useadsi = 0, valid = 0, logretries = 0;
11231  char password[AST_MAX_EXTENSION], *passptr = NULL;
11232  struct ast_vm_user vmus, *vmu = NULL;
11233 
11234  /* If ADSI is supported, setup login screen */
11235  adsi_begin(chan, &useadsi);
11236  if (!skipuser && useadsi)
11237  adsi_login(chan);
11238  if (!silent && !skipuser && ast_streamfile(chan, vm_login, ast_channel_language(chan))) {
11239  ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
11240  return -1;
11241  }
11242 
11243  /* Authenticate them and get their mailbox/password */
11244 
11245  while (!valid && (logretries < max_logins)) {
11246  /* Prompt for, and read in the username */
11247  if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
11248  ast_log(AST_LOG_WARNING, "Couldn't read username\n");
11249  return -1;
11250  }
11251  if (ast_strlen_zero(mailbox)) {
11252  if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
11253  ast_copy_string(mailbox, ast_channel_caller(chan)->id.number.str, mailbox_size);
11254  } else {
11255  ast_verb(3, "Username not entered\n");
11256  return -1;
11257  }
11258  } else if (mailbox[0] == '*') {
11259  /* user entered '*' */
11260  ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
11261  if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
11262  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11263  return -1;
11264  }
11265  ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
11266  mailbox[0] = '\0';
11267  }
11268 
11269  if (useadsi)
11270  adsi_password(chan);
11271 
11272  if (!ast_strlen_zero(prefix)) {
11273  char fullusername[80];
11274 
11275  ast_copy_string(fullusername, prefix, sizeof(fullusername));
11276  strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
11277  ast_copy_string(mailbox, fullusername, mailbox_size);
11278  }
11279 
11280  ast_debug(1, "Before find user for mailbox %s\n", mailbox);
11281  memset(&vmus, 0, sizeof(vmus));
11282  vmu = find_user(&vmus, context, mailbox);
11283  if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
11284  /* saved password is blank, so don't bother asking */
11285  password[0] = '\0';
11286  } else {
11287  if (ast_streamfile(chan, vm_password, ast_channel_language(chan))) {
11288  ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
11289  free_user(vmu);
11290  return -1;
11291  }
11292  if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
11293  ast_log(AST_LOG_WARNING, "Unable to read password\n");
11294  free_user(vmu);
11295  return -1;
11296  } else if (password[0] == '*') {
11297  /* user entered '*' */
11298  ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
11299  if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
11300  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11301  mailbox[0] = '*';
11302  free_user(vmu);
11303  return -1;
11304  }
11305  ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11306  mailbox[0] = '\0';
11307  /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
11308  free_user(vmu);
11309  vmu = NULL;
11310  }
11311  }
11312 
11313  if (vmu) {
11314  passptr = vmu->password;
11315  if (passptr[0] == '-') passptr++;
11316  }
11317  if (vmu && !strcmp(passptr, password))
11318  valid++;
11319  else {
11320  ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
11321  if (!ast_strlen_zero(prefix))
11322  mailbox[0] = '\0';
11323  }
11324  logretries++;
11325  if (!valid) {
11326  if (skipuser || logretries >= max_logins) {
11327  if (ast_streamfile(chan, "vm-incorrect", ast_channel_language(chan))) {
11328  ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
11329  free_user(vmu);
11330  return -1;
11331  }
11332  if (ast_waitstream(chan, "")) { /* Channel is hung up */
11333  free_user(vmu);
11334  return -1;
11335  }
11336  } else {
11337  if (useadsi)
11338  adsi_login(chan);
11339  if (ast_streamfile(chan, "vm-incorrect-mailbox", ast_channel_language(chan))) {
11340  ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
11341  free_user(vmu);
11342  return -1;
11343  }
11344  }
11345  }
11346  }
11347  if (!valid && (logretries >= max_logins)) {
11348  ast_stopstream(chan);
11349  ast_play_and_wait(chan, "vm-goodbye");
11350  free_user(vmu);
11351  return -1;
11352  }
11353  if (vmu && !skipuser) {
11354  *res_vmu = *vmu;
11355  }
11356  return 0;
11357 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
#define AST_LOG_WARNING
Definition: logger.h:279
static void adsi_login(struct ast_channel *chan)
char password[80]
#define NULL
Definition: resample.c:96
static struct ast_str * password
Definition: cdr_mysql.c:77
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
static void adsi_begin(struct ast_channel *chan, int *useadsi)
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_MAX_EXTENSION
Definition: channel.h:135
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: main/app.c:1470
#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:85
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:4179
static void free_user(struct ast_vm_user *vmu)
static void adsi_password(struct ast_channel *chan)
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:401
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1776
const char * ast_channel_language(const struct ast_channel *chan)
static char vm_password[80]
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6655
static char vm_login[80]
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ vm_browse_messages()

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

References ast_channel_language(), vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_ja(), vm_browse_messages_pt(), vm_browse_messages_vi(), and vm_browse_messages_zh().

Referenced by vm_execmain().

11204 {
11205  if (!strncasecmp(ast_channel_language(chan), "es", 2)) { /* SPANISH */
11206  return vm_browse_messages_es(chan, vms, vmu);
11207  } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK */
11208  return vm_browse_messages_gr(chan, vms, vmu);
11209  } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW */
11210  return vm_browse_messages_he(chan, vms, vmu);
11211  } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN */
11212  return vm_browse_messages_it(chan, vms, vmu);
11213  } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE */
11214  return vm_browse_messages_ja(chan, vms, vmu);
11215  } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE */
11216  return vm_browse_messages_pt(chan, vms, vmu);
11217  } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE */
11218  return vm_browse_messages_vi(chan, vms, vmu);
11219  } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) */
11220  return vm_browse_messages_zh(chan, vms, vmu);
11221  } else { /* Default to English syntax */
11222  return vm_browse_messages_en(chan, vms, vmu);
11223  }
11224 }
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_gr(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Greek syntax for &#39;You have N messages&#39; greeting.
static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Japanese 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_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Italian syntax for &#39;You have N messages&#39; greeting.
static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Spanish 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_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Portuguese 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 char * ast_channel_language(const struct ast_channel *chan)

◆ vm_browse_messages_en()

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

11016 {
11017  int cmd = 0;
11018 
11019  if (vms->lastmsg > -1) {
11020  cmd = play_message(chan, vmu, vms);
11021  } else {
11022  cmd = ast_play_and_wait(chan, "vm-youhave");
11023  if (!cmd)
11024  cmd = ast_play_and_wait(chan, "vm-no");
11025  if (!cmd) {
11026  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11027  cmd = ast_play_and_wait(chan, vms->fn);
11028  }
11029  if (!cmd)
11030  cmd = ast_play_and_wait(chan, "vm-messages");
11031  }
11032  return cmd;
11033 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_es()

static int vm_browse_messages_es ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Spanish syntax for 'You have N messages' greeting.

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

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

11097 {
11098  int cmd;
11099 
11100  if (vms->lastmsg > -1) {
11101  cmd = play_message(chan, vmu, vms);
11102  } else {
11103  cmd = ast_play_and_wait(chan, "vm-youhaveno");
11104  if (!cmd)
11105  cmd = ast_play_and_wait(chan, "vm-messages");
11106  if (!cmd) {
11107  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11108  cmd = ast_play_and_wait(chan, vms->fn);
11109  }
11110  }
11111  return cmd;
11112 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_gr()

static int vm_browse_messages_gr ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Greek syntax for 'You have N messages' greeting.

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

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

10964 {
10965  int cmd = 0;
10966 
10967  if (vms->lastmsg > -1) {
10968  cmd = play_message(chan, vmu, vms);
10969  } else {
10970  cmd = ast_play_and_wait(chan, "vm-youhaveno");
10971  if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
10972  if (!cmd) {
10973  snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
10974  cmd = ast_play_and_wait(chan, vms->fn);
10975  }
10976  if (!cmd)
10977  cmd = ast_play_and_wait(chan, "vm-messages");
10978  } else {
10979  if (!cmd)
10980  cmd = ast_play_and_wait(chan, "vm-messages");
10981  if (!cmd) {
10982  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
10983  cmd = ast_play_and_wait(chan, vms->fn);
10984  }
10985  }
10986  }
10987  return cmd;
10988 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470
char vmbox[PATH_MAX]

◆ vm_browse_messages_he()

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

Definition at line 10991 of file app_voicemail.c.

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

Referenced by vm_browse_messages().

10992 {
10993  int cmd = 0;
10994 
10995  if (vms->lastmsg > -1) {
10996  cmd = play_message(chan, vmu, vms);
10997  } else {
10998  if (!strcasecmp(vms->fn, "INBOX")) {
10999  cmd = ast_play_and_wait(chan, "vm-nonewmessages");
11000  } else {
11001  cmd = ast_play_and_wait(chan, "vm-nomessages");
11002  }
11003  }
11004  return cmd;
11005 }
char fn[PATH_MAX]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_it()

static int vm_browse_messages_it ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Italian syntax for 'You have N messages' greeting.

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

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

11044 {
11045  int cmd;
11046 
11047  if (vms->lastmsg > -1) {
11048  cmd = play_message(chan, vmu, vms);
11049  } else {
11050  cmd = ast_play_and_wait(chan, "vm-no");
11051  if (!cmd)
11052  cmd = ast_play_and_wait(chan, "vm-message");
11053  if (!cmd) {
11054  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11055  cmd = ast_play_and_wait(chan, vms->fn);
11056  }
11057  }
11058  return cmd;
11059 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_ja()

static int vm_browse_messages_ja ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Japanese syntax for 'You have N messages' greeting.

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

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

11070 {
11071  int cmd = 0;
11072 
11073  if (vms->lastmsg > -1) {
11074  cmd = play_message(chan, vmu, vms);
11075  } else {
11076  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11077  cmd = ast_play_and_wait(chan, vms->fn);
11078  if (!cmd)
11079  cmd = ast_play_and_wait(chan, "vm-messages");
11080  if (!cmd)
11081  cmd = ast_play_and_wait(chan, "jp-wa");
11082  if (!cmd)
11083  cmd = ast_play_and_wait(chan, "jp-arimasen");
11084  }
11085  return cmd;
11086 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_pt()

static int vm_browse_messages_pt ( struct ast_channel chan,
struct vm_state vms,
struct ast_vm_user vmu 
)
static

Portuguese syntax for 'You have N messages' greeting.

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

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

11123 {
11124  int cmd;
11125 
11126  if (vms->lastmsg > -1) {
11127  cmd = play_message(chan, vmu, vms);
11128  } else {
11129  cmd = ast_play_and_wait(chan, "vm-no");
11130  if (!cmd) {
11131  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11132  cmd = ast_play_and_wait(chan, vms->fn);
11133  }
11134  if (!cmd)
11135  cmd = ast_play_and_wait(chan, "vm-messages");
11136  }
11137  return cmd;
11138 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_vi()

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

11177 {
11178  int cmd = 0;
11179 
11180  if (vms->lastmsg > -1) {
11181  cmd = play_message(chan, vmu, vms);
11182  } else {
11183  cmd = ast_play_and_wait(chan, "vm-no");
11184  if (!cmd) {
11185  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11186  cmd = ast_play_and_wait(chan, vms->fn);
11187  }
11188  }
11189  return cmd;
11190 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_browse_messages_zh()

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

11149 {
11150  int cmd;
11151 
11152  if (vms->lastmsg > -1) {
11153  cmd = play_message(chan, vmu, vms);
11154  } else {
11155  cmd = ast_play_and_wait(chan, "vm-you");
11156  if (!cmd)
11157  cmd = ast_play_and_wait(chan, "vm-haveno");
11158  if (!cmd)
11159  cmd = ast_play_and_wait(chan, "vm-messages");
11160  if (!cmd) {
11161  snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11162  cmd = ast_play_and_wait(chan, vms->fn);
11163  }
11164  }
11165  return cmd;
11166 }
char fn[PATH_MAX]
char curbox[80]
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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: main/app.c:1470

◆ vm_change_password()

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

References 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_malloc, 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, NULL, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, PATH_MAX, reset_user_pw(), tmp(), valid_config(), value, var, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser_setup(), and vm_options().

1764 {
1765  struct ast_config *cfg = NULL;
1766  struct ast_variable *var = NULL;
1767  struct ast_category *cat = NULL;
1768  char *category = NULL;
1769  const char *tmp = NULL;
1770  struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
1771  char secretfn[PATH_MAX] = "";
1772  int found = 0;
1773 
1774  if (!change_password_realtime(vmu, newpassword))
1775  return;
1776 
1777  /* check if we should store the secret in the spool directory next to the messages */
1778  switch (vmu->passwordlocation) {
1779  case OPT_PWLOC_SPOOLDIR:
1780  snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
1781  if (write_password_to_file(secretfn, newpassword) == 0) {
1782  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
1783  ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
1784  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1785  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1786  break;
1787  } else {
1788  ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1789  }
1790  /* Fall-through */
1792  if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
1793  while ((category = ast_category_browse(cfg, category))) {
1794  if (!strcasecmp(category, vmu->context)) {
1795  char *value = NULL;
1796  char *new = NULL;
1797  if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
1798  ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
1799  break;
1800  }
1801  value = strstr(tmp, ",");
1802  if (!value) {
1803  new = ast_malloc(strlen(newpassword) + 1);
1804  sprintf(new, "%s", newpassword);
1805  } else {
1806  new = ast_malloc((strlen(value) + strlen(newpassword) + 1));
1807  sprintf(new, "%s%s", newpassword, value);
1808  }
1809  if (!(cat = ast_category_get(cfg, category, NULL))) {
1810  ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
1811  ast_free(new);
1812  break;
1813  }
1814  ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
1815  found = 1;
1816  ast_free(new);
1817  }
1818  }
1819  /* save the results */
1820  if (found) {
1821  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1822  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1823  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1824  ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "app_voicemail");
1825  ast_config_destroy(cfg);
1826  break;
1827  }
1828 
1829  ast_config_destroy(cfg);
1830  }
1831  /* Fall-through */
1832  case OPT_PWLOC_USERSCONF:
1833  /* check users.conf and update the password stored for the mailbox */
1834  /* if no vmsecret entry exists create one. */
1835  if ((cfg = ast_config_load("users.conf", config_flags)) && valid_config(cfg)) {
1836  ast_debug(4, "we are looking for %s\n", vmu->mailbox);
1837  for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
1838  ast_debug(4, "users.conf: %s\n", category);
1839  if (!strcasecmp(category, vmu->mailbox)) {
1840  char new[strlen(newpassword) + 1];
1841  if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
1842  ast_debug(3, "looks like we need to make vmsecret!\n");
1843  var = ast_variable_new("vmsecret", newpassword, "");
1844  } else {
1845  var = NULL;
1846  }
1847 
1848  sprintf(new, "%s", newpassword);
1849  if (!(cat = ast_category_get(cfg, category, NULL))) {
1850  ast_debug(4, "failed to get category!\n");
1851  ast_free(var);
1852  break;
1853  }
1854  if (!var) {
1855  ast_variable_update(cat, "vmsecret", new, NULL, 0);
1856  } else {
1857  ast_variable_append(cat, var);
1858  }
1859  found = 1;
1860  break;
1861  }
1862  }
1863  /* save the results and clean things up */
1864  if (found) {
1865  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
1866  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1867  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1868  ast_config_text_file_save("users.conf", cfg, "app_voicemail");
1869  }
1870 
1871  ast_config_destroy(cfg);
1872  }
1873  }
1874 }
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
Definition: main/config.c:2531
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
#define AST_LOG_WARNING
Definition: logger.h:279
#define var
Definition: ast_expr2f.c:614
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
char password[80]
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_verb(level,...)
Definition: logger.h:463
char context[MAX_VM_CONTEXT_LEN]
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
#define VOICEMAIL_CONFIG
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
int passwordlocation
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define ast_variable_new(name, value, filename)
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:196
#define ast_free(a)
Definition: astmm.h:182
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: main/config.c:1444
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define PATH_MAX
Definition: asterisk.h:40
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1022
char mailbox[MAX_VM_MBOX_ID_LEN]
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.

◆ vm_change_password_shell()

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

Definition at line 1876 of file app_voicemail.c.

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

Referenced by vm_newuser_setup(), and vm_options().

1877 {
1878  char buf[255];
1879  snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
1880  ast_debug(1, "External password: %s\n",buf);
1881  if (!ast_safe_system(buf)) {
1882  ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
1883  ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1884  /* Reset the password in memory, too */
1885  reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1886  }
1887 }
static char ext_pass_cmd[128]
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char password[80]
char context[MAX_VM_CONTEXT_LEN]
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char mailbox[MAX_VM_MBOX_ID_LEN]
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.

◆ vm_check_password_shell()

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

Definition at line 1391 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, buf, errno, and LOG_WARNING.

Referenced by check_password().

1392 {
1393  int fds[2], pid = 0;
1394 
1395  memset(buf, 0, len);
1396 
1397  if (pipe(fds)) {
1398  snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
1399  } else {
1400  /* good to go*/
1401  pid = ast_safe_fork(0);
1402 
1403  if (pid < 0) {
1404  /* ok maybe not */
1405  close(fds[0]);
1406  close(fds[1]);
1407  snprintf(buf, len, "FAILURE: Fork failed");
1408  } else if (pid) {
1409  /* parent */
1410  close(fds[1]);
1411  if (read(fds[0], buf, len) < 0) {
1412  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
1413  }
1414  close(fds[0]);
1415  } else {
1416  /* child */
1418  AST_APP_ARG(v)[20];
1419  );
1420  char *mycmd = ast_strdupa(command);
1421 
1422  close(fds[0]);
1423  dup2(fds[1], STDOUT_FILENO);
1424  close(fds[1]);
1425  ast_close_fds_above_n(STDOUT_FILENO);
1426 
1427  AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
1428 
1429  execv(arg.v[0], arg.v);
1430  printf("FAILURE: %s", strerror(errno));
1431  _exit(0);
1432  }
1433  }
1434  return buf;
1435 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3042
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
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: main/app.c:3047
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ vm_delete()

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

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

Referenced by copy_message(), and notify_new_message().

4750 {
4751  char *txt;
4752  int txtsize = 0;
4753 
4754  txtsize = (strlen(file) + 5)*sizeof(char);
4755  txt = ast_alloca(txtsize);
4756  /* Sprintf here would safe because we alloca'd exactly the right length,
4757  * but trying to eliminate all sprintf's anyhow
4758  */
4759  if (ast_check_realtime("voicemail_data")) {
4760  ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
4761  }
4762  snprintf(txt, txtsize, "%s.txt", file);
4763  unlink(txt);
4764  return ast_filedelete(file, NULL);
4765 }
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
#define NULL
Definition: resample.c:96
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
#define SENTINEL
Definition: compiler.h:87
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
Definition: main/config.c:3606

◆ vm_exec()

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

Definition at line 12278 of file app_voicemail.c.

References args, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), AST_CONTROL_PROGRESS, ast_copy_flags, AST_DECLARE_APP_ARGS, ast_indicate(), 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, leave_vm_options::beeptone, ERROR_LOCK_PATH, leave_vm_options::exitcontext, leave_voicemail(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_BEEP_TONE, OPT_ARG_DTMFEXIT, OPT_ARG_RECORDGAIN, OPT_BEEP, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_EARLYM_GREETING, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_RECORDGAIN, OPT_SILENT, OPT_UNAVAIL_GREETING, pbx_builtin_setvar_helper(), leave_vm_options::record_gain, tmp(), and vm_app_options.

Referenced by load_module(), and play_record_review().

12279 {
12280  int res = 0;
12281  char *tmp;
12282  struct leave_vm_options leave_options;
12283  struct ast_flags flags = { 0 };
12284  char *opts[OPT_ARG_ARRAY_SIZE];
12286  AST_APP_ARG(argv0);
12287  AST_APP_ARG(argv1);
12288  );
12289 
12290  memset(&leave_options, 0, sizeof(leave_options));
12291 
12292  if (!ast_strlen_zero(data)) {
12293  tmp = ast_strdupa(data);
12295  if (args.argc == 2) {
12296  if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
12297  return -1;
12299  if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
12300  int gain;
12301 
12302  if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
12303  ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
12304  return -1;
12305  } else {
12306  leave_options.record_gain = (signed char) gain;
12307  }
12308  }
12309  if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
12310  if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
12311  leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
12312  }
12313  }
12314  if (ast_test_flag(&flags, OPT_BEEP)) { /* Use custom beep (or none at all) */
12315  leave_options.beeptone = opts[OPT_ARG_BEEP_TONE];
12316  } else { /* Use default beep */
12317  leave_options.beeptone = "beep";
12318  }
12319  } else {
12320  char temp[256];
12321  res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
12322  if (res < 0)
12323  return res;
12324  if (ast_strlen_zero(temp))
12325  return 0;
12326  args.argv0 = ast_strdupa(temp);
12327  }
12328 
12329  if (ast_channel_state(chan) != AST_STATE_UP) {
12330  if (ast_test_flag(&flags, OPT_EARLYM_GREETING)) {
12332  } else {
12333  ast_answer(chan);
12334  }
12335  }
12336 
12337  res = leave_voicemail(chan, args.argv0, &leave_options);
12338  if (res == 't') {
12339  ast_play_and_wait(chan, "vm-goodbye");
12340  res = 0;
12341  }
12342 
12343  if (res == OPERATOR_EXIT) {
12344  res = 0;
12345  }
12346 
12347  if (res == ERROR_LOCK_PATH) {
12348  ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
12349  pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
12350  res = 0;
12351  }
12352 
12353  return res;
12354 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4322
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define ERROR_LOCK_PATH
static int tmp()
Definition: bt_open.c:389
unsigned int flags
Definition: utils.h:200
#define AST_LOG_WARNING
Definition: logger.h:279
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
const char * args
static const struct ast_app_option vm_app_options[128]
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
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: main/app.c:1470
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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: main/app.c:2906
#define OPERATOR_EXIT
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.
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: main/app.c:197
Structure used to handle boolean flags.
Definition: utils.h:199
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:650
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...
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ vm_execmain()

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

Definition at line 11503 of file app_voicemail.c.

References adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_channel_context(), ast_channel_language(), ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_strlen_zero, ast_test_flag, ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, vm_state::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, ast_vm_user::dialout, dialout(), ERROR_LOCK_PATH, find_user(), vm_state::fn, forward_message(), free_user(), get_folder2(), get_folder_by_name(), vm_state::heard, ast_vm_user::language, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, mbox(), NEW_FOLDER, vm_state::newmessages, NULL, 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, out, 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_setup(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, VM_SVMAIL, and vm_state::vmbox.

Referenced by load_module().

11504 {
11505  /* XXX This is, admittedly, some pretty horrendous code. For some
11506  reason it just seemed a lot easier to do with GOTO's. I feel
11507  like I'm back in my GWBASIC days. XXX */
11508  int res = -1;
11509  int cmd = 0;
11510  int valid = 0;
11511  char prefixstr[80] ="";
11512  char ext_context[256]="";
11513  int box;
11514  int useadsi = 0;
11515  int skipuser = 0;
11516  struct vm_state vms = {{0}};
11517  struct ast_vm_user *vmu = NULL, vmus = {{0}};
11518  char *context = NULL;
11519  int silentexit = 0;
11520  struct ast_flags flags = { 0 };
11521  signed char record_gain = 0;
11522  int play_auto = 0;
11523  int play_folder = 0;
11524  int in_urgent = 0;
11525 #ifdef IMAP_STORAGE
11526  int deleted = 0;
11527 #endif
11528 
11529  /* Add the vm_state to the active list and keep it active */
11530  vms.lastmsg = -1;
11531 
11532  ast_test_suite_event_notify("START", "Message: vm_execmain started");
11533  if (ast_channel_state(chan) != AST_STATE_UP) {
11534  ast_debug(1, "Before ast_answer\n");
11535  ast_answer(chan);
11536  }
11537 
11538  if (!ast_strlen_zero(data)) {
11539  char *opts[OPT_ARG_ARRAY_SIZE];
11540  char *parse;
11542  AST_APP_ARG(argv0);
11543  AST_APP_ARG(argv1);
11544  );
11545 
11546  parse = ast_strdupa(data);
11547 
11548  AST_STANDARD_APP_ARGS(args, parse);
11549 
11550  if (args.argc == 2) {
11551  if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
11552  return -1;
11553  if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
11554  int gain;
11555  if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
11556  if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
11557  ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
11558  return -1;
11559  } else {
11560  record_gain = (signed char) gain;
11561  }
11562  } else {
11563  ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
11564  }
11565  }
11566  if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
11567  play_auto = 1;
11568  if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
11569  /* See if it is a folder name first */
11570  if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
11571  if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
11572  play_folder = -1;
11573  }
11574  } else {
11575  play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
11576  }
11577  } else {
11578  ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
11579  }
11580  if (play_folder > 9 || play_folder < 0) {
11582  "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
11583  opts[OPT_ARG_PLAYFOLDER]);
11584  play_folder = 0;
11585  }
11586  }
11587  } else {
11588  /* old style options parsing */
11589  while (*(args.argv0)) {
11590  if (*(args.argv0) == 's')
11591  ast_set_flag(&flags, OPT_SILENT);
11592  else if (*(args.argv0) == 'p')
11594  else
11595  break;
11596  (args.argv0)++;
11597  }
11598 
11599  }
11600 
11601  valid = ast_test_flag(&flags, OPT_SILENT);
11602 
11603  if ((context = strchr(args.argv0, '@')))
11604  *context++ = '\0';
11605 
11606  if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
11607  ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
11608  else
11609  ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
11610 
11611  if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
11612  skipuser++;
11613  else
11614  valid = 0;
11615  }
11616 
11617  if (!valid)
11618  res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
11619 
11620  ast_debug(1, "After vm_authenticate\n");
11621 
11622  if (vms.username[0] == '*') {
11623  ast_debug(1, "user pressed * in context '%s'\n", ast_channel_context(chan));
11624 
11625  /* user entered '*' */
11626  if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) {
11627  ast_test_suite_event_notify("REDIRECT", "Message: redirecting user to 'a' extension");
11628  res = 0; /* prevent hangup */
11629  goto out;
11630  }
11631  }
11632 
11633  if (!res) {
11634  valid = 1;
11635  if (!skipuser)
11636  vmu = &vmus;
11637  } else {
11638  res = 0;
11639  }
11640 
11641  /* If ADSI is supported, setup login screen */
11642  adsi_begin(chan, &useadsi);
11643 
11644  if (!valid) {
11645  goto out;
11646  }
11647  ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated");
11648 
11649 #ifdef IMAP_STORAGE
11650  pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
11651  pthread_setspecific(ts_vmstate.key, &vms);
11652 
11653  vms.interactive = 1;
11654  vms.updated = 1;
11655  if (vmu)
11656  ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
11657  vmstate_insert(&vms);
11658  init_vm_state(&vms);
11659 #endif
11660 
11661  /* Set language from config to override channel language */
11662  if (!ast_strlen_zero(vmu->language)) {
11663  ast_channel_lock(chan);
11664  ast_channel_language_set(chan, vmu->language);
11665  ast_channel_unlock(chan);
11666  }
11667 
11668  /* Retrieve urgent, old and new message counts */
11669  ast_debug(1, "Before open_mailbox\n");
11670  res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
11671  if (res < 0)
11672  goto out;
11673  vms.oldmessages = vms.lastmsg + 1;
11674  ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
11675  /* check INBOX */
11676  res = open_mailbox(&vms, vmu, NEW_FOLDER);
11677  if (res < 0)
11678  goto out;
11679  vms.newmessages = vms.lastmsg + 1;
11680  ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
11681  /* Start in Urgent */
11682  in_urgent = 1;
11683  res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
11684  if (res < 0)
11685  goto out;
11686  vms.urgentmessages = vms.lastmsg + 1;
11687  ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
11688 
11689  /* Select proper mailbox FIRST!! */
11690  if (play_auto) {
11691  ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages");
11692  if (vms.urgentmessages) {
11693  in_urgent = 1;
11694  res = open_mailbox(&vms, vmu, 11);
11695  } else {
11696  in_urgent = 0;
11697  res = open_mailbox(&vms, vmu, play_folder);
11698  }
11699  if (res < 0)
11700  goto out;
11701 
11702  /* If there are no new messages, inform the user and hangup */
11703  if (vms.lastmsg == -1) {
11704  in_urgent = 0;
11705  cmd = vm_browse_messages(chan, &vms, vmu);
11706  res = 0;
11707  goto out;
11708  }
11709  } else {
11710  if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
11711  /* If we only have old messages start here */
11712  res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
11713  in_urgent = 0;
11714  play_folder = 1;
11715  if (res < 0)
11716  goto out;
11717  } else if (!vms.urgentmessages && vms.newmessages) {
11718  /* If we have new messages but none are urgent */
11719  in_urgent = 0;
11720  res = open_mailbox(&vms, vmu, NEW_FOLDER);
11721  if (res < 0)
11722  goto out;
11723  }
11724  }
11725 
11726  if (useadsi)
11727  adsi_status(chan, &vms);
11728  res = 0;
11729 
11730  /* Check to see if this is a new user */
11731  if (!strcasecmp(vmu->mailbox, vmu->password) &&
11733  if (ast_play_and_wait(chan, vm_newuser) == -1)
11734  ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
11735  cmd = vm_newuser_setup(chan, vmu, &vms, vmfmts, record_gain);
11736  if ((cmd == 't') || (cmd == '#')) {
11737  /* Timeout */
11738  ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out");
11739  res = 0;
11740  goto out;
11741  } else if (cmd < 0) {
11742  /* Hangup */
11743  ast_test_suite_event_notify("HANGUP", "Message: hangup detected");
11744  res = -1;
11745  goto out;
11746  }
11747  }
11748 #ifdef IMAP_STORAGE
11749  ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
11750  if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
11751  ast_debug(1, "*** QUOTA EXCEEDED!!\n");
11752  cmd = ast_play_and_wait(chan, "vm-mailboxfull");
11753  }
11754  ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
11755  if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
11756  ast_log(AST_LOG_WARNING, "No more messages possible. User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
11757  cmd = ast_play_and_wait(chan, "vm-mailboxfull");
11758  }
11759 #endif
11760 
11761  ast_test_suite_event_notify("INTRO", "Message: playing intro menu");
11762  if (play_auto) {
11763  cmd = '1';
11764  } else {
11765  cmd = vm_intro(chan, vmu, &vms);
11766  }
11767  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
11768  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
11769 
11770  vms.repeats = 0;
11771  vms.starting = 1;
11772  while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
11773  /* Run main menu */
11774  switch (cmd) {
11775  case '1': /* First message */
11776  vms.curmsg = 0;
11777  /* Fall through */
11778  case '5': /* Play current message */
11779  ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
11780  cmd = vm_browse_messages(chan, &vms, vmu);
11781  break;
11782  case '2': /* Change folders */
11783  ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder");
11784  if (useadsi)
11785  adsi_folders(chan, 0, "Change to folder...");
11786 
11787  cmd = get_folder2(chan, "vm-changeto", 0);
11788  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
11789  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
11790  if (cmd == '#') {
11791  cmd = 0;
11792  } else if (cmd > 0) {
11793  cmd = cmd - '0';
11794  res = close_mailbox(&vms, vmu);
11795  if (res == ERROR_LOCK_PATH)
11796  goto out;
11797  /* If folder is not urgent, set in_urgent to zero! */
11798  if (cmd != 11) in_urgent = 0;
11799  res = open_mailbox(&vms, vmu, cmd);
11800  if (res < 0)
11801  goto out;
11802  play_folder = cmd;
11803  cmd = 0;
11804  }
11805  if (useadsi)
11806  adsi_status2(chan, &vms);
11807 
11808  if (!cmd) {
11809  cmd = vm_play_folder_name(chan, vms.vmbox);
11810  }
11811 
11812  vms.starting = 1;
11813  vms.curmsg = 0;
11814  break;
11815  case '3': /* Advanced options */
11816  ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");
11817  cmd = 0;
11818  vms.repeats = 0;
11819  while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
11820  switch (cmd) {
11821  case '1': /* Reply */
11822  if (vms.lastmsg > -1 && !vms.starting) {
11823  cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
11824  if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
11825  res = cmd;
11826  goto out;
11827  }
11828  } else {
11829  cmd = ast_play_and_wait(chan, "vm-sorry");
11830  }
11831  cmd = 't';
11832  break;
11833  case '2': /* Callback */
11834  if (!vms.starting)
11835  ast_verb(3, "Callback Requested\n");
11836  if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
11837  cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
11838  if (cmd == 9) {
11839  silentexit = 1;
11840  goto out;
11841  } else if (cmd == ERROR_LOCK_PATH) {
11842  res = cmd;
11843  goto out;
11844  }
11845  } else {
11846  cmd = ast_play_and_wait(chan, "vm-sorry");
11847  }
11848  cmd = 't';
11849  break;
11850  case '3': /* Envelope */
11851  if (vms.lastmsg > -1 && !vms.starting) {
11852  cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
11853  if (cmd == ERROR_LOCK_PATH) {
11854  res = cmd;
11855  goto out;
11856  }
11857  } else {
11858  cmd = ast_play_and_wait(chan, "vm-sorry");
11859  }
11860  cmd = 't';
11861  break;
11862  case '4': /* Dialout */
11863  if (!ast_strlen_zero(vmu->dialout)) {
11864  cmd = dialout(chan, vmu, NULL, vmu->dialout);
11865  if (cmd == 9) {
11866  silentexit = 1;
11867  goto out;
11868  }
11869  } else {
11870  cmd = ast_play_and_wait(chan, "vm-sorry");
11871  }
11872  cmd = 't';
11873  break;
11874 
11875  case '5': /* Leave VoiceMail */
11876  if (ast_test_flag(vmu, VM_SVMAIL)) {
11877  cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
11878  if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
11879  res = cmd;
11880  goto out;
11881  }
11882  } else {
11883  cmd = ast_play_and_wait(chan, "vm-sorry");
11884  }
11885  cmd = 't';
11886  break;
11887 
11888  case '*': /* Return to main menu */
11889  cmd = 't';
11890  break;
11891 
11892  default:
11893  cmd = 0;
11894  if (!vms.starting) {
11895  cmd = ast_play_and_wait(chan, "vm-toreply");
11896  }
11897  if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
11898  cmd = ast_play_and_wait(chan, "vm-tocallback");
11899  }
11900  if (!cmd && !vms.starting) {
11901  cmd = ast_play_and_wait(chan, "vm-tohearenv");
11902  }
11903  if (!ast_strlen_zero(vmu->dialout) && !cmd) {
11904  cmd = ast_play_and_wait(chan, "vm-tomakecall");
11905  }
11906  if (ast_test_flag(vmu, VM_SVMAIL) && !cmd) {
11907  cmd = ast_play_and_wait(chan, "vm-leavemsg");
11908  }
11909  if (!cmd) {
11910  cmd = ast_play_and_wait(chan, "vm-starmain");
11911  }
11912  if (!cmd) {
11913  cmd = ast_waitfordigit(chan, 6000);
11914  }
11915  if (!cmd) {
11916  vms.repeats++;
11917  }
11918  if (vms.repeats > 3) {
11919  cmd = 't';
11920  }
11921  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
11922  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
11923  }
11924  }
11925  if (cmd == 't') {
11926  cmd = 0;
11927  vms.repeats = 0;
11928  }
11929  break;
11930  case '4': /* Go to the previous message */
11931  ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1);
11932  if (vms.curmsg > 0) {
11933  vms.curmsg--;
11934  cmd = play_message(chan, vmu, &vms);
11935  } else {
11936  /* Check if we were listening to new
11937  messages. If so, go to Urgent messages
11938  instead of saying "no more messages"
11939  */
11940  if (in_urgent == 0 && vms.urgentmessages > 0) {
11941  /* Check for Urgent messages */
11942  in_urgent = 1;
11943  res = close_mailbox(&vms, vmu);
11944  if (res == ERROR_LOCK_PATH)
11945  goto out;
11946  res = open_mailbox(&vms, vmu, 11); /* Open Urgent folder */
11947  if (res < 0)
11948  goto out;
11949  ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
11950  vms.curmsg = vms.lastmsg;
11951  if (vms.lastmsg < 0) {
11952  cmd = ast_play_and_wait(chan, "vm-nomore");
11953  }
11954  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
11955  vms.curmsg = vms.lastmsg;
11956  cmd = play_message(chan, vmu, &vms);
11957  } else {
11958  cmd = ast_play_and_wait(chan, "vm-nomore");
11959  }
11960  }
11961  break;
11962  case '6': /* Go to the next message */
11963  ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1);
11964  if (vms.curmsg < vms.lastmsg) {
11965  vms.curmsg++;
11966  cmd = play_message(chan, vmu, &vms);
11967  } else {
11968  if (in_urgent && vms.newmessages > 0) {
11969  /* Check if we were listening to urgent
11970  * messages. If so, go to regular new messages
11971  * instead of saying "no more messages"
11972  */
11973  in_urgent = 0;
11974  res = close_mailbox(&vms, vmu);
11975  if (res == ERROR_LOCK_PATH)
11976  goto out;
11977  res = open_mailbox(&vms, vmu, NEW_FOLDER);
11978  if (res < 0)
11979  goto out;
11980  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
11981  vms.curmsg = -1;
11982  if (vms.lastmsg < 0) {
11983  cmd = ast_play_and_wait(chan, "vm-nomore");
11984  }
11985  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
11986  vms.curmsg = 0;
11987  cmd = play_message(chan, vmu, &vms);
11988  } else {
11989  cmd = ast_play_and_wait(chan, "vm-nomore");
11990  }
11991  }
11992  break;
11993  case '7': /* Delete the current message */
11994  if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
11995  vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
11996  if (useadsi)
11997  adsi_delete(chan, &vms);
11998  if (vms.deleted[vms.curmsg]) {
11999  if (play_folder == 0) {
12000  if (in_urgent) {
12001  vms.urgentmessages--;
12002  } else {
12003  vms.newmessages--;
12004  }
12005  }
12006  else if (play_folder == 1)
12007  vms.oldmessages--;
12008  cmd = ast_play_and_wait(chan, "vm-deleted");
12009  } else {
12010  if (play_folder == 0) {
12011  if (in_urgent) {
12012  vms.urgentmessages++;
12013  } else {
12014  vms.newmessages++;
12015  }
12016  }
12017  else if (play_folder == 1)
12018  vms.oldmessages++;
12019  cmd = ast_play_and_wait(chan, "vm-undeleted");
12020  }
12021  if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
12022  if (vms.curmsg < vms.lastmsg) {
12023  vms.curmsg++;
12024  cmd = play_message(chan, vmu, &vms);
12025  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12026  vms.curmsg = 0;
12027  cmd = play_message(chan, vmu, &vms);
12028  } else {
12029  /* Check if we were listening to urgent
12030  messages. If so, go to regular new messages
12031  instead of saying "no more messages"
12032  */
12033  if (in_urgent == 1) {
12034  /* Check for new messages */
12035  in_urgent = 0;
12036  res = close_mailbox(&vms, vmu);
12037  if (res == ERROR_LOCK_PATH)
12038  goto out;
12039  res = open_mailbox(&vms, vmu, NEW_FOLDER);
12040  if (res < 0)
12041  goto out;
12042  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12043  vms.curmsg = -1;
12044  if (vms.lastmsg < 0) {
12045  cmd = ast_play_and_wait(chan, "vm-nomore");
12046  }
12047  } else {
12048  cmd = ast_play_and_wait(chan, "vm-nomore");
12049  }
12050  }
12051  }
12052  } else /* Delete not valid if we haven't selected a message */
12053  cmd = 0;
12054 #ifdef IMAP_STORAGE
12055  deleted = 1;
12056 #endif
12057  break;
12058 
12059  case '8': /* Forward the current message */
12060  if (vms.lastmsg > -1) {
12061  cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
12062  if (cmd == ERROR_LOCK_PATH) {
12063  res = cmd;
12064  goto out;
12065  }
12066  } else {
12067  /* Check if we were listening to urgent
12068  messages. If so, go to regular new messages
12069  instead of saying "no more messages"
12070  */
12071  if (in_urgent == 1 && vms.newmessages > 0) {
12072  /* Check for new messages */
12073  in_urgent = 0;
12074  res = close_mailbox(&vms, vmu);
12075  if (res == ERROR_LOCK_PATH)
12076  goto out;
12077  res = open_mailbox(&vms, vmu, NEW_FOLDER);
12078  if (res < 0)
12079  goto out;
12080  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12081  vms.curmsg = -1;
12082  if (vms.lastmsg < 0) {
12083  cmd = ast_play_and_wait(chan, "vm-nomore");
12084  }
12085  } else {
12086  cmd = ast_play_and_wait(chan, "vm-nomore");
12087  }
12088  }
12089  break;
12090  case '9': /* Save message to folder */
12091  ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
12092  if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
12093  /* No message selected */
12094  cmd = 0;
12095  break;
12096  }
12097  if (useadsi)
12098  adsi_folders(chan, 1, "Save to folder...");
12099  cmd = get_folder2(chan, "vm-savefolder", 1);
12100  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12101  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12102  box = 0; /* Shut up compiler */
12103  if (cmd == '#') {
12104  cmd = 0;
12105  break;
12106  } else if (cmd > 0) {
12107  box = cmd = cmd - '0';
12108  cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd, NULL, 0);
12109  if (cmd == ERROR_LOCK_PATH) {
12110  res = cmd;
12111  goto out;
12112 #ifndef IMAP_STORAGE
12113  } else if (!cmd) {
12114  vms.deleted[vms.curmsg] = 1;
12115 #endif
12116  } else {
12117  vms.deleted[vms.curmsg] = 0;
12118  vms.heard[vms.curmsg] = 0;
12119  }
12120  }
12121  make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
12122  if (useadsi)
12123  adsi_message(chan, &vms);
12124  snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
12125  if (!cmd) {
12126  cmd = ast_play_and_wait(chan, "vm-message");
12127  if (!cmd)
12128  cmd = say_and_wait(chan, vms.curmsg + 1, ast_channel_language(chan));
12129  if (!cmd)
12130  cmd = ast_play_and_wait(chan, "vm-savedto");
12131  if (!cmd)
12132  cmd = vm_play_folder_name(chan, vms.fn);
12133  } else {
12134  cmd = ast_play_and_wait(chan, "vm-mailboxfull");
12135  }
12137  if (vms.curmsg < vms.lastmsg) {
12138  vms.curmsg++;
12139  cmd = play_message(chan, vmu, &vms);
12140  } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12141  vms.curmsg = 0;
12142  cmd = play_message(chan, vmu, &vms);
12143  } else {
12144  /* Check if we were listening to urgent
12145  messages. If so, go to regular new messages
12146  instead of saying "no more messages"
12147  */
12148  if (in_urgent == 1 && vms.newmessages > 0) {
12149  /* Check for new messages */
12150  in_urgent = 0;
12151  res = close_mailbox(&vms, vmu);
12152  if (res == ERROR_LOCK_PATH)
12153  goto out;
12154  res = open_mailbox(&vms, vmu, NEW_FOLDER);
12155  if (res < 0)
12156  goto out;
12157  ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12158  vms.curmsg = -1;
12159  if (vms.lastmsg < 0) {
12160  cmd = ast_play_and_wait(chan, "vm-nomore");
12161  }
12162  } else {
12163  cmd = ast_play_and_wait(chan, "vm-nomore");
12164  }
12165  }
12166  }
12167  break;
12168  case '*': /* Help */
12169  if (!vms.starting) {
12170  if (!strncasecmp(ast_channel_language(chan), "ja", 2)) {
12171  cmd = vm_play_folder_name(chan, vms.vmbox);
12172  if (!cmd)
12173  cmd = ast_play_and_wait(chan, "jp-wa");
12174  if (!cmd)
12175  cmd = ast_play_and_wait(chan, "digits/1");
12176  if (!cmd)
12177  cmd = ast_play_and_wait(chan, "jp-wo");
12178  if (!cmd)
12179  cmd = ast_play_and_wait(chan, "silence/1");
12180  if (!cmd)
12181  cmd = ast_play_and_wait(chan, "vm-opts");
12182  if (!cmd)
12183  cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
12184  break;
12185  }
12186  cmd = ast_play_and_wait(chan, "vm-onefor");
12187  if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
12188  cmd = ast_play_and_wait(chan, "vm-for");
12189  }
12190  if (!cmd)
12191  cmd = vm_play_folder_name(chan, vms.vmbox);
12192  if (!cmd)
12193  cmd = ast_play_and_wait(chan, "vm-opts");
12194  if (!cmd)
12195  cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
12196  } else
12197  cmd = 0;
12198  break;
12199  case '0': /* Mailbox options */
12200  cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
12201  if (useadsi)
12202  adsi_status(chan, &vms);
12203  /* Reopen play_folder */
12204  res = open_mailbox(&vms, vmu, play_folder);
12205  if (res < 0) {
12206  goto out;
12207  }
12208  vms.starting = 1;
12209  break;
12210  default: /* Nothing */
12211  ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
12212  cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
12213  break;
12214  }
12215  }
12216  if ((cmd == 't') || (cmd == '#')) {
12217  /* Timeout */
12218  res = 0;
12219  } else {
12220  /* Hangup */
12221  res = -1;
12222  }
12223 
12224 out:
12225  if (res > -1) {
12226  ast_stopstream(chan);
12227  adsi_goodbye(chan);
12228  if (valid && res != OPERATOR_EXIT) {
12229  if (silentexit)
12230  res = ast_play_and_wait(chan, "vm-dialout");
12231  else
12232  res = ast_play_and_wait(chan, "vm-goodbye");
12233  }
12234  if ((valid && res > 0) || res == OPERATOR_EXIT) {
12235  res = 0;
12236  }
12237  if (useadsi)
12239  }
12240  if (vmu)
12241  close_mailbox(&vms, vmu);
12242  if (valid) {
12243  int new = 0, old = 0, urgent = 0;
12244  snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
12245  /* Urgent flag not passwd to externnotify here */
12246  run_externnotify(vmu->context, vmu->mailbox, NULL);
12247  ast_app_inboxcount2(ext_context, &urgent, &new, &old);
12248  queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgent, new, old);
12249  }
12250 #ifdef IMAP_STORAGE
12251  /* expunge message - use UID Expunge if supported on IMAP server*/
12252  ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
12253  if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
12254  ast_mutex_lock(&vms.lock);
12255 #ifdef HAVE_IMAP_TK2006
12256  if (LEVELUIDPLUS (vms.mailstream)) {
12257  mail_expunge_full(vms.mailstream, NIL, EX_UID);
12258  } else
12259 #endif
12260  mail_expunge(vms.mailstream);
12261  ast_mutex_unlock(&vms.lock);
12262  }
12263  /* before we delete the state, we should copy pertinent info
12264  * back to the persistent model */
12265  if (vmu) {
12266  vmstate_delete(&vms);
12267  }
12268 #endif
12269  if (vmu)
12270  free_user(vmu);
12271 
12272 #ifdef IMAP_STORAGE
12273  pthread_setspecific(ts_vmstate.key, NULL);
12274 #endif
12275  return res;
12276 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
int oldmessages
static char vm_newuser[80]
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
char username[80]
#define ast_test_flag(p, flag)
Definition: utils.h:63
int * deleted
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define ERROR_LOCK_PATH
static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
unsigned int flags
Definition: utils.h:200
#define AST_LOG_WARNING
Definition: logger.h:279
#define VM_MESSAGEWRAP
ast_channel_state
ast_channel states
Definition: channelstate.h:35
char curdir[PATH_MAX]
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define ast_mutex_lock(a)
Definition: lock.h:187
static int get_folder_by_name(const char *name)
const char * args
char password[80]
#define NULL
Definition: resample.c:96
char fn[PATH_MAX]
int urgentmessages
#define ast_verb(level,...)
Definition: logger.h:463
static const struct ast_app_option vm_app_options[128]
char context[MAX_VM_CONTEXT_LEN]
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
#define VM_SVMAIL
#define ast_strlen_zero(foo)
Definition: strings.h:52
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...
static void adsi_begin(struct ast_channel *chan, int *useadsi)
char context[80]
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: main/app.c:692
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char dialout[80]
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
int * heard
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: main/app.c:1470
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
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_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: main/app.c:2906
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:196
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static void run_externnotify(const char *context, const char *extension, const char *flag)
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
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
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)
char vmbox[PATH_MAX]
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8793
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)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
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:1872
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
static int maxlogins
char language[MAX_LANGUAGE]
Structure used to handle boolean flags.
Definition: utils.h:199
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:3184
FILE * out
Definition: utils/frame.c:33
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
char callback[80]
#define VM_SKIPAFTERCMD
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
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]
char mailbox[MAX_VM_MBOX_ID_LEN]
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
int newmessages
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define VM_FORCEGREET
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define AST_APP_ARG(name)
Define an application argument.

◆ vm_forwardoptions()

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

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

Referenced by forward_message().

7950 {
7951  int cmd = 0;
7952  int retries = 0, prepend_duration = 0, already_recorded = 0;
7953  char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
7954  char textfile[PATH_MAX];
7955  struct ast_config *msg_cfg;
7956  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
7957 #ifndef IMAP_STORAGE
7958  signed char zero_gain = 0;
7959 #else
7960  const char *msg_id = NULL;
7961 #endif
7962  const char *duration_str;
7963 
7964  /* Must always populate duration correctly */
7965  make_file(msgfile, sizeof(msgfile), curdir, curmsg);
7966  strcpy(textfile, msgfile);
7967  strcpy(backup, msgfile);
7968  strcpy(backup_textfile, msgfile);
7969  strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
7970  strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
7971  strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7972 
7973  if ((msg_cfg = ast_config_load(textfile, config_flags)) && valid_config(msg_cfg) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
7974  *duration = atoi(duration_str);
7975  } else {
7976  *duration = 0;
7977  }
7978 
7979  while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
7980  if (cmd)
7981  retries = 0;
7982  switch (cmd) {
7983  case '1':
7984 
7985 #ifdef IMAP_STORAGE
7986  /* Record new intro file */
7987  if (msg_cfg && msg_cfg != CONFIG_STATUS_FILEINVALID) {
7988  msg_id = ast_variable_retrieve(msg_cfg, "message", "msg_id");
7989  }
7990  make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
7991  strncat(vms->introfn, "intro", sizeof(vms->introfn));
7992  ast_play_and_wait(chan, "vm-record-prepend");
7993  ast_play_and_wait(chan, "beep");
7994  cmd = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag, msg_id, 1);
7995  if (cmd == -1) {
7996  break;
7997  }
7998  cmd = 't';
7999 #else
8000 
8001  /* prepend a message to the current message, update the metadata and return */
8002 
8003  make_file(msgfile, sizeof(msgfile), curdir, curmsg);
8004  strcpy(textfile, msgfile);
8005  strncat(textfile, ".txt", sizeof(textfile) - 1);
8006  *duration = 0;
8007 
8008  /* if we can't read the message metadata, stop now */
8009  if (!valid_config(msg_cfg)) {
8010  cmd = 0;
8011  break;
8012  }
8013 
8014  /* Back up the original file, so we can retry the prepend and restore it after forward. */
8015 #ifndef IMAP_STORAGE
8016  if (already_recorded) {
8017  ast_filecopy(backup, msgfile, NULL);
8018  copy(backup_textfile, textfile);
8019  }
8020  else {
8021  ast_filecopy(msgfile, backup, NULL);
8022  copy(textfile, backup_textfile);
8023  }
8024 #endif
8025  already_recorded = 1;
8026 
8027  if (record_gain)
8028  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
8029 
8030  cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
8031 
8032  if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
8033  ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
8035  ast_filerename(backup, msgfile, NULL);
8036  }
8037 
8038  if (record_gain)
8039  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
8040 
8041 
8042  if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
8043  *duration = atoi(duration_str);
8044 
8045  if (prepend_duration) {
8046  struct ast_category *msg_cat;
8047  /* need enough space for a maximum-length message duration */
8048  char duration_buf[12];
8049 
8050  *duration += prepend_duration;
8051  msg_cat = ast_category_get(msg_cfg, "message", NULL);
8052  snprintf(duration_buf, sizeof(duration_buf), "%ld", *duration);
8053  if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
8054  ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
8055  }
8056  }
8057 
8058 #endif
8059  break;
8060  case '2':
8061  /* NULL out introfile so we know there is no intro! */
8062 #ifdef IMAP_STORAGE
8063  *vms->introfn = '\0';
8064 #endif
8065  cmd = 't';
8066  break;
8067  case '*':
8068  cmd = '*';
8069  break;
8070  default:
8071  /* If time_out and return to menu, reset already_recorded */
8072  already_recorded = 0;
8073 
8074  cmd = ast_play_and_wait(chan, "vm-forwardoptions");
8075  /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
8076  if (!cmd) {
8077  cmd = ast_play_and_wait(chan, "vm-starmain");
8078  /* "press star to return to the main menu" */
8079  }
8080  if (!cmd) {
8081  cmd = ast_waitfordigit(chan, 6000);
8082  }
8083  if (!cmd) {
8084  retries++;
8085  }
8086  if (retries > 3) {
8087  cmd = '*'; /* Let's cancel this beast */
8088  }
8089  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
8090  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
8091  }
8092  }
8093 
8094  if (valid_config(msg_cfg))
8095  ast_config_destroy(msg_cfg);
8096  if (prepend_duration)
8097  *duration = prepend_duration;
8098 
8099  if (already_recorded && cmd == -1) {
8100  /* restore original message if prepention cancelled */
8101  ast_filerename(backup, msgfile, NULL);
8102  rename(backup_textfile, textfile);
8103  }
8104 
8105  if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */
8106  cmd = 0;
8107  return cmd;
8108 }
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:1108
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
Definition: main/config.c:2531
static int maxsilence
#define CONFIG_STATUS_FILEINVALID
static int copy(char *infile, char *outfile)
Utility function to copy a file.
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: main/app.c:2002
#define NULL
Definition: resample.c:96
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:7522
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_config_load(filename, flags)
Load a config file.
static int silencethreshold
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: main/app.c:1470
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static char vm_pls_try_again[80]
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
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, const char *msg_id, int forwardintro)
#define AST_OPTION_RXGAIN
long int flag
Definition: f2c.h:83
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:1814
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: main/config.c:1444
Structure used to handle boolean flags.
Definition: utils.h:199
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
#define PATH_MAX
Definition: asterisk.h:40
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1022
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char vm_prepend_timeout[80]

◆ vm_index_to_foldername()

static const char* vm_index_to_foldername ( int  id)
static

Definition at line 1971 of file app_voicemail.c.

References mbox(), and NULL.

1972 {
1973  return mbox(NULL, id);
1974 }
#define NULL
Definition: resample.c:96
static const char * mbox(struct ast_vm_user *vmu, int id)

◆ vm_instructions()

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

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

Referenced by vm_execmain().

10636 {
10637  if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
10638  return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent);
10639  } else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
10640  return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
10641  } else { /* Default to ENGLISH */
10642  return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
10643  }
10644 }
static int vm_instructions_ja(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)
const char * ast_channel_language(const struct ast_channel *chan)

◆ vm_instructions_en()

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

10428 {
10429  int res = 0;
10430  /* Play instructions and wait for new command */
10431  while (!res) {
10432  if (vms->starting) {
10433  if (vms->lastmsg > -1) {
10434  if (skipadvanced)
10435  res = ast_play_and_wait(chan, "vm-onefor-full");
10436  else
10437  res = ast_play_and_wait(chan, "vm-onefor");
10438  if (!res)
10439  res = vm_play_folder_name(chan, vms->vmbox);
10440  }
10441  if (!res) {
10442  if (skipadvanced)
10443  res = ast_play_and_wait(chan, "vm-opts-full");
10444  else
10445  res = ast_play_and_wait(chan, "vm-opts");
10446  }
10447  } else {
10448  /* Added for additional help */
10449  if (skipadvanced) {
10450  res = ast_play_and_wait(chan, "vm-onefor-full");
10451  if (!res)
10452  res = vm_play_folder_name(chan, vms->vmbox);
10453  res = ast_play_and_wait(chan, "vm-opts-full");
10454  }
10455  /* Logic:
10456  * If the current message is not the first OR
10457  * if we're listening to the first new message and there are
10458  * also urgent messages, then prompt for navigation to the
10459  * previous message
10460  */
10461  if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
10462  res = ast_play_and_wait(chan, "vm-prev");
10463  }
10464  if (!res && !skipadvanced)
10465  res = ast_play_and_wait(chan, "vm-advopts");
10466  if (!res)
10467  res = ast_play_and_wait(chan, "vm-repeat");
10468  /* Logic:
10469  * If we're not listening to the last message OR
10470  * we're listening to the last urgent message and there are
10471  * also new non-urgent messages, then prompt for navigation
10472  * to the next message
10473  */
10474  if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
10475  (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
10476  res = ast_play_and_wait(chan, "vm-next");
10477  }
10478  if (!res) {
10479  int curmsg_deleted;
10480 #ifdef IMAP_STORAGE
10481  ast_mutex_lock(&vms->lock);
10482 #endif
10483  curmsg_deleted = vms->deleted[vms->curmsg];
10484 #ifdef IMAP_STORAGE
10485  ast_mutex_unlock(&vms->lock);
10486 #endif
10487  if (!curmsg_deleted) {
10488  res = ast_play_and_wait(chan, "vm-delete");
10489  } else {
10490  res = ast_play_and_wait(chan, "vm-undelete");
10491  }
10492  if (!res) {
10493  res = ast_play_and_wait(chan, "vm-toforward");
10494  }
10495  if (!res) {
10496  res = ast_play_and_wait(chan, "vm-savemessage");
10497  }
10498  }
10499  }
10500  if (!res) {
10501  res = ast_play_and_wait(chan, "vm-helpexit");
10502  }
10503  if (!res)
10504  res = ast_waitfordigit(chan, 6000);
10505  if (!res) {
10506  vms->repeats++;
10507  if (vms->repeats > 2) {
10508  res = 't';
10509  }
10510  }
10511  }
10512  return res;
10513 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define ast_test_flag(p, flag)
Definition: utils.h:63
int * deleted
#define VM_MESSAGEWRAP
#define ast_mutex_lock(a)
Definition: lock.h:187
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: main/app.c:1470
char vmbox[PATH_MAX]
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
int newmessages
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ vm_instructions_ja()

static int vm_instructions_ja ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
)
static

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

10516 {
10517  int res = 0;
10518  /* Play instructions and wait for new command */
10519  while (!res) {
10520  if (vms->starting) {
10521  if (vms->lastmsg > -1) {
10522  res = vm_play_folder_name(chan, vms->vmbox);
10523  if (!res)
10524  res = ast_play_and_wait(chan, "jp-wa");
10525  if (!res)
10526  res = ast_play_and_wait(chan, "digits/1");
10527  if (!res)
10528  res = ast_play_and_wait(chan, "jp-wo");
10529  if (!res)
10530  res = ast_play_and_wait(chan, "silence/1");
10531  }
10532  if (!res)
10533  res = ast_play_and_wait(chan, "vm-opts");
10534  } else {
10535  /* Added for additional help */
10536  if (skipadvanced) {
10537  res = vm_play_folder_name(chan, vms->vmbox);
10538  if (!res)
10539  res = ast_play_and_wait(chan, "jp-wa");
10540  if (!res)
10541  res = ast_play_and_wait(chan, "digits/1");
10542  if (!res)
10543  res = ast_play_and_wait(chan, "jp-wo");
10544  if (!res)
10545  res = ast_play_and_wait(chan, "silence/1");
10546  res = ast_play_and_wait(chan, "vm-opts-full");
10547  }
10548  /* Logic:
10549  * If the current message is not the first OR
10550  * if we're listening to the first new message and there are
10551  * also urgent messages, then prompt for navigation to the
10552  * previous message
10553  */
10554  if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
10555  res = ast_play_and_wait(chan, "vm-prev");
10556  }
10557  if (!res && !skipadvanced)
10558  res = ast_play_and_wait(chan, "vm-advopts");
10559  if (!res)
10560  res = ast_play_and_wait(chan, "vm-repeat");
10561  /* Logic:
10562  * If we're not listening to the last message OR
10563  * we're listening to the last urgent message and there are
10564  * also new non-urgent messages, then prompt for navigation
10565  * to the next message
10566  */
10567  if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
10568  (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
10569  res = ast_play_and_wait(chan, "vm-next");
10570  }
10571  if (!res) {
10572  int curmsg_deleted;
10573 #ifdef IMAP_STORAGE
10574  ast_mutex_lock(&vms->lock);
10575 #endif
10576  curmsg_deleted = vms->deleted[vms->curmsg];
10577 #ifdef IMAP_STORAGE
10578  ast_mutex_unlock(&vms->lock);
10579 #endif
10580  if (!curmsg_deleted) {
10581  res = ast_play_and_wait(chan, "vm-delete");
10582  } else {
10583  res = ast_play_and_wait(chan, "vm-undelete");
10584  }
10585  if (!res) {
10586  res = ast_play_and_wait(chan, "vm-toforward");
10587  }
10588  if (!res) {
10589  res = ast_play_and_wait(chan, "vm-savemessage");
10590  }
10591  }
10592  }
10593 
10594  if (!res) {
10595  res = ast_play_and_wait(chan, "vm-helpexit");
10596  }
10597  if (!res)
10598  res = ast_waitfordigit(chan, 6000);
10599  if (!res) {
10600  vms->repeats++;
10601  if (vms->repeats > 2) {
10602  res = 't';
10603  }
10604  }
10605 
10606  }
10607 
10608  return res;
10609 }
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define ast_test_flag(p, flag)
Definition: utils.h:63
int * deleted
#define VM_MESSAGEWRAP
#define ast_mutex_lock(a)
Definition: lock.h:187
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: main/app.c:1470
char vmbox[PATH_MAX]
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
int newmessages
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ vm_instructions_zh()

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

10612 {
10613  int res = 0;
10614  /* Play instructions and wait for new command */
10615  while (!res) {
10616  if (vms->lastmsg > -1) {
10617  res = ast_play_and_wait(chan, "vm-listen");
10618  if (!res)
10619  res = vm_play_folder_name(chan, vms->vmbox);
10620  if (!res)
10621  res = ast_play_and_wait(chan, "press");
10622  if (!res)
10623  res = ast_play_and_wait(chan, "digits/1");
10624  }
10625  if (!res)
10626  res = ast_play_and_wait(chan, "vm-opts");
10627  if (!res) {
10628  vms->starting = 0;
10629  return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
10630  }
10631  }
10632  return res;
10633 }
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)
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: main/app.c:1470
char vmbox[PATH_MAX]

◆ vm_intro()

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

Definition at line 10361 of file app_voicemail.c.

References ast_channel_language(), ast_fileexists(), ast_log, ast_play_and_wait(), ast_test_flag, ast_vm_user::context, DISPOSE, LOG_WARNING, ast_vm_user::mailbox, NULL, 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_is(), vm_intro_it(), vm_intro_ja(), 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().

10362 {
10363  char prefile[256];
10364 
10365  /* Notify the user that the temp greeting is set and give them the option to remove it */
10366  snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10367  if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10368  RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10369  if (ast_fileexists(prefile, NULL, NULL) > 0) {
10370  ast_play_and_wait(chan, "vm-tempgreetactive");
10371  }
10372  DISPOSE(prefile, -1);
10373  }
10374 
10375  /* Play voicemail intro - syntax is different for different languages */
10376  if (0) {
10377  return 0;
10378  } else if (!strncasecmp(ast_channel_language(chan), "cs", 2)) { /* CZECH syntax */
10379  return vm_intro_cs(chan, vms);
10380  } else if (!strncasecmp(ast_channel_language(chan), "cz", 2)) { /* deprecated CZECH syntax */
10381  static int deprecation_warning = 0;
10382  if (deprecation_warning++ % 10 == 0) {
10383  ast_log(LOG_WARNING, "cz is not a standard language code. Please switch to using cs instead.\n");
10384  }
10385  return vm_intro_cs(chan, vms);
10386  } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */
10387  return vm_intro_de(chan, vms);
10388  } else if (!strncasecmp(ast_channel_language(chan), "es", 2)) { /* SPANISH syntax */
10389  return vm_intro_es(chan, vms);
10390  } else if (!strncasecmp(ast_channel_language(chan), "fr", 2)) { /* FRENCH syntax */
10391  return vm_intro_fr(chan, vms);
10392  } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */
10393  return vm_intro_gr(chan, vms);
10394  } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW syntax */
10395  return vm_intro_he(chan, vms);
10396  } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC syntax */
10397  return vm_intro_is(chan, vms);
10398  } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */
10399  return vm_intro_it(chan, vms);
10400  } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE syntax */
10401  return vm_intro_ja(chan, vms);
10402  } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */
10403  return vm_intro_nl(chan, vms);
10404  } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
10405  return vm_intro_no(chan, vms);
10406  } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
10407  return vm_intro_pl(chan, vms);
10408  } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* BRAZILIAN PORTUGUESE syntax */
10409  return vm_intro_pt_BR(chan, vms);
10410  } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE syntax */
10411  return vm_intro_pt(chan, vms);
10412  } else if (!strncasecmp(ast_channel_language(chan), "ru", 2)) { /* RUSSIAN syntax */
10413  return vm_intro_multilang(chan, vms, "n");
10414  } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
10415  return vm_intro_se(chan, vms);
10416  } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* UKRAINIAN syntax */
10417  return vm_intro_multilang(chan, vms, "n");
10418  } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
10419  return vm_intro_vi(chan, vms);
10420  } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
10421  return vm_intro_zh(chan, vms);
10422  } else { /* Default to ENGLISH */
10423  return vm_intro_en(chan, vms);
10424  }
10425 }
#define VM_TEMPGREETWARN
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
char username[80]
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:274
static int vm_intro_ja(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_pt(struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
static int vm_intro_en(struct ast_channel *chan, struct vm_state *vms)
char context[MAX_VM_CONTEXT_LEN]
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[])
#define ast_log
Definition: astobj2.c:42
static int vm_intro_fr(struct ast_channel *chan, struct vm_state *vms)
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: main/app.c:1470
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_is(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_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:1086
const char * ast_channel_language(const struct ast_channel *chan)
char mailbox[MAX_VM_MBOX_ID_LEN]
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)

◆ vm_intro_cs()

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

Definition at line 10231 of file app_voicemail.c.

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

Referenced by vm_intro().

10232 {
10233  int res;
10234  res = ast_play_and_wait(chan, "vm-youhave");
10235  if (!res) {
10236  if (vms->newmessages) {
10237  if (vms->newmessages == 1) {
10238  res = ast_play_and_wait(chan, "digits/jednu");
10239  } else {
10240  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10241  }
10242  if (!res) {
10243  if (vms->newmessages == 1)
10244  res = ast_play_and_wait(chan, "vm-novou");
10245  if ((vms->newmessages) > 1 && (vms->newmessages < 5))
10246  res = ast_play_and_wait(chan, "vm-nove");
10247  if (vms->newmessages > 4)
10248  res = ast_play_and_wait(chan, "vm-novych");
10249  }
10250  if (vms->oldmessages && !res)
10251  res = ast_play_and_wait(chan, "vm-and");
10252  else if (!res) {
10253  if (vms->newmessages == 1)
10254  res = ast_play_and_wait(chan, "vm-zpravu");
10255  if ((vms->newmessages) > 1 && (vms->newmessages < 5))
10256  res = ast_play_and_wait(chan, "vm-zpravy");
10257  if (vms->newmessages > 4)
10258  res = ast_play_and_wait(chan, "vm-zprav");
10259  }
10260  }
10261  if (!res && vms->oldmessages) {
10262  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10263  if (!res) {
10264  if (vms->oldmessages == 1)
10265  res = ast_play_and_wait(chan, "vm-starou");
10266  if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
10267  res = ast_play_and_wait(chan, "vm-stare");
10268  if (vms->oldmessages > 4)
10269  res = ast_play_and_wait(chan, "vm-starych");
10270  }
10271  if (!res) {
10272  if (vms->oldmessages == 1)
10273  res = ast_play_and_wait(chan, "vm-zpravu");
10274  if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
10275  res = ast_play_and_wait(chan, "vm-zpravy");
10276  if (vms->oldmessages > 4)
10277  res = ast_play_and_wait(chan, "vm-zprav");
10278  }
10279  }
10280  if (!res) {
10281  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10282  res = ast_play_and_wait(chan, "vm-no");
10283  if (!res)
10284  res = ast_play_and_wait(chan, "vm-zpravy");
10285  }
10286  }
10287  }
10288  return res;
10289 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_de()

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

Definition at line 9927 of file app_voicemail.c.

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

Referenced by vm_intro().

9928 {
9929  /* Introduce messages they have */
9930  int res;
9931  res = ast_play_and_wait(chan, "vm-youhave");
9932  if (!res) {
9933  if (vms->newmessages) {
9934  if (vms->newmessages == 1)
9935  res = ast_play_and_wait(chan, "digits/1F");
9936  else
9937  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9938  if (!res)
9939  res = ast_play_and_wait(chan, "vm-INBOX");
9940  if (vms->oldmessages && !res)
9941  res = ast_play_and_wait(chan, "vm-and");
9942  else if (!res) {
9943  if (vms->newmessages == 1)
9944  res = ast_play_and_wait(chan, "vm-message");
9945  else
9946  res = ast_play_and_wait(chan, "vm-messages");
9947  }
9948 
9949  }
9950  if (!res && vms->oldmessages) {
9951  if (vms->oldmessages == 1)
9952  res = ast_play_and_wait(chan, "digits/1F");
9953  else
9954  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9955  if (!res)
9956  res = ast_play_and_wait(chan, "vm-Old");
9957  if (!res) {
9958  if (vms->oldmessages == 1)
9959  res = ast_play_and_wait(chan, "vm-message");
9960  else
9961  res = ast_play_and_wait(chan, "vm-messages");
9962  }
9963  }
9964  if (!res) {
9965  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9966  res = ast_play_and_wait(chan, "vm-no");
9967  if (!res)
9968  res = ast_play_and_wait(chan, "vm-messages");
9969  }
9970  }
9971  }
9972  return res;
9973 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_en()

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

Definition at line 9607 of file app_voicemail.c.

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

Referenced by vm_intro().

9608 {
9609  int res;
9610 
9611  /* Introduce messages they have */
9612  res = ast_play_and_wait(chan, "vm-youhave");
9613  if (!res) {
9614  if (vms->urgentmessages) {
9615  res = say_and_wait(chan, vms->urgentmessages, ast_channel_language(chan));
9616  if (!res)
9617  res = ast_play_and_wait(chan, "vm-Urgent");
9618  if ((vms->oldmessages || vms->newmessages) && !res) {
9619  res = ast_play_and_wait(chan, "vm-and");
9620  } else if (!res) {
9621  if (vms->urgentmessages == 1)
9622  res = ast_play_and_wait(chan, "vm-message");
9623  else
9624  res = ast_play_and_wait(chan, "vm-messages");
9625  }
9626  }
9627  if (vms->newmessages) {
9628  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9629  if (!res)
9630  res = ast_play_and_wait(chan, "vm-INBOX");
9631  if (vms->oldmessages && !res)
9632  res = ast_play_and_wait(chan, "vm-and");
9633  else if (!res) {
9634  if (vms->newmessages == 1)
9635  res = ast_play_and_wait(chan, "vm-message");
9636  else
9637  res = ast_play_and_wait(chan, "vm-messages");
9638  }
9639 
9640  }
9641  if (!res && vms->oldmessages) {
9642  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9643  if (!res)
9644  res = ast_play_and_wait(chan, "vm-Old");
9645  if (!res) {
9646  if (vms->oldmessages == 1)
9647  res = ast_play_and_wait(chan, "vm-message");
9648  else
9649  res = ast_play_and_wait(chan, "vm-messages");
9650  }
9651  }
9652  if (!res) {
9653  if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
9654  res = ast_play_and_wait(chan, "vm-no");
9655  if (!res)
9656  res = ast_play_and_wait(chan, "vm-messages");
9657  }
9658  }
9659  }
9660  return res;
9661 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_es()

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

Definition at line 9976 of file app_voicemail.c.

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

Referenced by vm_intro().

9977 {
9978  /* Introduce messages they have */
9979  int res;
9980  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9981  res = ast_play_and_wait(chan, "vm-youhaveno");
9982  if (!res)
9983  res = ast_play_and_wait(chan, "vm-messages");
9984  } else {
9985  res = ast_play_and_wait(chan, "vm-youhave");
9986  }
9987  if (!res) {
9988  if (vms->newmessages) {
9989  if (!res) {
9990  if (vms->newmessages == 1) {
9991  res = ast_play_and_wait(chan, "digits/1M");
9992  if (!res)
9993  res = ast_play_and_wait(chan, "vm-message");
9994  if (!res)
9995  res = ast_play_and_wait(chan, "vm-INBOXs");
9996  } else {
9997  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9998  if (!res)
9999  res = ast_play_and_wait(chan, "vm-messages");
10000  if (!res)
10001  res = ast_play_and_wait(chan, "vm-INBOX");
10002  }
10003  }
10004  if (vms->oldmessages && !res)
10005  res = ast_play_and_wait(chan, "vm-and");
10006  }
10007  if (vms->oldmessages) {
10008  if (!res) {
10009  if (vms->oldmessages == 1) {
10010  res = ast_play_and_wait(chan, "digits/1M");
10011  if (!res)
10012  res = ast_play_and_wait(chan, "vm-message");
10013  if (!res)
10014  res = ast_play_and_wait(chan, "vm-Olds");
10015  } else {
10016  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10017  if (!res)
10018  res = ast_play_and_wait(chan, "vm-messages");
10019  if (!res)
10020  res = ast_play_and_wait(chan, "vm-Old");
10021  }
10022  }
10023  }
10024  }
10025 return res;
10026 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_fr()

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

Definition at line 10074 of file app_voicemail.c.

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

Referenced by vm_intro().

10075 {
10076  /* Introduce messages they have */
10077  int res;
10078  res = ast_play_and_wait(chan, "vm-youhave");
10079  if (!res) {
10080  if (vms->newmessages) {
10081  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10082  if (!res)
10083  res = ast_play_and_wait(chan, "vm-INBOX");
10084  if (vms->oldmessages && !res)
10085  res = ast_play_and_wait(chan, "vm-and");
10086  else if (!res) {
10087  if (vms->newmessages == 1)
10088  res = ast_play_and_wait(chan, "vm-message");
10089  else
10090  res = ast_play_and_wait(chan, "vm-messages");
10091  }
10092 
10093  }
10094  if (!res && vms->oldmessages) {
10095  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10096  if (!res)
10097  res = ast_play_and_wait(chan, "vm-Old");
10098  if (!res) {
10099  if (vms->oldmessages == 1)
10100  res = ast_play_and_wait(chan, "vm-message");
10101  else
10102  res = ast_play_and_wait(chan, "vm-messages");
10103  }
10104  }
10105  if (!res) {
10106  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10107  res = ast_play_and_wait(chan, "vm-no");
10108  if (!res)
10109  res = ast_play_and_wait(chan, "vm-messages");
10110  }
10111  }
10112  }
10113  return res;
10114 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_gr()

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

Definition at line 9367 of file app_voicemail.c.

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

Referenced by vm_intro().

9368 {
9369  int res = 0;
9370 
9371  if (vms->newmessages) {
9372  res = ast_play_and_wait(chan, "vm-youhave");
9373  if (!res)
9375  if (!res) {
9376  if (vms->newmessages == 1) {
9377  res = ast_play_and_wait(chan, "vm-INBOX");
9378  if (!res)
9379  res = ast_play_and_wait(chan, "vm-message");
9380  } else {
9381  res = ast_play_and_wait(chan, "vm-INBOXs");
9382  if (!res)
9383  res = ast_play_and_wait(chan, "vm-messages");
9384  }
9385  }
9386  } else if (vms->oldmessages){
9387  res = ast_play_and_wait(chan, "vm-youhave");
9388  if (!res)
9390  if (vms->oldmessages == 1){
9391  res = ast_play_and_wait(chan, "vm-Old");
9392  if (!res)
9393  res = ast_play_and_wait(chan, "vm-message");
9394  } else {
9395  res = ast_play_and_wait(chan, "vm-Olds");
9396  if (!res)
9397  res = ast_play_and_wait(chan, "vm-messages");
9398  }
9399  } else if (!vms->oldmessages && !vms->newmessages)
9400  res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
9401  return res;
9402 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:48
#define NULL
Definition: resample.c:96
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: main/app.c:1470
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:8337
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_he()

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

Definition at line 9501 of file app_voicemail.c.

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

Referenced by vm_intro().

9502 {
9503  int res = 0;
9504 
9505  /* Introduce messages they have */
9506  if (!res) {
9507  if ((vms->newmessages) || (vms->oldmessages)) {
9508  res = ast_play_and_wait(chan, "vm-youhave");
9509  }
9510  /*
9511  * The word "shtei" refers to the number 2 in hebrew when performing a count
9512  * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
9513  * an element, this is one of them.
9514  */
9515  if (vms->newmessages) {
9516  if (!res) {
9517  if (vms->newmessages == 1) {
9518  res = ast_play_and_wait(chan, "vm-INBOX1");
9519  } else {
9520  if (vms->newmessages == 2) {
9521  res = ast_play_and_wait(chan, "vm-shtei");
9522  } else {
9523  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9524  }
9525  res = ast_play_and_wait(chan, "vm-INBOX");
9526  }
9527  }
9528  if (vms->oldmessages && !res) {
9529  res = ast_play_and_wait(chan, "vm-and");
9530  if (vms->oldmessages == 1) {
9531  res = ast_play_and_wait(chan, "vm-Old1");
9532  } else {
9533  if (vms->oldmessages == 2) {
9534  res = ast_play_and_wait(chan, "vm-shtei");
9535  } else {
9536  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9537  }
9538  res = ast_play_and_wait(chan, "vm-Old");
9539  }
9540  }
9541  }
9542  if (!res && vms->oldmessages && !vms->newmessages) {
9543  if (!res) {
9544  if (vms->oldmessages == 1) {
9545  res = ast_play_and_wait(chan, "vm-Old1");
9546  } else {
9547  if (vms->oldmessages == 2) {
9548  res = ast_play_and_wait(chan, "vm-shtei");
9549  } else {
9550  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9551  }
9552  res = ast_play_and_wait(chan, "vm-Old");
9553  }
9554  }
9555  }
9556  if (!res) {
9557  if (!vms->oldmessages && !vms->newmessages) {
9558  if (!res) {
9559  res = ast_play_and_wait(chan, "vm-nomessages");
9560  }
9561  }
9562  }
9563  }
9564  return res;
9565 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:48
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: main/app.c:1470
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:8337
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_is()

static int vm_intro_is ( struct ast_channel chan,
struct vm_state vms 
)
static

Definition at line 9664 of file app_voicemail.c.

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

Referenced by vm_intro().

9665 {
9666  int res;
9667 
9668  /* Introduce messages they have */
9669  res = ast_play_and_wait(chan, "vm-youhave");
9670  if (!res) {
9671  if (vms->urgentmessages) {
9672  /* Digits 1-4 are spoken in neutral and plural when talking about messages,
9673  however, feminine is used for 1 as it is the same as the neutral for plural,
9674  and singular neutral is the same after 1. */
9675  if (vms->urgentmessages < 5) {
9676  char recname[16];
9677  if (vms->urgentmessages == 1)
9678  snprintf(recname, sizeof(recname), "digits/1kvk");
9679  else
9680  snprintf(recname, sizeof(recname), "digits/%dhk", vms->urgentmessages);
9681  res = ast_play_and_wait(chan, recname);
9682  } else if (!res)
9683  res = ast_play_and_wait(chan, "vm-Urgent");
9684  if ((vms->oldmessages || vms->newmessages) && !res) {
9685  res = ast_play_and_wait(chan, "vm-and");
9686  } else if (!res)
9687  res = ast_play_and_wait(chan, "vm-messages");
9688  }
9689  if (vms->newmessages) {
9690  if (vms->newmessages < 5) {
9691  char recname[16];
9692  if (vms->newmessages == 1)
9693  snprintf(recname, sizeof(recname), "digits/1kvk");
9694  else
9695  snprintf(recname, sizeof(recname), "digits/%dhk", vms->newmessages);
9696  res = ast_play_and_wait(chan, recname);
9697  } else
9698  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9699  if (!res)
9700  res = ast_play_and_wait(chan, "vm-INBOX");
9701  if (vms->oldmessages && !res)
9702  res = ast_play_and_wait(chan, "vm-and");
9703  else if (!res)
9704  res = ast_play_and_wait(chan, "vm-messages");
9705  }
9706  if (!res && vms->oldmessages) {
9707  if (vms->oldmessages < 5) {
9708  char recname[16];
9709  if (vms->oldmessages == 1)
9710  snprintf(recname, sizeof(recname), "digits/1kvk");
9711  else
9712  snprintf(recname, sizeof(recname), "digits/%dhk", vms->oldmessages);
9713  res = ast_play_and_wait(chan, recname);
9714  } else
9715  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9716  if (!res)
9717  res = ast_play_and_wait(chan, "vm-Old");
9718  if (!res)
9719  res = ast_play_and_wait(chan, "vm-messages");
9720  }
9721  if (!res) {
9722  if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
9723  res = ast_play_and_wait(chan, "vm-no");
9724  if (!res)
9725  res = ast_play_and_wait(chan, "vm-messages");
9726  }
9727  }
9728  }
9729  return res;
9730 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_it()

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

Definition at line 9733 of file app_voicemail.c.

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

Referenced by vm_intro().

9734 {
9735  /* Introduce messages they have */
9736  int res;
9737  if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
9738  res = ast_play_and_wait(chan, "vm-no") ||
9739  ast_play_and_wait(chan, "vm-message");
9740  else
9741  res = ast_play_and_wait(chan, "vm-youhave");
9742  if (!res && vms->newmessages) {
9743  res = (vms->newmessages == 1) ?
9744  ast_play_and_wait(chan, "digits/un") ||
9745  ast_play_and_wait(chan, "vm-nuovo") ||
9746  ast_play_and_wait(chan, "vm-message") :
9747  /* 2 or more new messages */
9748  say_and_wait(chan, vms->newmessages, ast_channel_language(chan)) ||
9749  ast_play_and_wait(chan, "vm-nuovi") ||
9750  ast_play_and_wait(chan, "vm-messages");
9751  if (!res && vms->oldmessages)
9752  res = ast_play_and_wait(chan, "vm-and");
9753  }
9754  if (!res && vms->oldmessages) {
9755  res = (vms->oldmessages == 1) ?
9756  ast_play_and_wait(chan, "digits/un") ||
9757  ast_play_and_wait(chan, "vm-vecchio") ||
9758  ast_play_and_wait(chan, "vm-message") :
9759  /* 2 or more old messages */
9760  say_and_wait(chan, vms->oldmessages, ast_channel_language(chan)) ||
9761  ast_play_and_wait(chan, "vm-vecchi") ||
9762  ast_play_and_wait(chan, "vm-messages");
9763  }
9764  return res;
9765 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_ja()

static int vm_intro_ja ( struct ast_channel chan,
struct vm_state vms 
)
static

Definition at line 9568 of file app_voicemail.c.

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

Referenced by vm_intro().

9569 {
9570  /* Introduce messages they have */
9571  int res;
9572  if (vms->newmessages) {
9573  res = ast_play_and_wait(chan, "vm-INBOX");
9574  if (!res)
9575  res = ast_play_and_wait(chan, "vm-message");
9576  if (!res)
9577  res = ast_play_and_wait(chan, "jp-ga");
9578  if (!res)
9579  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9580  if (vms->oldmessages && !res)
9581  res = ast_play_and_wait(chan, "silence/1");
9582 
9583  }
9584  if (vms->oldmessages) {
9585  res = ast_play_and_wait(chan, "vm-Old");
9586  if (!res)
9587  res = ast_play_and_wait(chan, "vm-message");
9588  if (!res)
9589  res = ast_play_and_wait(chan, "jp-ga");
9590  if (!res)
9591  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9592  }
9593  if (!vms->oldmessages && !vms->newmessages) {
9594  res = ast_play_and_wait(chan, "vm-messages");
9595  if (!res)
9596  res = ast_play_and_wait(chan, "jp-wa");
9597  if (!res)
9598  res = ast_play_and_wait(chan, "jp-arimasen");
9599  }
9600  else {
9601  res = ast_play_and_wait(chan, "jp-arimasu");
9602  }
9603  return res;
9604 } /* Japanese */
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_multilang()

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

Definition at line 9461 of file app_voicemail.c.

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

Referenced by vm_intro().

9462 {
9463  int res;
9464  int lastnum = 0;
9465 
9466  res = ast_play_and_wait(chan, "vm-youhave");
9467 
9468  if (!res && vms->newmessages) {
9469  lastnum = vms->newmessages;
9470 
9471  if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
9472  res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
9473  }
9474 
9475  if (!res && vms->oldmessages) {
9476  res = ast_play_and_wait(chan, "vm-and");
9477  }
9478  }
9479 
9480  if (!res && vms->oldmessages) {
9481  lastnum = vms->oldmessages;
9482 
9483  if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
9484  res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
9485  }
9486  }
9487 
9488  if (!res) {
9489  if (lastnum == 0) {
9490  res = ast_play_and_wait(chan, "vm-no");
9491  }
9492  if (!res) {
9493  res = ast_say_counted_noun(chan, lastnum, "vm-message");
9494  }
9495  }
9496 
9497  return res;
9498 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
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: main/app.c:1470
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:8337
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_nl()

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

Definition at line 10117 of file app_voicemail.c.

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

Referenced by vm_intro().

10118 {
10119  /* Introduce messages they have */
10120  int res;
10121  res = ast_play_and_wait(chan, "vm-youhave");
10122  if (!res) {
10123  if (vms->newmessages) {
10124  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10125  if (!res) {
10126  if (vms->newmessages == 1)
10127  res = ast_play_and_wait(chan, "vm-INBOXs");
10128  else
10129  res = ast_play_and_wait(chan, "vm-INBOX");
10130  }
10131  if (vms->oldmessages && !res)
10132  res = ast_play_and_wait(chan, "vm-and");
10133  else if (!res) {
10134  if (vms->newmessages == 1)
10135  res = ast_play_and_wait(chan, "vm-message");
10136  else
10137  res = ast_play_and_wait(chan, "vm-messages");
10138  }
10139 
10140  }
10141  if (!res && vms->oldmessages) {
10142  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10143  if (!res) {
10144  if (vms->oldmessages == 1)
10145  res = ast_play_and_wait(chan, "vm-Olds");
10146  else
10147  res = ast_play_and_wait(chan, "vm-Old");
10148  }
10149  if (!res) {
10150  if (vms->oldmessages == 1)
10151  res = ast_play_and_wait(chan, "vm-message");
10152  else
10153  res = ast_play_and_wait(chan, "vm-messages");
10154  }
10155  }
10156  if (!res) {
10157  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10158  res = ast_play_and_wait(chan, "vm-no");
10159  if (!res)
10160  res = ast_play_and_wait(chan, "vm-messages");
10161  }
10162  }
10163  }
10164  return res;
10165 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_no()

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

Definition at line 9883 of file app_voicemail.c.

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

Referenced by vm_intro().

9884 {
9885  /* Introduce messages they have */
9886  int res;
9887 
9888  res = ast_play_and_wait(chan, "vm-youhave");
9889  if (res)
9890  return res;
9891 
9892  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9893  res = ast_play_and_wait(chan, "vm-no");
9894  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9895  return res;
9896  }
9897 
9898  if (vms->newmessages) {
9899  if (vms->newmessages == 1) {
9900  res = ast_play_and_wait(chan, "digits/1");
9901  res = res ? res : ast_play_and_wait(chan, "vm-ny");
9902  res = res ? res : ast_play_and_wait(chan, "vm-message");
9903  } else {
9904  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9905  res = res ? res : ast_play_and_wait(chan, "vm-nye");
9906  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9907  }
9908  if (!res && vms->oldmessages)
9909  res = ast_play_and_wait(chan, "vm-and");
9910  }
9911  if (!res && vms->oldmessages) {
9912  if (vms->oldmessages == 1) {
9913  res = ast_play_and_wait(chan, "digits/1");
9914  res = res ? res : ast_play_and_wait(chan, "vm-gamel");
9915  res = res ? res : ast_play_and_wait(chan, "vm-message");
9916  } else {
9917  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9918  res = res ? res : ast_play_and_wait(chan, "vm-gamle");
9919  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9920  }
9921  }
9922 
9923  return res;
9924 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_pl()

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

Definition at line 9768 of file app_voicemail.c.

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

Referenced by vm_intro().

9769 {
9770  /* Introduce messages they have */
9771  int res;
9772  div_t num;
9773 
9774  if (!vms->oldmessages && !vms->newmessages) {
9775  res = ast_play_and_wait(chan, "vm-no");
9776  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9777  return res;
9778  } else {
9779  res = ast_play_and_wait(chan, "vm-youhave");
9780  }
9781 
9782  if (vms->newmessages) {
9783  num = div(vms->newmessages, 10);
9784  if (vms->newmessages == 1) {
9785  res = ast_play_and_wait(chan, "digits/1-a");
9786  res = res ? res : ast_play_and_wait(chan, "vm-new-a");
9787  res = res ? res : ast_play_and_wait(chan, "vm-message");
9788  } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9789  if (num.rem == 2) {
9790  if (!num.quot) {
9791  res = ast_play_and_wait(chan, "digits/2-ie");
9792  } else {
9793  res = say_and_wait(chan, vms->newmessages - 2 , ast_channel_language(chan));
9794  res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
9795  }
9796  } else {
9797  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9798  }
9799  res = res ? res : ast_play_and_wait(chan, "vm-new-e");
9800  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9801  } else {
9802  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9803  res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
9804  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9805  }
9806  if (!res && vms->oldmessages)
9807  res = ast_play_and_wait(chan, "vm-and");
9808  }
9809  if (!res && vms->oldmessages) {
9810  num = div(vms->oldmessages, 10);
9811  if (vms->oldmessages == 1) {
9812  res = ast_play_and_wait(chan, "digits/1-a");
9813  res = res ? res : ast_play_and_wait(chan, "vm-old-a");
9814  res = res ? res : ast_play_and_wait(chan, "vm-message");
9815  } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9816  if (num.rem == 2) {
9817  if (!num.quot) {
9818  res = ast_play_and_wait(chan, "digits/2-ie");
9819  } else {
9820  res = say_and_wait(chan, vms->oldmessages - 2 , ast_channel_language(chan));
9821  res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
9822  }
9823  } else {
9824  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9825  }
9826  res = res ? res : ast_play_and_wait(chan, "vm-old-e");
9827  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9828  } else {
9829  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9830  res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
9831  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9832  }
9833  }
9834 
9835  return res;
9836 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_pt()

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

Definition at line 10168 of file app_voicemail.c.

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

Referenced by vm_intro().

10169 {
10170  /* Introduce messages they have */
10171  int res;
10172  res = ast_play_and_wait(chan, "vm-youhave");
10173  if (!res) {
10174  if (vms->newmessages) {
10175  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10176  if (!res) {
10177  if (vms->newmessages == 1) {
10178  res = ast_play_and_wait(chan, "vm-message");
10179  if (!res)
10180  res = ast_play_and_wait(chan, "vm-INBOXs");
10181  } else {
10182  res = ast_play_and_wait(chan, "vm-messages");
10183  if (!res)
10184  res = ast_play_and_wait(chan, "vm-INBOX");
10185  }
10186  }
10187  if (vms->oldmessages && !res)
10188  res = ast_play_and_wait(chan, "vm-and");
10189  }
10190  if (!res && vms->oldmessages) {
10191  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10192  if (!res) {
10193  if (vms->oldmessages == 1) {
10194  res = ast_play_and_wait(chan, "vm-message");
10195  if (!res)
10196  res = ast_play_and_wait(chan, "vm-Olds");
10197  } else {
10198  res = ast_play_and_wait(chan, "vm-messages");
10199  if (!res)
10200  res = ast_play_and_wait(chan, "vm-Old");
10201  }
10202  }
10203  }
10204  if (!res) {
10205  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10206  res = ast_play_and_wait(chan, "vm-no");
10207  if (!res)
10208  res = ast_play_and_wait(chan, "vm-messages");
10209  }
10210  }
10211  }
10212  return res;
10213 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:48
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: main/app.c:1470
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:8337
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_pt_BR()

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

Definition at line 10029 of file app_voicemail.c.

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

Referenced by vm_intro().

10029  {
10030  /* Introduce messages they have */
10031  int res;
10032  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10033  res = ast_play_and_wait(chan, "vm-nomessages");
10034  return res;
10035  } else {
10036  res = ast_play_and_wait(chan, "vm-youhave");
10037  }
10038  if (vms->newmessages) {
10039  if (!res)
10040  res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10041  if (vms->newmessages == 1) {
10042  if (!res)
10043  res = ast_play_and_wait(chan, "vm-message");
10044  if (!res)
10045  res = ast_play_and_wait(chan, "vm-INBOXs");
10046  } else {
10047  if (!res)
10048  res = ast_play_and_wait(chan, "vm-messages");
10049  if (!res)
10050  res = ast_play_and_wait(chan, "vm-INBOX");
10051  }
10052  if (vms->oldmessages && !res)
10053  res = ast_play_and_wait(chan, "vm-and");
10054  }
10055  if (vms->oldmessages) {
10056  if (!res)
10057  res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10058  if (vms->oldmessages == 1) {
10059  if (!res)
10060  res = ast_play_and_wait(chan, "vm-message");
10061  if (!res)
10062  res = ast_play_and_wait(chan, "vm-Olds");
10063  } else {
10064  if (!res)
10065  res = ast_play_and_wait(chan, "vm-messages");
10066  if (!res)
10067  res = ast_play_and_wait(chan, "vm-Old");
10068  }
10069  }
10070  return res;
10071 }
int oldmessages
#define AST_DIGIT_ANY
Definition: file.h:48
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: main/app.c:1470
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:8337
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_se()

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

Definition at line 9839 of file app_voicemail.c.

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

Referenced by vm_intro().

9840 {
9841  /* Introduce messages they have */
9842  int res;
9843 
9844  res = ast_play_and_wait(chan, "vm-youhave");
9845  if (res)
9846  return res;
9847 
9848  if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9849  res = ast_play_and_wait(chan, "vm-no");
9850  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9851  return res;
9852  }
9853 
9854  if (vms->newmessages) {
9855  if (vms->newmessages == 1) {
9856  res = ast_play_and_wait(chan, "digits/ett");
9857  res = res ? res : ast_play_and_wait(chan, "vm-nytt");
9858  res = res ? res : ast_play_and_wait(chan, "vm-message");
9859  } else {
9860  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9861  res = res ? res : ast_play_and_wait(chan, "vm-nya");
9862  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9863  }
9864  if (!res && vms->oldmessages)
9865  res = ast_play_and_wait(chan, "vm-and");
9866  }
9867  if (!res && vms->oldmessages) {
9868  if (vms->oldmessages == 1) {
9869  res = ast_play_and_wait(chan, "digits/ett");
9870  res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
9871  res = res ? res : ast_play_and_wait(chan, "vm-message");
9872  } else {
9873  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9874  res = res ? res : ast_play_and_wait(chan, "vm-gamla");
9875  res = res ? res : ast_play_and_wait(chan, "vm-messages");
9876  }
9877  }
9878 
9879  return res;
9880 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_vi()

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

Definition at line 10331 of file app_voicemail.c.

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

Referenced by vm_intro().

10332 {
10333  int res;
10334 
10335  /* Introduce messages they have */
10336  res = ast_play_and_wait(chan, "vm-youhave");
10337  if (!res) {
10338  if (vms->newmessages) {
10339  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10340  if (!res)
10341  res = ast_play_and_wait(chan, "vm-INBOX");
10342  if (vms->oldmessages && !res)
10343  res = ast_play_and_wait(chan, "vm-and");
10344  }
10345  if (!res && vms->oldmessages) {
10346  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10347  if (!res)
10348  res = ast_play_and_wait(chan, "vm-Old");
10349  }
10350  if (!res) {
10351  if (!vms->oldmessages && !vms->newmessages) {
10352  res = ast_play_and_wait(chan, "vm-no");
10353  if (!res)
10354  res = ast_play_and_wait(chan, "vm-message");
10355  }
10356  }
10357  }
10358  return res;
10359 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_intro_zh()

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

Definition at line 10292 of file app_voicemail.c.

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

Referenced by vm_intro().

10293 {
10294  int res;
10295  /* Introduce messages they have */
10296  res = ast_play_and_wait(chan, "vm-you");
10297 
10298  if (!res && vms->newmessages) {
10299  res = ast_play_and_wait(chan, "vm-have");
10300  if (!res)
10301  res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10302  if (!res)
10303  res = ast_play_and_wait(chan, "vm-tong");
10304  if (!res)
10305  res = ast_play_and_wait(chan, "vm-INBOX");
10306  if (vms->oldmessages && !res)
10307  res = ast_play_and_wait(chan, "vm-and");
10308  else if (!res)
10309  res = ast_play_and_wait(chan, "vm-messages");
10310  }
10311  if (!res && vms->oldmessages) {
10312  res = ast_play_and_wait(chan, "vm-have");
10313  if (!res)
10314  res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10315  if (!res)
10316  res = ast_play_and_wait(chan, "vm-tong");
10317  if (!res)
10318  res = ast_play_and_wait(chan, "vm-Old");
10319  if (!res)
10320  res = ast_play_and_wait(chan, "vm-messages");
10321  }
10322  if (!res && !vms->oldmessages && !vms->newmessages) {
10323  res = ast_play_and_wait(chan, "vm-haveno");
10324  if (!res)
10325  res = ast_play_and_wait(chan, "vm-messages");
10326  }
10327  return res;
10328 }
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: main/app.c:1470
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
const char * ast_channel_language(const struct ast_channel *chan)
int newmessages

◆ vm_lock_path()

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

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

3730 {
3731  switch (ast_lock_path(path)) {
3732  case AST_LOCK_TIMEOUT:
3733  return -1;
3734  default:
3735  return 0;
3736  }
3737 }
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2457

◆ vm_mailbox_snapshot_create()

static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_create ( const char *  mailbox,
const char *  context,
const char *  folder,
int  descending,
enum ast_vm_snapshot_sort_val  sort_val,
int  combine_INBOX_and_OLD 
)
static

Definition at line 15931 of file app_voicemail.c.

References ARRAY_LEN, ast_calloc, ast_copy_string(), ast_free, ast_log, AST_LOG_ERROR, AST_LOG_WARNING, ast_strlen_zero, close_mailbox(), ERROR_LOCK_PATH, find_user(), ast_vm_mailbox_snapshot::folders, free_user(), get_folder_by_name(), vm_state::lastmsg, LOG_WARNING, NULL, open_mailbox(), ast_vm_mailbox_snapshot::snapshots, vm_state::username, and vm_msg_snapshot_create().

15937 {
15938  struct ast_vm_mailbox_snapshot *mailbox_snapshot;
15939  struct vm_state vms;
15940  struct ast_vm_user *vmu = NULL, vmus;
15941  int res;
15942  int i;
15943  int this_index_only = -1;
15944  int open = 0;
15945  int inbox_index = get_folder_by_name("INBOX");
15946  int old_index = get_folder_by_name("Old");
15947  int urgent_index = get_folder_by_name("Urgent");
15948 
15949  if (ast_strlen_zero(mailbox)) {
15950  ast_log(LOG_WARNING, "Cannot create a mailbox snapshot since no mailbox was specified\n");
15951  return NULL;
15952  }
15953 
15954  memset(&vmus, 0, sizeof(vmus));
15955 
15956  if (!(ast_strlen_zero(folder))) {
15957  /* find the folder index */
15958  for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
15959  if (!strcasecmp(mailbox_folders[i], folder)) {
15960  this_index_only = i;
15961  break;
15962  }
15963  }
15964  if (this_index_only == -1) {
15965  /* Folder was specified and it did not match any folder in our list */
15966  return NULL;
15967  }
15968  }
15969 
15970  if (!(vmu = find_user(&vmus, context, mailbox))) {
15971  ast_log(AST_LOG_WARNING, "Failed to create mailbox snapshot for unknown voicemail user %s@%s\n", mailbox, context);
15972  return NULL;
15973  }
15974 
15975  if (!(mailbox_snapshot = ast_calloc(1, sizeof(*mailbox_snapshot)))) {
15976  ast_log(AST_LOG_ERROR, "Failed to allocate memory for mailbox snapshot\n");
15977  free_user(vmu);
15978  return NULL;
15979  }
15980 
15981  if (!(mailbox_snapshot->snapshots = ast_calloc(ARRAY_LEN(mailbox_folders), sizeof(*mailbox_snapshot->snapshots)))) {
15982  ast_free(mailbox_snapshot);
15983  free_user(vmu);
15984  return NULL;
15985  }
15986 
15987  mailbox_snapshot->folders = ARRAY_LEN(mailbox_folders);
15988 
15989  for (i = 0; i < mailbox_snapshot->folders; i++) {
15990  int msg_folder_index = i;
15991 
15992  /* We want this message in the snapshot if any of the following:
15993  * No folder was specified.
15994  * The specified folder matches the current folder.
15995  * The specified folder is INBOX AND we were asked to combine messages AND the current folder is either Old or Urgent.
15996  */
15997  if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
15998  continue;
15999  }
16000 
16001  /* Make sure that Old or Urgent messages are marked as being in INBOX. */
16002  if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
16003  msg_folder_index = inbox_index;
16004  }
16005 
16006  memset(&vms, 0, sizeof(vms));
16007  ast_copy_string(vms.username, mailbox, sizeof(vms.username));
16008  vms.lastmsg = -1;
16009  open = 0;
16010 
16011  /* open the mailbox state */
16012  if ((res = open_mailbox(&vms, vmu, i)) < 0) {
16013  ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
16014  goto snapshot_cleanup;
16015  }
16016  open = 1;
16017 
16018  /* Iterate through each msg, storing off info */
16019  if (vms.lastmsg != -1) {
16020  if ((vm_msg_snapshot_create(vmu, &vms, mailbox_snapshot, msg_folder_index, i, descending, sort_val))) {
16021  ast_log(LOG_WARNING, "Failed to create msg snapshots for %s@%s\n", mailbox, context);
16022  goto snapshot_cleanup;
16023  }
16024  }
16025 
16026  /* close mailbox */
16027  if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
16028  goto snapshot_cleanup;
16029  }
16030  open = 0;
16031  }
16032 
16033 snapshot_cleanup:
16034  if (vmu && open) {
16035  close_mailbox(&vms, vmu);
16036  }
16037 
16038 #ifdef IMAP_STORAGE
16039  if (vmu) {
16040  vmstate_delete(&vms);
16041  }
16042 #endif
16043 
16044  free_user(vmu);
16045  return mailbox_snapshot;
16046 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int vm_msg_snapshot_create(struct ast_vm_user *vmu, struct vm_state *vms, struct ast_vm_mailbox_snapshot *mailbox_snapshot, int snapshot_index, int mailbox_index, int descending, enum ast_vm_snapshot_sort_val sort_val)
Create and store off all the msgs in an open mailbox.
#define ERROR_LOCK_PATH
#define LOG_WARNING
Definition: logger.h:274
#define AST_LOG_WARNING
Definition: logger.h:279
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int get_folder_by_name(const char *name)
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
static const char *const mailbox_folders[]
static void free_user(struct ast_vm_user *vmu)
struct ast_vm_mailbox_snapshot::@223 * snapshots
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.
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ vm_mailbox_snapshot_destroy()

static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_destroy ( struct ast_vm_mailbox_snapshot mailbox_snapshot)
static

Definition at line 16048 of file app_voicemail.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_vm_mailbox_snapshot::folders, NULL, ast_vm_mailbox_snapshot::snapshots, and vm_msg_snapshot_destroy().

16049 {
16050  int i;
16051  struct ast_vm_msg_snapshot *msg_snapshot;
16052 
16053  for (i = 0; i < mailbox_snapshot->folders; i++) {
16054  while ((msg_snapshot = AST_LIST_REMOVE_HEAD(&mailbox_snapshot->snapshots[i], msg))) {
16055  msg_snapshot = vm_msg_snapshot_destroy(msg_snapshot);
16056  }
16057  }
16058  ast_free(mailbox_snapshot->snapshots);
16059  ast_free(mailbox_snapshot);
16060  return NULL;
16061 }
struct ast_vm_msg_snapshot::@222 msg
#define NULL
Definition: resample.c:96
static struct ast_vm_msg_snapshot * vm_msg_snapshot_destroy(struct ast_vm_msg_snapshot *msg_snapshot)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct ast_vm_mailbox_snapshot::@223 * snapshots
#define ast_free(a)
Definition: astmm.h:182

◆ vm_mkftemp()

static FILE* vm_mkftemp ( char *  template)
static

Definition at line 1925 of file app_voicemail.c.

References NULL, and VOICEMAIL_FILE_MODE.

Referenced by sendmail(), sendpage(), and vm_allocate_dh().

1926 {
1927  FILE *p = NULL;
1928  int pfd = mkstemp(template);
1929  chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
1930  if (pfd > -1) {
1931  p = fdopen(pfd, "w+");
1932  if (!p) {
1933  close(pfd);
1934  pfd = -1;
1935  }
1936  }
1937  return p;
1938 }
#define NULL
Definition: resample.c:96
static int my_umask
#define VOICEMAIL_FILE_MODE

◆ vm_msg_forward()

static int vm_msg_forward ( const char *  from_mailbox,
const char *  from_context,
const char *  from_folder,
const char *  to_mailbox,
const char *  to_context,
const char *  to_folder,
size_t  num_msgs,
const char *  msg_ids[],
int  delete_old 
)
static

Definition at line 16142 of file app_voicemail.c.

References ast_alloca, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log, ast_strlen_zero, ast_variable_retrieve(), close_mailbox(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, copy_message(), vm_state::curdir, vm_state::deleted, DISPOSE, ERROR_LOCK_PATH, find_user(), vm_state::fn, free_user(), get_folder_by_name(), vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), message_range_and_existence_check(), notify_new_state(), NULL, open_mailbox(), PATH_MAX, RETRIEVE, vm_state::username, and value.

16151 {
16152  struct vm_state from_vms;
16153  struct ast_vm_user *vmu = NULL, vmus;
16154  struct ast_vm_user *to_vmu = NULL, to_vmus;
16155  struct ast_config *msg_cfg;
16156  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
16157  char filename[PATH_MAX];
16158  int from_folder_index;
16159  int open = 0;
16160  int res = 0;
16161  int i;
16162  int *msg_nums;
16163 
16164  if (ast_strlen_zero(from_mailbox) || ast_strlen_zero(to_mailbox)) {
16165  ast_log(LOG_WARNING, "Cannot forward message because either the from or to mailbox was not specified\n");
16166  return -1;
16167  }
16168 
16169  if (!num_msgs) {
16170  ast_log(LOG_WARNING, "Invalid number of messages specified to forward: %zu\n", num_msgs);
16171  return -1;
16172  }
16173 
16174  if (ast_strlen_zero(from_folder) || ast_strlen_zero(to_folder)) {
16175  ast_log(LOG_WARNING, "Cannot forward message because the from_folder or to_folder was not specified\n");
16176  return -1;
16177  }
16178 
16179  memset(&vmus, 0, sizeof(vmus));
16180  memset(&to_vmus, 0, sizeof(to_vmus));
16181  memset(&from_vms, 0, sizeof(from_vms));
16182 
16183  from_folder_index = get_folder_by_name(from_folder);
16184  if (from_folder_index == -1) {
16185  return -1;
16186  }
16187 
16188  if (get_folder_by_name(to_folder) == -1) {
16189  return -1;
16190  }
16191 
16192  if (!(vmu = find_user(&vmus, from_context, from_mailbox))) {
16193  ast_log(LOG_WARNING, "Can't find voicemail user to forward from (%s@%s)\n", from_mailbox, from_context);
16194  return -1;
16195  }
16196 
16197  if (!(to_vmu = find_user(&to_vmus, to_context, to_mailbox))) {
16198  ast_log(LOG_WARNING, "Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
16199  free_user(vmu);
16200  return -1;
16201  }
16202 
16203  ast_copy_string(from_vms.username, from_mailbox, sizeof(from_vms.username));
16204  from_vms.lastmsg = -1;
16205  open = 0;
16206 
16207  /* open the mailbox state */
16208  if ((res = open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
16209  ast_log(LOG_WARNING, "Could not open mailbox %s\n", from_mailbox);
16210  res = -1;
16211  goto vm_forward_cleanup;
16212  }
16213 
16214  open = 1;
16215 
16216  if ((from_vms.lastmsg + 1) < num_msgs) {
16217  ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", from_folder, num_msgs);
16218  res = -1;
16219  goto vm_forward_cleanup;
16220  }
16221 
16222  msg_nums = ast_alloca(sizeof(int) * num_msgs);
16223 
16224  if ((res = message_range_and_existence_check(&from_vms, msg_ids, num_msgs, msg_nums, vmu) < 0)) {
16225  goto vm_forward_cleanup;
16226  }
16227 
16228  /* Now we actually forward the messages */
16229  for (i = 0; i < num_msgs; i++) {
16230  int cur_msg = msg_nums[i];
16231  int duration = 0;
16232  const char *value;
16233 
16234  make_file(from_vms.fn, sizeof(from_vms.fn), from_vms.curdir, cur_msg);
16235  snprintf(filename, sizeof(filename), "%s.txt", from_vms.fn);
16236  RETRIEVE(from_vms.curdir, cur_msg, vmu->mailbox, vmu->context);
16237  msg_cfg = ast_config_load(filename, config_flags);
16238  /* XXX This likely will not fail since we previously ensured that the
16239  * message we are looking for exists. However, there still could be some
16240  * circumstance where this fails, so atomicity is not guaranteed.
16241  */
16242  if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
16243  DISPOSE(from_vms.curdir, cur_msg);
16244  continue;
16245  }
16246  if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
16247  duration = atoi(value);
16248  }
16249 
16250  copy_message(NULL, vmu, from_folder_index, cur_msg, duration, to_vmu, vmfmts, from_vms.curdir, "", to_folder);
16251 
16252  if (delete_old) {
16253  from_vms.deleted[cur_msg] = 1;
16254  }
16255  ast_config_destroy(msg_cfg);
16256  DISPOSE(from_vms.curdir, cur_msg);
16257  }
16258 
16259  /* close mailbox */
16260  if ((res = close_mailbox(&from_vms, vmu) == ERROR_LOCK_PATH)) {
16261  res = -1;
16262  goto vm_forward_cleanup;
16263  }
16264  open = 0;
16265 
16266 vm_forward_cleanup:
16267  if (vmu && open) {
16268  close_mailbox(&from_vms, vmu);
16269  }
16270 #ifdef IMAP_STORAGE
16271  if (vmu) {
16272  vmstate_delete(&from_vms);
16273  }
16274 #endif
16275 
16276  if (!res) {
16277  notify_new_state(to_vmu);
16278  }
16279 
16280  free_user(vmu);
16281  free_user(to_vmu);
16282  return res;
16283 }
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, const char *dest_folder)
Copies a message from one mailbox to another.
#define ERROR_LOCK_PATH
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int get_folder_by_name(const char *name)
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
int value
Definition: syslog.c:37
char context[MAX_VM_CONTEXT_LEN]
def from_mailbox(key, val, section, pjsip, nmapped)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
static void notify_new_state(struct ast_vm_user *vmu)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static void free_user(struct ast_vm_user *vmu)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
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.
Structure used to handle boolean flags.
Definition: utils.h:199
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
#define RETRIEVE(a, b, c, d)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define PATH_MAX
Definition: asterisk.h:40
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.
static char vmfmts[80]
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ vm_msg_move()

static int vm_msg_move ( const char *  mailbox,
const char *  context,
size_t  num_msgs,
const char *  oldfolder,
const char *  old_msg_ids[],
const char *  newfolder 
)
static

Definition at line 16285 of file app_voicemail.c.

References ast_alloca, ast_copy_string(), ast_log, ast_strlen_zero, close_mailbox(), vm_state::deleted, ERROR_LOCK_PATH, find_user(), free_user(), get_folder_by_name(), vm_state::lastmsg, LOG_WARNING, message_range_and_existence_check(), notify_new_state(), NULL, open_mailbox(), save_to_folder(), and vm_state::username.

16291 {
16292  struct vm_state vms;
16293  struct ast_vm_user *vmu = NULL, vmus;
16294  int old_folder_index;
16295  int new_folder_index;
16296  int open = 0;
16297  int res = 0;
16298  int i;
16299  int *old_msg_nums;
16300 
16301  if (ast_strlen_zero(mailbox)) {
16302  ast_log(LOG_WARNING, "Cannot move message because no mailbox was specified\n");
16303  return -1;
16304  }
16305 
16306  if (!num_msgs) {
16307  ast_log(LOG_WARNING, "Invalid number of messages specified to move: %zu\n", num_msgs);
16308  return -1;
16309  }
16310 
16311  if (ast_strlen_zero(oldfolder) || ast_strlen_zero(newfolder)) {
16312  ast_log(LOG_WARNING, "Cannot move message because either oldfolder or newfolder was not specified\n");
16313  return -1;
16314  }
16315 
16316  old_folder_index = get_folder_by_name(oldfolder);
16317  new_folder_index = get_folder_by_name(newfolder);
16318 
16319  memset(&vmus, 0, sizeof(vmus));
16320  memset(&vms, 0, sizeof(vms));
16321 
16322  if (old_folder_index == -1 || new_folder_index == -1) {
16323  return -1;
16324  }
16325 
16326  if (!(vmu = find_user(&vmus, context, mailbox))) {
16327  return -1;
16328  }
16329 
16330  ast_copy_string(vms.username, mailbox, sizeof(vms.username));
16331  vms.lastmsg = -1;
16332  open = 0;
16333 
16334  /* open the mailbox state */
16335  if ((res = open_mailbox(&vms, vmu, old_folder_index)) < 0) {
16336  ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
16337  res = -1;
16338  goto vm_move_cleanup;
16339  }
16340 
16341  open = 1;
16342 
16343  if ((vms.lastmsg + 1) < num_msgs) {
16344  ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", oldfolder, num_msgs);
16345  res = -1;
16346  goto vm_move_cleanup;
16347  }
16348 
16349  old_msg_nums = ast_alloca(sizeof(int) * num_msgs);
16350 
16351  if ((res = message_range_and_existence_check(&vms, old_msg_ids, num_msgs, old_msg_nums, vmu)) < 0) {
16352  goto vm_move_cleanup;
16353  }
16354 
16355  /* Now actually move the message */
16356  for (i = 0; i < num_msgs; ++i) {
16357  if (save_to_folder(vmu, &vms, old_msg_nums[i], new_folder_index, NULL, 0)) {
16358  res = -1;
16359  goto vm_move_cleanup;
16360  }
16361  vms.deleted[old_msg_nums[i]] = 1;
16362  }
16363 
16364  /* close mailbox */
16365  if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
16366  res = -1;
16367  goto vm_move_cleanup;
16368  }
16369  open = 0;
16370 
16371 vm_move_cleanup:
16372  if (vmu && open) {
16373  close_mailbox(&vms, vmu);
16374  }
16375 #ifdef IMAP_STORAGE
16376  if (vmu) {
16377  vmstate_delete(&vms);
16378  }
16379 #endif
16380 
16381  if (!res) {
16382  notify_new_state(vmu);
16383  }
16384 
16385  free_user(vmu);
16386  return res;
16387 }
#define ERROR_LOCK_PATH
#define LOG_WARNING
Definition: logger.h:274
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int get_folder_by_name(const char *name)
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
static void notify_new_state(struct ast_vm_user *vmu)
static void free_user(struct ast_vm_user *vmu)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
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 int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.

◆ vm_msg_play()

static int vm_msg_play ( struct ast_channel chan,
const char *  mailbox,
const char *  context,
const char *  folder,
const char *  msg_num,
ast_vm_msg_play_cb  cb 
)
static

Definition at line 16487 of file app_voicemail.c.

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_fileexists(), ast_log, AST_LOG_WARNING, AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_strlen_zero, ast_variable_retrieve(), ASTERISK_GPL_KEY, close_mailbox(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, find_user(), vm_state::fn, free_user(), get_folder_by_name(), vm_state::heard, vm_state::lastmsg, load_module(), LOG_WARNING, ast_vm_user::mailbox, make_file(), message_range_and_existence_check(), notify_new_state(), NULL, open_mailbox(), PATH_MAX, RETRIEVE, tdesc, unload_module(), vm_state::username, value, and wait_file().

16493 {
16494  struct vm_state vms;
16495  struct ast_vm_user *vmu = NULL, vmus;
16496  int res = 0;
16497  int open = 0;
16498  int i;
16499  char filename[PATH_MAX];
16500  struct ast_config *msg_cfg;
16501  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
16502  int duration = 0;
16503  const char *value;
16504 
16505  if (ast_strlen_zero(mailbox)) {
16506  ast_log(LOG_WARNING, "Cannot play message because no mailbox was specified\n");
16507  return -1;
16508  }
16509 
16510  if (ast_strlen_zero(folder)) {
16511  ast_log(LOG_WARNING, "Cannot play message because no folder was specified\n");
16512  return -1;
16513  }
16514 
16515  if (ast_strlen_zero(msg_id)) {
16516  ast_log(LOG_WARNING, "Cannot play message because no message number was specified\n");
16517  return -1;
16518  }
16519 
16520  memset(&vmus, 0, sizeof(vmus));
16521  memset(&vms, 0, sizeof(vms));
16522 
16523  if (ast_strlen_zero(context)) {
16524  context = "default";
16525  }
16526 
16527  if (!(vmu = find_user(&vmus, context, mailbox))) {
16528  return -1;
16529  }
16530 
16531  i = get_folder_by_name(folder);
16532  ast_copy_string(vms.username, mailbox, sizeof(vms.username));
16533  vms.lastmsg = -1;
16534  if ((res = open_mailbox(&vms, vmu, i)) < 0) {
16535  ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
16536  goto play2_msg_cleanup;
16537  }
16538  open = 1;
16539 
16540  if (message_range_and_existence_check(&vms, &msg_id, 1, &vms.curmsg, vmu)) {
16541  res = -1;
16542  goto play2_msg_cleanup;
16543  }
16544 
16545  /* Find the msg */
16546  make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
16547  snprintf(filename, sizeof(filename), "%s.txt", vms.fn);
16548  RETRIEVE(vms.curdir, vms.curmsg, vmu->mailbox, vmu->context);
16549 
16550  msg_cfg = ast_config_load(filename, config_flags);
16551  if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
16552  DISPOSE(vms.curdir, vms.curmsg);
16553  res = -1;
16554  goto play2_msg_cleanup;
16555  }
16556  if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
16557  duration = atoi(value);
16558  }
16559  ast_config_destroy(msg_cfg);
16560 
16561 #ifdef IMAP_STORAGE
16562  /*IMAP storage stores any prepended message from a forward
16563  * as a separate file from the rest of the message
16564  */
16565  if (!ast_strlen_zero(vms.introfn) && ast_fileexists(vms.introfn, NULL, NULL) > 0) {
16566  wait_file(chan, &vms, vms.introfn);
16567  }
16568 #endif
16569  if (cb) {
16570  cb(chan, vms.fn, duration);
16571  } else if ((wait_file(chan, &vms, vms.fn)) < 0) {
16572  ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms.fn);
16573  } else {
16574  res = 0;
16575  }
16576 
16577  vms.heard[vms.curmsg] = 1;
16578 
16579  /* cleanup configs and msg */
16580  DISPOSE(vms.curdir, vms.curmsg);
16581 
16582 play2_msg_cleanup:
16583  if (vmu && open) {
16584  close_mailbox(&vms, vmu);
16585  }
16586 
16587 #ifdef IMAP_STORAGE
16588  if (vmu) {
16589  vmstate_delete(&vms);
16590  }
16591 #endif
16592 
16593  if (!res) {
16594  notify_new_state(vmu);
16595  }
16596 
16597  free_user(vmu);
16598  return res;
16599 }
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
#define AST_LOG_WARNING
Definition: logger.h:279
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int get_folder_by_name(const char *name)
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
int value
Definition: syslog.c:37
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
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 mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
static void notify_new_state(struct ast_vm_user *vmu)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static void free_user(struct ast_vm_user *vmu)
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
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.
Structure used to handle boolean flags.
Definition: utils.h:199
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
#define RETRIEVE(a, b, c, d)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
#define PATH_MAX
Definition: asterisk.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ vm_msg_remove()

static int vm_msg_remove ( const char *  mailbox,
const char *  context,
size_t  num_msgs,
const char *  folder,
const char *  msgs[] 
)
static

Definition at line 16389 of file app_voicemail.c.

References ast_alloca, ast_copy_string(), ast_log, AST_LOG_ERROR, ast_strlen_zero, close_mailbox(), vm_state::deleted, ERROR_LOCK_PATH, find_user(), free_user(), get_folder_by_name(), vm_state::lastmsg, LOG_WARNING, message_range_and_existence_check(), notify_new_state(), NULL, open_mailbox(), and vm_state::username.

16394 {
16395  struct vm_state vms;
16396  struct ast_vm_user *vmu = NULL, vmus;
16397  int folder_index;
16398  int open = 0;
16399  int res = 0;
16400  int i;
16401  int *msg_nums;
16402 
16403  if (ast_strlen_zero(mailbox)) {
16404  ast_log(LOG_WARNING, "Cannot remove message because no mailbox was specified\n");
16405  return -1;
16406  }
16407 
16408  if (!num_msgs) {
16409  ast_log(LOG_WARNING, "Invalid number of messages specified to remove: %zu\n", num_msgs);
16410  return -1;
16411  }
16412 
16413  if (ast_strlen_zero(folder)) {
16414  ast_log(LOG_WARNING, "Cannot remove message because no folder was specified\n");
16415  return -1;
16416  }
16417 
16418  memset(&vmus, 0, sizeof(vmus));
16419  memset(&vms, 0, sizeof(vms));
16420 
16421  folder_index = get_folder_by_name(folder);
16422  if (folder_index == -1) {
16423  ast_log(LOG_WARNING, "Could not remove msgs from unknown folder %s\n", folder);
16424  return -1;
16425  }
16426 
16427  if (!(vmu = find_user(&vmus, context, mailbox))) {
16428  ast_log(LOG_WARNING, "Can't find voicemail user to remove msg from (%s@%s)\n", mailbox, context);
16429  return -1;
16430  }
16431 
16432  ast_copy_string(vms.username, mailbox, sizeof(vms.username));
16433  vms.lastmsg = -1;
16434  open = 0;
16435 
16436  /* open the mailbox state */
16437  if ((res = open_mailbox(&vms, vmu, folder_index)) < 0) {
16438  ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
16439  res = -1;
16440  goto vm_remove_cleanup;
16441  }
16442 
16443  open = 1;
16444 
16445  if ((vms.lastmsg + 1) < num_msgs) {
16446  ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", folder, num_msgs);
16447  res = -1;
16448  goto vm_remove_cleanup;
16449  }
16450 
16451  msg_nums = ast_alloca(sizeof(int) * num_msgs);
16452 
16453  if ((res = message_range_and_existence_check(&vms, msgs, num_msgs, msg_nums, vmu)) < 0) {
16454  goto vm_remove_cleanup;
16455  }
16456 
16457  for (i = 0; i < num_msgs; i++) {
16458  vms.deleted[msg_nums[i]] = 1;
16459  }
16460 
16461  /* close mailbox */
16462  if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
16463  res = -1;
16464  ast_log(AST_LOG_ERROR, "Failed to close mailbox folder %s while removing msgs\n", folder);
16465  goto vm_remove_cleanup;
16466  }
16467  open = 0;
16468 
16469 vm_remove_cleanup:
16470  if (vmu && open) {
16471  close_mailbox(&vms, vmu);
16472  }
16473 #ifdef IMAP_STORAGE
16474  if (vmu) {
16475  vmstate_delete(&vms);
16476  }
16477 #endif
16478 
16479  if (!res) {
16480  notify_new_state(vmu);
16481  }
16482 
16483  free_user(vmu);
16484  return res;
16485 }
#define ERROR_LOCK_PATH
#define LOG_WARNING
Definition: logger.h:274
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int get_folder_by_name(const char *name)
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
static void notify_new_state(struct ast_vm_user *vmu)
static void free_user(struct ast_vm_user *vmu)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
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 int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.

◆ vm_msg_snapshot_alloc()

static struct ast_vm_msg_snapshot* vm_msg_snapshot_alloc ( void  )
static

Definition at line 15748 of file app_voicemail.c.

References ast_calloc, ast_free, ast_string_field_init, and NULL.

Referenced by vm_msg_snapshot_create().

15749 {
15750  struct ast_vm_msg_snapshot *msg_snapshot;
15751 
15752  if (!(msg_snapshot = ast_calloc(1, sizeof(*msg_snapshot)))) {
15753  return NULL;
15754  }
15755 
15756  if (ast_string_field_init(msg_snapshot, 512)) {
15757  ast_free(msg_snapshot);
15758  return NULL;
15759  }
15760 
15761  return msg_snapshot;
15762 }
#define NULL
Definition: resample.c:96
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ vm_msg_snapshot_create()

static int vm_msg_snapshot_create ( struct ast_vm_user vmu,
struct vm_state vms,
struct ast_vm_mailbox_snapshot mailbox_snapshot,
int  snapshot_index,
int  mailbox_index,
int  descending,
enum ast_vm_snapshot_sort_val  sort_val 
)
static

Create and store off all the msgs in an open mailbox.

Note
TODO XXX This function should work properly for all voicemail storage options, but is far more expensive for ODBC at the moment. This is because the RETRIEVE macro not only pulls out the message's meta data file from the database, but also the actual audio for each message, temporarily writing it to the file system. This is an area that needs to be made more efficient.

Definition at line 15816 of file app_voicemail.c.

References add_message_id(), ast_config_destroy(), ast_config_load, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_string_field_set, ast_variable_retrieve(), AST_VM_SNAPSHOT_SORT_BY_ID, AST_VM_SNAPSHOT_SORT_BY_TIME, CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, exten, vm_state::fn, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), MSG_ID_LEN, ast_vm_msg_snapshot::msg_number, ast_vm_msg_snapshot::origtime, PATH_MAX, RETRIEVE, ast_vm_mailbox_snapshot::snapshots, ast_vm_mailbox_snapshot::total_msg_num, value, and vm_msg_snapshot_alloc().

Referenced by vm_mailbox_snapshot_create().

15823 {
15824  struct ast_vm_msg_snapshot *msg_snapshot;
15825  struct ast_vm_msg_snapshot *msg_snapshot_tmp;
15826  struct ast_config *msg_cfg;
15827  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
15828  char filename[PATH_MAX];
15829  const char *value;
15830 
15831  for (vms->curmsg = 0; vms->curmsg <= vms->lastmsg; vms->curmsg++) {
15832  int inserted = 0;
15833  /* Find the msg */
15834  make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
15835  snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
15836  RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
15837  msg_cfg = ast_config_load(filename, config_flags);
15838  if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
15839  DISPOSE(vms->curdir, vms->curmsg);
15840  continue;
15841  }
15842 
15843  /* Create the snapshot object */
15844  if (!(msg_snapshot = vm_msg_snapshot_alloc())) {
15845  ast_config_destroy(msg_cfg);
15846  return -1;
15847  }
15848 
15849  /* Fill in the snapshot object */
15850  if ((value = ast_variable_retrieve(msg_cfg, "message", "msg_id"))) {
15851  ast_string_field_set(msg_snapshot, msg_id, value);
15852  } else {
15853  /* Message snapshots *really* should have a
15854  * message ID. Add one to the message config
15855  * if it does not already exist
15856  */
15857  char id[MSG_ID_LEN];
15858  if (!(add_message_id(msg_cfg, vms->curdir, vms->curmsg,
15859  filename, id, sizeof(id), vmu, mailbox_index))) {
15860  ast_string_field_set(msg_snapshot, msg_id, id);
15861  } else {
15862  ast_log(LOG_WARNING, "Unable to create a message ID for message %s/%d\n", vms->curdir, vms->curmsg);
15863  }
15864  }
15865  if ((value = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
15866  ast_string_field_set(msg_snapshot, callerid, value);
15867  }
15868  if ((value = ast_variable_retrieve(msg_cfg, "message", "callerchan"))) {
15869  ast_string_field_set(msg_snapshot, callerchan, value);
15870  }
15871  if ((value = ast_variable_retrieve(msg_cfg, "message", "exten"))) {
15872  ast_string_field_set(msg_snapshot, exten, value);
15873  }
15874  if ((value = ast_variable_retrieve(msg_cfg, "message", "origdate"))) {
15875  ast_string_field_set(msg_snapshot, origdate, value);
15876  }
15877  if ((value = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
15878  ast_string_field_set(msg_snapshot, origtime, value);
15879  }
15880  if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
15881  ast_string_field_set(msg_snapshot, duration, value);
15882  }
15883  if ((value = ast_variable_retrieve(msg_cfg, "message", "flag"))) {
15884  ast_string_field_set(msg_snapshot, flag, value);
15885  }
15886  msg_snapshot->msg_number = vms->curmsg;
15887  ast_string_field_set(msg_snapshot, folder_name, mailbox_folders[mailbox_index]);
15888 
15889  /* store msg snapshot in mailbox snapshot */
15890  switch (sort_val) {
15891  default:
15893  if (descending) {
15894  AST_LIST_INSERT_HEAD(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
15895  } else {
15896  AST_LIST_INSERT_TAIL(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
15897  }
15898  inserted = 1;
15899  break;
15901  AST_LIST_TRAVERSE_SAFE_BEGIN(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot_tmp, msg) {
15902  int val = strcmp(msg_snapshot->origtime, msg_snapshot_tmp->origtime);
15903  if (descending && val >= 0) {
15904  AST_LIST_INSERT_BEFORE_CURRENT(msg_snapshot, msg);
15905  inserted = 1;
15906  break;
15907  } else if (!descending && val <= 0) {
15908  AST_LIST_INSERT_BEFORE_CURRENT(msg_snapshot, msg);
15909  inserted = 1;
15910  break;
15911  }
15912  }
15914  break;
15915  }
15916 
15917  if (!inserted) {
15918  AST_LIST_INSERT_TAIL(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
15919  }
15920 
15921  mailbox_snapshot->total_msg_num++;
15922 
15923  /* cleanup configs and msg */
15924  ast_config_destroy(msg_cfg);
15925  DISPOSE(vms->curdir, vms->curmsg);
15926  }
15927 
15928  return 0;
15929 }
#define MSG_ID_LEN
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Definition: ast_expr2.c:325
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
char curdir[PATH_MAX]
#define DISPOSE(a, b)
int value
Definition: syslog.c:37
char fn[PATH_MAX]
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
char context[MAX_VM_CONTEXT_LEN]
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 int add_message_id(struct ast_config *msg_cfg, char *dir, int msg, char *filename, char *id, size_t id_size, struct ast_vm_user *vmu, int folder)
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
static const char *const mailbox_folders[]
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
const ast_string_field origtime
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct ast_vm_mailbox_snapshot::@223 * snapshots
long int flag
Definition: f2c.h:83
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
Structure used to handle boolean flags.
Definition: utils.h:199
#define RETRIEVE(a, b, c, d)
static struct ast_vm_msg_snapshot * vm_msg_snapshot_alloc(void)
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define PATH_MAX
Definition: asterisk.h:40
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:598
char mailbox[MAX_VM_MBOX_ID_LEN]
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ vm_msg_snapshot_destroy()

static struct ast_vm_msg_snapshot* vm_msg_snapshot_destroy ( struct ast_vm_msg_snapshot msg_snapshot)
static

Definition at line 15764 of file app_voicemail.c.

References ast_free, ast_string_field_free_memory, and NULL.

Referenced by vm_mailbox_snapshot_destroy().

15765 {
15766  ast_string_field_free_memory(msg_snapshot);
15767  ast_free(msg_snapshot);
15768 
15769  return NULL;
15770 }
#define NULL
Definition: resample.c:96
#define ast_free(a)
Definition: astmm.h:182
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ vm_newuser_setup()

static int vm_newuser_setup ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
char *  fmtc,
signed char  record_gain 
)
static

Definition at line 10646 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, NULL, PATH_MAX, 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().

10647 {
10648  int cmd = 0;
10649  int duration = 0;
10650  int tries = 0;
10651  char newpassword[80] = "";
10652  char newpassword2[80] = "";
10653  char prefile[PATH_MAX] = "";
10654  unsigned char buf[256];
10655  int bytes = 0;
10656 
10657  ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
10658  if (ast_adsi_available(chan)) {
10659  bytes += adsi_logo(buf + bytes);
10660  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
10661  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
10662  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
10663  bytes += ast_adsi_voice_mode(buf + bytes, 0);
10664  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
10665  }
10666 
10667  /* If forcename is set, have the user record their name */
10668  if (ast_test_flag(vmu, VM_FORCENAME)) {
10669  snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
10670  if (ast_fileexists(prefile, NULL, NULL) < 1) {
10671  cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10672  if (cmd < 0 || cmd == 't' || cmd == '#')
10673  return cmd;
10674  }
10675  }
10676 
10677  /* If forcegreetings is set, have the user record their greetings */
10678  if (ast_test_flag(vmu, VM_FORCEGREET)) {
10679  snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
10680  if (ast_fileexists(prefile, NULL, NULL) < 1) {
10681  cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10682  if (cmd < 0 || cmd == 't' || cmd == '#')
10683  return cmd;
10684  }
10685 
10686  snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
10687  if (ast_fileexists(prefile, NULL, NULL) < 1) {
10688  cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10689  if (cmd < 0 || cmd == 't' || cmd == '#')
10690  return cmd;
10691  }
10692  }
10693 
10694  /*
10695  * Change the password last since new users will be able to skip over any steps this one comes before
10696  * by hanging up and calling back to voicemail main since the password is used to verify new user status.
10697  */
10698  for (;;) {
10699  newpassword[1] = '\0';
10700  newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
10701  if (cmd == '#')
10702  newpassword[0] = '\0';
10703  if (cmd < 0 || cmd == 't' || cmd == '#')
10704  return cmd;
10705  cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
10706  if (cmd < 0 || cmd == 't' || cmd == '#')
10707  return cmd;
10708  cmd = check_password(vmu, newpassword); /* perform password validation */
10709  if (cmd != 0) {
10710  ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
10712  } else {
10713  newpassword2[1] = '\0';
10714  newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
10715  if (cmd == '#')
10716  newpassword2[0] = '\0';
10717  if (cmd < 0 || cmd == 't' || cmd == '#')
10718  return cmd;
10719  cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
10720  if (cmd < 0 || cmd == 't' || cmd == '#')
10721  return cmd;
10722  if (!strcmp(newpassword, newpassword2))
10723  break;
10724  ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
10725  cmd = ast_play_and_wait(chan, vm_mismatch);
10726  }
10727  if (++tries == 3)
10728  return -1;
10729  if (cmd != 0) {
10730  cmd = ast_play_and_wait(chan, vm_pls_try_again);
10731  }
10732  }
10734  vm_change_password(vmu, newpassword);
10736  vm_change_password_shell(vmu, newpassword);
10737 
10738  ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
10739  cmd = ast_play_and_wait(chan, vm_passchanged);
10740 
10741  return cmd;
10742 }
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
char username[80]
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int adsi_logo(unsigned char *buf)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int pwdchange
static int maxgreet
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_LOG_NOTICE
Definition: logger.h:268
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:452
#define ast_log
Definition: astobj2.c:42
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
#define VM_FORCENAME
static char vm_reenterpassword[80]
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: main/app.c:1470
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:196
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
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, const char *msg_id, int forwardintro)
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:1086
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
#define PWDCHANGE_EXTERNAL
#define PATH_MAX
Definition: asterisk.h:40
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6655
static char vm_newpassword[80]
#define ADSI_JUST_CENT
Definition: adsi.h:114
#define VM_FORCEGREET

◆ vm_options()

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 10744 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, NULL, ast_vm_user::password, PATH_MAX, 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().

10745 {
10746  int cmd = 0;
10747  int retries = 0;
10748  int duration = 0;
10749  char newpassword[80] = "";
10750  char newpassword2[80] = "";
10751  char prefile[PATH_MAX] = "";
10752  unsigned char buf[256];
10753  int bytes = 0;
10754 
10755  ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
10756  if (ast_adsi_available(chan)) {
10757  bytes += adsi_logo(buf + bytes);
10758  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
10759  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
10760  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
10761  bytes += ast_adsi_voice_mode(buf + bytes, 0);
10762  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
10763  }
10764  while ((cmd >= 0) && (cmd != 't')) {
10765  if (cmd)
10766  retries = 0;
10767  switch (cmd) {
10768  case '1': /* Record your unavailable message */
10769  snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
10770  cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10771  break;
10772  case '2': /* Record your busy message */
10773  snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
10774  cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10775  break;
10776  case '3': /* Record greeting */
10777  snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
10778  cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10779  break;
10780  case '4': /* manage the temporary greeting */
10781  cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
10782  break;
10783  case '5': /* change password */
10784  if (vmu->password[0] == '-') {
10785  cmd = ast_play_and_wait(chan, "vm-no");
10786  break;
10787  }
10788  newpassword[1] = '\0';
10789  newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
10790  if (cmd == '#')
10791  newpassword[0] = '\0';
10792  else {
10793  if (cmd < 0)
10794  break;
10795  if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
10796  break;
10797  }
10798  }
10799  cmd = check_password(vmu, newpassword); /* perform password validation */
10800  if (cmd != 0) {
10801  ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
10803  if (!cmd) {
10804  cmd = ast_play_and_wait(chan, vm_pls_try_again);
10805  }
10806  break;
10807  }
10808  newpassword2[1] = '\0';
10809  newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
10810  if (cmd == '#')
10811  newpassword2[0] = '\0';
10812  else {
10813  if (cmd < 0)
10814  break;
10815 
10816  if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
10817  break;
10818  }
10819  }
10820  if (strcmp(newpassword, newpassword2)) {
10821  ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
10822  cmd = ast_play_and_wait(chan, vm_mismatch);
10823  if (!cmd) {
10824  cmd = ast_play_and_wait(chan, vm_pls_try_again);
10825  }
10826  break;
10827  }
10828 
10829  if (pwdchange & PWDCHANGE_INTERNAL) {
10830  vm_change_password(vmu, newpassword);
10831  }
10833  vm_change_password_shell(vmu, newpassword);
10834  }
10835 
10836  ast_debug(1, "User %s set password to %s of length %d\n",
10837  vms->username, newpassword, (int) strlen(newpassword));
10838  cmd = ast_play_and_wait(chan, vm_passchanged);
10839  break;
10840  case '*':
10841  cmd = 't';
10842  break;
10843  default:
10844  cmd = 0;
10845  snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10846  RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10847  if (ast_fileexists(prefile, NULL, NULL)) {
10848  cmd = ast_play_and_wait(chan, "vm-tmpexists");
10849  }
10850  DISPOSE(prefile, -1);
10851  if (!cmd) {
10852  cmd = ast_play_and_wait(chan, "vm-options");
10853  }
10854  if (!cmd) {
10855  cmd = ast_waitfordigit(chan, 6000);
10856  }
10857  if (!cmd) {
10858  retries++;
10859  }
10860  if (retries > 3) {
10861  cmd = 't';
10862  }
10863  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
10864  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
10865  }
10866  }
10867  if (cmd == 't')
10868  cmd = 0;
10869  return cmd;
10870 }
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
char username[80]
static int adsi_logo(unsigned char *buf)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int pwdchange
static int maxgreet
char password[80]
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char context[MAX_VM_CONTEXT_LEN]
#define ADSI_COMM_PAGE
Definition: adsi.h:107
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_LOG_NOTICE
Definition: logger.h:268
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:452
#define ast_log
Definition: astobj2.c:42
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
static char vm_reenterpassword[80]
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: main/app.c:1470
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:196
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
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, const char *msg_id, int forwardintro)
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:3184
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:1086
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
#define PWDCHANGE_EXTERNAL
#define PATH_MAX
Definition: asterisk.h:40
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6655
static char vm_newpassword[80]
#define ADSI_JUST_CENT
Definition: adsi.h:114
char mailbox[MAX_VM_MBOX_ID_LEN]
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;.

◆ vm_play_folder_name()

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

Definition at line 9328 of file app_voicemail.c.

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

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

9329 {
9330  int cmd;
9331 
9332  if ( !strncasecmp(ast_channel_language(chan), "it", 2) ||
9333  !strncasecmp(ast_channel_language(chan), "es", 2) ||
9334  !strncasecmp(ast_channel_language(chan), "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
9335  cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
9336  return cmd ? cmd : ast_play_and_wait(chan, box);
9337  } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {
9338  return vm_play_folder_name_gr(chan, box);
9339  } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* Hebrew syntax */
9340  return ast_play_and_wait(chan, box);
9341  } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
9342  return vm_play_folder_name_ja(chan, box);
9343  } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
9344  return vm_play_folder_name_pl(chan, box);
9345  } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* Ukrainian syntax */
9346  return vm_play_folder_name_ua(chan, box);
9347  } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
9348  return ast_play_and_wait(chan, box);
9349  } else { /* Default English */
9350  cmd = ast_play_and_wait(chan, box);
9351  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
9352  }
9353 }
static int vm_play_folder_name_ja(struct ast_channel *chan, char *box)
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: main/app.c:1470
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 char * ast_channel_language(const struct ast_channel *chan)

◆ vm_play_folder_name_gr()

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

Definition at line 9268 of file app_voicemail.c.

References ast_alloca, ast_play_and_wait(), and buf.

Referenced by vm_play_folder_name().

9269 {
9270  int cmd;
9271  char *buf;
9272 
9273  buf = ast_alloca(strlen(box) + 2);
9274  strcpy(buf, box);
9275  strcat(buf, "s");
9276 
9277  if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
9278  cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
9279  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
9280  } else {
9281  cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
9282  return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
9283  }
9284 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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: main/app.c:1470
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290

◆ vm_play_folder_name_ja()

static int vm_play_folder_name_ja ( struct ast_channel chan,
char *  box 
)
static

Definition at line 9286 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

9287 {
9288  int cmd;
9289 
9290  if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9291  cmd = ast_play_and_wait(chan, box);
9292  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9293  } else {
9294  cmd = ast_play_and_wait(chan, box);
9295  return cmd;
9296  }
9297 }
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: main/app.c:1470

◆ vm_play_folder_name_pl()

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

Definition at line 9299 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

9300 {
9301  int cmd;
9302 
9303  if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9304  if (!strcasecmp(box, "vm-INBOX"))
9305  cmd = ast_play_and_wait(chan, "vm-new-e");
9306  else
9307  cmd = ast_play_and_wait(chan, "vm-old-e");
9308  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9309  } else {
9310  cmd = ast_play_and_wait(chan, "vm-messages");
9311  return cmd ? cmd : ast_play_and_wait(chan, box);
9312  }
9313 }
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: main/app.c:1470

◆ vm_play_folder_name_ua()

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

Definition at line 9315 of file app_voicemail.c.

References ast_play_and_wait().

Referenced by vm_play_folder_name().

9316 {
9317  int cmd;
9318 
9319  if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
9320  cmd = ast_play_and_wait(chan, "vm-messages");
9321  return cmd ? cmd : ast_play_and_wait(chan, box);
9322  } else {
9323  cmd = ast_play_and_wait(chan, box);
9324  return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9325  }
9326 }
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: main/app.c:1470

◆ vm_playmsgexec()

static int vm_playmsgexec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 11464 of file app_voicemail.c.

References args, ast_answer(), AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero, NULL, parse(), pbx_builtin_setvar_helper(), and play_message_by_id().

Referenced by load_module().

11465 {
11466  char *parse;
11467  char *mailbox = NULL;
11468  char *context = NULL;
11469  int res;
11470 
11472  AST_APP_ARG(mailbox);
11473  AST_APP_ARG(msg_id);
11474  );
11475 
11476  if (ast_channel_state(chan) != AST_STATE_UP) {
11477  ast_debug(1, "Before ast_answer\n");
11478  ast_answer(chan);
11479  }
11480 
11481  if (ast_strlen_zero(data)) {
11482  return -1;
11483  }
11484 
11485  parse = ast_strdupa(data);
11486  AST_STANDARD_APP_ARGS(args, parse);
11487 
11488  if (ast_strlen_zero(args.mailbox) || ast_strlen_zero(args.msg_id)) {
11489  return -1;
11490  }
11491 
11492  if ((context = strchr(args.mailbox, '@'))) {
11493  *context++ = '\0';
11494  }
11495  mailbox = args.mailbox;
11496 
11497  res = play_message_by_id(chan, mailbox, context, args.msg_id);
11498  pbx_builtin_setvar_helper(chan, "VOICEMAIL_PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS");
11499 
11500  return 0;
11501 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
ast_channel_state
ast_channel states
Definition: channelstate.h:35
const char * args
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
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...
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
static int play_message_by_id(struct ast_channel *chan, const char *mailbox, const char *context, const char *msg_id)
Finds a message in a specific mailbox by msg_id and plays it to the channel.
#define AST_APP_ARG(name)
Define an application argument.

◆ vm_sayname()

static int vm_sayname ( struct ast_channel chan,
const char *  mailbox_id 
)
static

Definition at line 14384 of file app_voicemail.c.

References ast_strdupa, ast_strlen_zero, context, mailbox, sayname(), and separate_mailbox().

14385 {
14386  char *context;
14387  char *mailbox;
14388 
14389  if (ast_strlen_zero(mailbox_id)
14390  || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
14391  return -1;
14392  }
14393  return sayname(chan, mailbox, context);
14394 }
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ vm_tempgreeting()

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 10888 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, NULL, PATH_MAX, play_record_review(), RETRIEVE, and vm_state::username.

Referenced by vm_options().

10889 {
10890  int cmd = 0;
10891  int retries = 0;
10892  int duration = 0;
10893  char prefile[PATH_MAX] = "";
10894  unsigned char buf[256];
10895  int bytes = 0;
10896 
10897  if (ast_adsi_available(chan)) {
10898  bytes += adsi_logo(buf + bytes);
10899  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
10900  bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
10901  bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
10902  bytes += ast_adsi_voice_mode(buf + bytes, 0);
10903  ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
10904  }
10905 
10906  ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
10907  snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10908  while ((cmd >= 0) && (cmd != 't')) {
10909  if (cmd)
10910  retries = 0;
10911  RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10912  if (ast_fileexists(prefile, NULL, NULL) <= 0) {
10913  cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10914  if (cmd == -1) {
10915  break;
10916  }
10917  cmd = 't';
10918  } else {
10919  switch (cmd) {
10920  case '1':
10921  cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10922  break;
10923  case '2':
10924  DELETE(prefile, -1, prefile, vmu);
10925  ast_play_and_wait(chan, "vm-tempremoved");
10926  cmd = 't';
10927  break;
10928  case '*':
10929  cmd = 't';
10930  break;
10931  default:
10932  cmd = ast_play_and_wait(chan,
10933  ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
10934  "vm-tempgreeting2" : "vm-tempgreeting");
10935  if (!cmd) {
10936  cmd = ast_waitfordigit(chan, 6000);
10937  }
10938  if (!cmd) {
10939  retries++;
10940  }
10941  if (retries > 3) {
10942  cmd = 't';
10943  }
10944  ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
10945  isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
10946  }
10947  }
10948  DISPOSE(prefile, -1);
10949  }
10950  if (cmd == 't')
10951  cmd = 0;
10952  return cmd;
10953 }
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
char username[80]
static int adsi_logo(unsigned char *buf)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int maxgreet
#define NULL
Definition: resample.c:96
#define DISPOSE(a, b)
char context[MAX_VM_CONTEXT_LEN]
#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: main/app.c:1470
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:196
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
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, const char *msg_id, int forwardintro)
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
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:1086
#define PATH_MAX
Definition: asterisk.h:40
#define ADSI_JUST_CENT
Definition: adsi.h:114
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ vm_test_create_user()

static int vm_test_create_user ( const char *  context,
const char *  mailbox 
)
static

Definition at line 15792 of file app_voicemail.c.

References find_or_create(), and populate_defaults().

Referenced by load_module().

15793 {
15794  struct ast_vm_user *vmu;
15795 
15796  if (!(vmu = find_or_create(context, mailbox))) {
15797  return -1;
15798  }
15799  populate_defaults(vmu);
15800  return 0;
15801 }
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static struct ast_vm_user * find_or_create(const char *context, const char *box)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.

◆ vm_test_destroy_user()

static int vm_test_destroy_user ( const char *  context,
const char *  mailbox 
)
static

Definition at line 15774 of file app_voicemail.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_vm_user::context, ast_vm_user::list, and ast_vm_user::mailbox.

Referenced by load_module().

15775 {
15776  struct ast_vm_user *vmu;
15777 
15778  AST_LIST_LOCK(&users);
15780  if (!strcmp(context, vmu->context)
15781  && !strcmp(mailbox, vmu->mailbox)) {
15783  ast_free(vmu);
15784  break;
15785  }
15786  }
15789  return 0;
15790 }
#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
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
char context[MAX_VM_CONTEXT_LEN]
struct ast_vm_user::@82 list
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define ast_free(a)
Definition: astmm.h:182
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char mailbox[MAX_VM_MBOX_ID_LEN]

◆ vmauthenticate()

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

Definition at line 12765 of file app_voicemail.c.

References ast_channel_context(), ast_copy_string(), ast_goto_if_exists(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero, ast_vm_user::context, NULL, options, pbx_builtin_setvar_helper(), strsep(), user, and vm_authenticate().

Referenced by load_module().

12766 {
12767  char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
12768  struct ast_vm_user vmus = {{0}};
12769  char *options = NULL;
12770  int silent = 0, skipuser = 0;
12771  int res = -1;
12772 
12773  if (data) {
12774  s = ast_strdupa(data);
12775  user = strsep(&s, ",");
12776  options = strsep(&s, ",");
12777  if (user) {
12778  s = user;
12779  user = strsep(&s, "@");
12780  context = strsep(&s, "");
12781  if (!ast_strlen_zero(user))
12782  skipuser++;
12783  ast_copy_string(mailbox, user, sizeof(mailbox));
12784  }
12785  }
12786 
12787  if (options) {
12788  silent = (strchr(options, 's')) != NULL;
12789  }
12790 
12791  if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
12792  pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
12793  pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
12794  ast_play_and_wait(chan, "auth-thankyou");
12795  res = 0;
12796  } else if (mailbox[0] == '*') {
12797  /* user entered '*' */
12798  if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) {
12799  res = 0; /* prevent hangup */
12800  }
12801  }
12802 
12803  return res;
12804 }
static char user[512]
#define NULL
Definition: resample.c:96
char context[MAX_VM_CONTEXT_LEN]
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define AST_MAX_EXTENSION
Definition: channel.h:135
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: main/app.c:1470
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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)
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8793
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...
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_context(const struct ast_channel *chan)
static struct test_options options
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ vmsayname_exec()

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

Definition at line 14446 of file app_voicemail.c.

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

Referenced by AST_TEST_DEFINE(), and load_module().

14447 {
14448  char *context;
14449  char *mailbox;
14450  int res;
14451 
14452  if (ast_strlen_zero(data)
14453  || separate_mailbox(ast_strdupa(data), &mailbox, &context)) {
14454  ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
14455  return -1;
14456  }
14457 
14458  if ((res = sayname(chan, mailbox, context)) < 0) {
14459  ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", mailbox, context);
14460  res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
14461  if (!res) {
14463  }
14464  }
14465 
14466  return res;
14467 }
#define AST_DIGIT_ANY
Definition: file.h:48
#define LOG_WARNING
Definition: logger.h:274
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
Definition: channel.c:8367
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
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:1814
const char * ast_channel_language(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ vmu_tm()

static const 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 4979 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, NULL, vm_zone::timezone, and ast_vm_user::zonetag.

Referenced by make_email_file(), and sendpage().

4980 {
4981  const struct vm_zone *z = NULL;
4982  struct timeval t = ast_tvnow();
4983 
4984  /* Does this user have a timezone specified? */
4985  if (!ast_strlen_zero(vmu->zonetag)) {
4986  /* Find the zone in the list */
4987  AST_LIST_LOCK(&zones);
4988  AST_LIST_TRAVERSE(&zones, z, list) {
4989  if (!strcmp(z->name, vmu->zonetag))
4990  break;
4991  }
4993  }
4994  ast_localtime(&t, tm, z ? z->timezone : NULL);
4995  return tm;
4996 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char timezone[80]
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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:1739
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
char zonetag[80]
char name[80]
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490

◆ wait_file()

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

Definition at line 8617 of file app_voicemail.c.

References ast_control_streamfile(), ast_test_suite_event_notify, and NULL.

Referenced by advanced_options(), play_message(), play_message_by_id_helper(), and vm_msg_play().

8618 {
8619  ast_test_suite_event_notify("PLAYVOICE", "Message: Playing %s", file);
8621 }
static char listen_control_reverse_key[12]
#define NULL
Definition: resample.c:96
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: main/app.c:1319
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
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]

◆ wait_file2()

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

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

8610 {
8611  int res;
8612  if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
8613  ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file);
8614  return res;
8615 }
#define AST_DIGIT_ANY
Definition: file.h:48
#define AST_LOG_WARNING
Definition: logger.h:279
#define ast_log
Definition: astobj2.c:42
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:1814

◆ write_password_to_file()

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

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

14413  {
14414  struct ast_config *conf;
14415  struct ast_category *cat;
14416  struct ast_variable *var;
14417  int res = -1;
14418 
14419  if (!(conf = ast_config_new())) {
14420  ast_log(LOG_ERROR, "Error creating new config structure\n");
14421  return res;
14422  }
14423  if (!(cat = ast_category_new("general", "", 1))) {
14424  ast_log(LOG_ERROR, "Error creating new category structure\n");
14425  ast_config_destroy(conf);
14426  return res;
14427  }
14428  if (!(var = ast_variable_new("password", password, ""))) {
14429  ast_log(LOG_ERROR, "Error creating new variable structure\n");
14430  ast_config_destroy(conf);
14431  ast_category_destroy(cat);
14432  return res;
14433  }
14434  ast_category_append(conf, cat);
14435  ast_variable_append(cat, var);
14436  if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
14437  res = 0;
14438  } else {
14439  ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
14440  }
14441 
14442  ast_config_destroy(conf);
14443  return res;
14444 }
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
Definition: extconf.c:2790
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
Definition: main/config.c:2531
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
void ast_category_destroy(struct ast_category *cat)
Definition: extconf.c:2847
static struct ast_str * password
Definition: cdr_mysql.c:77
All configuration options for statsd client.
Definition: res_statsd.c:95
#define ast_log
Definition: astobj2.c:42
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_variable_new(name, value, filename)
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3276
#define LOG_ERROR
Definition: logger.h:285
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
Definition: extconf.c:2835

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .optional_modules = "res_adsi,res_smdi", }
static

Definition at line 16611 of file app_voicemail.c.

◆ addesc

char* addesc = "Comedian Mail"
static

Definition at line 901 of file app_voicemail.c.

◆ adsifdn

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

Definition at line 1024 of file app_voicemail.c.

◆ adsisec

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

Definition at line 1025 of file app_voicemail.c.

◆ adsiver

int adsiver = 1
static

Definition at line 1026 of file app_voicemail.c.

◆ alias_mailbox_mappings

struct ao2_container* alias_mailbox_mappings
static

Definition at line 967 of file app_voicemail.c.

◆ aliasescontext

char aliasescontext[MAX_VM_CONTEXT_LEN]
static

Definition at line 936 of file app_voicemail.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 16611 of file app_voicemail.c.

◆ callcontext

char callcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1010 of file app_voicemail.c.

◆ charset

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

Definition at line 1022 of file app_voicemail.c.

◆ cidinternalcontexts

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static

Definition at line 1013 of file app_voicemail.c.

◆ cli_voicemail

struct ast_cli_entry cli_voicemail[]
static

Definition at line 13042 of file app_voicemail.c.

◆ dialcontext

char dialcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1009 of file app_voicemail.c.

Referenced by directory_exec().

◆ emailbody

char* emailbody
static

Definition at line 1016 of file app_voicemail.c.

Referenced by make_email_file(), and message_template_parse_emailbody().

◆ emaildateformat

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

Definition at line 1027 of file app_voicemail.c.

◆ emailsubject

char* emailsubject
static

Definition at line 1017 of file app_voicemail.c.

Referenced by make_email_file().

◆ exitcontext

char exitcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1011 of file app_voicemail.c.

Referenced by common_exec(), and conf_run().

◆ ext_pass_check_cmd

char ext_pass_check_cmd[128]
static

Definition at line 881 of file app_voicemail.c.

◆ ext_pass_cmd

char ext_pass_cmd[128]
static

Definition at line 880 of file app_voicemail.c.

◆ externnotify

char externnotify[160]
static

Definition at line 925 of file app_voicemail.c.

◆ fromstring

char fromstring[100]
static

Definition at line 1020 of file app_voicemail.c.

Referenced by make_email_file().

◆ globalflags

struct ast_flags globalflags = {0}
static

Definition at line 1005 of file app_voicemail.c.

◆ inprocess_container

struct ao2_container* inprocess_container

Definition at line 1110 of file app_voicemail.c.

◆ listen_control_forward_key

char listen_control_forward_key[12]
static

Definition at line 976 of file app_voicemail.c.

◆ listen_control_pause_key

char listen_control_pause_key[12]
static

Definition at line 978 of file app_voicemail.c.

◆ listen_control_restart_key

char listen_control_restart_key[12]
static

Definition at line 979 of file app_voicemail.c.

◆ listen_control_reverse_key

char listen_control_reverse_key[12]
static

Definition at line 977 of file app_voicemail.c.

◆ listen_control_stop_key

char listen_control_stop_key[12]
static

Definition at line 980 of file app_voicemail.c.

◆ locale

char locale[20]
static

Definition at line 918 of file app_voicemail.c.

Referenced by handle_minivm_list_templates().

◆ mailbox_alias_mappings

struct ao2_container* mailbox_alias_mappings
static

Definition at line 971 of file app_voicemail.c.

◆ mailbox_folders

const char* const mailbox_folders[]
static

Definition at line 623 of file app_voicemail.c.

◆ mailcmd

char mailcmd[160] = SENDMAIL
static

Definition at line 924 of file app_voicemail.c.

◆ maxdeletedmsg

int maxdeletedmsg
static

Definition at line 921 of file app_voicemail.c.

Referenced by populate_defaults().

◆ maxgreet

int maxgreet
static

Definition at line 931 of file app_voicemail.c.

◆ maxlogins

int maxlogins = 3
static

Definition at line 933 of file app_voicemail.c.

◆ maxmsg

int maxmsg = MAXMSG
static

Definition at line 920 of file app_voicemail.c.

Referenced by populate_defaults().

◆ maxsilence

int maxsilence
static
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 919 of file app_voicemail.c.

Referenced by ast_record_review().

◆ minpassword

int minpassword = MINPASSWORD
static

Definition at line 934 of file app_voicemail.c.

◆ msg_id_incrementor

int msg_id_incrementor
static

Definition at line 3742 of file app_voicemail.c.

◆ mwi_observer

struct ast_mwi_observer mwi_observer
Initial value:
= {
.on_subscribe = mwi_handle_subscribe,
.on_unsubscribe = mwi_handle_unsubscribe,
}
static void mwi_handle_subscribe(const char *id, struct ast_mwi_subscriber *sub)
static void mwi_handle_unsubscribe(const char *id, struct ast_mwi_subscriber *sub)

Definition at line 13192 of file app_voicemail.c.

◆ mwi_subscription_tps

struct ast_taskprocessor* mwi_subscription_tps
static

Definition at line 952 of file app_voicemail.c.

◆ my_umask

int my_umask
static

Definition at line 883 of file app_voicemail.c.

◆ pagerbody

char* pagerbody
static

Definition at line 1018 of file app_voicemail.c.

◆ pagerdateformat

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

Definition at line 1028 of file app_voicemail.c.

◆ pagerfromstring

char pagerfromstring[100]
static

Definition at line 1021 of file app_voicemail.c.

◆ pagersubject

char* pagersubject
static

Definition at line 1019 of file app_voicemail.c.

◆ passwordlocation

int passwordlocation
static

Definition at line 935 of file app_voicemail.c.

Referenced by populate_defaults().

◆ playmsg_app

char* playmsg_app = "VoiceMailPlayMsg"
static

Definition at line 911 of file app_voicemail.c.

◆ poll_cond

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static

Definition at line 948 of file app_voicemail.c.

◆ poll_freq

unsigned int poll_freq = DEFAULT_POLL_FREQ
static

Polling frequency

Definition at line 945 of file app_voicemail.c.

◆ poll_lock

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

Definition at line 947 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

◆ poll_mailboxes

unsigned int poll_mailboxes
static

Poll mailboxes for changes since there is something external to app_voicemail that may change them.

Definition at line 940 of file app_voicemail.c.

◆ poll_thread

pthread_t poll_thread = AST_PTHREADT_NULL
static

Definition at line 949 of file app_voicemail.c.

◆ poll_thread_run

unsigned char poll_thread_run
static

Definition at line 950 of file app_voicemail.c.

◆ pwdchange

int pwdchange = PWDCHANGE_INTERNAL
static

Definition at line 887 of file app_voicemail.c.

◆ saydurationminfo

int saydurationminfo = 2
static

Definition at line 1007 of file app_voicemail.c.

Referenced by populate_defaults().

◆ sayname_app

char* sayname_app = "VMSayName"
static

Definition at line 913 of file app_voicemail.c.

◆ serveremail

char serveremail[80] = ASTERISK_USERNAME
static

Definition at line 923 of file app_voicemail.c.

Referenced by forward_message(), notify_new_message(), and vm_allocate_dh().

◆ silencethreshold

int silencethreshold = 128
static
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 922 of file app_voicemail.c.

Referenced by ast_record_review(), and setup_privacy_args().

◆ skipms

int skipms = 3000
static

◆ smdi_iface

struct ast_smdi_interface* smdi_iface = NULL
static

Definition at line 926 of file app_voicemail.c.

◆ users

struct users users = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ userscontext

char userscontext[AST_MAX_EXTENSION] = "default"
static

Definition at line 899 of file app_voicemail.c.

◆ vm_app_options

const 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 }, [ 'e' ] = { .flag = OPT_EARLYM_GREETING }, [ 't' ] = { .flag = OPT_BEEP , .arg_index = OPT_ARG_BEEP_TONE + 1 } }
static

Definition at line 621 of file app_voicemail.c.

Referenced by vm_exec(), and vm_execmain().

◆ vm_greeter_table

const struct ast_vm_greeter_functions vm_greeter_table
static

Definition at line 15038 of file app_voicemail.c.

◆ vm_info_acf

struct ast_custom_function vm_info_acf
static
Initial value:
= {
.name = "VM_INFO",
.read = acf_vm_info,
}
static int acf_vm_info(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)

Definition at line 12760 of file app_voicemail.c.

◆ vm_invalid_password

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

Definition at line 990 of file app_voicemail.c.

◆ vm_login

char vm_login[80] = "vm-login"
static

Definition at line 983 of file app_voicemail.c.

◆ vm_mismatch

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

Definition at line 989 of file app_voicemail.c.

◆ vm_newpassword

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

Definition at line 986 of file app_voicemail.c.

◆ vm_newuser

char vm_newuser[80] = "vm-newuser"
static

Definition at line 984 of file app_voicemail.c.

◆ vm_passchanged

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

Definition at line 987 of file app_voicemail.c.

◆ vm_password

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

Definition at line 985 of file app_voicemail.c.

◆ vm_pls_try_again

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

Definition at line 991 of file app_voicemail.c.

◆ vm_prepend_timeout

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

Definition at line 1003 of file app_voicemail.c.

◆ vm_reenterpassword

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

Definition at line 988 of file app_voicemail.c.

◆ VM_SPOOL_DIR

char VM_SPOOL_DIR[PATH_MAX]
static

Definition at line 878 of file app_voicemail.c.

◆ vm_table

const struct ast_vm_functions vm_table
static

◆ vmauthenticate_app

char* vmauthenticate_app = "VMAuthenticate"
static

Definition at line 909 of file app_voicemail.c.

◆ vmfmts

char vmfmts[80] = "wav"
static

Definition at line 927 of file app_voicemail.c.

◆ vmmaxsecs

int vmmaxsecs
static

Definition at line 930 of file app_voicemail.c.

Referenced by apply_option(), and populate_defaults().

◆ vmminsecs

int vmminsecs
static

Definition at line 929 of file app_voicemail.c.

Referenced by apply_option(), and populate_defaults().

◆ voicemail_app

char* voicemail_app = "VoiceMail"
static

Definition at line 904 of file app_voicemail.c.

◆ voicemailmain_app

char* voicemailmain_app = "VoiceMailMain"
static

Definition at line 907 of file app_voicemail.c.

◆ volgain

double volgain
static

Definition at line 928 of file app_voicemail.c.

Referenced by populate_defaults().

◆ zones

struct zones zones = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ zonetag

char zonetag[80]
static

Definition at line 917 of file app_voicemail.c.

Referenced by build_peer().