Asterisk - The Open Source Telephony Project GIT-master-a358458
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  inprocess
 
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
 
struct  mailbox_alias_mapping
 
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 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 force_reload_config()   load_config_force(1, 1)
 Forcibly reload voicemail.conf, even if it has not changed. This is necessary after running unit tests. More...
 
#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_DIRECTFORWARD   (1 << 10)
 
#define VM_EMAIL_EXT_RECS   (1 << 19)
 
#define VM_ENVELOPE   (1 << 4)
 
#define VM_FORCEGREET   (1 << 8)
 
#define VM_FORCENAME   (1 << 7)
 
#define VM_FWDURGAUTO   (1 << 18)
 
#define VM_MARK_URGENT   (1 << 20)
 
#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_STRING_HEADER_FORMAT   "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"
 
#define VM_SVMAIL   (1 << 3)
 
#define VM_TEMPGREETWARN   (1 << 15)
 
#define VMBOX_STRING_DATA_FORMAT   "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
 
#define VMBOX_STRING_HEADER_FORMAT   "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
 
#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 , NEW_FOLDER = 0 , OLD_FOLDER = 1 ,
  WORK_FOLDER = 2 , FAMILY_FOLDER = 3 , FRIENDS_FOLDER = 4 , GREETINGS_FOLDER = -1 ,
  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 , OPT_ARG_RECORDGAIN = 0 , OPT_ARG_PLAYFOLDER = 1 , OPT_ARG_DTMFEXIT = 2 ,
  OPT_ARG_BEEP_TONE = 3 , OPT_ARG_ARRAY_SIZE = 4 , 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) , OPT_SILENT_IF_GREET = (1 << 12) ,
  OPT_READONLY = (1 << 13) , 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) ,
  OPT_SILENT_IF_GREET = (1 << 12) , OPT_READONLY = (1 << 13) , 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) , OPT_SILENT_IF_GREET = (1 << 12) , OPT_READONLY = (1 << 13)
}
 
enum  vm_passwordlocation {
  OPT_PWLOC_VOICEMAILCONF = 0 , OPT_PWLOC_SPOOLDIR = 1 , OPT_PWLOC_USERSCONF = 2 , OPT_PWLOC_VOICEMAILCONF = 0 ,
  OPT_PWLOC_SPOOLDIR = 1 , OPT_PWLOC_USERSCONF = 2 , OPT_PWLOC_VOICEMAILCONF = 0 , OPT_PWLOC_SPOOLDIR = 1 ,
  OPT_PWLOC_USERSCONF = 2
}
 

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int acf_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_vmbox_info_astman (struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
 Append vmbox info string into given astman with event_name. More...
 
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...
 
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_move_message (struct ast_cli_args *a, int maxpos)
 
static char * complete_voicemail_show_mailbox (struct ast_cli_args *a)
 
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_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 int forward_message_from_mailbox (struct ast_cli_args *a)
 
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_forward_message (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_voicemail_move_message (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
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_remove_message (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
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_mailbox (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
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 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 (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_force (int reload, int force)
 Reload voicemail.conf. More...
 
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_get_mailbox_summary (struct mansession *s, const struct message *m)
 
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_forward (struct mansession *s, const struct message *m)
 
static int manager_voicemail_move (struct mansession *s, const struct message *m)
 
static int manager_voicemail_refresh (struct mansession *s, const struct message *m)
 
static int manager_voicemail_remove (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 move_message_from_mailbox (struct ast_cli_args *a)
 
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 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 int remove_message_from_mailbox (struct ast_cli_args *a)
 
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 int show_mailbox_details (struct ast_cli_args *a)
 
static int show_mailbox_snapshot (struct ast_cli_args *a)
 
static int show_messages_for_mailbox (struct ast_cli_args *a)
 
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, int nodelete)
 
static int vm_instructions_en (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
 
static int vm_instructions_ja (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
 
static int vm_instructions_zh (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
 
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_da (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 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 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 = AST_BUILDOPT_SUM, .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 }, [ 'S' ] = { .flag = OPT_SILENT_IF_GREET }, [ '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 }, [ 'r' ] = { .flag = OPT_READONLY }, }
 
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
Note
For information about voicemail IMAP storage, https://docs.asterisk.org/Configuration/Applications/Voicemail/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 638 of file app_voicemail.c.

◆ CHUNKSIZE

#define CHUNKSIZE   65536

Definition at line 635 of file app_voicemail.c.

◆ COMMAND_TIMEOUT

#define COMMAND_TIMEOUT   5000

Definition at line 631 of file app_voicemail.c.

◆ COPY

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

Definition at line 1005 of file app_voicemail.c.

◆ DEFAULT_LISTEN_CONTROL_FORWARD_KEY

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 643 of file app_voicemail.c.

◆ DEFAULT_LISTEN_CONTROL_PAUSE_KEY

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 645 of file app_voicemail.c.

◆ DEFAULT_LISTEN_CONTROL_RESTART_KEY

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 646 of file app_voicemail.c.

◆ DEFAULT_LISTEN_CONTROL_REVERSE_KEY

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 644 of file app_voicemail.c.

◆ DEFAULT_LISTEN_CONTROL_STOP_KEY

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 647 of file app_voicemail.c.

◆ DEFAULT_POLL_FREQ

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 1076 of file app_voicemail.c.

◆ DELETE

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

Definition at line 1006 of file app_voicemail.c.

◆ DISPOSE

#define DISPOSE (   a,
  b 
)

Definition at line 1001 of file app_voicemail.c.

◆ ENDL

#define ENDL   "\n"

Definition at line 665 of file app_voicemail.c.

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

Definition at line 692 of file app_voicemail.c.

◆ ERROR_MAX_MSGS

#define ERROR_MAX_MSGS   -101

Definition at line 693 of file app_voicemail.c.

◆ EXISTS

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

Definition at line 1003 of file app_voicemail.c.

◆ force_reload_config

#define force_reload_config ( )    load_config_force(1, 1)

Forcibly reload voicemail.conf, even if it has not changed. This is necessary after running unit tests.

Definition at line 781 of file app_voicemail.c.

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

◆ MAPPING_BUCKETS

#define MAPPING_BUCKETS   511

Definition at line 1099 of file app_voicemail.c.

◆ MAX_DATETIME_FORMAT

#define MAX_DATETIME_FORMAT   512

Definition at line 668 of file app_voicemail.c.

◆ MAX_MAIL_BODY_CONTENT_SIZE

#define MAX_MAIL_BODY_CONTENT_SIZE   134217728L

Definition at line 655 of file app_voicemail.c.

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 669 of file app_voicemail.c.

◆ MAX_VM_CONTEXT_LEN

#define MAX_VM_CONTEXT_LEN   (AST_MAX_CONTEXT)

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

◆ MAX_VM_MBOX_ID_LEN

#define MAX_VM_MBOX_ID_LEN   (AST_MAX_EXTENSION)

Definition at line 881 of file app_voicemail.c.

◆ MAXMSG

#define MAXMSG   100

Definition at line 657 of file app_voicemail.c.

◆ MAXMSGLIMIT

#define MAXMSGLIMIT   9999

Definition at line 658 of file app_voicemail.c.

◆ MINPASSWORD

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 660 of file app_voicemail.c.

◆ MSG_ID_LEN

#define MSG_ID_LEN   256

Definition at line 3878 of file app_voicemail.c.

◆ OPERATOR_EXIT

#define OPERATOR_EXIT   300

Definition at line 694 of file app_voicemail.c.

◆ PWDCHANGE_EXTERNAL

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 1019 of file app_voicemail.c.

◆ PWDCHANGE_INTERNAL

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 1018 of file app_voicemail.c.

◆ RENAME

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

Definition at line 1004 of file app_voicemail.c.

◆ RETRIEVE

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

Definition at line 1000 of file app_voicemail.c.

◆ SENDMAIL

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

Definition at line 652 of file app_voicemail.c.

◆ SMDI_MWI_WAIT_TIMEOUT

#define SMDI_MWI_WAIT_TIMEOUT   1000 /* 1 second */

Definition at line 629 of file app_voicemail.c.

◆ STORE

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

Definition at line 1002 of file app_voicemail.c.

◆ tdesc

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 1028 of file app_voicemail.c.

◆ UPDATE_MSG_ID

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

Definition at line 1007 of file app_voicemail.c.

◆ VALID_DTMF

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

Definition at line 648 of file app_voicemail.c.

◆ VM_ALLOCED

#define VM_ALLOCED   (1 << 13)

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

Definition at line 684 of file app_voicemail.c.

◆ VM_ATTACH

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 682 of file app_voicemail.c.

◆ VM_DELETE

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 683 of file app_voicemail.c.

◆ VM_DIRECTFORWARD

#define VM_DIRECTFORWARD   (1 << 10)

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

Definition at line 681 of file app_voicemail.c.

◆ VM_EMAIL_EXT_RECS

#define VM_EMAIL_EXT_RECS   (1 << 19)

Send voicemail emails when an external recording is added to a mailbox

Definition at line 690 of file app_voicemail.c.

◆ VM_ENVELOPE

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 675 of file app_voicemail.c.

◆ VM_FORCEGREET

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 679 of file app_voicemail.c.

◆ VM_FORCENAME

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 678 of file app_voicemail.c.

◆ VM_FWDURGAUTO

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 689 of file app_voicemail.c.

◆ VM_MARK_URGENT

#define VM_MARK_URGENT   (1 << 20)

After recording, permit the caller to mark the message as urgent

Definition at line 691 of file app_voicemail.c.

◆ VM_MESSAGEWRAP

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 688 of file app_voicemail.c.

◆ VM_MOVEHEARD

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 687 of file app_voicemail.c.

◆ VM_OPERATOR

#define VM_OPERATOR   (1 << 1)

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

Definition at line 672 of file app_voicemail.c.

◆ VM_PBXSKIP

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 680 of file app_voicemail.c.

◆ VM_REVIEW

#define VM_REVIEW   (1 << 0)

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

Definition at line 671 of file app_voicemail.c.

◆ VM_SAYCID

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 673 of file app_voicemail.c.

◆ VM_SAYDURATION

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 676 of file app_voicemail.c.

◆ VM_SEARCH

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 685 of file app_voicemail.c.

◆ VM_SKIPAFTERCMD

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 677 of file app_voicemail.c.

◆ VM_STRING_HEADER_FORMAT

#define VM_STRING_HEADER_FORMAT   "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"

◆ VM_SVMAIL

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 674 of file app_voicemail.c.

◆ VM_TEMPGREETWARN

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 686 of file app_voicemail.c.

◆ VMBOX_STRING_DATA_FORMAT

#define VMBOX_STRING_DATA_FORMAT   "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"

◆ VMBOX_STRING_HEADER_FORMAT

#define VMBOX_STRING_HEADER_FORMAT   "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"

◆ VMSTATE_MAX_MSG_ARRAY

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 936 of file app_voicemail.c.

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 637 of file app_voicemail.c.

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0777

Definition at line 633 of file app_voicemail.c.

◆ VOICEMAIL_FILE_MODE

#define VOICEMAIL_FILE_MODE   0666

Definition at line 634 of file app_voicemail.c.

Enumeration Type Documentation

◆ vm_box

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

Definition at line 696 of file app_voicemail.c.

696 {
697 NEW_FOLDER = 0,
698 OLD_FOLDER = 1,
699 WORK_FOLDER = 2,
700 FAMILY_FOLDER = 3,
701 FRIENDS_FOLDER = 4,
703};
@ FRIENDS_FOLDER
@ NEW_FOLDER
@ GREETINGS_FOLDER
@ FAMILY_FOLDER
@ WORK_FOLDER
@ OLD_FOLDER

◆ vm_option_args

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

Definition at line 721 of file app_voicemail.c.

721 {
726 /* This *must* be the last value in this enum! */
728};
@ OPT_ARG_RECORDGAIN
@ OPT_ARG_PLAYFOLDER
@ OPT_ARG_BEEP_TONE
@ OPT_ARG_ARRAY_SIZE
@ OPT_ARG_DTMFEXIT

◆ 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 
OPT_SILENT_IF_GREET 
OPT_READONLY 
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 
OPT_SILENT_IF_GREET 
OPT_READONLY 
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 
OPT_SILENT_IF_GREET 
OPT_READONLY 

Definition at line 705 of file app_voicemail.c.

705 {
706 OPT_SILENT = (1 << 0),
707 OPT_BUSY_GREETING = (1 << 1),
708 OPT_UNAVAIL_GREETING = (1 << 2),
709 OPT_RECORDGAIN = (1 << 3),
710 OPT_PREPEND_MAILBOX = (1 << 4),
711 OPT_AUTOPLAY = (1 << 6),
712 OPT_DTMFEXIT = (1 << 7),
713 OPT_MESSAGE_Urgent = (1 << 8),
714 OPT_MESSAGE_PRIORITY = (1 << 9),
715 OPT_EARLYM_GREETING = (1 << 10),
716 OPT_BEEP = (1 << 11),
717 OPT_SILENT_IF_GREET = (1 << 12),
718 OPT_READONLY = (1 << 13),
719};
@ OPT_MESSAGE_PRIORITY
@ OPT_PREPEND_MAILBOX
@ OPT_BEEP
@ OPT_BUSY_GREETING
@ OPT_RECORDGAIN
@ OPT_EARLYM_GREETING
@ OPT_SILENT_IF_GREET
@ OPT_UNAVAIL_GREETING
@ OPT_READONLY
@ OPT_SILENT
@ OPT_DTMFEXIT
@ OPT_MESSAGE_Urgent
@ OPT_AUTOPLAY

◆ vm_passwordlocation

Enumerator
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 730 of file app_voicemail.c.

730 {
734};
@ OPT_PWLOC_USERSCONF
@ OPT_PWLOC_SPOOLDIR
@ OPT_PWLOC_VOICEMAILCONF

Function Documentation

◆ __has_voicemail()

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

Definition at line 6057 of file app_voicemail.c.

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

References alias_mailbox_mappings, aliasescontext, ao2_find, ao2_ref, ast_strdupa, ast_strlen_zero(), c, voicemailpwcheck::context, alias_mailbox_mapping::mailbox, voicemailpwcheck::mailbox, MAX_VM_MAILBOX_LEN, OBJ_SEARCH_KEY, separate_mailbox(), tmp(), and VM_SPOOL_DIR.

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

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 17323 of file app_voicemail.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

13131{
13132 struct ast_vm_user svm;
13133 struct ast_vm_user *vmu = NULL;
13134 char *parse;
13135 char *mailbox;
13136 char *context;
13137 int res = 0;
13138
13140 AST_APP_ARG(mailbox_context);
13141 AST_APP_ARG(attribute);
13142 AST_APP_ARG(folder);
13143 );
13144
13145 buf[0] = '\0';
13146
13147 if (ast_strlen_zero(args)) {
13148 ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13149 return -1;
13150 }
13151
13152 parse = ast_strdupa(args);
13153 AST_STANDARD_APP_ARGS(arg, parse);
13154
13155 if (ast_strlen_zero(arg.mailbox_context)
13156 || ast_strlen_zero(arg.attribute)
13157 || separate_mailbox(ast_strdupa(arg.mailbox_context), &mailbox, &context)) {
13158 ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13159 return -1;
13160 }
13161
13162 memset(&svm, 0, sizeof(svm));
13163 vmu = find_user(&svm, context, mailbox);
13164
13165 if (!strncasecmp(arg.attribute, "exists", 5)) {
13166 ast_copy_string(buf, vmu ? "1" : "0", len);
13167 free_user(vmu);
13168 return 0;
13169 }
13170
13171 if (vmu) {
13172 if (!strncasecmp(arg.attribute, "password", 8)) {
13174 } else if (!strncasecmp(arg.attribute, "fullname", 8)) {
13176 } else if (!strncasecmp(arg.attribute, "email", 5)) {
13177 ast_copy_string(buf, vmu->email, len);
13178 } else if (!strncasecmp(arg.attribute, "pager", 5)) {
13179 ast_copy_string(buf, vmu->pager, len);
13180 } else if (!strncasecmp(arg.attribute, "language", 8)) {
13182 } else if (!strncasecmp(arg.attribute, "locale", 6)) {
13183 ast_copy_string(buf, vmu->locale, len);
13184 } else if (!strncasecmp(arg.attribute, "tz", 2)) {
13186 } else if (!strncasecmp(arg.attribute, "count", 5)) {
13187 char *mailbox_id;
13188
13189 mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2);
13190 sprintf(mailbox_id, "%s@%s", mailbox, context);/* Safe */
13191
13192 /* If mbxfolder is empty messagecount will default to INBOX */
13193 res = messagecount(mailbox_id, arg.folder);
13194 if (res < 0) {
13195 ast_log(LOG_ERROR, "Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
13196 free_user(vmu);
13197 return -1;
13198 }
13199 snprintf(buf, len, "%d", res);
13200 } else {
13201 ast_log(LOG_ERROR, "Unknown attribute '%s' for VM_INFO\n", arg.attribute);
13202 free_user(vmu);
13203 return -1;
13204 }
13205 free_user(vmu);
13206 }
13207
13208 return 0;
13209}
static void free_user(struct ast_vm_user *vmu)
static int messagecount(const char *mailbox_id, const char *folder)
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_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_language(const struct ast_channel *chan)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char pager[80]
char password[80]
char zonetag[80]
char locale[20]
char language[MAX_LANGUAGE]
char fullname[80]
const char * args

References args, 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(), buf, voicemailpwcheck::context, ast_vm_user::email, find_user(), free_user(), ast_vm_user::fullname, ast_vm_user::language, len(), ast_vm_user::locale, LOG_ERROR, voicemailpwcheck::mailbox, messagecount(), NULL, ast_vm_user::pager, ast_vm_user::password, S_OR, separate_mailbox(), and ast_vm_user::zonetag.

◆ actual_load_config()

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

Definition at line 14365 of file app_voicemail.c.

14366{
14367 struct ast_vm_user *current;
14368 char *cat;
14369 const char *val;
14370 char *q, *stringp, *tmp;
14371 int x;
14372 unsigned int tmpadsi[4];
14373 char secretfn[PATH_MAX] = "";
14374 long tps_queue_low;
14375 long tps_queue_high;
14376
14377#ifdef IMAP_STORAGE
14378 ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
14379#endif
14380 /* set audio control prompts */
14386
14387#ifdef IMAP_STORAGE
14388 ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
14389#endif
14390
14391 /* Free all the users structure */
14392 free_vm_users();
14393
14394 /* Free all the zones structure */
14395 free_vm_zones();
14396
14397 /* Remove all aliases */
14400
14402
14403 memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
14404 memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
14405
14406 if (cfg) {
14407 /* General settings */
14408
14409 if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
14410 val = "default";
14412
14413 aliasescontext[0] = '\0';
14414 val = ast_variable_retrieve(cfg, "general", "aliasescontext");
14416
14417 /* Attach voice message to mail message ? */
14418 if (!(val = ast_variable_retrieve(cfg, "general", "attach")))
14419 val = "yes";
14421
14422 if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
14423 val = "no";
14425
14426 volgain = 0.0;
14427 if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
14428 sscanf(val, "%30lf", &volgain);
14429
14430#ifdef ODBC_STORAGE
14431 strcpy(odbc_database, "asterisk");
14432 if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
14433 ast_copy_string(odbc_database, val, sizeof(odbc_database));
14434 }
14435 strcpy(odbc_table, "voicemessages");
14436 if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
14437 ast_copy_string(odbc_table, val, sizeof(odbc_table));
14438 }
14439#endif
14440 /* Mail command */
14441 strcpy(mailcmd, SENDMAIL);
14442 if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
14443 ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
14444
14445 maxsilence = 0;
14446 if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
14447 maxsilence = atoi(val);
14448 if (maxsilence > 0)
14449 maxsilence *= 1000;
14450 }
14451
14452 if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
14453 maxmsg = MAXMSG;
14454 } else {
14455 maxmsg = atoi(val);
14456 if (maxmsg < 0) {
14457 ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
14458 maxmsg = MAXMSG;
14459 } else if (maxmsg > MAXMSGLIMIT) {
14460 ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
14462 }
14463 }
14464
14465 if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
14466 maxdeletedmsg = 0;
14467 } else {
14468 if (sscanf(val, "%30d", &x) == 1)
14469 maxdeletedmsg = x;
14470 else if (ast_true(val))
14472 else
14473 maxdeletedmsg = 0;
14474
14475 if (maxdeletedmsg < 0) {
14476 ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
14478 } else if (maxdeletedmsg > MAXMSGLIMIT) {
14479 ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
14481 }
14482 }
14483
14484 /* Load date format config for voicemail mail */
14485 if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
14487 }
14488
14489 /* Load date format config for voicemail pager mail */
14490 if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
14492 }
14493
14494 /* External password changing command */
14495 if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
14498 } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
14501 }
14502
14503 /* External password validation command */
14504 if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
14506 ast_debug(1, "found externpasscheck: %s\n", ext_pass_check_cmd);
14507 }
14508
14509#ifdef IMAP_STORAGE
14510 /* IMAP server address */
14511 if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
14512 ast_copy_string(imapserver, val, sizeof(imapserver));
14513 } else {
14514 ast_copy_string(imapserver, "localhost", sizeof(imapserver));
14515 }
14516 /* IMAP server port */
14517 if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
14518 ast_copy_string(imapport, val, sizeof(imapport));
14519 } else {
14520 ast_copy_string(imapport, "143", sizeof(imapport));
14521 }
14522 /* IMAP server flags */
14523 if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
14524 ast_copy_string(imapflags, val, sizeof(imapflags));
14525 }
14526 /* IMAP server master username */
14527 if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
14528 ast_copy_string(authuser, val, sizeof(authuser));
14529 }
14530 /* IMAP server master password */
14531 if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
14532 ast_copy_string(authpassword, val, sizeof(authpassword));
14533 }
14534 /* Expunge on exit */
14535 if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
14536 if (ast_false(val))
14537 expungeonhangup = 0;
14538 else
14539 expungeonhangup = 1;
14540 } else {
14541 expungeonhangup = 1;
14542 }
14543 /* IMAP voicemail folder */
14544 if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
14545 ast_copy_string(imapfolder, val, sizeof(imapfolder));
14546 } else {
14547 ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
14548 }
14549 if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
14550 ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
14551 }
14552 if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
14553 imapgreetings = ast_true(val);
14554 } else {
14555 imapgreetings = 0;
14556 }
14557 if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
14558 ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
14559 } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
14560 /* Also support greetingsfolder as documented in voicemail.conf.sample */
14561 ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
14562 } else {
14563 ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
14564 }
14565 if ((val = ast_variable_retrieve(cfg, "general", "imap_poll_logout"))) {
14566 imap_poll_logout = ast_true(val);
14567 } else {
14568 imap_poll_logout = 0;
14569 }
14570
14571 /* There is some very unorthodox casting done here. This is due
14572 * to the way c-client handles the argument passed in. It expects a
14573 * void pointer and casts the pointer directly to a long without
14574 * first dereferencing it. */
14575 if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
14576 mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
14577 } else {
14578 mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
14579 }
14580
14581 if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
14582 mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
14583 } else {
14584 mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
14585 }
14586
14587 if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
14588 mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
14589 } else {
14590 mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
14591 }
14592
14593 if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
14594 mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
14595 } else {
14596 mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
14597 }
14598
14599 /* Increment configuration version */
14600 imapversion++;
14601#endif
14602 /* External voicemail notify application */
14603 if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
14605 ast_debug(1, "found externnotify: %s\n", externnotify);
14606 } else {
14607 externnotify[0] = '\0';
14608 }
14609
14610 /* SMDI voicemail notification */
14611 if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
14612 ast_debug(1, "Enabled SMDI voicemail notification\n");
14613 if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
14615 } else {
14616 ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
14617 smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
14618 }
14619 if (!smdi_iface) {
14620 ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
14621 }
14622 }
14623
14624 /* Silence treshold */
14626 if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
14627 silencethreshold = atoi(val);
14628
14629 if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
14632
14633 vmmaxsecs = 0;
14634 if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
14635 if (sscanf(val, "%30d", &x) == 1) {
14636 vmmaxsecs = x;
14637 } else {
14638 ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
14639 }
14640 } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
14641 static int maxmessage_deprecate = 0;
14642 if (maxmessage_deprecate == 0) {
14643 maxmessage_deprecate = 1;
14644 ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
14645 }
14646 if (sscanf(val, "%30d", &x) == 1) {
14647 vmmaxsecs = x;
14648 } else {
14649 ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
14650 }
14651 }
14652
14653 vmminsecs = 0;
14654 if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
14655 if (sscanf(val, "%30d", &x) == 1) {
14656 vmminsecs = x;
14657 if (maxsilence / 1000 >= vmminsecs) {
14658 ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
14659 }
14660 } else {
14661 ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
14662 }
14663 } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
14664 static int maxmessage_deprecate = 0;
14665 if (maxmessage_deprecate == 0) {
14666 maxmessage_deprecate = 1;
14667 ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
14668 }
14669 if (sscanf(val, "%30d", &x) == 1) {
14670 vmminsecs = x;
14671 if (maxsilence / 1000 >= vmminsecs) {
14672 ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
14673 }
14674 } else {
14675 ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
14676 }
14677 }
14678
14679 val = ast_variable_retrieve(cfg, "general", "format");
14680 if (!val) {
14681 val = "wav";
14682 } else {
14683 tmp = ast_strdupa(val);
14685 if (!val) {
14686 ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
14687 val = "wav";
14688 }
14689 }
14690 ast_copy_string(vmfmts, val, sizeof(vmfmts));
14691
14692 skipms = 3000;
14693 if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
14694 if (sscanf(val, "%30d", &x) == 1) {
14695 maxgreet = x;
14696 } else {
14697 ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
14698 }
14699 }
14700
14701 if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
14702 if (sscanf(val, "%30d", &x) == 1) {
14703 skipms = x;
14704 } else {
14705 ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
14706 }
14707 }
14708
14709 maxlogins = 3;
14710 if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
14711 if (sscanf(val, "%30d", &x) == 1) {
14712 maxlogins = x;
14713 } else {
14714 ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
14715 }
14716 }
14717
14719 if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
14720 if (sscanf(val, "%30d", &x) == 1) {
14721 minpassword = x;
14722 } else {
14723 ast_log(AST_LOG_WARNING, "Invalid minimum password length. Default to %d\n", minpassword);
14724 }
14725 }
14726
14727 /* Force new user to record name ? */
14728 if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
14729 val = "no";
14731
14732 /* Force new user to record greetings ? */
14733 if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
14734 val = "no";
14736
14737 if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
14738 ast_debug(1, "VM_CID Internal context string: %s\n", val);
14739 stringp = ast_strdupa(val);
14740 for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
14741 if (!ast_strlen_zero(stringp)) {
14742 q = strsep(&stringp, ",");
14743 while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
14744 q++;
14746 ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
14747 } else {
14748 cidinternalcontexts[x][0] = '\0';
14749 }
14750 }
14751 }
14752 if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
14753 ast_debug(1, "VM Review Option disabled globally\n");
14754 val = "no";
14755 }
14757
14758 if (!(val = ast_variable_retrieve(cfg, "general", "leaveurgent"))){
14759 val = "yes";
14760 } else if (ast_false(val)) {
14761 ast_debug(1, "VM leave urgent messages disabled globally\n");
14762 val = "no";
14763 }
14765
14766 /* Temporary greeting reminder */
14767 if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
14768 ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
14769 val = "no";
14770 } else {
14771 ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
14772 }
14774 if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
14775 ast_debug(1, "VM next message wrap disabled globally\n");
14776 val = "no";
14777 }
14779
14780 if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
14781 ast_debug(1, "VM Operator break disabled globally\n");
14782 val = "no";
14783 }
14785
14786 if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
14787 ast_debug(1, "VM CID Info before msg disabled globally\n");
14788 val = "no";
14789 }
14791
14792 if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
14793 ast_debug(1, "Send Voicemail msg disabled globally\n");
14794 val = "no";
14795 }
14797
14798 if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
14799 ast_debug(1, "ENVELOPE before msg enabled globally\n");
14800 val = "yes";
14801 }
14803
14804 if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
14805 ast_debug(1, "Move Heard enabled globally\n");
14806 val = "yes";
14807 }
14809
14810 if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
14811 ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
14812 val = "no";
14813 }
14815
14816 if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
14817 ast_debug(1, "Duration info before msg enabled globally\n");
14818 val = "yes";
14819 }
14821
14822 saydurationminfo = 2;
14823 if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
14824 if (sscanf(val, "%30d", &x) == 1) {
14825 saydurationminfo = x;
14826 } else {
14827 ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
14828 }
14829 }
14830
14831 if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
14832 ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
14833 val = "no";
14834 }
14836
14837 if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
14839 ast_debug(1, "found dialout context: %s\n", dialcontext);
14840 } else {
14841 dialcontext[0] = '\0';
14842 }
14843
14844 if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
14846 ast_debug(1, "found callback context: %s\n", callcontext);
14847 } else {
14848 callcontext[0] = '\0';
14849 }
14850
14851 if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
14853 ast_debug(1, "found operator context: %s\n", exitcontext);
14854 } else {
14855 exitcontext[0] = '\0';
14856 }
14857
14858 /* load password sounds configuration */
14859 if ((val = ast_variable_retrieve(cfg, "general", "vm-login")))
14861 if ((val = ast_variable_retrieve(cfg, "general", "vm-newuser")))
14863 if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
14865 if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
14867 if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
14869 if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
14871 if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
14873 if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
14875 if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
14877 }
14878 if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
14880 }
14881 /* load configurable audio prompts */
14882 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
14884 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
14886 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
14888 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
14890 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
14892
14893 if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory")))
14894 val = "no";
14896
14897 if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
14898 val = "voicemail.conf";
14899 }
14900 if (!(strcmp(val, "spooldir"))) {
14902 } else {
14904 }
14905
14907 if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
14908 if (sscanf(val, "%30u", &poll_freq) != 1) {
14910 ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
14911 }
14912 }
14913
14914 poll_mailboxes = 0;
14915 if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
14917
14918 memset(fromstring, 0, sizeof(fromstring));
14919 memset(pagerfromstring, 0, sizeof(pagerfromstring));
14920 strcpy(charset, "ISO-8859-1");
14921 if (emailbody) {
14923 emailbody = NULL;
14924 }
14925 if (emailsubject) {
14928 }
14929 if (pagerbody) {
14931 pagerbody = NULL;
14932 }
14933 if (pagersubject) {
14936 }
14937 if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
14939 if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
14941 if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
14943 if ((val = ast_variable_retrieve(cfg, "general", "charset")))
14945 if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
14946 sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14947 for (x = 0; x < 4; x++) {
14948 memcpy(&adsifdn[x], &tmpadsi[x], 1);
14949 }
14950 }
14951 if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
14952 sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14953 for (x = 0; x < 4; x++) {
14954 memcpy(&adsisec[x], &tmpadsi[x], 1);
14955 }
14956 }
14957 if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
14958 if (atoi(val)) {
14959 adsiver = atoi(val);
14960 }
14961 }
14962 if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
14964 }
14965 if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
14966 ast_copy_string(locale, val, sizeof(locale));
14967 }
14968 if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
14970 }
14971 if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
14973 }
14974 if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
14976 }
14977 if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
14979 }
14980
14981 tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
14982 if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_high"))) {
14983 if (sscanf(val, "%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
14984 ast_log(AST_LOG_WARNING, "Invalid the taskprocessor high water alert trigger level '%s'\n", val);
14985 tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
14986 }
14987 }
14988 tps_queue_low = -1;
14989 if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_low"))) {
14990 if (sscanf(val, "%30ld", &tps_queue_low) != 1 ||
14991 tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
14992 ast_log(AST_LOG_WARNING, "Invalid the taskprocessor low water clear alert level '%s'\n", val);
14993 tps_queue_low = -1;
14994 }
14995 }
14996 if (ast_taskprocessor_alert_set_levels(mwi_subscription_tps, tps_queue_low, tps_queue_high)) {
14997 ast_log(AST_LOG_WARNING, "Failed to set alert levels for voicemail taskprocessor.\n");
14998 }
14999
15000 /* load mailboxes from users.conf */
15001 if (ucfg) {
15002 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15003 if (!strcasecmp(cat, "general")) {
15004 continue;
15005 }
15006 if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
15007 continue;
15008 if ((current = find_or_create(userscontext, cat))) {
15011 ast_copy_string(current->context, userscontext, sizeof(current->context));
15012 if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
15013 current->passwordlocation = OPT_PWLOC_USERSCONF;
15014 }
15015
15016 switch (current->passwordlocation) {
15017 case OPT_PWLOC_SPOOLDIR:
15018 snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
15019 read_password_from_file(secretfn, current->password, sizeof(current->password));
15020 }
15021 }
15022 }
15023 }
15024
15025 /* load mailboxes from voicemail.conf */
15026
15027 /*
15028 * Aliases must be loaded before users or the aliases won't be notified
15029 * if there's existing voicemail in the user mailbox.
15030 */
15031 load_aliases(cfg);
15032
15033 load_zonemessages(cfg);
15034
15035 load_users(cfg);
15036
15038
15043
15044 return 0;
15045 } else {
15047 ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
15048 return 0;
15049 }
15050}
static char pagerfromstring[100]
static char vm_password[80]
static char vm_invalid_password[80]
#define VM_SEARCH
static char listen_control_reverse_key[12]
static char serveremail[80]
#define VM_SAYCID
#define VM_FWDURGAUTO
#define VM_SAYDURATION
static int pwdchange
#define VM_TEMPGREETWARN
static int skipms
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY
static char mailcmd[160]
static int vmminsecs
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static struct ast_taskprocessor * mwi_subscription_tps
#define VM_OPERATOR
static char vm_newpassword[80]
#define VM_MARK_URGENT
static struct ast_flags globalflags
static char listen_control_forward_key[12]
static char vm_login[80]
#define VM_DIRECTFORWARD
static char vm_newuser[80]
static unsigned char adsisec[4]
static const char * substitute_escapes(const char *value)
#define VM_SKIPAFTERCMD
static pthread_t poll_thread
static char zonetag[80]
static char * pagersubject
static int maxmsg
static char vmfmts[80]
static void load_zonemessages(struct ast_config *cfg)
static int passwordlocation
static char vm_mismatch[80]
#define ASTERISK_USERNAME
static char vm_pls_try_again[80]
#define VM_PBXSKIP
static char ext_pass_check_cmd[128]
static char * pagerbody
static char dialcontext[AST_MAX_CONTEXT]
#define DEFAULT_POLL_FREQ
#define VM_ENVELOPE
static void stop_poll_thread(void)
#define MAXMSG
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
static char listen_control_stop_key[12]
static char fromstring[100]
#define PWDCHANGE_INTERNAL
#define VM_FORCEGREET
#define VM_MESSAGEWRAP
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
#define DEFAULT_LISTEN_CONTROL_STOP_KEY
static char emaildateformat[32]
static char vm_reenterpassword[80]
static int saydurationminfo
#define VM_ATTACH
static void load_users(struct ast_config *cfg)
static int maxgreet
#define SENDMAIL
#define VM_FORCENAME
static char ext_pass_cmd[128]
static int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
static char pagerdateformat[32]
static double volgain
static int adsiver
static int maxlogins
static char * emailsubject
static struct ao2_container * mailbox_alias_mappings
#define VM_MOVEHEARD
static char externnotify[160]
static char listen_control_restart_key[12]
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY
#define MAX_NUM_CID_CONTEXTS
static char vm_prepend_timeout[80]
static char userscontext[AST_MAX_EXTENSION]
static char callcontext[AST_MAX_CONTEXT]
static int maxdeletedmsg
static char * emailbody
static char listen_control_pause_key[12]
static int silencethreshold
static void start_poll_thread(void)
static unsigned int poll_mailboxes
#define MINPASSWORD
static int minpassword
static unsigned int poll_freq
static void free_vm_zones(void)
Free the zones structure.
#define VM_SVMAIL
#define PWDCHANGE_EXTERNAL
static struct ast_vm_user * find_or_create(const char *context, const char *box)
static char locale[20]
static unsigned char adsifdn[4]
static int maxsilence
static void load_aliases(struct ast_config *cfg)
static int vmmaxsecs
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
#define MAXMSGLIMIT
static char exitcontext[AST_MAX_CONTEXT]
#define VM_REVIEW
static char vm_passchanged[80]
static struct ast_smdi_interface * smdi_iface
static void free_vm_users(void)
Free the users structure.
#define PATH_MAX
Definition: asterisk.h:40
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
charset
Definition: chan_unistim.c:336
@ THRESHOLD_SILENCE
Definition: dsp.h:73
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:2009
char * ast_format_str_reduce(char *fmts)
Definition: file.c:1894
char * strsep(char **str, const char *delims)
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
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:773
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define AST_LOG_WARNING
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_PTHREADT_NULL
Definition: lock.h:66
size_t current
Definition: main/cli.c:113
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
Definition: mwi.c:338
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
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
list of users found in the config file
Definition: ast_expr2.c:325
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:64
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.
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94

References adsifdn, adsisec, adsiver, alias_mailbox_mappings, aliasescontext, 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, callcontext, cidinternalcontexts, current, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, ext_pass_check_cmd, ext_pass_cmd, externnotify, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, load_aliases(), load_users(), load_zonemessages(), locale, LOG_ERROR, mailbox_alias_mappings, mailcmd, MAX_NUM_CID_CONTEXTS, maxdeletedmsg, maxgreet, maxlogins, MAXMSG, maxmsg, MAXMSGLIMIT, maxsilence, MINPASSWORD, minpassword, mwi_subscription_tps, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, passwordlocation, PATH_MAX, poll_freq, poll_mailboxes, poll_thread, populate_defaults(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), S_OR, saydurationminfo, SENDMAIL, serveremail, silencethreshold, skipms, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, tmp(), userscontext, VM_ATTACH, VM_DIRECTFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, vm_login, VM_MARK_URGENT, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, vm_newuser, VM_OPERATOR, vm_passchanged, vm_password, VM_PBXSKIP, vm_pls_try_again, vm_prepend_timeout, vm_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SPOOL_DIR, VM_SVMAIL, VM_TEMPGREETWARN, vmfmts, vmmaxsecs, vmminsecs, volgain, and zonetag.

Referenced by load_config_force().

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

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

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

Referenced by make_email_file().

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

12803{
12804 struct ast_variable *var;
12805 struct ast_category *cat;
12806 generate_msg_id(id);
12807
12808 var = ast_variable_new("msg_id", id, "");
12809 if (!var) {
12810 return -1;
12811 }
12812
12813 cat = ast_category_get(msg_cfg, "message", NULL);
12814 if (!cat) {
12815 ast_log(LOG_ERROR, "Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
12817 return -1;
12818 }
12819
12821
12822 if (ast_config_text_file_save(filename, msg_cfg, "app_voicemail")) {
12823 ast_log(LOG_WARNING, "Unable to update %s to have a message ID\n", filename);
12824 return -1;
12825 }
12826
12827 UPDATE_MSG_ID(dir, msg, id, vmu, msg_cfg, folder);
12828 return 0;
12829}
#define UPDATE_MSG_ID(a, b, c, d, e, f)
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
#define var
Definition: ast_expr2f.c:605
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:2701
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#define ast_variable_new(name, value, filename)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
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:1111
Structure for variables, used for configurations and for channel variables.

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

◆ adsi_begin()

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

Definition at line 7453 of file app_voicemail.c.

7454{
7455 int x;
7456 if (!ast_adsi_available(chan))
7457 return;
7458 x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
7459 if (x < 0) {
7460 *useadsi = 0;
7462 return;
7463 }
7464 if (!x) {
7465 if (adsi_load_vmail(chan, useadsi)) {
7466 ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
7467 return;
7468 }
7469 } else
7470 *useadsi = 1;
7471}
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_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)
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:871
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)

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

Referenced by vm_authenticate(), and vm_execmain().

◆ adsi_delete()

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

Definition at line 7652 of file app_voicemail.c.

7653{
7654 int bytes = 0;
7655 unsigned char buf[256];
7656 unsigned char keys[8];
7657
7658 int x;
7659
7660 if (!ast_adsi_available(chan))
7661 return;
7662
7663 /* New meaning for keys */
7664 for (x = 0; x < 5; x++)
7665 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
7666
7667 keys[6] = 0x0;
7668 keys[7] = 0x0;
7669
7670 if (!vms->curmsg) {
7671 /* No prev key, provide "Folder" instead */
7672 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7673 }
7674 if (vms->curmsg >= vms->lastmsg) {
7675 /* If last message ... */
7676 if (vms->curmsg) {
7677 /* but not only message, provide "Folder" instead */
7678 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7679 } else {
7680 /* Otherwise if only message, leave blank */
7681 keys[3] = 1;
7682 }
7683 }
7684
7685 /* If deleted, show "undeleted" */
7686#ifdef IMAP_STORAGE
7687 ast_mutex_lock(&vms->lock);
7688#endif
7689 if (vms->deleted[vms->curmsg]) {
7690 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
7691 }
7692#ifdef IMAP_STORAGE
7693 ast_mutex_unlock(&vms->lock);
7694#endif
7695
7696 /* Except "Exit" */
7697 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
7698 bytes += ast_adsi_set_keys(buf + bytes, keys);
7699 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7700
7702}
#define ADSI_KEY_APPS
Definition: adsi.h:109
#define ADSI_KEY_SKT
Definition: adsi.h:117
#define ADSI_MSG_DISPLAY
Definition: adsi.h:32
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition: adsi.c:98
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition: adsi.c:307
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition: adsi.c:252
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
int * deleted

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, buf, vm_state::curmsg, vm_state::deleted, and vm_state::lastmsg.

Referenced by vm_execmain().

◆ adsi_folders()

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

Definition at line 7521 of file app_voicemail.c.

7522{
7523 unsigned char buf[256];
7524 int bytes = 0;
7525 unsigned char keys[8];
7526 int x, y;
7527
7528 if (!ast_adsi_available(chan))
7529 return;
7530
7531 for (x = 0; x < 5; x++) {
7532 y = ADSI_KEY_APPS + 12 + start + x;
7533 if (y > ADSI_KEY_APPS + 12 + 4)
7534 y = 0;
7535 keys[x] = ADSI_KEY_SKT | y;
7536 }
7537 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
7538 keys[6] = 0;
7539 keys[7] = 0;
7540
7541 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
7542 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
7543 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7544 bytes += ast_adsi_set_keys(buf + bytes, keys);
7545 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7546
7548}
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
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition: adsi.c:285
#define ADSI_COMM_PAGE
Definition: adsi.h:107

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(), ast_adsi_voice_mode(), and buf.

Referenced by vm_execmain().

◆ adsi_goodbye()

static void adsi_goodbye ( struct ast_channel chan)
static

Definition at line 7807 of file app_voicemail.c.

7808{
7809 unsigned char buf[256];
7810 int bytes = 0;
7811
7812 if (!ast_adsi_available(chan))
7813 return;
7814 bytes += adsi_logo(buf + bytes);
7815 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
7816 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
7817 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7818 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7819
7821}
#define ADSI_JUST_LEFT
Definition: adsi.h:112
static int adsi_logo(unsigned char *buf)

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(), ast_adsi_voice_mode(), and buf.

Referenced by vm_execmain().

◆ adsi_load_vmail()

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

Definition at line 7324 of file app_voicemail.c.

7325{
7326 unsigned char buf[256];
7327 int bytes = 0;
7328 int x;
7329 char num[5];
7330
7331 *useadsi = 0;
7332 bytes += ast_adsi_data_mode(buf + bytes);
7334
7335 bytes = 0;
7336 bytes += adsi_logo(buf);
7337 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
7338#ifdef DISPLAY
7339 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
7340#endif
7341 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7342 bytes += ast_adsi_data_mode(buf + bytes);
7344
7346 bytes = 0;
7347 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
7348 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
7349 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7350 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7352 return 0;
7353 }
7354
7355#ifdef DISPLAY
7356 /* Add a dot */
7357 bytes = 0;
7358 bytes += ast_adsi_logo(buf);
7359 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
7360 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
7361 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7363#endif
7364 bytes = 0;
7365 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
7366 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
7367 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advanced", "3", 1);
7368 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
7369 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
7370 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
7372
7373#ifdef DISPLAY
7374 /* Add another dot */
7375 bytes = 0;
7376 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
7377 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7378
7379 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7381#endif
7382
7383 bytes = 0;
7384 /* These buttons we load but don't use yet */
7385 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
7386 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
7387 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
7388 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
7389 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
7390 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
7392
7393#ifdef DISPLAY
7394 /* Add another dot */
7395 bytes = 0;
7396 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
7397 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7399#endif
7400
7401 bytes = 0;
7402 for (x = 0; x < 5; x++) {
7403 snprintf(num, sizeof(num), "%d", x);
7404 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
7405 }
7406 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
7408
7409#ifdef DISPLAY
7410 /* Add another dot */
7411 bytes = 0;
7412 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
7413 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7415#endif
7416
7417 if (ast_adsi_end_download(chan)) {
7418 bytes = 0;
7419 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
7420 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
7421 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7422 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7424 return 0;
7425 }
7426 bytes = 0;
7427 bytes += ast_adsi_download_disconnect(buf + bytes);
7428 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7430
7431 ast_debug(1, "Done downloading scripts...\n");
7432
7433#ifdef DISPLAY
7434 /* Add last dot */
7435 bytes = 0;
7436 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
7437 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7438#endif
7439 ast_debug(1, "Restarting session...\n");
7440
7441 bytes = 0;
7442 /* Load the session now */
7443 if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
7444 *useadsi = 1;
7445 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
7446 } else
7447 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
7448
7450 return 0;
7451}
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
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
Definition: adsi.c:219
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
Definition: adsi.c:32
int ast_adsi_end_download(struct ast_channel *chan)
Definition: adsi.c:43
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
Definition: adsi.c:208
static char * addesc
static const char * mbox(struct ast_vm_user *vmu, int id)

References addesc, ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ADSI_MSG_DOWNLOAD, adsifdn, adsisec, adsiver, ast_adsi_begin_download(), ast_adsi_data_mode(), ast_adsi_display(), ast_adsi_download_disconnect(), ast_adsi_end_download(), ast_adsi_load_session(), ast_adsi_load_soft_key(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, buf, mbox(), and NULL.

Referenced by adsi_begin().

◆ adsi_login()

static void adsi_login ( struct ast_channel chan)
static

Definition at line 7473 of file app_voicemail.c.

7474{
7475 unsigned char buf[256];
7476 int bytes = 0;
7477 unsigned char keys[8];
7478 int x;
7479 if (!ast_adsi_available(chan))
7480 return;
7481
7482 for (x = 0; x < 8; x++)
7483 keys[x] = 0;
7484 /* Set one key for next */
7485 keys[3] = ADSI_KEY_APPS + 3;
7486
7487 bytes += adsi_logo(buf + bytes);
7488 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
7489 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
7490 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7491 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
7492 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
7493 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
7494 bytes += ast_adsi_set_keys(buf + bytes, keys);
7495 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7497}
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
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
#define ADSI_DIR_FROM_LEFT
Definition: adsi.h:120

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(), ast_adsi_voice_mode(), and buf.

Referenced by vm_authenticate().

◆ adsi_logo()

static int adsi_logo ( unsigned char *  buf)
static

Definition at line 7316 of file app_voicemail.c.

7317{
7318 int bytes = 0;
7319 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
7320 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
7321 return bytes;
7322}

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ast_adsi_display(), and buf.

Referenced by adsi_goodbye(), adsi_load_vmail(), adsi_login(), vm_newuser_setup(), vm_options(), and vm_tempgreeting().

◆ adsi_message()

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

Definition at line 7550 of file app_voicemail.c.

7551{
7552 int bytes = 0;
7553 unsigned char buf[256];
7554 char buf1[256], buf2[256];
7555 char fn2[PATH_MAX];
7556
7557 char cid[256] = "";
7558 char *val;
7559 char *name, *num;
7560 char datetime[21] = "";
7561 FILE *f;
7562
7563 unsigned char keys[8];
7564
7565 int x;
7566
7567 if (!ast_adsi_available(chan))
7568 return;
7569
7570 /* Retrieve important info */
7571 snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
7572 f = fopen(fn2, "r");
7573 if (f) {
7574 while (!feof(f)) {
7575 if (!fgets((char *) buf, sizeof(buf), f)) {
7576 continue;
7577 }
7578 if (!feof(f)) {
7579 char *stringp = NULL;
7580 stringp = (char *) buf;
7581 strsep(&stringp, "=");
7582 val = strsep(&stringp, "=");
7583 if (!ast_strlen_zero(val)) {
7584 if (!strcmp((char *) buf, "callerid"))
7585 ast_copy_string(cid, val, sizeof(cid));
7586 if (!strcmp((char *) buf, "origdate"))
7587 ast_copy_string(datetime, val, sizeof(datetime));
7588 }
7589 }
7590 }
7591 fclose(f);
7592 }
7593 /* New meaning for keys */
7594 for (x = 0; x < 5; x++)
7595 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
7596 keys[6] = 0x0;
7597 keys[7] = 0x0;
7598
7599 if (!vms->curmsg) {
7600 /* No prev key, provide "Folder" instead */
7601 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7602 }
7603 if (vms->curmsg >= vms->lastmsg) {
7604 /* If last message ... */
7605 if (vms->curmsg) {
7606 /* but not only message, provide "Folder" instead */
7607 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
7608 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7609
7610 } else {
7611 /* Otherwise if only message, leave blank */
7612 keys[3] = 1;
7613 }
7614 }
7615
7616 if (!ast_strlen_zero(cid)) {
7617 ast_callerid_parse(cid, &name, &num);
7618 if (!name)
7619 name = num;
7620 } else {
7621 name = "Unknown Caller";
7622 }
7623
7624 /* If deleted, show "undeleted" */
7625#ifdef IMAP_STORAGE
7626 ast_mutex_lock(&vms->lock);
7627#endif
7628 if (vms->deleted[vms->curmsg]) {
7629 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
7630 }
7631#ifdef IMAP_STORAGE
7632 ast_mutex_unlock(&vms->lock);
7633#endif
7634
7635 /* Except "Exit" */
7636 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
7637 snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
7638 strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
7639 snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
7640
7641 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
7642 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
7643 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
7644 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
7645 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7646 bytes += ast_adsi_set_keys(buf + bytes, keys);
7647 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7648
7650}
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1063
static const char name[]
Definition: format_mp3.c:68
static struct ast_threadstorage buf2
static struct ast_threadstorage buf1
char curbox[80]
char fn[PATH_MAX]

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

◆ adsi_password()

static void adsi_password ( struct ast_channel chan)
static

Definition at line 7499 of file app_voicemail.c.

7500{
7501 unsigned char buf[256];
7502 int bytes = 0;
7503 unsigned char keys[8];
7504 int x;
7505 if (!ast_adsi_available(chan))
7506 return;
7507
7508 for (x = 0; x < 8; x++)
7509 keys[x] = 0;
7510 /* Set one key for next */
7511 keys[3] = ADSI_KEY_APPS + 3;
7512
7513 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7514 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
7515 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
7516 bytes += ast_adsi_set_keys(buf + bytes, keys);
7517 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7519}

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(), ast_adsi_voice_mode(), and buf.

Referenced by vm_authenticate().

◆ adsi_status()

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

Definition at line 7704 of file app_voicemail.c.

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

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(), buf, buf1, buf2, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

Referenced by vm_execmain().

◆ adsi_status2()

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

Definition at line 7751 of file app_voicemail.c.

7752{
7753 unsigned char buf[256] = "";
7754 char buf1[256] = "", buf2[256] = "";
7755 int bytes = 0;
7756 unsigned char keys[8];
7757 int x;
7758
7759 char *mess = (vms->lastmsg == 0) ? "message" : "messages";
7760
7761 if (!ast_adsi_available(chan))
7762 return;
7763
7764 /* Original command keys */
7765 for (x = 0; x < 6; x++)
7766 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
7767
7768 keys[6] = 0;
7769 keys[7] = 0;
7770
7771 if ((vms->lastmsg + 1) < 1)
7772 keys[0] = 0;
7773
7774 snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
7775 strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
7776
7777 if (vms->lastmsg + 1)
7778 snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
7779 else
7780 strcpy(buf2, "no messages.");
7781 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
7782 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
7783 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
7784 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7785 bytes += ast_adsi_set_keys(buf + bytes, keys);
7786
7787 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7788
7790
7791}

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(), buf, buf1, buf2, vm_state::curbox, and vm_state::lastmsg.

Referenced by vm_execmain().

◆ 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_gain

Provides handling for the play message envelope, call the person back, or reply to message.

Returns
zero on success, -1 on error.

Definition at line 16013 of file app_voicemail.c.

16014{
16015 int res = 0;
16016 char filename[PATH_MAX];
16017 struct ast_config *msg_cfg = NULL;
16018 const char *origtime, *context;
16019 char *name, *num;
16020 int retries = 0;
16021 char *cid;
16022 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
16023
16024 vms->starting = 0;
16025
16026 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
16027
16028 /* Retrieve info from VM attribute file */
16029 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
16030 RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
16031 msg_cfg = ast_config_load(filename, config_flags);
16032 DISPOSE(vms->curdir, vms->curmsg);
16033 if (!valid_config(msg_cfg)) {
16034 ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
16035 return 0;
16036 }
16037
16038 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
16039 ast_config_destroy(msg_cfg);
16040 return 0;
16041 }
16042
16043 cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
16044
16045 context = ast_variable_retrieve(msg_cfg, "message", "context");
16046 switch (option) {
16047 case 3: /* Play message envelope */
16048 if (!res) {
16049 res = play_message_datetime(chan, vmu, origtime, filename);
16050 }
16051 if (!res) {
16052 res = play_message_callerid(chan, vms, cid, context, 0, 1);
16053 }
16054
16055 res = 't';
16056 break;
16057
16058 case 2: /* Call back */
16059
16060 if (ast_strlen_zero(cid))
16061 break;
16062
16063 ast_callerid_parse(cid, &name, &num);
16064 while ((res > -1) && (res != 't')) {
16065 switch (res) {
16066 case '1':
16067 if (num) {
16068 /* Dial the CID number */
16069 res = dialout(chan, vmu, num, vmu->callback);
16070 if (res) {
16071 ast_config_destroy(msg_cfg);
16072 return 9;
16073 }
16074 } else {
16075 res = '2';
16076 }
16077 break;
16078
16079 case '2':
16080 /* Want to enter a different number, can only do this if there's a dialout context for this user */
16081 if (!ast_strlen_zero(vmu->dialout)) {
16082 res = dialout(chan, vmu, NULL, vmu->dialout);
16083 if (res) {
16084 ast_config_destroy(msg_cfg);
16085 return 9;
16086 }
16087 } else {
16088 ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
16089 res = ast_play_and_wait(chan, "vm-sorry");
16090 }
16091 ast_config_destroy(msg_cfg);
16092 return res;
16093 case '*':
16094 res = 't';
16095 break;
16096 case '3':
16097 case '4':
16098 case '5':
16099 case '6':
16100 case '7':
16101 case '8':
16102 case '9':
16103 case '0':
16104
16105 res = ast_play_and_wait(chan, "vm-sorry");
16106 retries++;
16107 break;
16108 default:
16109 if (num) {
16110 ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
16111 res = ast_play_and_wait(chan, "vm-num-i-have");
16112 if (!res)
16113 res = play_message_callerid(chan, vms, num, vmu->context, 1, 1);
16114 if (!res)
16115 res = ast_play_and_wait(chan, "vm-tocallnum");
16116 /* Only prompt for a caller-specified number if there is a dialout context specified */
16117 if (!ast_strlen_zero(vmu->dialout)) {
16118 if (!res)
16119 res = ast_play_and_wait(chan, "vm-calldiffnum");
16120 }
16121 } else {
16122 res = ast_play_and_wait(chan, "vm-nonumber");
16123 if (!ast_strlen_zero(vmu->dialout)) {
16124 if (!res)
16125 res = ast_play_and_wait(chan, "vm-toenternumber");
16126 }
16127 }
16128 if (!res) {
16129 res = ast_play_and_wait(chan, "vm-star-cancel");
16130 }
16131 if (!res) {
16132 res = ast_waitfordigit(chan, 6000);
16133 }
16134 if (!res) {
16135 retries++;
16136 if (retries > 3) {
16137 res = 't';
16138 }
16139 }
16140 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
16141 isprint(res) ? res : '?', isprint(res) ? res : '?');
16142 break;
16143
16144 }
16145 if (res == 't')
16146 res = 0;
16147 else if (res == '*')
16148 res = -1;
16149 }
16150 break;
16151
16152 case 1: /* Reply */
16153 /* Send reply directly to sender */
16154 if (ast_strlen_zero(cid))
16155 break;
16156
16157 ast_callerid_parse(cid, &name, &num);
16158 if (!num) {
16159 ast_verb(3, "No CID number available, no reply sent\n");
16160 if (!res)
16161 res = ast_play_and_wait(chan, "vm-nonumber");
16162 ast_config_destroy(msg_cfg);
16163 return res;
16164 } else {
16165 struct ast_vm_user vmu2, *vmu3;
16166 memset(&vmu2, 0, sizeof(vmu2));
16167 vmu3 = find_user(&vmu2, vmu->context, num);
16168 if (vmu3) {
16169 struct leave_vm_options leave_options;
16170 char mailbox[AST_MAX_EXTENSION * 2 + 2];
16171 snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
16172
16173 ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
16174
16175 memset(&leave_options, 0, sizeof(leave_options));
16176 leave_options.record_gain = record_gain;
16177 leave_options.beeptone = "beep";
16178 res = leave_voicemail(chan, mailbox, &leave_options);
16179 if (!res)
16180 res = 't';
16181 ast_config_destroy(msg_cfg);
16182 free_user(vmu3);
16183 return res;
16184 } else {
16185 /* Sender has no mailbox, can't reply */
16186 ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
16187 ast_play_and_wait(chan, "vm-nobox");
16188 res = 't';
16189 ast_config_destroy(msg_cfg);
16190 return res;
16191 }
16192 }
16193 res = 0;
16194
16195 break;
16196 }
16197
16198 ast_config_destroy(msg_cfg);
16199
16200#ifndef IMAP_STORAGE
16201 if (!res) {
16202 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
16203 vms->heard[msg] = 1;
16204 res = wait_file(chan, vms, vms->fn);
16205 }
16206#endif
16207 return res;
16208}
static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
Prompts the user and records a voicemail to a mailbox.
static int 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 valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
#define DISPOSE(a, b)
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
#define RETRIEVE(a, b, c, d)
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
#define AST_MAX_EXTENSION
Definition: channel.h:134
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:1616
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
@ CONFIG_FLAG_NOCACHE
#define ast_verb(level,...)
Structure used to handle boolean flags.
Definition: utils.h:199
char callback[80]
char dialout[80]
Options for leaving voicemail with the voicemail() application.
Definition: app_minivm.c:654
signed char record_gain
Definition: app_minivm.c:656
char curdir[PATH_MAX]
int * heard
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189

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, ast_vm_user::context, voicemailpwcheck::context, vm_state::curdir, vm_state::curmsg, dialout(), ast_vm_user::dialout, DISPOSE, find_user(), vm_state::fn, free_user(), vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, voicemailpwcheck::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().

◆ alias_mailbox_mapping_create()

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

Definition at line 14273 of file app_voicemail.c.

14274{
14275 struct alias_mailbox_mapping *mapping;
14276 size_t from_len = strlen(alias) + 1;
14277 size_t to_len = strlen(mailbox) + 1;
14278
14279 mapping = ao2_alloc(sizeof(*mapping) + from_len + to_len, NULL);
14280 if (!mapping) {
14281 return NULL;
14282 }
14283 mapping->alias = mapping->buf;
14284 mapping->mailbox = mapping->buf + from_len;
14285 ast_copy_string(mapping->alias, alias, from_len); /* Safe */
14286 ast_copy_string(mapping->mailbox, mailbox, to_len); /* Safe */
14287
14288 return mapping;
14289}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409

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

Referenced by load_aliases().

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

12872{
12873 /* Assumes lock is already held */
12874 char *tmp;
12875 char *stringp;
12876 char *s;
12877 struct ast_vm_user *vmu;
12878 char mailbox_full[MAX_VM_MAILBOX_LEN];
12879 int new = 0, old = 0, urgent = 0;
12880 char secretfn[PATH_MAX] = "";
12881
12882 tmp = ast_strdupa(data);
12883
12884 if (!(vmu = find_or_create(context, box)))
12885 return -1;
12886
12887 populate_defaults(vmu);
12888
12889 stringp = tmp;
12890 if ((s = strsep(&stringp, ","))) {
12891 if (!ast_strlen_zero(s) && s[0] == '*') {
12892 ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
12893 "\n\tmust be reset in voicemail.conf.\n", box);
12894 }
12895 /* assign password regardless of validity to prevent NULL password from being assigned */
12896 ast_copy_string(vmu->password, s, sizeof(vmu->password));
12897 }
12898 if (stringp && (s = strsep(&stringp, ","))) {
12899 ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
12900 }
12901 if (stringp && (s = strsep(&stringp, ","))) {
12902 vmu->email = ast_strdup(s);
12903 }
12904 if (stringp && (s = strsep(&stringp, ","))) {
12905 ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
12906 }
12907 if (stringp) {
12908 apply_options(vmu, stringp);
12909 }
12910
12911 switch (vmu->passwordlocation) {
12912 case OPT_PWLOC_SPOOLDIR:
12913 snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
12914 read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
12915 }
12916
12917 snprintf(mailbox_full, MAX_VM_MAILBOX_LEN, "%s%s%s",
12918 box,
12919 ast_strlen_zero(context) ? "" : "@",
12920 context);
12921
12922 inboxcount2(mailbox_full, &urgent, &new, &old);
12923#ifdef IMAP_STORAGE
12924 imap_logout(mailbox_full);
12925#endif
12926 queue_mwi_event(NULL, mailbox_full, urgent, new, old);
12927
12928 return 0;
12929}
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox's message count.
int passwordlocation

References apply_options(), ast_copy_string(), ast_log, ast_strdup, ast_strdupa, ast_strlen_zero(), ast_vm_user::context, voicemailpwcheck::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(), tmp(), and VM_SPOOL_DIR.

Referenced by load_users().

◆ append_vmbox_info_astman()

static int append_vmbox_info_astman ( struct mansession s,
const struct message m,
struct ast_vm_user vmu,
const char *  event_name,
const char *  actionid 
)
static

Append vmbox info string into given astman with event_name.

Returns
0 if unable to append details, 1 otherwise.

Definition at line 13812 of file app_voicemail.c.

13818{
13819 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
13820 struct ast_vm_msg_snapshot *msg;
13821 int nummessages = 0;
13822 int i;
13823
13824 /* Take a snapshot of the mailbox */
13825 mailbox_snapshot = ast_vm_mailbox_snapshot_create(vmu->mailbox, vmu->context, NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0);
13826 if (!mailbox_snapshot) {
13827 ast_log(LOG_ERROR, "Could not append voicemail box info for box %s@%s.",
13828 vmu->mailbox, vmu->context);
13829 return 0;
13830 }
13831
13832 astman_send_listack(s, m, "Voicemail box detail will follow", "start");
13833 /* walk through each folder's contents and append info for each message */
13834 for (i = 0; i < mailbox_snapshot->folders; i++) {
13835 AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) {
13836 astman_append(s,
13837 "Event: %s\r\n"
13838 "%s"
13839 "Folder: %s\r\n"
13840 "CallerID: %s\r\n"
13841 "Date: %s\r\n"
13842 "Duration: %s\r\n"
13843 "Flag: %s\r\n"
13844 "ID: %s\r\n"
13845 "\r\n",
13846 event_name,
13847 actionid,
13848 msg->folder_name,
13849 msg->callerid,
13850 msg->origdate,
13851 msg->duration,
13852 msg->flag,
13853 msg->msg_id
13854 );
13855 nummessages++;
13856 }
13857 }
13858
13859 /* done, destroy. */
13860 mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
13861 astman_send_list_complete_start(s, m, "VoicemailBoxDetailComplete", nummessages);
13863
13864 return 1;
13865}
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:3423
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:3459
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3467
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3302
@ AST_VM_SNAPSHOT_SORT_BY_ID
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
destroy a snapshot
Definition: main/app.c:675
struct ast_vm_mailbox_snapshot * ast_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)
Create a snapshot of a mailbox which contains information about every msg.
Definition: main/app.c:661
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct ast_vm_msg_snapshot::@184 msg

References AST_LIST_TRAVERSE, ast_log, ast_vm_mailbox_snapshot_create(), ast_vm_mailbox_snapshot_destroy(), AST_VM_SNAPSHOT_SORT_BY_ID, astman_append(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), ast_vm_user::context, ast_vm_mailbox_snapshot::folders, LOG_ERROR, ast_vm_user::mailbox, ast_vm_msg_snapshot::msg, and NULL.

Referenced by manager_get_mailbox_summary().

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

13694{
13695 int new;
13696 int old;
13697 char *mailbox;
13698 int ret;
13699
13700 if((s == NULL) || (vmu == NULL) || (event_name == NULL) || (actionid == NULL)) {
13701 ast_log(LOG_ERROR, "Wrong input parameter.");
13702 return 0;
13703 }
13704
13705 /* create mailbox string */
13706 if (!ast_strlen_zero(vmu->context)) {
13707 ret = ast_asprintf(&mailbox, "%s@%s", vmu->mailbox, vmu->context);
13708 } else {
13709 ret = ast_asprintf(&mailbox, "%s", vmu->mailbox);
13710 }
13711 if (ret == -1) {
13712 ast_log(LOG_ERROR, "Could not create mailbox string. err[%s]\n", strerror(errno));
13713 return 0;
13714 }
13715
13716 /* get mailbox count */
13717 ret = inboxcount(mailbox, &new, &old);
13719 if (ret == -1) {
13720 ast_log(LOG_ERROR, "Could not get mailbox count. user[%s], context[%s]\n",
13721 vmu->mailbox ?: "", vmu->context ?: "");
13722 return 0;
13723 }
13724
13725 astman_append(s,
13726 "Event: %s\r\n"
13727 "%s"
13728 "VMContext: %s\r\n"
13729 "VoiceMailbox: %s\r\n"
13730 "Fullname: %s\r\n"
13731 "Email: %s\r\n"
13732 "Pager: %s\r\n"
13733 "ServerEmail: %s\r\n"
13734 "FromString: %s\r\n"
13735 "MailCommand: %s\r\n"
13736 "Language: %s\r\n"
13737 "TimeZone: %s\r\n"
13738 "Callback: %s\r\n"
13739 "Dialout: %s\r\n"
13740 "UniqueID: %s\r\n"
13741 "ExitContext: %s\r\n"
13742 "SayDurationMinimum: %d\r\n"
13743 "SayEnvelope: %s\r\n"
13744 "SayCID: %s\r\n"
13745 "AttachMessage: %s\r\n"
13746 "AttachmentFormat: %s\r\n"
13747 "DeleteMessage: %s\r\n"
13748 "VolumeGain: %.2f\r\n"
13749 "CanReview: %s\r\n"
13750 "CanMarkUrgent: %s\r\n"
13751 "CallOperator: %s\r\n"
13752 "MaxMessageCount: %d\r\n"
13753 "MaxMessageLength: %d\r\n"
13754 "NewMessageCount: %d\r\n"
13755 "OldMessageCount: %d\r\n"
13756#ifdef IMAP_STORAGE
13757 "IMAPUser: %s\r\n"
13758 "IMAPServer: %s\r\n"
13759 "IMAPPort: %s\r\n"
13760 "IMAPFlags: %s\r\n"
13761#endif
13762 "\r\n",
13763
13764 event_name,
13765 actionid,
13766 vmu->context,
13767 vmu->mailbox,
13768 vmu->fullname,
13769 vmu->email,
13770 vmu->pager,
13773 mailcmd,
13774 vmu->language,
13775 vmu->zonetag,
13776 vmu->callback,
13777 vmu->dialout,
13778 vmu->uniqueid,
13779 vmu->exit,
13780 vmu->saydurationm,
13781 ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
13782 ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
13783 ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
13784 vmu->attachfmt,
13785 ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
13786 vmu->volgain,
13787 ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
13788 ast_test_flag(vmu, VM_MARK_URGENT) ? "Yes" : "No",
13789 ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
13790 vmu->maxmsg,
13791 vmu->maxsecs,
13792 new,
13793 old
13794#ifdef IMAP_STORAGE
13795 ,
13796 vmu->imapuser,
13797 vmu->imapserver,
13798 vmu->imapport,
13799 vmu->imapflags
13800#endif
13801 );
13802
13803 return 1;
13804
13805}
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
#define VM_DELETE
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
char exit[80]
char fromstring[100]
char uniqueid[80]
char serveremail[80]
char attachfmt[20]
#define ast_test_flag(p, flag)
Definition: utils.h:63

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, fromstring, ast_vm_user::fullname, inboxcount(), ast_vm_user::language, LOG_ERROR, ast_vm_user::mailbox, voicemailpwcheck::mailbox, mailcmd, ast_vm_user::maxmsg, ast_vm_user::maxsecs, NULL, ast_vm_user::pager, ast_vm_user::saydurationm, ast_vm_user::serveremail, serveremail, ast_vm_user::uniqueid, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_MARK_URGENT, 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().

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

1387{
1388 int x;
1389 if (!strcasecmp(var, "attach")) {
1391 } else if (!strcasecmp(var, "attachfmt")) {
1392 ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
1393 } else if (!strcasecmp(var, "attachextrecs")) {
1395 } else if (!strcasecmp(var, "serveremail")) {
1396 ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
1397 } else if (!strcasecmp(var, "fromstring")) {
1398 ast_copy_string(vmu->fromstring, value, sizeof(vmu->fromstring));
1399 } else if (!strcasecmp(var, "emailbody")) {
1400 ast_free(vmu->emailbody);
1402 } else if (!strcasecmp(var, "emailsubject")) {
1403 ast_free(vmu->emailsubject);
1405 } else if (!strcasecmp(var, "language")) {
1406 ast_copy_string(vmu->language, value, sizeof(vmu->language));
1407 } else if (!strcasecmp(var, "tz")) {
1408 ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
1409 } else if (!strcasecmp(var, "locale")) {
1410 ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
1411#ifdef IMAP_STORAGE
1412 } else if (!strcasecmp(var, "imapuser")) {
1413 ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
1414 vmu->imapversion = imapversion;
1415 } else if (!strcasecmp(var, "imapserver")) {
1416 ast_copy_string(vmu->imapserver, value, sizeof(vmu->imapserver));
1417 vmu->imapversion = imapversion;
1418 } else if (!strcasecmp(var, "imapport")) {
1419 ast_copy_string(vmu->imapport, value, sizeof(vmu->imapport));
1420 vmu->imapversion = imapversion;
1421 } else if (!strcasecmp(var, "imapflags")) {
1422 ast_copy_string(vmu->imapflags, value, sizeof(vmu->imapflags));
1423 vmu->imapversion = imapversion;
1424 } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
1425 ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
1426 vmu->imapversion = imapversion;
1427 } else if (!strcasecmp(var, "imapfolder")) {
1428 ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
1429 vmu->imapversion = imapversion;
1430 } else if (!strcasecmp(var, "imapvmshareid")) {
1431 ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
1432 vmu->imapversion = imapversion;
1433#endif
1434 } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
1436 } else if (!strcasecmp(var, "saycid")){
1438 } else if (!strcasecmp(var, "sendvoicemail")){
1440 } else if (!strcasecmp(var, "review")){
1442 } else if (!strcasecmp(var, "leaveurgent")){
1444 } else if (!strcasecmp(var, "tempgreetwarn")){
1446 } else if (!strcasecmp(var, "messagewrap")){
1448 } else if (!strcasecmp(var, "operator")) {
1450 } else if (!strcasecmp(var, "envelope")){
1452 } else if (!strcasecmp(var, "moveheard")){
1454 } else if (!strcasecmp(var, "sayduration")){
1456 } else if (!strcasecmp(var, "saydurationm")){
1457 if (sscanf(value, "%30d", &x) == 1) {
1458 vmu->saydurationm = x;
1459 } else {
1460 ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
1461 }
1462 } else if (!strcasecmp(var, "forcename")){
1464 } else if (!strcasecmp(var, "forcegreetings")){
1466 } else if (!strcasecmp(var, "callback")) {
1467 ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
1468 } else if (!strcasecmp(var, "dialout")) {
1469 ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
1470 } else if (!strcasecmp(var, "exitcontext")) {
1471 ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
1472 } else if (!strcasecmp(var, "minsecs")) {
1473 if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
1474 vmu->minsecs = x;
1475 } else {
1476 ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1477 vmu->minsecs = vmminsecs;
1478 }
1479 } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
1480 vmu->maxsecs = atoi(value);
1481 if (vmu->maxsecs <= 0) {
1482 ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
1483 vmu->maxsecs = vmmaxsecs;
1484 } else {
1485 vmu->maxsecs = atoi(value);
1486 }
1487 if (!strcasecmp(var, "maxmessage"))
1488 ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1489 } else if (!strcasecmp(var, "maxmsg")) {
1490 vmu->maxmsg = atoi(value);
1491 /* Accept maxmsg=0 (Greetings only voicemail) */
1492 if (vmu->maxmsg < 0) {
1493 ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
1494 vmu->maxmsg = MAXMSG;
1495 } else if (vmu->maxmsg > MAXMSGLIMIT) {
1496 ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
1497 vmu->maxmsg = MAXMSGLIMIT;
1498 }
1499 } else if (!strcasecmp(var, "nextaftercmd")) {
1501 } else if (!strcasecmp(var, "backupdeleted")) {
1502 if (sscanf(value, "%30d", &x) == 1)
1503 vmu->maxdeletedmsg = x;
1504 else if (ast_true(value))
1505 vmu->maxdeletedmsg = MAXMSG;
1506 else
1507 vmu->maxdeletedmsg = 0;
1508
1509 if (vmu->maxdeletedmsg < 0) {
1510 ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
1511 vmu->maxdeletedmsg = MAXMSG;
1512 } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
1513 ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
1515 }
1516 } else if (!strcasecmp(var, "volgain")) {
1517 sscanf(value, "%30lf", &vmu->volgain);
1518 } else if (!strcasecmp(var, "passwordlocation")) {
1519 if (!strcasecmp(value, "spooldir")) {
1521 } else {
1523 }
1524 } else if (!strcasecmp(var, "options")) {
1525 apply_options(vmu, value);
1526 }
1527}
#define VM_EMAIL_EXT_RECS
char * emailbody
char * emailsubject
int value
Definition: syslog.c:37

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(), value, var, VM_ATTACH, VM_DELETE, VM_EMAIL_EXT_RECS, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MARK_URGENT, 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().

◆ apply_options()

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

Destructively Parse options and apply.

Definition at line 1645 of file app_voicemail.c.

1646{
1647 char *stringp;
1648 char *s;
1649 char *var, *value;
1650 stringp = ast_strdupa(options);
1651 while ((s = strsep(&stringp, "|"))) {
1652 value = s;
1653 if ((var = strsep(&value, "=")) && value) {
1654 apply_option(vmu, var, value);
1655 }
1656 }
1657}
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a specific property value.
static struct test_options options

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

Referenced by append_mailbox(), and apply_option().

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

1665{
1666 for (; var; var = var->next) {
1667 if (!strcasecmp(var->name, "vmsecret")) {
1668 ast_copy_string(retval->password, var->value, sizeof(retval->password));
1669 } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
1670 if (ast_strlen_zero(retval->password)) {
1671 if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
1672 ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
1673 "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
1674 } else {
1675 ast_copy_string(retval->password, var->value, sizeof(retval->password));
1676 }
1677 }
1678 } else if (!strcasecmp(var->name, "uniqueid")) {
1679 ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
1680 } else if (!strcasecmp(var->name, "pager")) {
1681 ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
1682 } else if (!strcasecmp(var->name, "email")) {
1683 ast_free(retval->email);
1684 retval->email = ast_strdup(var->value);
1685 } else if (!strcasecmp(var->name, "fullname")) {
1686 ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
1687 } else if (!strcasecmp(var->name, "context")) {
1688 ast_copy_string(retval->context, var->value, sizeof(retval->context));
1689 } else if (!strcasecmp(var->name, "emailsubject")) {
1690 ast_free(retval->emailsubject);
1691 retval->emailsubject = ast_strdup(substitute_escapes(var->value));
1692 } else if (!strcasecmp(var->name, "emailbody")) {
1693 ast_free(retval->emailbody);
1694 retval->emailbody = ast_strdup(substitute_escapes(var->value));
1695#ifdef IMAP_STORAGE
1696 } else if (!strcasecmp(var->name, "imapuser")) {
1697 ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
1698 retval->imapversion = imapversion;
1699 } else if (!strcasecmp(var->name, "imapserver")) {
1700 ast_copy_string(retval->imapserver, var->value, sizeof(retval->imapserver));
1701 retval->imapversion = imapversion;
1702 } else if (!strcasecmp(var->name, "imapport")) {
1703 ast_copy_string(retval->imapport, var->value, sizeof(retval->imapport));
1704 retval->imapversion = imapversion;
1705 } else if (!strcasecmp(var->name, "imapflags")) {
1706 ast_copy_string(retval->imapflags, var->value, sizeof(retval->imapflags));
1707 retval->imapversion = imapversion;
1708 } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
1709 ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
1710 retval->imapversion = imapversion;
1711 } else if (!strcasecmp(var->name, "imapfolder")) {
1712 ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
1713 retval->imapversion = imapversion;
1714 } else if (!strcasecmp(var->name, "imapvmshareid")) {
1715 ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
1716 retval->imapversion = imapversion;
1717#endif
1718 } else
1719 apply_option(retval, var->name, var->value);
1720 }
1721}
static ENTRY retval
Definition: hsearch.c:50

References apply_option(), ast_copy_string(), ast_free, ast_log, ast_strdup, ast_strlen_zero(), LOG_WARNING, retval, substitute_escapes(), and var.

Referenced by actual_load_config(), and find_user_realtime().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

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

5026{
5027 struct ast_str *tmp = ast_str_alloca(80);
5028 int first_section = 1;
5029
5031 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
5032 for (; *start; start++) {
5033 int need_encoding = 0;
5034 if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
5035 need_encoding = 1;
5036 }
5037 if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
5038 (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
5039 (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
5040 (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
5041 /* Start new line */
5042 ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
5043 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
5044 first_section = 0;
5045 }
5046 if (need_encoding && *start == ' ') {
5047 ast_str_append(&tmp, -1, "_");
5048 } else if (need_encoding) {
5049 ast_str_append(&tmp, -1, "=%hhX", *start);
5050 } else {
5051 ast_str_append(&tmp, -1, "%c", *start);
5052 }
5053 }
5054 ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
5055 return ast_str_buffer(*end);
5056}
char * end
Definition: eagi_proxy.c:73
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:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_alloca(init_len)
Definition: strings.h:848
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:693
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:1113
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
Support for dynamic strings.
Definition: strings.h:623

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

Referenced by make_email_file(), and sendpage().

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

4954{
4955 const char *ptr;
4956
4957 /* We're only ever passing 0 to maxlen, so short output isn't possible */
4958 ast_str_set(buf, maxlen, "\"");
4959 for (ptr = from; *ptr; ptr++) {
4960 if (*ptr == '"' || *ptr == '\\') {
4961 ast_str_append(buf, maxlen, "\\%c", *ptr);
4962 } else {
4963 ast_str_append(buf, maxlen, "%c", *ptr);
4964 }
4965 }
4966 ast_str_append(buf, maxlen, "\"");
4967
4968 return ast_str_buffer(*buf);
4969}

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

Referenced by make_email_file(), and sendpage().

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

1624{
1625 int res = -1;
1626 if (!strcmp(vmu->password, password)) {
1627 /* No change (but an update would return 0 rows updated, so we opt out here) */
1628 return 0;
1629 }
1630
1631 if (strlen(password) > 10) {
1632 ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
1633 }
1634 if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
1635 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
1636 ast_copy_string(vmu->password, password, sizeof(vmu->password));
1637 res = 0;
1638 }
1639 return res;
1640}
#define SENTINEL
Definition: compiler.h:87
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3695
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: main/config.c:3549

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

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

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

References str.

Referenced by make_email_file(), and sendpage().

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

1583{
1584 /* check minimum length */
1585 if (strlen(password) < minpassword)
1586 return 1;
1587 /* check that password does not contain '*' character */
1588 if (!ast_strlen_zero(password) && password[0] == '*')
1589 return 1;
1591 char cmd[255], buf[255];
1592
1593 ast_debug(1, "Verify password policies for %s\n", password);
1594
1595 snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
1596 if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
1597 ast_debug(5, "Result: %s\n", buf);
1598 if (!strncasecmp(buf, "VALID", 5)) {
1599 ast_debug(3, "Passed password check: '%s'\n", buf);
1600 return 0;
1601 } else if (!strncasecmp(buf, "FAILURE", 7)) {
1602 ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
1603 return 0;
1604 } else {
1605 ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
1606 return 1;
1607 }
1608 }
1609 }
1610 return 0;
1611}
static char * vm_check_password_shell(char *command, char *buf, size_t len)
#define AST_LOG_NOTICE

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

Referenced by vm_newuser_setup(), and vm_options().

◆ close_mailbox()

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

Definition at line 9158 of file app_voicemail.c.

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

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_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

◆ complete_voicemail_move_message()

static char * complete_voicemail_move_message ( struct ast_cli_args a,
int  maxpos 
)
static

Definition at line 11769 of file app_voicemail.c.

11770{
11771 const char *word = a->word;
11772 int pos = a->pos;
11773 int state = a->n;
11774 int which = 0;
11775 int wordlen;
11776 struct ast_vm_user *vmu;
11777 const char *context = "", *mailbox = "", *folder = "", *id = "";
11778 char *ret = NULL;
11779
11780 if (pos > maxpos) {
11781 /* If the passed in pos is above the max, return NULL to avoid 'over-filling' the cli */
11782 return NULL;
11783 }
11784
11785 /* if we are in pos 2 or pos 6 in 'forward' mode */
11786 if (pos == 2 || (pos == 6 && maxpos == 8)) {
11787 /* find users */
11788 wordlen = strlen(word);
11790 AST_LIST_TRAVERSE(&users, vmu, list) {
11791 if (!strncasecmp(word, vmu->mailbox , wordlen)) {
11792 if (mailbox && strcmp(mailbox, vmu->mailbox) && ++which > state) {
11793 ret = ast_strdup(vmu->mailbox);
11795 return ret;
11796 }
11797 mailbox = vmu->mailbox;
11798 }
11799 }
11801 } else if (pos == 3 || pos == 7) {
11802 /* find contexts that match the user */
11803 mailbox = (pos == 3) ? a->argv[2] : a->argv[6];
11804 wordlen = strlen(word);
11806 AST_LIST_TRAVERSE(&users, vmu, list) {
11807 if (!strncasecmp(word, vmu->context, wordlen) && !strcasecmp(mailbox, vmu->mailbox)) {
11808 if (context && strcmp(context, vmu->context) && ++which > state) {
11809 ret = ast_strdup(vmu->context);
11811 return ret;
11812 }
11813 context = vmu->context;
11814 }
11815 }
11817 } else if (pos == 4 || pos == 8 || (pos == 6 && maxpos == 6) ) {
11818 int i;
11819 /* Walk through the standard folders */
11820 wordlen = strlen(word);
11821 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
11822 if (folder && !strncasecmp(word, mailbox_folders[i], wordlen) && ++which > state) {
11823 return ast_strdup(mailbox_folders[i]);
11824 }
11825 folder = mailbox_folders[i];
11826 }
11827 } else if (pos == 5) {
11828 /* find messages in the folder */
11829 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
11830 struct ast_vm_msg_snapshot *msg;
11831 mailbox = a->argv[2];
11832 context = a->argv[3];
11833 folder = a->argv[4];
11834 wordlen = strlen(word);
11835
11836 /* Take a snapshot of the mailbox and snag the individual info */
11837 if ((mailbox_snapshot = ast_vm_mailbox_snapshot_create(mailbox, context, folder, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0))) {
11838 int i;
11839 /* we are only requesting the one folder, but we still need to know it's index */
11840 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
11841 if (!strcasecmp(mailbox_folders[i], folder)) {
11842 break;
11843 }
11844 }
11845 AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) {
11846 if (id && !strncasecmp(word, msg->msg_id, wordlen) && ++which > state) {
11847 ret = ast_strdup(msg->msg_id);
11848 break;
11849 }
11850 id = msg->msg_id;
11851 }
11852 /* done, destroy. */
11853 mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
11854 }
11855 }
11856
11857 return ret;
11858}
static const char *const mailbox_folders[]
enum cc_state state
Definition: ccss.c:393
short word
struct ast_vm_user::@82 list
static struct test_val a
#define ARRAY_LEN(a)
Definition: utils.h:666

References a, ARRAY_LEN, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_vm_mailbox_snapshot_create(), ast_vm_mailbox_snapshot_destroy(), AST_VM_SNAPSHOT_SORT_BY_ID, ast_vm_user::context, voicemailpwcheck::context, ast_vm_user::list, ast_vm_user::mailbox, voicemailpwcheck::mailbox, mailbox_folders, ast_vm_msg_snapshot::msg, NULL, and state.

Referenced by handle_voicemail_forward_message(), handle_voicemail_move_message(), and handle_voicemail_remove_message().

◆ complete_voicemail_show_mailbox()

static char * complete_voicemail_show_mailbox ( struct ast_cli_args a)
static

Definition at line 11679 of file app_voicemail.c.

11680{
11681 const char *word = a->word;
11682 int pos = a->pos;
11683 int state = a->n;
11684 int which = 0;
11685 int wordlen;
11686 struct ast_vm_user *vmu;
11687 const char *context = "", *mailbox = "";
11688 char *ret = NULL;
11689
11690 /* 0 - voicemail; 1 - show; 2 - mailbox; 3 - <mailbox>; 4 - <context> */
11691 if (pos == 3) {
11692 wordlen = strlen(word);
11694 AST_LIST_TRAVERSE(&users, vmu, list) {
11695 if (!strncasecmp(word, vmu->mailbox , wordlen)) {
11696 if (mailbox && strcmp(mailbox, vmu->mailbox) && ++which > state) {
11697 ret = ast_strdup(vmu->mailbox);
11699 return ret;
11700 }
11701 mailbox = vmu->mailbox;
11702 }
11703 }
11705 } else if (pos == 4) {
11706 /* Only display contexts that match the user in pos 3 */
11707 const char *box = a->argv[3];
11708 wordlen = strlen(word);
11710 AST_LIST_TRAVERSE(&users, vmu, list) {
11711 if (!strncasecmp(word, vmu->context, wordlen) && !strcasecmp(box, vmu->mailbox)) {
11712 if (context && strcmp(context, vmu->context) && ++which > state) {
11713 ret = ast_strdup(vmu->context);
11715 return ret;
11716 }
11717 context = vmu->context;
11718 }
11719 }
11721 }
11722
11723 return ret;
11724}

References a, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_vm_user::context, voicemailpwcheck::context, ast_vm_user::list, ast_vm_user::mailbox, voicemailpwcheck::mailbox, and NULL.

Referenced by handle_voicemail_show_mailbox().

◆ complete_voicemail_show_users()

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

Definition at line 13296 of file app_voicemail.c.

13297{
13298 int which = 0;
13299 int wordlen;
13300 struct ast_vm_user *vmu;
13301 const char *context = "";
13302 char *ret;
13303
13304 /* 0 - voicemail; 1 - show; 2 - users; 3 - for; 4 - <context> */
13305 if (pos > 4)
13306 return NULL;
13307 wordlen = strlen(word);
13309 AST_LIST_TRAVERSE(&users, vmu, list) {
13310 if (!strncasecmp(word, vmu->context, wordlen)) {
13311 if (context && strcmp(context, vmu->context) && ++which > state) {
13312 ret = ast_strdup(vmu->context);
13314 return ret;
13315 }
13316 /* ignore repeated contexts ? */
13317 context = vmu->context;
13318 }
13319 }
13321 return NULL;
13322}

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_vm_user::context, voicemailpwcheck::context, ast_vm_user::list, and NULL.

Referenced by handle_voicemail_show_users().

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

4756{
4757 int ifd;
4758 int ofd;
4759 int res = -1;
4760 int len;
4761 char buf[4096];
4762
4763#ifdef HARDLINK_WHEN_POSSIBLE
4764 /* Hard link if possible; saves disk space & is faster */
4765 if (!link(infile, outfile)) {
4766 return 0;
4767 }
4768#endif
4769
4770 if ((ifd = open(infile, O_RDONLY)) < 0) {
4771 ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
4772 return -1;
4773 }
4774
4775 if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
4776 ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
4777 close(ifd);
4778 return -1;
4779 }
4780
4781 for (;;) {
4782 int wrlen;
4783
4784 len = read(ifd, buf, sizeof(buf));
4785 if (!len) {
4786 res = 0;
4787 break;
4788 }
4789
4790 if (len < 0) {
4791 ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
4792 break;
4793 }
4794
4795 wrlen = write(ofd, buf, len);
4796 if (errno == ENOMEM || errno == ENOSPC || wrlen != len) {
4797 ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, wrlen, len, strerror(errno));
4798 break;
4799 }
4800 }
4801
4802 close(ifd);
4803 close(ofd);
4804 if (res) {
4805 unlink(outfile);
4806 }
4807
4808 return res;
4809}
#define VOICEMAIL_FILE_MODE

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

Referenced by __bt_ret(), ast_ari_asterisk_update_object(), ast_bucket_file_copy(), 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(), handle_cli_transcoder_show(), handle_updates(), iax2_register(), module_load_error(), parse_hint_device(), parse_hint_presence(), process_dahdi(), reload_followme(), and vm_forwardoptions().

◆ 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_folder

This is only used by file storage based mailboxes.

Returns
zero on success, -1 on error.

Definition at line 5978 of file app_voicemail.c.

5979{
5980 char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
5981 const char *frombox = mbox(vmu, imbox);
5982 const char *userfolder;
5983 int recipmsgnum;
5984 int res = 0;
5985
5986 ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
5987
5988 if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
5989 userfolder = "Urgent";
5990 } else if (!ast_strlen_zero(dest_folder)) {
5991 userfolder = dest_folder;
5992 } else {
5993 userfolder = "INBOX";
5994 }
5995
5996 create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
5997
5998 if (!dir)
5999 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
6000 else
6001 ast_copy_string(fromdir, dir, sizeof(fromdir));
6002
6003 make_file(frompath, sizeof(frompath), fromdir, msgnum);
6004 make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
6005
6006 if (vm_lock_path(todir))
6007 return ERROR_LOCK_PATH;
6008
6009 recipmsgnum = last_message_index(todir) + 1;
6010 if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
6011 make_file(topath, sizeof(topath), todir, recipmsgnum);
6012#ifndef ODBC_STORAGE
6013 if (EXISTS(fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : "")) {
6014 COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
6015 } else {
6016#endif
6017 /* If we are prepending a message for ODBC, then the message already
6018 * exists in the database, but we want to force copying from the
6019 * filesystem (since only the FS contains the prepend). */
6020 copy_plain_file(frompath, topath);
6021 STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL);
6022 vm_delete(topath);
6023#ifndef ODBC_STORAGE
6024 }
6025#endif
6026 } else {
6027 ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
6028 res = -1;
6029 }
6030 ast_unlock_path(todir);
6031 if (chan) {
6032 struct ast_party_caller *caller = ast_channel_caller(chan);
6033 notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
6034 S_COR(caller->id.number.valid, caller->id.number.str, NULL),
6035 S_COR(caller->id.name.valid, caller->id.name.str, NULL),
6036 flag);
6037 }
6038
6039 return res;
6040}
static int vm_delete(char *file)
Removes the voicemail sound and information file.
#define COPY(a, b, c, d, e, f, g, h)
static int inprocess_count(const char *context, const char *mailbox, int delta)
static int make_dir(char *dest, int len, const char *context, const char *ext, const char *folder)
Creates a file system path expression for a folder within the voicemail data folder and the appropria...
static void copy_plain_file(char *frompath, char *topath)
Copies a voicemail information (envelope) file.
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
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.
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
long int flag
Definition: f2c.h:83
#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:87
Caller Party information.
Definition: channel.h:418
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
char * str
Subscriber name (Malloced)
Definition: channel.h:264
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291

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(), maxmsg, 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(), and vm_msg_forward().

◆ copy_plain_file()

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

Copies a voicemail information (envelope) file.

Parameters
frompath
topath

Every voicemail has the data (.wav) file, and the information file. This function performs the file system copying of the information file for a voicemail, handling the internal fields and their values. This is used by the COPY macro when not using IMAP storage.

Definition at line 4820 of file app_voicemail.c.

4821{
4822 char frompath2[PATH_MAX], topath2[PATH_MAX];
4823 struct ast_variable *tmp, *var = NULL;
4824 const char *origmailbox = "", *context = "", *exten = "";
4825 const char *priority = "", *callerchan = "", *callerid = "", *origdate = "";
4826 const char *origtime = "", *category = "", *duration = "";
4827
4828 ast_filecopy(frompath, topath, NULL);
4829 snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
4830 snprintf(topath2, sizeof(topath2), "%s.txt", topath);
4831
4832 if (ast_check_realtime("voicemail_data")) {
4833 var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
4834 /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
4835 for (tmp = var; tmp; tmp = tmp->next) {
4836 if (!strcasecmp(tmp->name, "origmailbox")) {
4837 origmailbox = tmp->value;
4838 } else if (!strcasecmp(tmp->name, "context")) {
4839 context = tmp->value;
4840 } else if (!strcasecmp(tmp->name, "exten")) {
4841 exten = tmp->value;
4842 } else if (!strcasecmp(tmp->name, "priority")) {
4843 priority = tmp->value;
4844 } else if (!strcasecmp(tmp->name, "callerchan")) {
4845 callerchan = tmp->value;
4846 } else if (!strcasecmp(tmp->name, "callerid")) {
4847 callerid = tmp->value;
4848 } else if (!strcasecmp(tmp->name, "origdate")) {
4849 origdate = tmp->value;
4850 } else if (!strcasecmp(tmp->name, "origtime")) {
4851 origtime = tmp->value;
4852 } else if (!strcasecmp(tmp->name, "category")) {
4853 category = tmp->value;
4854 } else if (!strcasecmp(tmp->name, "duration")) {
4855 duration = tmp->value;
4856 }
4857 }
4858 ast_store_realtime("voicemail_data", "filename", topath, "origmailbox", origmailbox, "context", context, "exten", exten, "priority", priority, "callerchan", callerchan, "callerid", callerid, "origdate", origdate, "origtime", origtime, "category", category, "duration", duration, SENTINEL);
4859 }
4860 copy(frompath2, topath2);
4862}
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static int priority
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:1151
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
Definition: main/config.c:3740
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3506

References ast_check_realtime(), ast_filecopy(), ast_load_realtime(), ast_store_realtime(), ast_variables_destroy(), voicemailpwcheck::context, copy(), NULL, PATH_MAX, priority, SENTINEL, tmp(), and var.

Referenced by copy_message().

◆ 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
dir

This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP).

Returns
the count of messages, zero or more.

Definition at line 4655 of file app_voicemail.c.

4656{
4657
4658 int vmcount = 0;
4659 DIR *vmdir = NULL;
4660 struct dirent *vment = NULL;
4661
4662 if (vm_lock_path(dir))
4663 return ERROR_LOCK_PATH;
4664
4665 if ((vmdir = opendir(dir))) {
4666 while ((vment = readdir(vmdir))) {
4667 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
4668 vmcount++;
4669 }
4670 }
4671 closedir(vmdir);
4672 }
4673 ast_unlock_path(dir);
4674
4675 return vmcount;
4676}

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

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

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

2081{
2082 mode_t mode = VOICEMAIL_DIR_MODE;
2083 int res;
2084
2085 make_dir(dest, len, context, ext, folder);
2086 if ((res = ast_mkdir(dest, mode))) {
2087 ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
2088 return -1;
2089 }
2090 return 0;
2091}
#define VOICEMAIL_DIR_MODE
const char * ext
Definition: http.c:150
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2479

References ast_log, AST_LOG_WARNING, ast_mkdir(), voicemailpwcheck::context, ext, len(), make_dir(), and VOICEMAIL_DIR_MODE.

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

◆ dialout()

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

Definition at line 15941 of file app_voicemail.c.

15942{
15943 int cmd = 0;
15944 char destination[80] = "";
15945 int retries = 0;
15946
15947 if (!num) {
15948 ast_verb(3, "Destination number will be entered manually\n");
15949 while (retries < 3 && cmd != 't') {
15950 destination[1] = '\0';
15951 destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
15952 if (!cmd)
15953 destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
15954 if (!cmd)
15955 destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
15956 if (!cmd) {
15957 cmd = ast_waitfordigit(chan, 6000);
15958 if (cmd)
15959 destination[0] = cmd;
15960 }
15961 if (!cmd) {
15962 retries++;
15963 } else {
15964
15965 if (cmd < 0)
15966 return 0;
15967 if (cmd == '*') {
15968 ast_verb(3, "User hit '*' to cancel outgoing call\n");
15969 return 0;
15970 }
15971 if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0)
15972 retries++;
15973 else
15974 cmd = 't';
15975 }
15976 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
15977 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
15978 }
15979 if (retries >= 3) {
15980 return 0;
15981 }
15982
15983 } else {
15984 ast_verb(3, "Destination number is CID number '%s'\n", num);
15985 ast_copy_string(destination, num, sizeof(destination));
15986 }
15987
15988 if (!ast_strlen_zero(destination)) {
15989 if (destination[strlen(destination) -1 ] == '*')
15990 return 0;
15991 ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, ast_channel_context(chan));
15992 ast_channel_exten_set(chan, destination);
15993 ast_channel_context_set(chan, outgoing_context);
15994 ast_channel_priority_set(chan, 0);
15995 return 9;
15996 }
15997 return 0;
15998}
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_context(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6558

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

◆ find_or_create()

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

Definition at line 12831 of file app_voicemail.c.

12832{
12833 struct ast_vm_user *vmu;
12834
12835 if (!ast_strlen_zero(box) && box[0] == '*') {
12836 ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character. The '*' character,"
12837 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
12838 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
12839 "\n\tand will be ignored.\n", box, context);
12840 return NULL;
12841 }
12842
12843 AST_LIST_TRAVERSE(&users, vmu, list) {
12844 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
12845 if (strcasecmp(vmu->context, context)) {
12846 ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
12847 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
12848 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
12849 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
12850 }
12851 ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
12852 return NULL;
12853 }
12854 if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
12855 ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
12856 return NULL;
12857 }
12858 }
12859
12860 if (!(vmu = ast_calloc(1, sizeof(*vmu))))
12861 return NULL;
12862
12863 ast_copy_string(vmu->context, context, sizeof(vmu->context));
12864 ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
12865
12867
12868 return vmu;
12869}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731

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, voicemailpwcheck::context, globalflags, ast_vm_user::list, LOG_WARNING, ast_vm_user::mailbox, NULL, and VM_SEARCH.

Referenced by actual_load_config(), and append_mailbox().

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

1797{
1798 /* This function could be made to generate one from a database, too */
1799 struct ast_vm_user *vmu = NULL, *cur;
1801
1803 context = "default";
1804
1805 AST_LIST_TRAVERSE(&users, cur, list) {
1806#ifdef IMAP_STORAGE
1807 if (cur->imapversion != imapversion) {
1808 continue;
1809 }
1810#endif
1811 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
1812 break;
1813 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1814 break;
1815 }
1816 if (cur) {
1817 /* Make a copy, so that on a reload, we have no race */
1818 if ((vmu = (ivm ? ivm : ast_calloc(1, sizeof(*vmu))))) {
1819 ast_free(vmu->email);
1820 ast_free(vmu->emailbody);
1821 ast_free(vmu->emailsubject);
1822 *vmu = *cur;
1823 vmu->email = ast_strdup(cur->email);
1824 vmu->emailbody = ast_strdup(cur->emailbody);
1825 vmu->emailsubject = ast_strdup(cur->emailsubject);
1826 ast_set2_flag(vmu, !ivm, VM_ALLOCED);
1827 AST_LIST_NEXT(vmu, list) = NULL;
1828 }
1829 }
1831 if (!vmu) {
1832 vmu = find_user_realtime(ivm, context, mailbox);
1833 }
1834 if (!vmu && !ast_strlen_zero(aliasescontext)) {
1835 struct alias_mailbox_mapping *mapping;
1836 char *search_string = ast_alloca(MAX_VM_MAILBOX_LEN);
1837
1838 snprintf(search_string, MAX_VM_MAILBOX_LEN, "%s%s%s",
1839 mailbox,
1840 ast_strlen_zero(context) ? "" : "@",
1841 S_OR(context, ""));
1842
1843 mapping = ao2_find(alias_mailbox_mappings, search_string, OBJ_SEARCH_KEY);
1844 if (mapping) {
1845 char *search_mailbox = NULL;
1846 char *search_context = NULL;
1847
1848 separate_mailbox(ast_strdupa(mapping->mailbox), &search_mailbox, &search_context);
1849 ao2_ref(mapping, -1);
1850 vmu = find_user(ivm, search_mailbox, search_context);
1851 }
1852 }
1853
1854 return vmu;
1855}
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.
#define VM_ALLOCED
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439

References alias_mailbox_mappings, aliasescontext, 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, voicemailpwcheck::context, ast_vm_user::email, ast_vm_user::emailbody, ast_vm_user::emailsubject, find_user(), find_user_realtime(), globalflags, ast_vm_user::list, alias_mailbox_mapping::mailbox, voicemailpwcheck::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(), find_user(), forward_message(), leave_voicemail(), manager_get_mailbox_summary(), manager_status_voicemail_user(), msg_create_from_file(), play_message_by_id(), show_mailbox_details(), vm_authenticate(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

◆ 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
mailbox

This is called as a fall through case when the normal find_user() was not able to find a user. That is, the default it so look in the usual voicemail users file first.

Returns
The ast_vm_user structure for the user that was found.

Definition at line 1755 of file app_voicemail.c.

1756{
1757 struct ast_variable *var;
1758 struct ast_vm_user *retval;
1759
1760 if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
1761 if (ivm) {
1762 memset(retval, 0, sizeof(*retval));
1763 }
1765 if (!ivm) {
1767 }
1768 if (mailbox) {
1769 ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
1770 }
1772 var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
1773 } else {
1774 var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
1775 }
1776 if (var) {
1779 } else {
1780 if (!ivm)
1782 retval = NULL;
1783 }
1784 }
1785 return retval;
1786}
#define ast_set_flag(p, flag)
Definition: utils.h:70

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

Referenced by find_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
urgent

Reads the destination mailbox(es) from keypad input for CID, or if use_directory feature is enabled, the Directory.

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

  • allow the leaving of a message for ourselves. (Will not allow us to forward a message to ourselves, when is_new_message == 0).
  • attempt to determine the context and 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 8277 of file app_voicemail.c.

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

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, voicemailpwcheck::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, done, find_user(), vm_state::fn, free_user(), globalflags, inboxcount(), inprocess_count(), leave_voicemail(), LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, voicemailpwcheck::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_DIRECTFORWARD, vm_forwardoptions(), VM_FWDURGAUTO, VM_SPOOL_DIR, and vmfmts.

Referenced by vm_execmain().

◆ forward_message_from_mailbox()

static int forward_message_from_mailbox ( struct ast_cli_args a)
static

Definition at line 11624 of file app_voicemail.c.

11625{
11626 const char *from_mailbox = a->argv[2];
11627 const char *from_context = a->argv[3];
11628 const char *from_folder = a->argv[4];
11629 const char *id[] = { a->argv[5] };
11630 const char *to_mailbox = a->argv[6];
11631 const char *to_context = a->argv[7];
11632 const char *to_folder = a->argv[8];
11633 int ret = vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0);
11634 if (ret) {
11635 ast_cli(a->fd, "Error forwarding message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
11636 id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
11637 } else {
11638 ast_cli(a->fd, "Forwarded message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
11639 id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
11640 }
11641 return ret;
11642}
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)
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
def from_mailbox(key, val, section, pjsip, nmapped)

References a, ast_cli(), sip_to_pjsip::from_mailbox(), and vm_msg_forward().

Referenced by handle_voicemail_forward_message().

◆ free_user()

static void free_user ( struct ast_vm_user vmu)
static

◆ free_user_final()

static void free_user_final ( struct ast_vm_user vmu)
static

Definition at line 2140 of file app_voicemail.c.

2141{
2142 if (!vmu) {
2143 return;
2144 }
2145
2146 if (!ast_strlen_zero(vmu->mailbox)) {
2148 }
2149
2150 free_user(vmu);
2151}
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:404

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

◆ free_vm_users()

static void free_vm_users ( void  )
static

Free the users structure.

Definition at line 14150 of file app_voicemail.c.

14151{
14152 struct ast_vm_user *current;
14154 while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
14157 }
14159}
static void free_user_final(struct ast_vm_user *vmu)

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

Referenced by actual_load_config(), and unload_module().

◆ free_vm_zones()

static void free_vm_zones ( void  )
static

Free the zones structure.

Definition at line 14162 of file app_voicemail.c.

14163{
14164 struct vm_zone *zcur;
14166 while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
14167 free_zone(zcur);
14169}
static void free_zone(struct vm_zone *z)
struct vm_zone::@83 list

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

◆ free_zone()

static void free_zone ( struct vm_zone z)
static

Definition at line 5766 of file app_voicemail.c.

5767{
5768 ast_free(z);
5769}

References ast_free.

Referenced by free_vm_zones().

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

6288{
6289 /* msg id is time of msg_id generation plus an incrementing value
6290 * called each time a new msg_id is generated. This should achieve uniqueness,
6291 * but only in single system solutions.
6292 */
6293 unsigned int unique_counter = ast_atomic_fetchadd_int(&msg_id_incrementor, +1);
6294 snprintf(dst, MSG_ID_LEN, "%ld-%08x", (long) time(NULL), unique_counter);
6295}
static int msg_id_incrementor
#define MSG_ID_LEN
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:757

References ast_atomic_fetchadd_int(), msg_id_incrementor, MSG_ID_LEN, and NULL.

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

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

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

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

Referenced by leave_voicemail(), and msg_create_from_file().

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

7828{
7829 int x;
7830 int d;
7831 char fn[PATH_MAX];
7832 d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
7833 if (d)
7834 return d;
7835 for (x = start; x < 5; x++) { /* For all folders */
7836 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
7837 return d;
7838 d = ast_play_and_wait(chan, "vm-for"); /* "for" */
7839 if (d)
7840 return d;
7841 snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
7842
7843 /* The inbox folder can have its name changed under certain conditions
7844 * so this checks if the sound file exists for the inbox folder name and
7845 * if it doesn't, plays the default name instead. */
7846 if (x == 0) {
7847 if (ast_fileexists(fn, NULL, NULL)) {
7848 d = vm_play_folder_name(chan, fn);
7849 } else {
7850 ast_verb(4, "Failed to find file %s; falling back to INBOX\n", fn);
7851 d = vm_play_folder_name(chan, "vm-INBOX");
7852 }
7853 } else {
7854 ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
7855 d = vm_play_folder_name(chan, fn);
7856 }
7857
7858 if (d)
7859 return d;
7860 d = ast_waitfordigit(chan, 500);
7861 if (d)
7862 return d;
7863 }
7864
7865 d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
7866 if (d)
7867 return d;
7868 d = ast_waitfordigit(chan, 4000);
7869 return d;
7870}
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define AST_DIGIT_ANY
Definition: file.h:48
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:8235
static struct test_val d

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

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

7913{
7914 int res = 0;
7915 int loops = 0;
7916
7917 res = ast_play_and_wait(chan, fn); /* Folder name */
7918 while (((res < '0') || (res > '9')) &&
7919 (res != '#') && (res >= 0) &&
7920 loops < 4) {
7921 /* res = get_folder(chan, 0); */
7922 if (!strcasecmp(ast_channel_language(chan), "ja")) { /* Japanese syntax */
7923 res = get_folder_ja(chan, 0);
7924 } else { /* Default syntax */
7925 res = get_folder(chan, 0);
7926 }
7927 loops++;
7928 }
7929 if (loops == 4) { /* give up */
7930 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
7931 return '#';
7932 }
7933 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
7934 isprint(res) ? res : '?', isprint(res) ? res : '?');
7935 return res;
7936}
static int get_folder(struct ast_channel *chan, int start)
get_folder: Folder menu Plays "press 1 for INBOX messages" etc. Should possibly be internationalized
static int get_folder_ja(struct ast_channel *chan, int start)

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

Referenced by vm_execmain().

◆ get_folder_by_name()

static int get_folder_by_name ( const char *  name)
static

Definition at line 2109 of file app_voicemail.c.

2110{
2111 size_t i;
2112
2113 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
2114 if (strcasecmp(name, mailbox_folders[i]) == 0) {
2115 return i;
2116 }
2117 }
2118
2119 return -1;
2120}

References ARRAY_LEN, mailbox_folders, and name.

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

◆ get_folder_ja()

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

Definition at line 7873 of file app_voicemail.c.

7874{
7875 int x;
7876 int d;
7877 char fn[256];
7878 for (x = start; x < 5; x++) { /* For all folders */
7879 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL))) {
7880 return d;
7881 }
7882 snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
7883 d = vm_play_folder_name(chan, fn);
7884 if (d) {
7885 return d;
7886 }
7887 d = ast_waitfordigit(chan, 500);
7888 if (d) {
7889 return d;
7890 }
7891 }
7892 d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
7893 if (d) {
7894 return d;
7895 }
7896 d = ast_waitfordigit(chan, 4000);
7897 return d;
7898}

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

◆ handle_voicemail_forward_message()

static char * handle_voicemail_forward_message ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 11860 of file app_voicemail.c.

11861{
11862 switch (cmd) {
11863 case CLI_INIT:
11864 e->command = "voicemail forward";
11865 e->usage =
11866 "Usage: voicemail forward <from_mailbox> <from_context> <from_folder> <messageid> <to_mailbox> <to_context> <to_folder>\n"
11867 " Forward message <messageid> in mailbox <mailbox>@<context> <from_folder>\n"
11868 " to mailbox <mailbox>@<context> <to_folder>\n";
11869 return NULL;
11870 case CLI_GENERATE:
11872 case CLI_HANDLER:
11873 break;
11874 }
11875
11876 if (a->argc != 9) {
11877 return CLI_SHOWUSAGE;
11878 }
11879
11881 return CLI_FAILURE;
11882 }
11883
11884 return CLI_SUCCESS;
11885}
static int forward_message_from_mailbox(struct ast_cli_args *a)
static char * complete_voicemail_move_message(struct ast_cli_args *a, int maxpos)
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
@ CLI_HANDLER
Definition: cli.h:154
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177

References a, CLI_FAILURE, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_voicemail_move_message(), forward_message_from_mailbox(), NULL, and ast_cli_entry::usage.

◆ handle_voicemail_move_message()

static char * handle_voicemail_move_message ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 11887 of file app_voicemail.c.

11888{
11889 switch (cmd) {
11890 case CLI_INIT:
11891 e->command = "voicemail move";
11892 e->usage =
11893 "Usage: voicemail move <mailbox> <context> <from_folder> <messageid> <to_folder>\n"
11894 " Move message <messageid> in mailbox <mailbox>&<context> from <from_folder> to <to_folder>\n";
11895 return NULL;
11896 case CLI_GENERATE:
11898 case CLI_HANDLER:
11899 break;
11900 }
11901
11902 if (a->argc != 7) {
11903 return CLI_SHOWUSAGE;
11904 }
11905
11907 return CLI_FAILURE;
11908 }
11909
11910 return CLI_SUCCESS;
11911}
static int move_message_from_mailbox(struct ast_cli_args *a)

References a, CLI_FAILURE, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_voicemail_move_message(), move_message_from_mailbox(), NULL, and ast_cli_entry::usage.

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

13478{
13479 switch (cmd) {
13480 case CLI_INIT:
13481 e->command = "voicemail reload";
13482 e->usage =
13483 "Usage: voicemail reload\n"
13484 " Reload voicemail configuration\n";
13485 return NULL;
13486 case CLI_GENERATE:
13487 return NULL;
13488 }
13489
13490 if (a->argc != 2)
13491 return CLI_SHOWUSAGE;
13492
13493 ast_cli(a->fd, "Reloading voicemail configuration...\n");
13494 load_config(1);
13495
13496 return CLI_SUCCESS;
13497}
static int load_config(int reload)

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, load_config(), NULL, and ast_cli_entry::usage.

◆ handle_voicemail_remove_message()

static char * handle_voicemail_remove_message ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 11913 of file app_voicemail.c.

11914{
11915 switch (cmd) {
11916 case CLI_INIT:
11917 e->command = "voicemail remove";
11918 e->usage =
11919 "Usage: voicemail remove <mailbox> <context> <from_folder> <messageid>\n"
11920 " Remove message <messageid> from <from_folder> in mailbox <mailbox>@<context>\n";
11921 return NULL;
11922 case CLI_GENERATE:
11924 case CLI_HANDLER:
11925 break;
11926 }
11927
11928 if (a->argc != 6) {
11929 return CLI_SHOWUSAGE;
11930 }
11931
11933 return CLI_FAILURE;
11934 }
11935
11936 return CLI_SUCCESS;
11937}
static int remove_message_from_mailbox(struct ast_cli_args *a)

References a, CLI_FAILURE, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_voicemail_move_message(), NULL, remove_message_from_mailbox(), and ast_cli_entry::usage.

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

13438{
13439 struct ao2_iterator aliases;
13440 struct alias_mailbox_mapping *mapping;
13441#define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"
13442 char *res = CLI_SUCCESS;
13443
13444 switch (cmd) {
13445 case CLI_INIT:
13446 e->command = "voicemail show aliases";
13447 e->usage =
13448 "Usage: voicemail show aliases\n"
13449 " Lists mailbox aliases\n";
13450 return NULL;
13451 case CLI_GENERATE:
13452 return NULL;
13453 }
13454
13455 if (a->argc != 3)
13456 return CLI_SHOWUSAGE;
13457
13459 ast_cli(a->fd, "Aliases are not enabled\n");
13460 return res;
13461 }
13462
13463 ast_cli(a->fd, "Aliases context: %s\n", aliasescontext);
13464 ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, "Alias", "Mailbox");
13465
13467 while ((mapping = ao2_iterator_next(&aliases))) {
13468 ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, mapping->alias, mapping->mailbox);
13469 ao2_ref(mapping, -1);
13470 }
13472
13473 return res;
13474}
#define ALIASES_OUTPUT_FORMAT
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static struct progalias aliases[]
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References a, alias_mailbox_mapping::alias, alias_mailbox_mappings, aliases, ALIASES_OUTPUT_FORMAT, aliasescontext, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, alias_mailbox_mapping::mailbox, NULL, and ast_cli_entry::usage.

◆ handle_voicemail_show_mailbox()

static char * handle_voicemail_show_mailbox ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 11726 of file app_voicemail.c.

11727{
11728 switch (cmd) {
11729 case CLI_INIT:
11730 e->command = "voicemail show mailbox";
11731 e->usage =
11732 "Usage: voicemail show mailbox <mailbox> <context>\n"
11733 " Show contents of mailbox <mailbox>@<context>\n";
11734 return NULL;
11735 case CLI_GENERATE:
11737 case CLI_HANDLER:
11738 break;
11739 }
11740
11741 if (a->argc != 5) {
11742 return CLI_SHOWUSAGE;
11743 }
11744
11746 return CLI_FAILURE;
11747 }
11748
11749 return CLI_SUCCESS;
11750}
static int show_messages_for_mailbox(struct ast_cli_args *a)
static char * complete_voicemail_show_mailbox(struct ast_cli_args *a)

References a, CLI_FAILURE, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_voicemail_show_mailbox(), NULL, show_messages_for_mailbox(), and ast_cli_entry::usage.

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

13326{
13327 struct ast_vm_user *vmu;
13328#define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
13329 const char *context = NULL;
13330 int users_counter = 0;
13331
13332 switch (cmd) {
13333 case CLI_INIT:
13334 e->command = "voicemail show users [for]";
13335 e->usage =
13336 "Usage: voicemail show users [for <context>]\n"
13337 " Lists all mailboxes currently set up\n";
13338 return NULL;
13339 case CLI_GENERATE:
13340 return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
13341 }
13342
13343 if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
13344 return CLI_SHOWUSAGE;
13345 if (a->argc == 5) {
13346 if (strcmp(a->argv[3],"for"))
13347 return CLI_SHOWUSAGE;
13348 context = a->argv[4];
13349 }
13350
13351 if (ast_check_realtime("voicemail")) {
13352 if (!context) {
13353 ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
13354 return CLI_SHOWUSAGE;
13355 }
13356 return show_users_realtime(a->fd, context);
13357 }
13358
13360 if (AST_LIST_EMPTY(&users)) {
13361 ast_cli(a->fd, "There are no voicemail users currently defined\n");
13363 return CLI_FAILURE;
13364 }
13365 if (!context) {
13366 ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
13367 } else {
13368 int count = 0;
13369 AST_LIST_TRAVERSE(&users, vmu, list) {
13370 if (!strcmp(context, vmu->context)) {
13371 count++;
13372 break;
13373 }
13374 }
13375 if (count) {
13376 ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
13377 } else {
13378 ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
13380 return CLI_FAILURE;
13381 }
13382 }
13383 AST_LIST_TRAVERSE(&users, vmu, list) {
13384 int newmsgs = 0, oldmsgs = 0;
13385 char count[12], tmp[256] = "";
13386
13387 if (!context || !strcmp(context, vmu->context)) {
13388 snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
13389 inboxcount(tmp, &newmsgs, &oldmsgs);
13390 snprintf(count, sizeof(count), "%d", newmsgs);
13391 ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
13392 users_counter++;
13393 }
13394 }
13396 ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
13397 return CLI_SUCCESS;
13398}
#define HVSU_OUTPUT_FORMAT
static char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
static char * show_users_realtime(int fd, const char *context)

References a, 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, voicemailpwcheck::context, ast_vm_user::fullname, HVSU_OUTPUT_FORMAT, inboxcount(), ast_vm_user::list, ast_vm_user::mailbox, NULL, show_users_realtime(), tmp(), ast_cli_entry::usage, and ast_vm_user::zonetag.

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

13402{
13403 struct vm_zone *zone;
13404#define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
13405 char *res = CLI_SUCCESS;
13406
13407 switch (cmd) {
13408 case CLI_INIT:
13409 e->command = "voicemail show zones";
13410 e->usage =
13411 "Usage: voicemail show zones\n"
13412 " Lists zone message formats\n";
13413 return NULL;
13414 case CLI_GENERATE:
13415 return NULL;
13416 }
13417
13418 if (a->argc != 3)
13419 return CLI_SHOWUSAGE;
13420
13422 if (!AST_LIST_EMPTY(&zones)) {
13423 ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
13424 AST_LIST_TRAVERSE(&zones, zone, list) {
13425 ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
13426 }
13427 } else {
13428 ast_cli(a->fd, "There are no voicemail zones currently defined\n");
13429 res = CLI_FAILURE;
13430 }
13432
13433 return res;
13434}
#define HVSZ_OUTPUT_FORMAT
char name[80]
char timezone[80]
char msg_format[512]

References a, 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, HVSZ_OUTPUT_FORMAT, vm_zone::list, vm_zone::msg_format, vm_zone::name, NULL, vm_zone::timezone, and ast_cli_entry::usage.

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

Definition at line 6120 of file app_voicemail.c.

6121{
6122 char tmp[256], *tmp2 = tmp, *box, *context;
6123 ast_copy_string(tmp, mailbox, sizeof(tmp));
6124 if (ast_strlen_zero(folder)) {
6125 folder = "INBOX";
6126 }
6127 while ((box = strsep(&tmp2, ",&"))) {
6128 if ((context = strchr(box, '@')))
6129 *context++ = '\0';
6130 else
6131 context = "default";
6132 if (__has_voicemail(context, box, folder, 1))
6133 return 1;
6134 /* If we are checking INBOX, we should check Urgent as well */
6135 if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
6136 return 1;
6137 }
6138 }
6139 return 0;
6140}
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)

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

Referenced by ast_app_has_voicemail().

◆ inboxcount()

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

Definition at line 6220 of file app_voicemail.c.

6221{
6222 int urgentmsgs = 0;
6223 int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
6224 if (newmsgs) {
6225 *newmsgs += urgentmsgs;
6226 }
6227 return res;
6228}

References inboxcount2(), and voicemailpwcheck::mailbox.

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

◆ 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@context. 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.

Definition at line 6150 of file app_voicemail.c.

6151{
6152 char tmp[256];
6153 char *context;
6154
6155 /* If no mailbox, return immediately */
6156 if (ast_strlen_zero(mailbox)) {
6157 return 0;
6158 }
6159
6160 if (newmsgs) {
6161 *newmsgs = 0;
6162 }
6163 if (oldmsgs) {
6164 *oldmsgs = 0;
6165 }
6166 if (urgentmsgs) {
6167 *urgentmsgs = 0;
6168 }
6169
6170 if (strchr(mailbox, ',')) {
6171 int tmpnew, tmpold, tmpurgent;
6172 char *mb, *cur;
6173
6174 ast_copy_string(tmp, mailbox, sizeof(tmp));
6175 mb = tmp;
6176 while ((cur = strsep(&mb, ", "))) {
6177 if (!ast_strlen_zero(cur)) {
6178 if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL)) {
6179 return -1;
6180 } else {
6181 if (newmsgs) {
6182 *newmsgs += tmpnew;
6183 }
6184 if (oldmsgs) {
6185 *oldmsgs += tmpold;
6186 }
6187 if (urgentmsgs) {
6188 *urgentmsgs += tmpurgent;
6189 }
6190 }
6191 }
6192 }
6193 return 0;
6194 }
6195
6196 ast_copy_string(tmp, mailbox, sizeof(tmp));
6197
6198 if ((context = strchr(tmp, '@'))) {
6199 *context++ = '\0';
6200 } else {
6201 context = "default";
6202 }
6203
6204 if (newmsgs) {
6205 *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
6206 }
6207 if (oldmsgs) {
6208 *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
6209 }
6210 if (urgentmsgs) {
6211 *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
6212 }
6213
6214 return 0;
6215}

References __has_voicemail(), ast_copy_string(), ast_strlen_zero(), voicemailpwcheck::context, inboxcount2(), voicemailpwcheck::mailbox, NULL, strsep(), and tmp().

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

◆ inprocess_cmp_fn()

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

Definition at line 1258 of file app_voicemail.c.

1259{
1260 struct inprocess *i = obj, *j = arg;
1261 if (strcmp(i->mailbox, j->mailbox)) {
1262 return 0;
1263 }
1264 return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
1265}
@ CMP_MATCH
Definition: astobj2.h:1027
char mailbox[0]
char * context

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

Referenced by load_module().

◆ inprocess_count()

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

Definition at line 1267 of file app_voicemail.c.

1268{
1269 int context_len = strlen(context) + 1;
1270 int mailbox_len = strlen(mailbox) + 1;
1271 struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + context_len + mailbox_len);
1272 arg->context = arg->mailbox + mailbox_len;
1273 ast_copy_string(arg->mailbox, mailbox, mailbox_len); /* SAFE */
1274 ast_copy_string(arg->context, context, context_len); /* SAFE */
1276 if ((i = ao2_find(inprocess_container, arg, 0))) {
1277 int ret = ast_atomic_fetchadd_int(&i->count, delta);
1279 ao2_ref(i, -1);
1280 return ret;
1281 }
1282 if (delta < 0) {
1283 ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
1284 }
1285 if (!(i = ao2_alloc(sizeof(*i) + context_len + mailbox_len, NULL))) {
1287 return 0;
1288 }
1289 i->context = i->mailbox + mailbox_len;
1290 ast_copy_string(i->mailbox, mailbox, mailbox_len); /* SAFE */
1291 ast_copy_string(i->context, context, context_len); /* SAFE */
1292 i->count = delta;
1295 ao2_ref(i, -1);
1296 return 0;
1297}
struct ao2_container * inprocess_container
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717

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

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

◆ inprocess_hash_fn()

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

Definition at line 1252 of file app_voicemail.c.

1253{
1254 const struct inprocess *i = obj;
1255 return atoi(i->mailbox);
1256}

References inprocess::mailbox.

Referenced by load_module().

◆ invent_message()

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

Definition at line 5732 of file app_voicemail.c.

5733{
5734 int res;
5735 char fn[PATH_MAX];
5736 char dest[PATH_MAX];
5737
5738 snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
5739
5740 if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
5741 ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
5742 return -1;
5743 }
5744
5745 RETRIEVE(fn, -1, ext, context);
5746 if (ast_fileexists(fn, NULL, NULL) > 0) {
5747 res = ast_stream_and_wait(chan, fn, ecodes);
5748 if (res) {
5749 DISPOSE(fn, -1);
5750 return res;
5751 }
5752 } else {
5753 /* Dispose just in case */
5754 DISPOSE(fn, -1);
5755 res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
5756 if (res)
5757 return res;
5758 res = ast_say_digit_str(chan, ext, ecodes, ast_channel_language(chan));
5759 if (res)
5760 return res;
5761 }
5762 res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
5763 return res;
5764}

References ast_channel_language(), ast_fileexists(), ast_log, AST_LOG_WARNING, ast_say_digit_str(), ast_stream_and_wait(), voicemailpwcheck::context, create_dirpath(), DISPOSE, ext, NULL, PATH_MAX, RETRIEVE, and VM_SPOOL_DIR.

Referenced by leave_voicemail().

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

1731{
1732 int i;
1733 char *local_key = ast_strdupa(key);
1734
1735 for (i = 0; i < strlen(key); ++i) {
1736 if (!strchr(VALID_DTMF, *local_key)) {
1737 ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
1738 return 0;
1739 }
1740 local_key++;
1741 }
1742 return 1;
1743}
#define VALID_DTMF

References ast_log, AST_LOG_WARNING, ast_strdupa, and VALID_DTMF.

Referenced by actual_load_config().

◆ last_message_index()

static int last_message_index ( char *  dir)
static

Determines the highest message number in use for a given user and mailbox folder.

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

4709{
4710 int x;
4711 unsigned char map[MAXMSGLIMIT] = "";
4712 DIR *msgdir;
4713 struct dirent *msgdirent;
4714 int msgdirint;
4715 char extension[4];
4716 int stopcount = 0;
4717
4718 /* Reading the entire directory into a file map scales better than
4719 * doing a stat repeatedly on a predicted sequence. I suspect this
4720 * is partially due to stat(2) internally doing a readdir(2) itself to
4721 * find each file. */
4722 if (!(msgdir = opendir(dir))) {
4723 return -1;
4724 }
4725
4726 while ((msgdirent = readdir(msgdir))) {
4727 if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
4728 map[msgdirint] = 1;
4729 stopcount++;
4730 ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4731 }
4732 }
4733 closedir(msgdir);
4734
4735 for (x = 0; x < MAXMSGLIMIT && stopcount; x++) {
4736 stopcount -= map[x];
4737 }
4738
4739 return x - 1;
4740}
structure to hold extensions

References ast_debug, and MAXMSGLIMIT.

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

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

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

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_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(), ast_vm_user::context, voicemailpwcheck::context, copy_message(), count_messages(), create_dirpath(), DISPOSE, errno, ast_vm_user::exit, ext, find_user(), vm_state::fn, 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, my_umask, name, vm_state::newmessages, notify_new_message(), NULL, OPERATOR_EXIT, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_SILENT, OPT_SILENT_IF_GREET, OPT_UNAVAIL_GREETING, options, PATH_MAX, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), play_record_review(), priority, RETRIEVE, S_COR, S_OR, SENTINEL, STORE, strsep(), tmp(), transfer(), vm_lock_path(), VM_OPERATOR, VM_SPOOL_DIR, vmfmts, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

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

◆ load_aliases()

static void load_aliases ( struct ast_config cfg)
static

Definition at line 14291 of file app_voicemail.c.

14292{
14293 struct ast_variable *var;
14294
14296 return;
14297 }
14299 while (var) {
14300 struct alias_mailbox_mapping *mapping = alias_mailbox_mapping_create(var->name, var->value);
14301 if (mapping) {
14304 ao2_ref(mapping, -1);
14305 }
14306 var = var->next;
14307 }
14308}
static struct alias_mailbox_mapping * alias_mailbox_mapping_create(const char *alias, const char *mailbox)

References alias_mailbox_mapping_create(), alias_mailbox_mappings, aliasescontext, ao2_link, ao2_ref, ast_strlen_zero(), ast_variable_browse(), mailbox_alias_mappings, and var.

Referenced by actual_load_config().

◆ load_config()

static int load_config ( int  reload)
static

Definition at line 14259 of file app_voicemail.c.

14260{
14261 return load_config_force(reload, 0);
14262}
static int load_config_force(int reload, int force)
Reload voicemail.conf.
static int reload(void)

References load_config_force(), and reload().

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

◆ load_config_force()

static int load_config_force ( int  reload,
int  force 
)
static

Reload voicemail.conf.

Parameters
reloadWhether this is a reload as opposed to module load
forceForcefully reload the config, even it has not changed
Return values
0on success, nonzero on failure

Definition at line 14218 of file app_voicemail.c.

14219{
14220 struct ast_config *cfg, *ucfg;
14221 struct ast_flags config_flags = { reload && !force ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14222 int res;
14223
14224 ast_unload_realtime("voicemail");
14225 ast_unload_realtime("voicemail_data");
14226
14227 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
14228 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
14229 return 0;
14230 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
14231 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
14232 ucfg = NULL;
14233 }
14235 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
14236 ast_config_destroy(ucfg);
14237 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
14238 return 0;
14239 }
14240 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
14241 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
14242 return 0;
14243 } else {
14245 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
14246 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
14247 ucfg = NULL;
14248 }
14249 }
14250
14251 res = actual_load_config(reload, cfg, ucfg);
14252
14253 ast_config_destroy(cfg);
14254 ast_config_destroy(ucfg);
14255
14256 return res;
14257}
#define VOICEMAIL_CONFIG
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: main/config.c:3576
#define CONFIG_STATUS_FILEUNCHANGED
@ CONFIG_FLAG_FILEUNCHANGED

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, reload(), and VOICEMAIL_CONFIG.

Referenced by load_config().

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

15828{
15829 int res;
15830 my_umask = umask(0);
15831 umask(my_umask);
15832
15835 if (!inprocess_container) {
15837 }
15838
15840 alias_mailbox_mapping_hash_fn, NULL, alias_mailbox_mapping_cmp_fn);
15842 ast_log(LOG_ERROR, "Unable to create alias_mailbox_mappings container\n");
15845 }
15846 res = ao2_container_register("voicemail_alias_mailbox_mappings", alias_mailbox_mappings, print_mappings);
15847 if (res) {
15848 ast_log(LOG_ERROR, "Unable to register alias_mailbox_mappings container\n");
15852 }
15853
15855 mailbox_alias_mapping_hash_fn, NULL, mailbox_alias_mapping_cmp_fn);
15857 ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");
15859 ao2_container_unregister("voicemail_alias_mailbox_mappings");
15862 }
15863 res = ao2_container_register("voicemail_mailbox_alias_mappings", mailbox_alias_mappings, print_mappings);
15864 if (res) {
15865 ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");
15867 ao2_container_unregister("voicemail_alias_mailbox_mappings");
15871 }
15872
15873 /* compute the location of the voicemail spool directory */
15874 snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
15875
15876 if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
15877 ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor. MWI will not work\n");
15878 }
15879
15880 if ((res = load_config(0))) {
15881 unload_module();
15883 }
15884
15898#ifdef TEST_FRAMEWORK
15899 res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
15900 res |= AST_TEST_REGISTER(test_voicemail_msgcount);
15901 res |= AST_TEST_REGISTER(test_voicemail_vmuser);
15902 res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
15903 res |= AST_TEST_REGISTER(test_voicemail_load_config);
15904 res |= AST_TEST_REGISTER(test_voicemail_vm_info);
15905#endif
15906
15907 if (res) {
15908 ast_log(LOG_ERROR, "Failure registering applications, functions or tests\n");
15909 unload_module();
15911 }
15912
15913 /* ast_vm_register may return DECLINE if another module registered for vm */
15914 res = ast_vm_register(&vm_table);
15915 if (res) {
15916 ast_log(LOG_ERROR, "Failure registering as a voicemail provider\n");
15917 unload_module();
15919 }
15920
15921 /* ast_vm_greeter_register may return DECLINE if another module registered as a greeter */
15923 if (res) {
15924 ast_log(LOG_ERROR, "Failure registering as a greeter provider\n");
15925 unload_module();
15927 }
15928
15930
15931#ifdef TEST_FRAMEWORK
15932 ast_install_vm_test_functions(vm_test_create_user, vm_test_destroy_user);
15933#endif
15934
15935 ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
15936 ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
15937
15939}
static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
static int inprocess_hash_fn(const void *obj, const int flags)
static struct ast_custom_function vm_info_acf
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
Manager list voicemail users command.
static const struct ast_vm_functions vm_table
static int vm_execmain(struct ast_channel *chan, const char *data)
#define MAPPING_BUCKETS
static int vmauthenticate(struct ast_channel *chan, const char *data)
static int vm_exec(struct ast_channel *chan, const char *data)
static int manager_voicemail_forward(struct mansession *s, const struct message *m)
static int manager_voicemail_move(struct mansession *s, const struct message *m)
static int vm_playmsgexec(struct ast_channel *chan, const char *data)
static char * voicemail_app
static char * playmsg_app
static const struct ast_vm_greeter_functions vm_greeter_table
static int vmsayname_exec(struct ast_channel *chan, const char *data)
static int manager_voicemail_remove(struct mansession *s, const struct message *m)
static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)
static struct ast_cli_entry cli_voicemail[]
static int manager_get_mailbox_summary(struct mansession *s, const struct message *m)
static char * sayname_app
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
static int unload_module(void)
static int manager_status_voicemail_user(struct mansession *s, const struct message *m)
static char * vmauthenticate_app
static char * voicemailmain_app
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
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.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_vm_register(vm_table)
See __ast_vm_register()
#define ast_vm_greeter_register(vm_table)
See __ast_vm_greeter_register()
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
#define EVENT_FLAG_CALL
Definition: manager.h:76
#define EVENT_FLAG_USER
Definition: manager.h:81
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References alias_mailbox_mappings, 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_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, cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, EVENT_FLAG_USER, inprocess_cmp_fn(), inprocess_container, inprocess_hash_fn(), load_config(), LOG_ERROR, mailbox_alias_mappings, manager_get_mailbox_summary(), manager_list_voicemail_users(), manager_status_voicemail_user(), manager_voicemail_forward(), manager_voicemail_move(), manager_voicemail_refresh(), manager_voicemail_remove(), MAPPING_BUCKETS, mwi_subscription_tps, my_umask, NULL, playmsg_app, print_mappings(), RQ_CHAR, RQ_UINTEGER3, sayname_app, SENTINEL, unload_module(), vm_exec(), vm_execmain(), vm_greeter_table, vm_info_acf, vm_playmsgexec(), VM_SPOOL_DIR, vm_table, vmauthenticate(), vmauthenticate_app, vmsayname_exec(), voicemail_app, and voicemailmain_app.

◆ load_users()

static void load_users ( struct ast_config cfg)
static

Definition at line 14345 of file app_voicemail.c.

14346{
14347 struct ast_variable *var;
14348 char *cat = NULL;
14349
14350 while ((cat = ast_category_browse(cfg, cat))) {
14351 if (strcasecmp(cat, "general") == 0
14352 || strcasecmp(cat, aliasescontext) == 0
14353 || strcasecmp(cat, "zonemessages") == 0) {
14354 continue;
14355 }
14356
14357 var = ast_variable_browse(cfg, cat);
14358 while (var) {
14359 append_mailbox(cat, var->name, var->value);
14360 var = var->next;
14361 }
14362 }
14363}
static int append_mailbox(const char *context, const char *box, const char *data)

References aliasescontext, append_mailbox(), ast_category_browse(), ast_variable_browse(), NULL, and var.

Referenced by actual_load_config().

◆ load_zonemessages()

static void load_zonemessages ( struct ast_config cfg)
static

Definition at line 14310 of file app_voicemail.c.

14311{
14312 struct ast_variable *var;
14313
14314 var = ast_variable_browse(cfg, "zonemessages");
14315 while (var) {
14316 if (var->value) {
14317 struct vm_zone *z;
14318 char *msg_format, *tzone;
14319 char storage[strlen(var->value) + 1];
14320
14321 z = ast_malloc(sizeof(*z));
14322 if (!z) {
14323 return;
14324 }
14325
14326 strcpy(storage, var->value); /* safe */
14327 msg_format = storage;
14328 tzone = strsep(&msg_format, "|,");
14329 if (msg_format) {
14330 ast_copy_string(z->name, var->name, sizeof(z->name));
14331 ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
14336 } else {
14337 ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
14338 ast_free(z);
14339 }
14340 }
14341 var = var->next;
14342 }
14343}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191

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(), vm_zone::list, vm_zone::msg_format, vm_zone::name, strsep(), vm_zone::timezone, and var.

Referenced by actual_load_config().

◆ 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
folder

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns
zero on success, -1 on error.

Definition at line 2050 of file app_voicemail.c.

2051{
2052 return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
2053}

References voicemailpwcheck::context, ext, len(), and VM_SPOOL_DIR.

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

◆ 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_id

The email body, and base 64 encoded attachment (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 5081 of file app_voicemail.c.

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

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, voicemailpwcheck::context, ast_vm_user::email, email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, ast_vm_user::fromstring, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, voicemailpwcheck::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 sendmail().

◆ 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
num

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns
zero on success, -1 on error.

Definition at line 2067 of file app_voicemail.c.

2068{
2069 return snprintf(dest, len, "%s/msg%04d", dir, num);
2070}

References len().

Referenced by advanced_options(), 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_execmain(), vm_forwardoptions(), vm_msg_forward(), vm_msg_play(), and vm_msg_snapshot_create().

◆ manager_get_mailbox_summary()

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

Definition at line 13992 of file app_voicemail.c.

13993{
13994 struct ast_vm_user *vmu = NULL;
13995 const char *id = astman_get_header(m, "ActionID");
13996 char actionid[128];
13997 struct ast_vm_user svm;
13998
13999 const char *context = astman_get_header(m, "Context");
14000 const char *mailbox = astman_get_header(m, "Mailbox");
14001
14003 astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters.");
14004 return 0;
14005 }
14006
14007 actionid[0] = '\0';
14008 if (!ast_strlen_zero(id)) {
14009 snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
14010 }
14011
14012 /* find user */
14013 memset(&svm, 0, sizeof(svm));
14014 vmu = find_user(&svm, context, mailbox);
14015 if (!vmu) {
14016 /* could not find it */
14017 astman_send_ack(s, m, "There is no voicemail user matching the given user.");
14018 return 0;
14019 }
14020
14021 /* Append the mailbox details */
14022 if (!append_vmbox_info_astman(s, m, vmu, "VoicemailBoxDetail", actionid)) {
14023 astman_send_error(s, m, "Unable to get mailbox info for the given user.");
14024 }
14025
14026 free_user(vmu);
14027 return 0;
14028}
static int append_vmbox_info_astman(struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmbox info string into given astman with event_name.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3381
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3413
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3042

References append_vmbox_info_astman(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), voicemailpwcheck::context, find_user(), free_user(), voicemailpwcheck::mailbox, and NULL.

Referenced by load_module().

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

13952{
13953 struct ast_vm_user *vmu = NULL;
13954 const char *id = astman_get_header(m, "ActionID");
13955 char actionid[128];
13956 int num_users = 0;
13957 int ret;
13958
13959 actionid[0] = '\0';
13960 if (!ast_strlen_zero(id)) {
13961 snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
13962 }
13963
13965
13966 if (AST_LIST_EMPTY(&users)) {
13967 astman_send_ack(s, m, "There are no voicemail users currently defined.");
13969 return RESULT_SUCCESS;
13970 }
13971
13972 astman_send_listack(s, m, "Voicemail user list will follow", "start");
13973
13974 AST_LIST_TRAVERSE(&users, vmu, list) {
13975 /* append vmu info event */
13976 ret = append_vmu_info_astman(s, vmu, "VoicemailUserEntry", actionid);
13977 if(ret == 0) {
13978 ast_log(LOG_ERROR, "Could not append voicemail user info.");
13979 continue;
13980 }
13981 ++num_users;
13982 }
13983
13984 astman_send_list_complete_start(s, m, "VoicemailUserEntryComplete", num_users);
13986
13988
13989 return RESULT_SUCCESS;
13990}
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 RESULT_SUCCESS
Definition: cli.h:40

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

◆ manager_match_mailbox()

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

Definition at line 13867 of file app_voicemail.c.

13868{
13869 const char *context = astman_get_header(data, "Context");
13870 const char *mailbox = astman_get_header(data, "Mailbox");
13871 const char *at;
13872
13873 if (!ast_strlen_zero(mwi_state->uniqueid)) {
13874 if (
13875 /* First case: everything matches */
13877 /* Second case: match the mailbox only */
13879 (at = strchr(mwi_state->uniqueid, '@')) &&
13880 strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0) ||
13881 /* Third case: match the context only */
13883 (at = strchr(mwi_state->uniqueid, '@')) &&
13884 strcmp(context, at + 1) == 0) ||
13885 /* Final case: match an exact specified mailbox */
13887 (at = strchr(mwi_state->uniqueid, '@')) &&
13888 strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0 &&
13889 strcmp(context, at + 1) == 0)
13890 ) {
13891 poll_subscribed_mailbox(mwi_state, NULL);
13892 }
13893 }
13894
13895 return 0;
13896}
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)
const ast_string_field uniqueid
Definition: mwi.h:458

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

Referenced by manager_voicemail_refresh().

◆ manager_status_voicemail_user()

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

Definition at line 13905 of file app_voicemail.c.

13906{
13907 struct ast_vm_user *vmu = NULL;
13908 const char *id = astman_get_header(m, "ActionID");
13909 char actionid[128];
13910 struct ast_vm_user svm;
13911 int ret;
13912
13913 const char *context = astman_get_header(m, "Context");
13914 const char *mailbox = astman_get_header(m, "Mailbox");
13915
13917 astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters.");
13918 return RESULT_SUCCESS;
13919 }
13920
13921 actionid[0] = '\0';
13922 if (!ast_strlen_zero(id)) {
13923 snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
13924 }
13925
13926 /* find user */
13927 memset(&svm, 0, sizeof(svm));
13928 vmu = find_user(&svm, context, mailbox);
13929 if (!vmu) {
13930 /* could not find it */
13931 astman_send_ack(s, m, "There is no voicemail user of the given info.");
13932 return RESULT_SUCCESS;
13933 }
13934
13935 astman_send_listack(s, m, "Voicemail user detail will follow", "start");
13936
13937 /* append vmu info event */
13938 ret = append_vmu_info_astman(s, vmu, "VoicemailUserDetail", actionid);
13939 free_user(vmu);
13940 if(ret == 0) {
13941 ast_log(LOG_ERROR, "Could not append voicemail user info.");
13942 }
13943
13944 astman_send_list_complete_start(s, m, "VoicemailUserDetailComplete", 1);
13946
13947 return RESULT_SUCCESS;
13948}

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(), voicemailpwcheck::context, find_user(), free_user(), LOG_ERROR, voicemailpwcheck::mailbox, NULL, and RESULT_SUCCESS.

Referenced by load_module().

◆ manager_voicemail_forward()

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

Definition at line 14101 of file app_voicemail.c.

14102{
14103 const char *from_mailbox = astman_get_header(m, "Mailbox");
14104 const char *from_context = astman_get_header(m, "Context");
14105 const char *from_folder = astman_get_header(m, "Folder");
14106 const char *id[] = { astman_get_header(m, "ID") };
14107 const char *to_mailbox = astman_get_header(m, "ToMailbox");
14108 const char *to_context = astman_get_header(m, "ToContext");
14109 const char *to_folder = astman_get_header(m, "ToFolder");
14110
14112 astman_send_error(s, m, "Mailbox not specified, required");
14113 return 0;
14114 }
14115 if (ast_strlen_zero(from_context)) {
14116 astman_send_error(s, m, "Context not specified, required");
14117 return 0;
14118 }
14119 if (ast_strlen_zero(from_folder)) {
14120 astman_send_error(s, m, "Folder not specified, required");
14121 return 0;
14122 }
14123 if (ast_strlen_zero(id[0])) {
14124 astman_send_error(s, m, "ID not specified, required");
14125 return 0;
14126 }
14127 if (ast_strlen_zero(to_mailbox)) {
14128 astman_send_error(s, m, "ToMailbox not specified, required");
14129 return 0;
14130 }
14131 if (ast_strlen_zero(to_context)) {
14132 astman_send_error(s, m, "ToContext not specified, required");
14133 return 0;
14134 }
14135 if (ast_strlen_zero(to_folder)) {
14136 astman_send_error(s, m, "ToFolder not specified, required");
14137 return 0;
14138 }
14139
14140 if (vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0)) {
14141 astman_send_ack(s, m, "Message forward failed\n");
14142 } else {
14143 astman_send_ack(s, m, "Message forward successful\n");
14144 }
14145
14146 return 0;
14147}

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), sip_to_pjsip::from_mailbox(), and vm_msg_forward().

Referenced by load_module().

◆ manager_voicemail_move()

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

Definition at line 14030 of file app_voicemail.c.

14031{
14032 const char *mailbox = astman_get_header(m, "Mailbox");
14033 const char *context = astman_get_header(m, "Context");
14034 const char *from_folder = astman_get_header(m, "Folder");
14035 const char *id[] = { astman_get_header(m, "ID") };
14036 const char *to_folder = astman_get_header(m, "ToFolder");
14037
14038 if (ast_strlen_zero(mailbox)) {
14039 astman_send_error(s, m, "Mailbox not specified, required");
14040 return 0;
14041 }
14042 if (ast_strlen_zero(context)) {
14043 astman_send_error(s, m, "Context not specified, required");
14044 return 0;
14045 }
14046 if (ast_strlen_zero(from_folder)) {
14047 astman_send_error(s, m, "Folder not specified, required");
14048 return 0;
14049 }
14050 if (ast_strlen_zero(id[0])) {
14051 astman_send_error(s, m, "ID not specified, required");
14052 return 0;
14053 }
14054 if (ast_strlen_zero(to_folder)) {
14055 astman_send_error(s, m, "ToFolder not specified, required");
14056 return 0;
14057 }
14058
14059 if (vm_msg_move(mailbox, context, 1, from_folder, id, to_folder)) {
14060 astman_send_ack(s, m, "Message move failed\n");
14061 } else {
14062 astman_send_ack(s, m, "Message move successful\n");
14063 }
14064
14065 return 0;
14066}
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)

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), voicemailpwcheck::context, voicemailpwcheck::mailbox, and vm_msg_move().

Referenced by load_module().

◆ manager_voicemail_refresh()

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

Definition at line 13898 of file app_voicemail.c.

13899{
13901 astman_send_ack(s, m, "Refresh sent");
13902 return RESULT_SUCCESS;
13903}
static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data)

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

Referenced by load_module().

◆ manager_voicemail_remove()

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

Definition at line 14068 of file app_voicemail.c.

14069{
14070 const char *mailbox = astman_get_header(m, "Mailbox");
14071 const char *context = astman_get_header(m, "Context");
14072 const char *folder = astman_get_header(m, "Folder");
14073 const char *id[] = { astman_get_header(m, "ID") };
14074
14075 if (ast_strlen_zero(mailbox)) {
14076 astman_send_error(s, m, "Mailbox not specified, required");
14077 return 0;
14078 }
14079 if (ast_strlen_zero(context)) {
14080 astman_send_error(s, m, "Context not specified, required");
14081 return 0;
14082 }
14083 if (ast_strlen_zero(folder)) {
14084 astman_send_error(s, m, "Folder not specified, required");
14085 return 0;
14086 }
14087 if (ast_strlen_zero(id[0])) {
14088 astman_send_error(s, m, "ID not specified, required");
14089 return 0;
14090 }
14091
14092 if (vm_msg_remove(mailbox, context, 1, folder, id)) {
14093 astman_send_ack(s, m, "Message remove failed\n");
14094 } else {
14095 astman_send_ack(s, m, "Message remove successful\n");
14096 }
14097
14098 return 0;
14099}
static int vm_msg_remove(const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), voicemailpwcheck::context, voicemailpwcheck::mailbox, and vm_msg_remove().

Referenced by load_module().

◆ mb_poll_thread()

static void * mb_poll_thread ( void *  data)
static

Definition at line 13535 of file app_voicemail.c.

13536{
13537 while (poll_thread_run) {
13538 struct timespec ts = { 0, };
13539 struct timeval wait;
13540
13542
13543 if (!poll_thread_run) {
13544 break;
13545 }
13546
13548 ts.tv_sec = wait.tv_sec;
13549 ts.tv_nsec = wait.tv_usec * 1000;
13550
13554 }
13555
13556 return NULL;
13557}
static ast_mutex_t poll_lock
static unsigned char poll_thread_run
static ast_cond_t poll_cond
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
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:348
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:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_mwi_state_callback_subscribed(), ast_samp2tv(), ast_tvadd(), ast_tvnow(), NULL, poll_cond, poll_freq, poll_lock, poll_subscribed_mailbox(), and poll_thread_run.

Referenced by start_poll_thread().

◆ mbox()

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

Definition at line 2093 of file app_voicemail.c.

2094{
2095#ifdef IMAP_STORAGE
2096 if (vmu && id == 0) {
2097 return vmu->imapfolder;
2098 }
2099#endif
2100 return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
2101}
enum queue_result id
Definition: app_queue.c:1638

References ARRAY_LEN, id, and mailbox_folders.

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

◆ 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
[out]msg_numsThe 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 16794 of file app_voicemail.c.

16795{
16796 int i;
16797 int res = 0;
16798 for (i = 0; i < num_msgs; ++i) {
16799 const char *msg_id = msg_ids[i];
16800 int found = 0;
16801 for (vms->curmsg = 0; vms->curmsg <= vms->lastmsg; vms->curmsg++) {
16802 const char *other_msg_id;
16803 char filename[PATH_MAX];
16804 struct ast_config *msg_cfg;
16805 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
16806
16807 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
16808 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
16809 RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
16810 msg_cfg = ast_config_load(filename, config_flags);
16811 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
16812 DISPOSE(vms->curdir, vms->curmsg);
16813 res = -1;
16814 goto done;
16815 }
16816
16817 other_msg_id = ast_variable_retrieve(msg_cfg, "message", "msg_id");
16818
16819 if (!ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
16820 /* Message found. We can get out of this inner loop
16821 * and move on to the next message to find
16822 */
16823 found = 1;
16824 msg_nums[i] = vms->curmsg;
16825 ast_config_destroy(msg_cfg);
16826 DISPOSE(vms->curdir, vms->curmsg);
16827 break;
16828 }
16829 ast_config_destroy(msg_cfg);
16830 DISPOSE(vms->curdir, vms->curmsg);
16831 }
16832 if (!found) {
16833 /* If we can't find one of the message IDs requested, then OH NO! */
16834 res = -1;
16835 goto done;
16836 }
16837 }
16838
16839done:
16840 return res;
16841}

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(), ast_vm_msg_snapshot::msg_id, PATH_MAX, and RETRIEVE.

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

◆ messagecount()

static int messagecount ( const char *  mailbox_id,
const char *  folder 
)
static

Definition at line 6044 of file app_voicemail.c.

6045{
6046 char *context;
6047 char *mailbox;
6048
6049 if (ast_strlen_zero(mailbox_id)
6050 || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
6051 return 0;
6052 }
6053
6054 return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
6055}

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

Referenced by acf_vm_info(), and ast_app_messagecount().

◆ move_message_from_mailbox()

static int move_message_from_mailbox ( struct ast_cli_args a)
static

Definition at line 11644 of file app_voicemail.c.

11645{
11646 const char *mailbox = a->argv[2];
11647 const char *context = a->argv[3];
11648 const char *from_folder = a->argv[4];
11649 const char *id[] = { a->argv[5] };
11650 const char *to_folder = a->argv[6];
11651 int ret = vm_msg_move(mailbox, context, 1, from_folder, id, to_folder);
11652 if (ret) {
11653 ast_cli(a->fd, "Error moving message %s from mailbox %s@%s %s to %s\n",
11654 id[0], mailbox, context, from_folder, to_folder);
11655 } else {
11656 ast_cli(a->fd, "Moved message %s from mailbox %s@%s %s to %s\n",
11657 id[0], mailbox, context, from_folder, to_folder);
11658 }
11659 return ret;
11660}

References a, ast_cli(), voicemailpwcheck::context, voicemailpwcheck::mailbox, and vm_msg_move().

Referenced by handle_voicemail_move_message().

◆ msg_create_from_file()

static int msg_create_from_file ( struct ast_vm_recording_data recdata)
static

Definition at line 6311 of file app_voicemail.c.

6312{
6313 /* voicemail recipient structure */
6314 struct ast_vm_user *recipient; /* points to svm once it's been created */
6315 struct ast_vm_user svm; /* struct storing the voicemail recipient */
6316
6317 /* File paths */
6318 char tmpdir[PATH_MAX]; /* directory temp files are stored in */
6319 char tmptxtfile[PATH_MAX]; /* tmp file for voicemail txt file */
6320 char desttxtfile[PATH_MAX]; /* final destination for txt file */
6321 char tmpaudiofile[PATH_MAX]; /* tmp file where audio is stored */
6322 char dir[PATH_MAX]; /* destination for tmp files on completion */
6323 char destination[PATH_MAX]; /* destination with msgXXXX. Basically <dir>/msgXXXX */
6324
6325 /* stuff that only seems to be needed for IMAP */
6326 #ifdef IMAP_STORAGE
6327 struct vm_state *vms = NULL;
6328 char ext_context[256] = "";
6329 int newmsgs = 0;
6330 int oldmsgs = 0;
6331 #endif
6332
6333 /* miscellaneous operational variables */
6334 int res = 0; /* Used to store error codes from functions */
6335 int txtdes /* File descriptor for the text file used to write the voicemail info */;
6336 FILE *txt; /* FILE pointer to text file used to write the voicemail info */
6337 char date[256]; /* string used to hold date of the voicemail (only used for ODBC) */
6338 int msgnum; /* the 4 digit number designated to the voicemail */
6339 int duration = 0; /* Length of the audio being recorded in seconds */
6340 struct ast_filestream *recording_fs; /*used to read the recording to get duration data */
6341
6342 /* We aren't currently doing anything with category, since it comes from a channel variable and
6343 * this function doesn't use channels, but this function could add that as an argument later. */
6344 const char *category = NULL; /* pointless for now */
6345 char msg_id[MSG_ID_LEN];
6346
6347 /* Start by checking to see if the file actually exists... */
6348 if (!(ast_fileexists(recdata->recording_file, recdata->recording_ext, NULL))) {
6349 ast_log(LOG_ERROR, "File: %s not found.\n", recdata->recording_file);
6350 return -1;
6351 }
6352
6353 memset(&svm, 0, sizeof(svm));
6354 if (!(recipient = find_user(&svm, recdata->context, recdata->mailbox))) {
6355 ast_log(LOG_ERROR, "No entry in voicemail config file for '%s@%s'\n", recdata->mailbox, recdata->context);
6356 return -1;
6357 }
6358
6359 /* determine duration in seconds */
6360 if ((recording_fs = ast_readfile(recdata->recording_file, recdata->recording_ext, NULL, 0, 0, VOICEMAIL_DIR_MODE))) {
6361 if (!ast_seekstream(recording_fs, 0, SEEK_END)) {
6362 long framelength = ast_tellstream(recording_fs);
6363 int sample_rate = ast_ratestream(recording_fs);
6364 if (sample_rate) {
6365 duration = (int) (framelength / sample_rate);
6366 } else {
6367 ast_log(LOG_ERROR,"Unable to determine sample rate of recording %s\n", recdata->recording_file);
6368 }
6369 }
6370 ast_closestream(recording_fs);
6371 }
6372
6373 /* If the duration was below the minimum duration for the user, let's just drop the whole thing now */
6374 if (duration < recipient->minsecs) {
6375 ast_log(LOG_NOTICE, "Copying recording to voicemail %s@%s skipped because duration was shorter than "
6376 "minmessage of recipient\n", recdata->mailbox, recdata->context);
6377 return -1;
6378 }
6379
6380 /* Note that this number must be dropped back to a net sum of zero before returning from this function */
6381
6382 if ((res = create_dirpath(tmpdir, sizeof(tmpdir), recipient->context, recdata->mailbox, "tmp"))) {
6383 ast_log(LOG_ERROR, "Failed to make directory.\n");
6384 }
6385
6386 snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
6387 txtdes = mkstemp(tmptxtfile);
6388 if (txtdes < 0) {
6389 chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
6390 /* Something screwed up. Abort. */
6391 ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
6392 free_user(recipient);
6393 return -1;
6394 }
6395
6396 /* Store information */
6397 txt = fdopen(txtdes, "w+");
6398 if (txt) {
6399 generate_msg_id(msg_id);
6400 get_date(date, sizeof(date));
6401 fprintf(txt,
6402 ";\n"
6403 "; Message Information file\n"
6404 ";\n"
6405 "[message]\n"
6406 "origmailbox=%s\n"
6407 "context=%s\n"
6408 "exten=%s\n"
6409 "rdnis=Unknown\n"
6410 "priority=%d\n"
6411 "callerchan=%s\n"
6412 "callerid=%s\n"
6413 "origdate=%s\n"
6414 "origtime=%ld\n"
6415 "category=%s\n"
6416 "msg_id=%s\n"
6417 "flag=\n" /* flags not supported in copy from file yet */
6418 "duration=%d\n", /* Don't have any reliable way to get duration of file. */
6419
6420 recdata->mailbox,
6421 S_OR(recdata->call_context, ""),
6422 S_OR(recdata->call_extension, ""),
6423 recdata->call_priority,
6424 S_OR(recdata->call_callerchan, "Unknown"),
6425 S_OR(recdata->call_callerid, "Unknown"),
6426 date, (long) time(NULL),
6427 S_OR(category, ""),
6428 msg_id,
6429 duration);
6430
6431 /* Since we are recording from a file, we shouldn't need to do anything else with
6432 * this txt file */
6433 fclose(txt);
6434
6435 } else {
6436 ast_log(LOG_WARNING, "Error opening text file for output\n");
6437 if (ast_check_realtime("voicemail_data")) {
6438 ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
6439 }
6440 free_user(recipient);
6441 return -1;
6442 }
6443
6444 /* At this point, the actual creation of a voicemail message should be finished.
6445 * Now we just need to copy the files being recorded into the receiving folder. */
6446
6447 create_dirpath(dir, sizeof(dir), recipient->context, recipient->mailbox, recdata->folder);
6448
6449#ifdef IMAP_STORAGE
6450 /* make recipient info into an inboxcount friendly string */
6451 snprintf(ext_context, sizeof(ext_context), "%s@%s", recipient->mailbox, recipient->context);
6452
6453 /* Is ext a mailbox? */
6454 /* must open stream for this user to get info! */
6455 res = inboxcount(ext_context, &newmsgs, &oldmsgs);
6456 if (res < 0) {
6457 ast_log(LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
6458 free_user(recipient);
6459 unlink(tmptxtfile);
6460 return -1;
6461 }
6462 if (!(vms = get_vm_state_by_mailbox(recipient->mailbox, recipient->context, 0))) {
6463 /* It is possible under certain circumstances that inboxcount did not
6464 * create a vm_state when it was needed. This is a catchall which will
6465 * rarely be used.
6466 */
6467 if (!(vms = create_vm_state_from_user(recipient))) {
6468 ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
6469 free_user(recipient);
6470 unlink(tmptxtfile);
6471 return -1;
6472 }
6473 }
6474 vms->newmessages++;
6475
6476 /* here is a big difference! We add one to it later */
6477 msgnum = newmsgs + oldmsgs;
6478 ast_debug(3, "Messagecount set to %d\n", msgnum);
6479 snprintf(destination, sizeof(destination), "%simap/msg%s%04d", VM_SPOOL_DIR, recipient->mailbox, msgnum);
6480
6481 /* Check to see if we have enough room in the mailbox. If not, spit out an error and end
6482 * Note that imap_check_limits raises inprocess_count if successful */
6483 if ((res = imap_check_limits(NULL, vms, recipient, msgnum))) {
6484 ast_log(LOG_NOTICE, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context);
6485 inprocess_count(recipient->mailbox, recipient->context, -1);
6486 free_user(recipient);
6487 unlink(tmptxtfile);
6488 return -1;
6489 }
6490
6491#else
6492
6493 /* Check to see if the mailbox is full for ODBC/File storage */
6494 ast_debug(3, "mailbox = %d : inprocess = %d\n", count_messages(recipient, dir),
6495 inprocess_count(recipient->mailbox, recipient->context, 0));
6496 if (count_messages(recipient, dir) > recipient->maxmsg - inprocess_count(recipient->mailbox, recipient->context, +1)) {
6497 ast_log(AST_LOG_WARNING, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context);
6498 inprocess_count(recipient->mailbox, recipient->context, -1);
6499 free_user(recipient);
6500 unlink(tmptxtfile);
6501 return -1;
6502 }
6503
6504 msgnum = last_message_index(dir) + 1;
6505#endif
6506
6507 /* Lock the directory receiving the voicemail since we want it to still exist when we attempt to copy the voicemail.
6508 * We need to unlock it before we return. */
6509 if (vm_lock_path(dir)) {
6510 ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6511 /* Delete files */
6512 ast_filedelete(tmptxtfile, NULL);
6513 unlink(tmptxtfile);
6514 free_user(recipient);
6515 return -1;
6516 }
6517
6518 make_file(destination, sizeof(destination), dir, msgnum);
6519
6520 make_file(tmpaudiofile, sizeof(tmpaudiofile), tmpdir, msgnum);
6521
6522 if (ast_filecopy(recdata->recording_file, tmpaudiofile, recdata->recording_ext)) {
6523 ast_log(LOG_ERROR, "Audio file failed to copy to tmp dir. Probably low disk space.\n");
6524
6525 inprocess_count(recipient->mailbox, recipient->context, -1);
6526 ast_unlock_path(dir);
6527 free_user(recipient);
6528 unlink(tmptxtfile);
6529 return -1;
6530 }
6531
6532 /* Alright, try to copy to the destination folder now. */
6533 if (ast_filerename(tmpaudiofile, destination, recdata->recording_ext)) {
6534 ast_log(LOG_ERROR, "Audio file failed to move to destination directory. Permissions/Overlap?\n");
6535 inprocess_count(recipient->mailbox, recipient->context, -1);
6536 ast_unlock_path(dir);
6537 free_user(recipient);
6538 unlink(tmptxtfile);
6539 return -1;
6540 }
6541
6542 snprintf(desttxtfile, sizeof(desttxtfile), "%s.txt", destination);
6543 rename(tmptxtfile, desttxtfile);
6544
6545 if (chmod(desttxtfile, VOICEMAIL_FILE_MODE) < 0) {
6546 ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", desttxtfile, strerror(errno));
6547 }
6548
6549
6550 ast_unlock_path(dir);
6551 inprocess_count(recipient->mailbox, recipient->context, -1);
6552
6553 /* If we copied something, we should store it either to ODBC or IMAP if we are using those. The STORE macro allows us
6554 * 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
6555 * time to create the voicemail database entry. */
6556 if (ast_fileexists(destination, NULL, NULL) > 0) {
6557 struct ast_channel *chan = NULL;
6558 char fmt[80];
6559 char clid[80];
6560 char cidnum[80], cidname[80];
6561 int send_email;
6562
6563 if (ast_check_realtime("voicemail_data")) {
6564 get_date(date, sizeof(date));
6565 ast_store_realtime("voicemail_data",
6566 "origmailbox", recdata->mailbox,
6567 "context", S_OR(recdata->context, ""),
6568 "exten", S_OR(recdata->call_extension, ""),
6569 "priority", recdata->call_priority,
6570 "callerchan", S_OR(recdata->call_callerchan, "Unknown"),
6571 "callerid", S_OR(recdata->call_callerid, "Unknown"),
6572 "origdate", date,
6573 "origtime", time(NULL),
6574 "category", S_OR(category, ""),
6575 "filename", tmptxtfile,
6576 "duration", duration,
6577 SENTINEL);
6578 }
6579
6580 STORE(dir, recipient->mailbox, recipient->context, msgnum, NULL, recipient, fmt, 0, vms, "", msg_id);
6581
6582 send_email = ast_test_flag(recipient, VM_EMAIL_EXT_RECS);
6583
6584 if (send_email) {
6585 /* Send an email if possible, fall back to just notifications if not. */
6586 ast_copy_string(fmt, recdata->recording_ext, sizeof(fmt));
6587 ast_copy_string(clid, recdata->call_callerid, sizeof(clid));
6588 ast_callerid_split(clid, cidname, sizeof(cidname), cidnum, sizeof(cidnum));
6589
6590 /* recdata->call_callerchan itself no longer exists, so we can't use the real channel. Use a dummy one. */
6591 chan = ast_dummy_channel_alloc();
6592 }
6593 if (chan) {
6594 notify_new_message(chan, recipient, NULL, msgnum, duration, fmt, cidnum, cidname, "");
6595 ast_channel_unref(chan);
6596 } else {
6597 if (send_email) { /* We tried and failed. */
6598 ast_log(LOG_WARNING, "Failed to allocate dummy channel, email will not be sent\n");
6599 }
6600 notify_new_state(recipient);
6601 }
6602 }
6603
6604 free_user(recipient);
6605 unlink(tmptxtfile);
6606 return 0;
6607}
static void notify_new_state(struct ast_vm_user *vmu)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1193
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1085
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1075
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:1371
int ast_ratestream(struct ast_filestream *fs)
Return the sample rate of the stream's format.
Definition: file.c:1090
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1111
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
const ast_string_field recording_file
const ast_string_field call_callerchan
const ast_string_field context
const ast_string_field folder
const ast_string_field call_callerid
const ast_string_field call_context
const ast_string_field recording_ext
const ast_string_field call_extension
const ast_string_field mailbox

References ast_callerid_split(), ast_channel_unref, ast_check_realtime(), ast_closestream(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_dummy_channel_alloc, 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_tellstream(), ast_test_flag, 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_priority, ast_vm_user::context, ast_vm_recording_data::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_user::mailbox, ast_vm_recording_data::mailbox, make_file(), ast_vm_user::maxmsg, MSG_ID_LEN, my_umask, vm_state::newmessages, notify_new_message(), notify_new_state(), NULL, PATH_MAX, ast_vm_recording_data::recording_ext, ast_vm_recording_data::recording_file, S_OR, SENTINEL, STORE, VM_EMAIL_EXT_RECS, vm_lock_path(), VM_SPOOL_DIR, VOICEMAIL_DIR_MODE, and VOICEMAIL_FILE_MODE.

◆ mwi_handle_subscribe()

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

Definition at line 13642 of file app_voicemail.c.

13643{
13644 void *data = ast_mwi_subscriber_data(sub);
13645
13646 /* Don't bump data's reference. We'll just use the one returned above */
13648 /* A reference was returned for data when retrieving, so remove it on error */
13649 ao2_ref(data, -1);
13650 }
13651}
static int mwi_handle_subscribe2(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:269
struct stasis_forward * sub
Definition: res_corosync.c:240
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.

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

◆ mwi_handle_subscribe2()

static int mwi_handle_subscribe2 ( void *  data)
static

Definition at line 13635 of file app_voicemail.c.

13636{
13638 ao2_ref(data, -1);
13639 return 0;
13640}

References ao2_ref, NULL, and poll_subscribed_mailbox().

Referenced by mwi_handle_subscribe().

◆ mwi_handle_unsubscribe()

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

Definition at line 13624 of file app_voicemail.c.

13625{
13626 void *data = ast_mwi_subscriber_data(sub);
13627
13628 /* Don't bump data's reference. We'll just use the one returned above */
13630 /* A reference was returned for data when retrieving, so remove it on error */
13631 ao2_ref(data, -1);
13632 }
13633}
static int mwi_handle_unsubscribe2(void *data)

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

◆ mwi_handle_unsubscribe2()

static int mwi_handle_unsubscribe2 ( void *  data)
static

Definition at line 13605 of file app_voicemail.c.

13606{
13607 struct ast_mwi_state *mwi_state = data;
13608
13609 /*
13610 * Go ahead and clear the implicit MWI publisher here to avoid a leak. If a backing
13611 * configuration is available it'll re-initialize (reset the cached state) on its
13612 * next publish.
13613 */
13615
13616#ifdef IMAP_STORAGE
13617 imap_close_subscribed_mailbox(mwi_state, NULL);
13618#endif
13619
13620 ao2_ref(mwi_state, -1);
13621 return 0;
13622}
The structure that contains MWI state.
Definition: mwi.h:455

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

Referenced by mwi_handle_unsubscribe().

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

8164{
8165 char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
8166 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8167 const char *category;
8168 char *myserveremail = serveremail;
8169
8170 ast_channel_lock(chan);
8171 if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
8172 category = ast_strdupa(category);
8173 }
8174 ast_channel_unlock(chan);
8175
8176#ifndef IMAP_STORAGE
8177 make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
8178#else
8179 snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
8180#endif
8181 make_file(fn, sizeof(fn), todir, msgnum);
8182 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
8183
8184 if (!ast_strlen_zero(vmu->attachfmt)) {
8185 if (strstr(fmt, vmu->attachfmt))
8186 fmt = vmu->attachfmt;
8187 else
8188 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);
8189 }
8190
8191 /* Attach only the first format */
8192 fmt = ast_strdupa(fmt);
8193 stringp = fmt;
8194 strsep(&stringp, "|");
8195
8196 if (!ast_strlen_zero(vmu->serveremail))
8197 myserveremail = vmu->serveremail;
8198
8199 if (!ast_strlen_zero(vmu->email)) {
8200 int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
8201 char *msg_id = NULL;
8202#ifdef IMAP_STORAGE
8203 struct ast_config *msg_cfg;
8204 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8205 char filename[PATH_MAX];
8206
8207 snprintf(filename, sizeof(filename), "%s.txt", fn);
8208 msg_cfg = ast_config_load(filename, config_flags);
8209 if (msg_cfg && msg_cfg != CONFIG_STATUS_FILEINVALID) {
8210 msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
8211 ast_config_destroy(msg_cfg);
8212 }
8213#endif
8214
8215 if (attach_user_voicemail)
8216 RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
8217
8218 /* XXX possible imap issue, should category be NULL XXX */
8219 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);
8220
8221 if (attach_user_voicemail)
8222 DISPOSE(todir, msgnum);
8223 }
8224
8225 if (!ast_strlen_zero(vmu->pager)) {
8226 sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
8227 }
8228
8229 if (ast_test_flag(vmu, VM_DELETE))
8230 DELETE(todir, msgnum, fn, vmu);
8231
8232 /* Leave voicemail for someone */
8233 if (ast_app_has_voicemail(ext_context, NULL))
8234 ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
8235
8236 queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgentmsgs, newmsgs, oldmsgs);
8237 run_externnotify(vmu->context, vmu->mailbox, flag);
8238
8239#ifdef IMAP_STORAGE
8240 vm_delete(fn); /* Delete the file, but not the IMAP message */
8241 if (ast_test_flag(vmu, VM_DELETE)) { /* Delete the IMAP message if delete = yes */
8242 vm_imap_delete(NULL, vms->curmsg, vmu);
8243 vms->newmessages--; /* Fix new message count */
8244 }
8245#endif
8246
8247 return 0;
8248}
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)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
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"....
Definition: main/app.c:582
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:619

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, vm_delete(), and VM_SPOOL_DIR.

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

◆ notify_new_state()

static void notify_new_state ( struct ast_vm_user vmu)
static

Definition at line 16843 of file app_voicemail.c.

16844{
16845 int new = 0, old = 0, urgent = 0;
16846 char ext_context[1024];
16847
16848 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
16849 run_externnotify(vmu->context, vmu->mailbox, NULL);
16850 ast_app_inboxcount2(ext_context, &urgent, &new, &old);
16851 queue_mwi_event(NULL, ext_context, urgent, new, old);
16852}

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

◆ open_mailbox()

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

Definition at line 9105 of file app_voicemail.c.

9106{
9107 int count_msg, last_msg;
9108
9109 ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
9110
9111 /* Rename the member vmbox HERE so that we don't try to return before
9112 * we know what's going on.
9113 */
9114 snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
9115
9116 /* Faster to make the directory than to check if it exists. */
9117 create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
9118
9119 /* traverses directory using readdir (or select query for ODBC) */
9120 count_msg = count_messages(vmu, vms->curdir);
9121 if (count_msg < 0) {
9122 return count_msg;
9123 } else {
9124 vms->lastmsg = count_msg - 1;
9125 }
9126
9127 if (vm_allocate_dh(vms, vmu, count_msg)) {
9128 return -1;
9129 }
9130
9131 /*
9132 The following test is needed in case sequencing gets messed up.
9133 There appears to be more than one way to mess up sequence, so
9134 we will not try to find all of the root causes--just fix it when
9135 detected.
9136 */
9137
9138 if (vm_lock_path(vms->curdir)) {
9139 ast_log(AST_LOG_ERROR, "Could not open mailbox %s: mailbox is locked\n", vms->curdir);
9140 return ERROR_LOCK_PATH;
9141 }
9142
9143 /* for local storage, checks directory for messages up to MAXMSGLIMIT */
9144 last_msg = last_message_index(vms->curdir);
9145 ast_unlock_path(vms->curdir);
9146
9147 if (last_msg < -1) {
9148 return last_msg;
9149 } else if (vms->lastmsg != last_msg) {
9150 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);
9151 resequence_mailbox(vmu, vms->curdir, count_msg);
9152 }
9153
9154 return 0;
9155}
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
char vmbox[PATH_MAX]

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 play_message_by_id(), vm_execmain(), vm_mailbox_snapshot_create(), vm_msg_forward(), vm_msg_move(), vm_msg_play(), and vm_msg_remove().

◆ play_message()

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

Definition at line 8851 of file app_voicemail.c.

8852{
8853 int res = 0;
8854 char filename[PATH_MAX], *cid;
8855 const char *origtime, *context, *category, *duration, *flag;
8856 struct ast_config *msg_cfg;
8857 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8858
8859 vms->starting = 0;
8860 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
8861 adsi_message(chan, vms);
8862 if (!vms->curmsg) {
8863 res = wait_file2(chan, vms, "vm-first"); /* "First" */
8864 } else if (vms->curmsg == vms->lastmsg) {
8865 res = wait_file2(chan, vms, "vm-last"); /* "last" */
8866 }
8867
8868 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
8869 RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
8870 msg_cfg = ast_config_load(filename, config_flags);
8871 if (!valid_config(msg_cfg)) {
8872 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
8873 return 0;
8874 }
8875 flag = ast_variable_retrieve(msg_cfg, "message", "flag");
8876
8877 /* Play the word urgent if we are listening to urgent messages */
8878 if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
8879 res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
8880 }
8881
8882 if (!res) {
8883 /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
8884 /* POLISH syntax */
8885 if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
8886 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
8887 int ten, one;
8888 char nextmsg[256];
8889 ten = (vms->curmsg + 1) / 10;
8890 one = (vms->curmsg + 1) % 10;
8891
8892 if (vms->curmsg < 20) {
8893 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
8894 res = wait_file2(chan, vms, nextmsg);
8895 } else {
8896 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
8897 res = wait_file2(chan, vms, nextmsg);
8898 if (one > 0) {
8899 if (!res) {
8900 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
8901 res = wait_file2(chan, vms, nextmsg);
8902 }
8903 }
8904 }
8905 }
8906 if (!res)
8907 res = wait_file2(chan, vms, "vm-message");
8908 /* HEBREW syntax */
8909 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
8910 if (!vms->curmsg) {
8911 res = wait_file2(chan, vms, "vm-message");
8912 res = wait_file2(chan, vms, "vm-first");
8913 } else if (vms->curmsg == vms->lastmsg) {
8914 res = wait_file2(chan, vms, "vm-message");
8915 res = wait_file2(chan, vms, "vm-last");
8916 } else {
8917 res = wait_file2(chan, vms, "vm-message");
8918 res = wait_file2(chan, vms, "vm-number");
8919 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "f");
8920 }
8921 /* ICELANDIC syntax */
8922 } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) {
8923 res = wait_file2(chan, vms, "vm-message");
8924 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
8925 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "n");
8926 }
8927 /* VIETNAMESE syntax */
8928 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
8929 if (!vms->curmsg) {
8930 res = wait_file2(chan, vms, "vm-message");
8931 res = wait_file2(chan, vms, "vm-first");
8932 } else if (vms->curmsg == vms->lastmsg) {
8933 res = wait_file2(chan, vms, "vm-message");
8934 res = wait_file2(chan, vms, "vm-last");
8935 } else {
8936 res = wait_file2(chan, vms, "vm-message");
8937 res = wait_file2(chan, vms, "vm-number");
8938 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "f");
8939 }
8940 } else {
8941 if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
8942 res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
8943 } else { /* DEFAULT syntax */
8944 res = wait_file2(chan, vms, "vm-message");
8945 }
8946 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
8947 if (!res) {
8948 ast_test_suite_event_notify("PLAYBACK", "Message: message number");
8949 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
8950 }
8951 }
8952 }
8953 }
8954
8955 if (!valid_config(msg_cfg)) {
8956 ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
8957 return 0;
8958 }
8959
8960 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
8961 ast_log(AST_LOG_WARNING, "No origtime?!\n");
8962 DISPOSE(vms->curdir, vms->curmsg);
8963 ast_config_destroy(msg_cfg);
8964 return 0;
8965 }
8966
8967 cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
8968 duration = ast_variable_retrieve(msg_cfg, "message", "duration");
8969 category = ast_variable_retrieve(msg_cfg, "message", "category");
8970
8971 context = ast_variable_retrieve(msg_cfg, "message", "context");
8972 if (!res) {
8973 res = play_message_category(chan, category);
8974 }
8975 if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
8976 res = play_message_datetime(chan, vmu, origtime, filename);
8977 }
8978 if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
8979 res = play_message_callerid(chan, vms, cid, context, 0, 0);
8980 }
8981 if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
8982 res = play_message_duration(chan, vms, duration, vmu->saydurationm);
8983 }
8984 /* Allow pressing '1' to skip envelope / callerid */
8985 if (res == '1') {
8986 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
8987 res = 0;
8988 }
8989 ast_config_destroy(msg_cfg);
8990
8991 if (!res) {
8992 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
8993#ifdef IMAP_STORAGE
8994 ast_mutex_lock(&vms->lock);
8995#endif
8996 vms->heard[vms->curmsg] = 1;
8997#ifdef IMAP_STORAGE
8998 ast_mutex_unlock(&vms->lock);
8999 /*IMAP storage stores any prepended message from a forward
9000 * as a separate file from the rest of the message
9001 */
9002 if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
9003 wait_file(chan, vms, vms->introfn);
9004 }
9005#endif
9006 if ((res = wait_file(chan, vms, vms->fn)) < 0) {
9007 ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
9008 res = 0;
9009 }
9010 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
9011 isprint(res) ? res : '?', isprint(res) ? res : '?');
9012 }
9013 DISPOSE(vms->curdir, vms->curmsg);
9014 return res;
9015}
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
static int play_message_category(struct ast_channel *chan, const char *category)
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)

References adsi_message(), ast_channel_language(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, voicemailpwcheck::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), NULL, PATH_MAX, play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, valid_config(), VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

Referenced by vm_browse_messages_en(), vm_browse_messages_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().

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

11460{
11461 struct vm_state vms;
11462 struct ast_vm_user *vmu = NULL, vmus;
11463 int res = 0;
11464 int open = 0;
11465 int played = 0;
11466 int i;
11467
11468 memset(&vmus, 0, sizeof(vmus));
11469 memset(&vms, 0, sizeof(vms));
11470
11471 if (!(vmu = find_user(&vmus, context, mailbox))) {
11472 goto play_msg_cleanup;
11473 }
11474
11475 /* Iterate through every folder, find the msg, and play it */
11476 for (i = 0; i < ARRAY_LEN(mailbox_folders) && !played; i++) {
11477 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
11478 vms.lastmsg = -1;
11479
11480 /* open the mailbox state */
11481 if ((res = open_mailbox(&vms, vmu, i)) < 0) {
11482 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
11483 res = -1;
11484 goto play_msg_cleanup;
11485 }
11486 open = 1;
11487
11488 /* play msg if it exists in this mailbox */
11489 if ((vms.lastmsg != -1) && !(play_message_by_id_helper(chan, vmu, &vms, msg_id))) {
11490 played = 1;
11491 }
11492
11493 /* close mailbox */
11494 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
11495 res = -1;
11496 goto play_msg_cleanup;
11497 }
11498 open = 0;
11499 }
11500
11501play_msg_cleanup:
11502 if (!played) {
11503 res = -1;
11504 }
11505
11506 if (vmu && open) {
11507 close_mailbox(&vms, vmu);
11508 }
11509
11510#ifdef IMAP_STORAGE
11511 if (vmu) {
11512 vmstate_delete(&vms);
11513 }
11514#endif
11515
11516 free_user(vmu);
11517
11518 return res;
11519}
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int play_message_by_id_helper(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)

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

Referenced by vm_playmsgexec().

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

11420{
11421 if (message_range_and_existence_check(vms, &msg_id, 1, &vms->curmsg, vmu)) {
11422 return -1;
11423 }
11424 /* Found the msg, so play it back */
11425
11426 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
11427
11428#ifdef IMAP_STORAGE
11429 /*IMAP storage stores any prepended message from a forward
11430 * as a separate file from the rest of the message
11431 */
11432 if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
11433 wait_file(chan, vms, vms->introfn);
11434 }
11435#endif
11436 RETRIEVE(vms->curdir,vms->curmsg,vmu->mailbox, vmu->context);
11437
11438 if ((wait_file(chan, vms, vms->fn)) < 0) {
11439 ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
11440 } else {
11441#ifdef IMAP_STORAGE
11442 ast_mutex_lock(&vms->lock);
11443#endif
11444 vms->heard[vms->curmsg] = 1;
11445#ifdef IMAP_STORAGE
11446 ast_mutex_unlock(&vms->lock);
11447#endif
11448 }
11449 DISPOSE(vms->curdir, vms->curmsg);
11450 return 0;
11451}
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.

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

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

8725{
8726 int res = 0;
8727 int i;
8728 char *callerid, *name;
8729 char prefile[PATH_MAX] = "";
8730
8731 /* If voicemail cid is not enabled, or we didn't get cid or context from
8732 * the attribute file, leave now.
8733 *
8734 * TODO Still need to change this so that if this function is called by the
8735 * message envelope (and someone is explicitly requesting to hear the CID),
8736 * it does not check to see if CID is enabled in the config file.
8737 */
8738 if ((cid == NULL)||(context == NULL))
8739 return res;
8740
8741 /* Strip off caller ID number from name */
8742 ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
8743 ast_callerid_parse(cid, &name, &callerid);
8744 if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
8745 /* Check for internal contexts and only */
8746 /* say extension when the call didn't come from an internal context in the list */
8747 for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
8748 ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
8749 if ((strcmp(cidinternalcontexts[i], context) == 0))
8750 break;
8751 }
8752 if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
8753 if (!res) {
8754 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
8755 if (!ast_strlen_zero(prefile)) {
8756 /* See if we can find a recorded name for this callerid
8757 * and if found, use that instead of saying number. */
8758 if (ast_fileexists(prefile, NULL, NULL) > 0) {
8759 ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
8760 if (!callback)
8761 res = wait_file2(chan, vms, "vm-from");
8762 res = ast_stream_and_wait(chan, prefile, "");
8763 } else {
8764 ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
8765 /* Say "from extension" as one saying to sound smoother */
8766 if (!callback)
8767 res = wait_file2(chan, vms, "vm-from-extension");
8768 res = ast_say_digit_str(chan, callerid, "", ast_channel_language(chan));
8769 }
8770 }
8771 }
8772 } else if (!res) {
8773 ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
8774 /* If there is a recording for this numeric callerid then play that */
8775 if (!callback) {
8776 /* See if we can find a recorded name for this person instead of their extension number */
8777 snprintf(prefile, sizeof(prefile), "%s/recordings/callerids/%s", ast_config_AST_SPOOL_DIR, callerid);
8778 if (!saycidnumber && ast_fileexists(prefile, NULL, NULL) > 0) {
8779 ast_verb(3, "Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
8780 wait_file2(chan, vms, "vm-from");
8781 res = ast_stream_and_wait(chan, prefile, "");
8782 ast_verb(3, "Played recorded name result '%d'\n", res);
8783 } else {
8784 /* Since this is all nicely figured out, why not say "from phone number" in this case" */
8785 wait_file2(chan, vms, "vm-from-phonenumber");
8786 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
8787 }
8788 } else {
8789 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
8790 }
8791 }
8792 } else {
8793 /* Number unknown */
8794 ast_debug(1, "VM-CID: From an unknown number\n");
8795 /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
8796 res = wait_file2(chan, vms, "vm-unknown-caller");
8797 }
8798 return res;
8799}

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

Referenced by advanced_options(), and play_message().

◆ play_message_category()

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

Definition at line 8631 of file app_voicemail.c.

8632{
8633 int res = 0;
8634
8635 if (!ast_strlen_zero(category))
8636 res = ast_play_and_wait(chan, category);
8637
8638 if (res) {
8639 ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
8640 res = 0;
8641 }
8642
8643 return res;
8644}

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

Referenced by play_message().

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

8647{
8648 int res = 0;
8649 struct vm_zone *the_zone = NULL;
8650 time_t t;
8651
8652 if (ast_get_time_t(origtime, &t, 0, NULL)) {
8653 ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
8654 return 0;
8655 }
8656
8657 /* Does this user have a timezone specified? */
8658 if (!ast_strlen_zero(vmu->zonetag)) {
8659 /* Find the zone in the list */
8660 struct vm_zone *z;
8663 if (!strcmp(z->name, vmu->zonetag)) {
8664 the_zone = z;
8665 break;
8666 }
8667 }
8669 }
8670
8671/* No internal variable parsing for now, so we'll comment it out for the time being */
8672#if 0
8673 /* Set the DIFF_* variables */
8674 ast_localtime(&t, &time_now, NULL);
8675 tv_now = ast_tvnow();
8676 ast_localtime(&tv_now, &time_then, NULL);
8677
8678 /* Day difference */
8679 if (time_now.tm_year == time_then.tm_year)
8680 snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
8681 else
8682 snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
8683 pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
8684
8685 /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
8686#endif
8687 if (the_zone) {
8688 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), the_zone->msg_format, the_zone->timezone);
8689 } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */
8690 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
8691 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */
8692 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q H 'digits/kai' M ", NULL);
8693 } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC 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), "it", 2)) { /* ITALIAN syntax */
8696 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);
8697 } else if (!strcasecmp(ast_channel_language(chan),"ja")) { /* Japanese syntax */
8698 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "PHM q 'jp-ni' 'vm-received'", NULL);
8699 } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */
8700 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/nl-om' HM", NULL);
8701 } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
8702 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
8703 } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
8704 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q HM", NULL);
8705 } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* Brazilian PORTUGUESE syntax */
8706 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);
8707 } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
8708 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' dB 'digits/at' k 'and' M", NULL);
8709 } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
8710 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "qR 'vm-received'", NULL);
8711 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
8712 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);
8713 } else {
8714 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' IMp", NULL);
8715 }
8716#if 0
8717 pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
8718#endif
8719 return res;
8720}
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:208
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
Parse a time (integer) string.
Definition: utils.c:2446

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

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

8802{
8803 int res = 0;
8804 int durationm;
8805 int durations;
8806 /* Verify that we have a duration for the message */
8807 if (duration == NULL)
8808 return res;
8809
8810 /* Convert from seconds to minutes */
8811 durations = atoi(duration);
8812 durationm = (durations / 60);
8813
8814 ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
8815
8816 if ((!res) && (durationm >= minduration)) {
8817 res = wait_file2(chan, vms, "vm-duration");
8818
8819 /* POLISH syntax */
8820 if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
8821 div_t num = div(durationm, 10);
8822
8823 if (durationm == 1) {
8824 res = ast_play_and_wait(chan, "digits/1z");
8825 res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
8826 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8827 if (num.rem == 2) {
8828 if (!num.quot) {
8829 res = ast_play_and_wait(chan, "digits/2-ie");
8830 } else {
8831 res = say_and_wait(chan, durationm - 2 , ast_channel_language(chan));
8832 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
8833 }
8834 } else {
8835 res = say_and_wait(chan, durationm, ast_channel_language(chan));
8836 }
8837 res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
8838 } else {
8839 res = say_and_wait(chan, durationm, ast_channel_language(chan));
8840 res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
8841 }
8842 /* DEFAULT syntax */
8843 } else {
8844 res = ast_say_number(chan, durationm, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
8845 res = wait_file2(chan, vms, "vm-minutes");
8846 }
8847 }
8848 return res;
8849}
static int say_and_wait(struct ast_channel *chan, int num, const char *language)

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

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

16213{
16214 /* Record message & let caller review or re-record it, or set options if applicable */
16215 int res = 0;
16216 int cmd = 0;
16217 int max_attempts = 3;
16218 int attempts = 0;
16219 int recorded = 0;
16220 int msg_exists = 0;
16221 signed char zero_gain = 0;
16222 char tempfile[PATH_MAX];
16223 char *acceptdtmf = "#";
16224 char *canceldtmf = "";
16225 int canceleddtmf = 0;
16226
16227 /* Note that urgent and private are for flagging messages as such in the future */
16228
16229 /* barf if no pointer passed to store duration in */
16230 if (duration == NULL) {
16231 ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
16232 return -1;
16233 }
16234
16235 if (!outsidecaller)
16236 snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
16237 else
16238 ast_copy_string(tempfile, recordfile, sizeof(tempfile));
16239
16240 cmd = '3'; /* Want to start by recording */
16241
16242 while ((cmd >= 0) && (cmd != 't')) {
16243 switch (cmd) {
16244 case '1':
16245 if (!msg_exists) {
16246 /* In this case, 1 is to record a message */
16247 cmd = '3';
16248 break;
16249 } else {
16250 /* Otherwise 1 is to save the existing message */
16251 ast_verb(3, "Saving message as is\n");
16252 if (!outsidecaller)
16253 ast_filerename(tempfile, recordfile, NULL);
16254 if (!forwardintro) {
16255 ast_stream_and_wait(chan, "vm-msgsaved", "");
16256 }
16257 if (!outsidecaller) {
16258 /* Saves to IMAP server only if imapgreeting=yes */
16259 STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id);
16260 DISPOSE(recordfile, -1);
16261 }
16262 cmd = 't';
16263 return res;
16264 }
16265 case '2':
16266 /* Review */
16267 ast_verb(3, "Reviewing the message\n");
16268 cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
16269 break;
16270 case '3':
16271 msg_exists = 0;
16272 /* Record */
16273 if (recorded == 1)
16274 ast_verb(3, "Re-recording the message\n");
16275 else
16276 ast_verb(3, "Recording the message\n");
16277
16278 if (recorded && outsidecaller) {
16279 if (forwardintro) {
16280 cmd = ast_play_and_wait(chan, "vm-record-prepend");
16281 } else {
16282 cmd = ast_play_and_wait(chan, INTRO);
16283 }
16284 cmd = ast_play_and_wait(chan, "beep");
16285 }
16286 if (cmd == -1) {
16287 /* User has hung up, no options to give */
16288 ast_debug(1, "User hung up before message could be rerecorded\n");
16289 ast_filedelete(tempfile, NULL);
16290 return cmd;
16291 }
16292 recorded = 1;
16293 /* 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 */
16294 if (record_gain)
16295 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
16296 if (ast_test_flag(vmu, VM_OPERATOR))
16297 canceldtmf = "0";
16298 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);
16299 if (strchr(canceldtmf, cmd)) {
16300 /* need this flag here to distinguish between pressing '0' during message recording or after */
16301 canceleddtmf = 1;
16302 }
16303 if (record_gain)
16304 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
16305 if (cmd == -1) {
16306 /* User has hung up, no options to give */
16307 if (!outsidecaller) {
16308 /* user was recording a greeting and they hung up, so let's delete the recording. */
16309 ast_filedelete(tempfile, NULL);
16310 }
16311 return cmd;
16312 }
16313 if (cmd == '0') {
16314 break;
16315 } else if (cmd == '*') {
16316 break;
16317#if 0
16318 } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
16319 /* Message is too short */
16320 ast_verb(3, "Message too short\n");
16321 cmd = ast_play_and_wait(chan, "vm-tooshort");
16322 cmd = ast_filedelete(tempfile, NULL);
16323 break;
16324 } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
16325 /* Message is all silence */
16326 ast_verb(3, "Nothing recorded\n");
16327 cmd = ast_filedelete(tempfile, NULL);
16328 cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
16329 if (!cmd)
16330 cmd = ast_play_and_wait(chan, "vm-speakup");
16331 break;
16332#endif
16333 } else {
16334 /* If all is well, a message exists */
16335 msg_exists = 1;
16336 cmd = 0;
16337 }
16338 break;
16339 case '4':
16340 if (outsidecaller && ast_test_flag(vmu, VM_MARK_URGENT)) { /* only mark vm messages */
16341 /* Mark Urgent */
16342 if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
16343 ast_verb(3, "marking message as Urgent\n");
16344 res = ast_play_and_wait(chan, "vm-marked-urgent");
16345 strcpy(flag, "Urgent");
16346 } else if (flag) {
16347 ast_verb(3, "UNmarking message as Urgent\n");
16348 res = ast_play_and_wait(chan, "vm-marked-nonurgent");
16349 strcpy(flag, "");
16350 } else {
16351 ast_play_and_wait(chan, "vm-sorry");
16352 }
16353 cmd = 0;
16354 } else {
16355 cmd = ast_play_and_wait(chan, "vm-sorry");
16356 }
16357 break;
16358 case '5':
16359 case '6':
16360 case '7':
16361 case '8':
16362 case '9':
16363 case '*':
16364 case '#':
16365 cmd = ast_play_and_wait(chan, "vm-sorry");
16366 break;
16367#if 0
16368/* XXX Commented out for the moment because of the dangers of deleting
16369 a message while recording (can put the message numbers out of sync) */
16370 case '*':
16371 /* Cancel recording, delete message, offer to take another message*/
16372 cmd = ast_play_and_wait(chan, "vm-deleted");
16373 cmd = ast_filedelete(tempfile, NULL);
16374 if (outsidecaller) {
16375 res = vm_exec(chan, NULL);
16376 return res;
16377 }
16378 else
16379 return 1;
16380#endif
16381 case '0':
16382 if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
16383 cmd = ast_play_and_wait(chan, "vm-sorry");
16384 break;
16385 }
16386 if (msg_exists || recorded) {
16387 cmd = ast_play_and_wait(chan, "vm-saveoper");
16388 if (!cmd)
16389 cmd = ast_waitfordigit(chan, 3000);
16390 if (cmd == '1') {
16391 ast_filerename(tempfile, recordfile, NULL);
16392 ast_play_and_wait(chan, "vm-msgsaved");
16393 cmd = '0';
16394 } else if (cmd == '4') {
16395 if (flag) {
16396 ast_play_and_wait(chan, "vm-marked-urgent");
16397 strcpy(flag, "Urgent");
16398 }
16399 ast_play_and_wait(chan, "vm-msgsaved");
16400 cmd = '0';
16401 } else {
16402 ast_play_and_wait(chan, "vm-deleted");
16403 DELETE(tempfile, -1, tempfile, vmu);
16404 DISPOSE(tempfile, -1);
16405 cmd = '0';
16406 }
16407 }
16408 return cmd;
16409 default:
16410 /* If the caller is an outside caller and the review option is enabled or it's forward intro
16411 allow them to review the message, but let the owner of the box review
16412 their OGM's */
16413 if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro)
16414 return cmd;
16415 if (msg_exists) {
16416 cmd = ast_play_and_wait(chan, "vm-review");
16417 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_MARK_URGENT)) {
16418 if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
16419 cmd = ast_play_and_wait(chan, "vm-review-urgent");
16420 } else if (flag) {
16421 cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
16422 }
16423 }
16424 } else {
16425 cmd = ast_play_and_wait(chan, "vm-torerecord");
16426 if (!cmd)
16427 cmd = ast_waitfordigit(chan, 600);
16428 }
16429
16430 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
16431 cmd = ast_play_and_wait(chan, "vm-reachoper");
16432 if (!cmd)
16433 cmd = ast_waitfordigit(chan, 600);
16434 }
16435#if 0
16436 if (!cmd)
16437 cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
16438#endif
16439 if (!cmd)
16440 cmd = ast_waitfordigit(chan, 6000);
16441 if (!cmd) {
16442 attempts++;
16443 }
16444 if (attempts > max_attempts) {
16445 cmd = 't';
16446 }
16447 }
16448 }
16449 if (!outsidecaller && (cmd == -1 || cmd == 't')) {
16450 /* Hang up or timeout, so delete the recording. */
16451 ast_filedelete(tempfile, NULL);
16452 }
16453
16454 if (cmd != 't' && outsidecaller)
16455 ast_play_and_wait(chan, "vm-goodbye");
16456
16457 return cmd;
16458}
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:7422
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:2139
@ AST_RECORD_IF_EXISTS_OVERWRITE
#define AST_OPTION_RXGAIN

References ast_channel_setoption(), ast_copy_string(), ast_debug, 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, maxsilence, NULL, PATH_MAX, leave_vm_options::record_gain, silencethreshold, STORE, vm_exec(), VM_MARK_URGENT, VM_OPERATOR, and VM_REVIEW.

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

◆ poll_subscribed_mailbox()

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

Definition at line 13510 of file app_voicemail.c.

13511{
13512 int new = 0, old = 0, urgent = 0;
13513
13514 if (!mwi_state) {
13515 /* This should only occur due to allocation failure of a default mwi state object */
13516 return 0;
13517 }
13518
13519 inboxcount2(mwi_state->uniqueid, &urgent, &new, &old);
13520
13521#ifdef IMAP_STORAGE
13522 if (imap_poll_logout) {
13523 imap_logout(mwi_state->uniqueid);
13524 }
13525#endif
13526
13527 if (urgent != mwi_state->urgent_msgs || new != mwi_state->new_msgs || old != mwi_state->old_msgs) {
13528 queue_mwi_event(NULL, mwi_state->uniqueid, urgent, new, old);
13529 run_externnotify(NULL, mwi_state->uniqueid, NULL);
13530 }
13531
13532 return 0;
13533}
int urgent_msgs
Definition: mwi.h:464
int old_msgs
Definition: mwi.h:460
int new_msgs
Definition: mwi.h:459

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

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

1340{
1343 if (saydurationminfo) {
1345 }
1346 ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
1347 ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
1348 ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
1349 ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
1350 ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
1351 if (vmminsecs) {
1352 vmu->minsecs = vmminsecs;
1353 }
1354 if (vmmaxsecs) {
1355 vmu->maxsecs = vmmaxsecs;
1356 }
1357 if (maxmsg) {
1358 vmu->maxmsg = maxmsg;
1359 }
1360 if (maxdeletedmsg) {
1362 }
1363 vmu->volgain = volgain;
1364 ast_free(vmu->email);
1365 vmu->email = NULL;
1366 ast_free(vmu->emailsubject);
1367 vmu->emailsubject = NULL;
1368 ast_free(vmu->emailbody);
1369 vmu->emailbody = NULL;
1370#ifdef IMAP_STORAGE
1371 ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
1372 ast_copy_string(vmu->imapserver, imapserver, sizeof(vmu->imapserver));
1373 ast_copy_string(vmu->imapport, imapport, sizeof(vmu->imapport));
1374 ast_copy_string(vmu->imapflags, imapflags, sizeof(vmu->imapflags));
1375#endif
1376}
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define AST_FLAGS_ALL
Definition: utils.h:196

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

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

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

4892{
4893 char callerid[256];
4894 char num[12];
4895 char fromdir[256], fromfile[256];
4896 struct ast_config *msg_cfg;
4897 const char *origcallerid, *origtime;
4898 char origcidname[80], origcidnum[80], origdate[80];
4899 int inttime;
4900 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
4901
4902 /* Prepare variables for substitution in email body and subject */
4903 pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
4904 pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
4905 snprintf(num, sizeof(num), "%d", msgnum);
4906 pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
4907 pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
4908 pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
4909 pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
4910 ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
4911 pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
4912 pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
4913 pbx_builtin_setvar_helper(ast, "VM_DATE", date);
4914 pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
4915 pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
4916
4917 /* Retrieve info from VM attribute file */
4918 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
4919 make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
4920 if (strlen(fromfile) < sizeof(fromfile) - 5) {
4921 strcat(fromfile, ".txt");
4922 }
4923 if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
4924 ast_debug(1, "Config load for message text file '%s' failed\n", fromfile);
4925 return;
4926 }
4927
4928 if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
4929 pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
4930 ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
4931 pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
4932 pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
4933 }
4934
4935 if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
4936 struct timeval tv = { inttime, };
4937 struct ast_tm tm;
4938 ast_localtime(&tv, &tm, NULL);
4939 ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
4940 pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
4941 }
4942 ast_config_destroy(msg_cfg);
4943}

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, voicemailpwcheck::context, emaildateformat, ast_vm_user::fullname, ast_vm_user::locale, ast_vm_user::mailbox, voicemailpwcheck::mailbox, make_dir(), make_file(), NULL, pbx_builtin_setvar_helper(), S_OR, and valid_config().

Referenced by make_email_file(), and sendpage().

◆ print_mappings()

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

Definition at line 15803 of file app_voicemail.c.

15804{
15805 struct alias_mailbox_mapping *mapping = v_obj;
15806
15807 if (!mapping) {
15808 return;
15809 }
15810 prnt(where, "Alias: %s Mailbox: %s", mapping->alias, mapping->mailbox);
15811}

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

Referenced by load_module().

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

8119{
8120 char *mailbox;
8121 char *context;
8122
8124 return;
8125 }
8126
8127 ast_debug(3, "Queueing event for mailbox %s New: %d Old: %d\n", box, new + urgent, old);
8128 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8129
8131 struct ao2_iterator *aliases;
8132 struct mailbox_alias_mapping *mapping;
8133
8135 while ((mapping = ao2_iterator_next(aliases))) {
8136 char alias[strlen(mapping->alias) + 1];
8137 strcpy(alias, mapping->alias); /* safe */
8138 mailbox = NULL;
8139 context = NULL;
8140 ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);
8142 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8143 ao2_ref(mapping, -1);
8144 }
8146 }
8147}
#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:395

References mailbox_alias_mapping::alias, aliases, aliasescontext, ao2_find, ao2_iterator_destroy(), ao2_iterator_next, ao2_ref, ast_debug, ast_publish_mwi_state_channel, ast_strdupa, ast_strlen_zero(), voicemailpwcheck::context, voicemailpwcheck::mailbox, mailbox_alias_mappings, 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().

◆ read_password_from_file()

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

Definition at line 15089 of file app_voicemail.c.

15089 {
15090 struct ast_config *pwconf;
15091 struct ast_flags config_flags = { 0 };
15092
15093 pwconf = ast_config_load(secretfn, config_flags);
15094 if (valid_config(pwconf)) {
15095 const char *val = ast_variable_retrieve(pwconf, "general", "password");
15096 if (val) {
15097 ast_copy_string(password, val, passwordlen);
15098 ast_config_destroy(pwconf);
15099 return;
15100 }
15101 ast_config_destroy(pwconf);
15102 }
15103 ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
15104}

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

◆ reload()

static int reload ( void  )
static

Definition at line 15745 of file app_voicemail.c.

15746{
15747 return load_config(1);
15748}

References load_config().

Referenced by load_config(), and load_config_force().

◆ remove_message_from_mailbox()

static int remove_message_from_mailbox ( struct ast_cli_args a)
static

Definition at line 11662 of file app_voicemail.c.

11663{
11664 const char *mailbox = a->argv[2];
11665 const char *context = a->argv[3];
11666 const char *folder = a->argv[4];
11667 const char *id[] = { a->argv[5] };
11668 int ret = vm_msg_remove(mailbox, context, 1, folder, id);
11669 if (ret) {
11670 ast_cli(a->fd, "Error removing message %s from mailbox %s@%s %s\n",
11671 id[0], mailbox, context, folder);
11672 } else {
11673 ast_cli(a->fd, "Removed message %s from mailbox %s@%s %s\n",
11674 id[0], mailbox, context, folder);
11675 }
11676 return ret;
11677}

References a, ast_cli(), voicemailpwcheck::context, voicemailpwcheck::mailbox, and vm_msg_remove().

Referenced by handle_voicemail_remove_message().

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

4686{
4687 char stxt[PATH_MAX];
4688 char dtxt[PATH_MAX];
4689 ast_filerename(sfn, dfn, NULL);
4690 snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
4691 snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
4692 if (ast_check_realtime("voicemail_data")) {
4693 ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
4694 }
4695 rename(stxt, dtxt);
4696}

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

◆ resequence_mailbox()

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

Definition at line 7182 of file app_voicemail.c.

7183{
7184 /* we know the actual number of messages, so stop process when number is hit */
7185
7186 int x, dest;
7187 char sfn[PATH_MAX];
7188 char dfn[PATH_MAX];
7189
7190 if (vm_lock_path(dir)) {
7191 return ERROR_LOCK_PATH;
7192 }
7193
7194 for (x = 0, dest = 0; dest != stopcount && x < MAXMSGLIMIT; x++) {
7195 make_file(sfn, sizeof(sfn), dir, x);
7196 if (EXISTS(dir, x, sfn, NULL)) {
7197
7198 if (x != dest) {
7199 make_file(dfn, sizeof(dfn), dir, dest);
7200 RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
7201 }
7202
7203 dest++;
7204 }
7205 }
7206 ast_unlock_path(dir);
7207
7208 return dest;
7209}

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

Referenced by open_mailbox().

◆ 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
newpass

This does the actual change password work, called by the vm_change_password() function.

Returns
zero on success, -1 on error.

Definition at line 1867 of file app_voicemail.c.

1868{
1869 /* This function could be made to generate one from a database, too */
1870 struct ast_vm_user *cur;
1871 int res = -1;
1873 AST_LIST_TRAVERSE(&users, cur, list) {
1874 if ((!context || !strcasecmp(context, cur->context)) &&
1875 (!strcasecmp(mailbox, cur->mailbox)))
1876 break;
1877 }
1878 if (cur) {
1879 ast_copy_string(cur->password, newpass, sizeof(cur->password));
1880 res = 0;
1881 }
1883 if (!res) {
1884 struct ast_json *json_object;
1885
1886 json_object = ast_json_pack("{s: s, s: s, s: s}",
1887 "Context", S_OR(context, "default"),
1888 "Mailbox", mailbox,
1889 "NewPassword", newpass);
1890 ast_manager_publish_event("VoicemailPasswordChange", EVENT_FLAG_SYSTEM | EVENT_FLAG_USER, json_object);
1891 ast_json_unref(json_object);
1892 }
1893 return res;
1894}
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:2055
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
Abstract JSON element (object, array, string, int, ...).

References ast_copy_string(), ast_json_pack(), ast_json_unref(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_manager_publish_event(), ast_vm_user::context, voicemailpwcheck::context, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, ast_vm_user::list, ast_vm_user::mailbox, voicemailpwcheck::mailbox, ast_vm_user::password, and S_OR.

Referenced by vm_change_password(), and vm_change_password_shell().

◆ run_externnotify()

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

Definition at line 6230 of file app_voicemail.c.

6231{
6232 char arguments[255];
6233 char ext_context[256] = "";
6234 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6235 struct ast_smdi_mwi_message *mwi_msg;
6236
6238 snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
6239 else
6240 ast_copy_string(ext_context, extension, sizeof(ext_context));
6241
6242 if (smdi_iface) {
6243 if (ast_app_has_voicemail(ext_context, NULL))
6245 else
6247
6249 ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
6250 if (!strncmp(mwi_msg->cause, "INV", 3))
6251 ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
6252 else if (!strncmp(mwi_msg->cause, "BLK", 3))
6253 ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
6254 ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
6255 ao2_ref(mwi_msg, -1);
6256 } else {
6257 ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
6258 }
6259 }
6260
6262 if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6263 ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
6264 } else {
6265 snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
6266 externnotify, S_OR(context, "\"\""),
6267 extension, newvoicemails,
6268 oldvoicemails, urgentvoicemails);
6269 ast_debug(1, "Executing %s\n", arguments);
6270 ast_safe_system(arguments);
6271 }
6272 }
6273}
#define SMDI_MWI_WAIT_TIMEOUT
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
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
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
An SMDI message waiting indicator message.
Definition: smdi.h:51
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
Definition: smdi.h:54
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:53

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, voicemailpwcheck::context, externnotify, ast_smdi_mwi_message::fwd_st, inboxcount2(), NULL, S_OR, smdi_iface, and SMDI_MWI_WAIT_TIMEOUT.

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

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

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

References ast_debug, ast_log, AST_LOG_ERROR, AST_LOG_NOTICE, ast_mutex_lock, ast_mutex_unlock, ast_unlock_path(), ast_vm_user::context, voicemailpwcheck::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, voicemailpwcheck::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_execmain(), and vm_msg_move().

◆ say_and_wait()

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

◆ sayname()

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

Definition at line 15052 of file app_voicemail.c.

15053{
15054 int res = -1;
15055 char dir[PATH_MAX];
15056 snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
15057 ast_debug(2, "About to try retrieving name file %s\n", dir);
15058 RETRIEVE(dir, -1, mailbox, context);
15059 if (ast_fileexists(dir, NULL, NULL)) {
15060 res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
15061 }
15062 DISPOSE(dir, -1);
15063 return res;
15064}

References ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_stream_and_wait(), voicemailpwcheck::context, DISPOSE, voicemailpwcheck::mailbox, NULL, PATH_MAX, RETRIEVE, and VM_SPOOL_DIR.

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

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

5533{
5534 FILE *p = NULL;
5535 char tmp[80] = "/tmp/astmail-XXXXXX";
5536 char tmp2[256];
5537 char *stringp;
5538
5539 if (vmu && ast_strlen_zero(vmu->email)) {
5540 ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
5541 return(0);
5542 }
5543
5544 /* Mail only the first format */
5545 format = ast_strdupa(format);
5546 stringp = format;
5547 strsep(&stringp, "|");
5548
5549 if (!strcmp(format, "wav49"))
5550 format = "WAV";
5551 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));
5552 /* Make a temporary file instead of piping directly to sendmail, in case the mail
5553 command hangs */
5555 ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
5556 return -1;
5557 } else {
5558 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);
5559 fclose(p);
5560 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5561 ast_safe_system(tmp2);
5562 ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
5563 }
5564 return 0;
5565}
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.
FILE * ast_file_mkftemp(char *template, mode_t mode)
same as mkstemp, but return a FILE
Definition: file.c:187

References ast_debug, ast_file_mkftemp(), ast_log, AST_LOG_WARNING, ast_safe_system(), ast_strdupa, ast_strlen_zero(), ast_test_flag, voicemailpwcheck::context, ast_vm_user::email, globalflags, ast_vm_user::mailbox, voicemailpwcheck::mailbox, mailcmd, make_email_file(), my_umask, NULL, strsep(), tmp(), VM_ATTACH, and VOICEMAIL_FILE_MODE.

Referenced by forward_message(), and notify_new_message().

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

5568{
5569 char enc_cidnum[256], enc_cidname[256];
5570 char date[256];
5571 char host[MAXHOSTNAMELEN] = "";
5572 char who[256];
5573 char dur[PATH_MAX];
5574 char tmp[80] = "/tmp/astmail-XXXXXX";
5575 char tmp2[PATH_MAX];
5576 struct ast_tm tm;
5577 FILE *p;
5578 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
5579
5580 if (!str1 || !str2) {
5581 ast_free(str1);
5582 ast_free(str2);
5583 return -1;
5584 }
5585
5586 if (cidnum) {
5587 strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
5588 }
5589 if (cidname) {
5590 strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
5591 }
5592
5594 ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
5595 ast_free(str1);
5596 ast_free(str2);
5597 return -1;
5598 }
5599 gethostname(host, sizeof(host)-1);
5600 if (strchr(srcemail, '@')) {
5601 ast_copy_string(who, srcemail, sizeof(who));
5602 } else {
5603 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
5604 }
5605 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
5606 ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
5607 fprintf(p, "Date: %s\n", date);
5608
5609 /* Reformat for custom pager format */
5610 ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
5611
5613 struct ast_channel *ast;
5614 if ((ast = ast_dummy_channel_alloc())) {
5615 char *ptr;
5616 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5618
5619 if (check_mime(ast_str_buffer(str1))) {
5620 int first_line = 1;
5621 ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
5622 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5623 *ptr = '\0';
5624 fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
5625 first_line = 0;
5626 /* Substring is smaller, so this will never grow */
5627 ast_str_set(&str2, 0, "%s", ptr + 1);
5628 }
5629 fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
5630 } else {
5631 fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
5632 }
5633 ast = ast_channel_unref(ast);
5634 } else {
5635 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5636 }
5637 } else {
5638 fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
5639 }
5640
5641 if (check_mime(vmu->fullname)) {
5642 int first_line = 1;
5643 char *ptr;
5644 ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
5645 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5646 *ptr = '\0';
5647 fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
5648 first_line = 0;
5649 /* Substring is smaller, so this will never grow */
5650 ast_str_set(&str2, 0, "%s", ptr + 1);
5651 }
5652 fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
5653 } else {
5654 fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
5655 }
5656
5658 struct ast_channel *ast;
5659 if ((ast = ast_dummy_channel_alloc())) {
5660 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5662 if (check_mime(ast_str_buffer(str1))) {
5663 int first_line = 1;
5664 char *ptr;
5665 ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
5666 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5667 *ptr = '\0';
5668 fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5669 first_line = 0;
5670 /* Substring is smaller, so this will never grow */
5671 ast_str_set(&str2, 0, "%s", ptr + 1);
5672 }
5673 fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5674 } else {
5675 fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
5676 }
5677 ast = ast_channel_unref(ast);
5678 } else {
5679 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5680 }
5681 } else {
5682 if (ast_strlen_zero(flag)) {
5683 fprintf(p, "Subject: New VM\n\n");
5684 } else {
5685 fprintf(p, "Subject: New %s VM\n\n", flag);
5686 }
5687 }
5688
5689 if (pagerbody) {
5690 struct ast_channel *ast;
5691 if ((ast = ast_dummy_channel_alloc())) {
5692 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5694 fprintf(p, "%s" ENDL, ast_str_buffer(str1));
5695 ast = ast_channel_unref(ast);
5696 } else {
5697 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5698 }
5699 } else {
5700 fprintf(p, "New %s long %s msg in box %s\n"
5701 "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
5702 }
5703
5704 fclose(p);
5705 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5706 ast_safe_system(tmp2);
5707 ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
5708 ast_free(str1);
5709 ast_free(str2);
5710 return 0;
5711}

References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_file_mkftemp(), 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(), voicemailpwcheck::context, ENDL, ast_vm_user::fullname, ast_vm_user::locale, voicemailpwcheck::mailbox, mailcmd, MAXHOSTNAMELEN, my_umask, NULL, pagerbody, pagerdateformat, pagerfromstring, pagersubject, PATH_MAX, prep_email_sub_vars(), S_OR, strip_control_and_high(), tmp(), vmu_tm(), and VOICEMAIL_FILE_MODE.

Referenced by notify_new_message().

◆ separate_mailbox()

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

Definition at line 1228 of file app_voicemail.c.

1229{
1230 if (ast_strlen_zero(mailbox_id) || !mailbox || !context) {
1231 return -1;
1232 }
1233 *context = mailbox_id;
1234 *mailbox = strsep(context, "@");
1235 if (ast_strlen_zero(*mailbox)) {
1236 return -1;
1237 }
1238 if (ast_strlen_zero(*context)) {
1239 *context = "default";
1240 }
1241 return 0;
1242}

References ast_strlen_zero(), voicemailpwcheck::context, voicemailpwcheck::mailbox, and strsep().

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

◆ show_mailbox_details()

static int show_mailbox_details ( struct ast_cli_args a)
static

Definition at line 11560 of file app_voicemail.c.

11561{
11562#define VMBOX_STRING_HEADER_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11563#define VMBOX_STRING_DATA_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11564
11565 const char *mailbox = a->argv[3];
11566 const char *context = a->argv[4];
11567 struct vm_state vms;
11568 struct ast_vm_user *vmu = NULL, vmus;
11569 memset(&vmus, 0, sizeof(vmus));
11570 memset(&vms, 0, sizeof(vms));
11571
11572 if (!(vmu = find_user(&vmus, context, mailbox))) {
11573 ast_cli(a->fd, "Can't find voicemail user %s@%s\n", mailbox, context);
11574 return -1;
11575 }
11576
11577 ast_cli(a->fd, VMBOX_STRING_HEADER_FORMAT, "Full Name", "Email", "Pager", "Language", "Locale", "Time Zone");
11578 ast_cli(a->fd, VMBOX_STRING_DATA_FORMAT, vmu->fullname, vmu->email, vmu->pager, vmu->language, vmu->locale, vmu->zonetag);
11579
11580 return 0;
11581}
#define VMBOX_STRING_DATA_FORMAT
#define VMBOX_STRING_HEADER_FORMAT

References a, ast_cli(), voicemailpwcheck::context, ast_vm_user::email, find_user(), ast_vm_user::fullname, ast_vm_user::language, ast_vm_user::locale, voicemailpwcheck::mailbox, NULL, ast_vm_user::pager, VMBOX_STRING_DATA_FORMAT, VMBOX_STRING_HEADER_FORMAT, and ast_vm_user::zonetag.

Referenced by show_messages_for_mailbox().

◆ show_mailbox_snapshot()

static int show_mailbox_snapshot ( struct ast_cli_args a)
static

Definition at line 11583 of file app_voicemail.c.

11584{
11585#define VM_STRING_HEADER_FORMAT "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"
11586 const char *mailbox = a->argv[3];
11587 const char *context = a->argv[4];
11588 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
11589 struct ast_vm_msg_snapshot *msg;
11590 int i;
11591
11592 /* Take a snapshot of the mailbox and walk through each folder's contents */
11594 if (!mailbox_snapshot) {
11595 ast_cli(a->fd, "Can't create snapshot for voicemail user %s@%s\n", mailbox, context);
11596 return -1;
11597 }
11598
11599 ast_cli(a->fd, VM_STRING_HEADER_FORMAT, "Folder", "Caller ID", "Date", "Duration", "Flag", "ID");
11600
11601 for (i = 0; i < mailbox_snapshot->folders; i++) {
11602 AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) {
11603 ast_cli(a->fd, VM_STRING_HEADER_FORMAT, msg->folder_name, msg->callerid, msg->origdate, msg->duration,
11604 msg->flag, msg->msg_id);
11605 }
11606 }
11607
11608 ast_cli(a->fd, "%d Message%s Total\n", mailbox_snapshot->total_msg_num, ESS(mailbox_snapshot->total_msg_num));
11609 /* done, destroy. */
11610 mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
11611
11612 return 0;
11613}
#define VM_STRING_HEADER_FORMAT
#define ESS(x)
Definition: cli.h:59

References a, ast_cli(), AST_LIST_TRAVERSE, ast_vm_mailbox_snapshot_create(), ast_vm_mailbox_snapshot_destroy(), AST_VM_SNAPSHOT_SORT_BY_ID, voicemailpwcheck::context, ESS, ast_vm_mailbox_snapshot::folders, voicemailpwcheck::mailbox, ast_vm_msg_snapshot::msg, NULL, ast_vm_mailbox_snapshot::total_msg_num, and VM_STRING_HEADER_FORMAT.

Referenced by show_messages_for_mailbox().

◆ show_messages_for_mailbox()

static int show_messages_for_mailbox ( struct ast_cli_args a)
static

Definition at line 11615 of file app_voicemail.c.

11616{
11617 if (show_mailbox_details(a)){
11618 return -1;
11619 }
11620 ast_cli(a->fd, "\n");
11621 return show_mailbox_snapshot(a);
11622}
static int show_mailbox_snapshot(struct ast_cli_args *a)
static int show_mailbox_details(struct ast_cli_args *a)

References a, ast_cli(), show_mailbox_details(), and show_mailbox_snapshot().

Referenced by handle_voicemail_show_mailbox().

◆ show_users_realtime()

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

Definition at line 13257 of file app_voicemail.c.

13258{
13259 struct ast_config *cfg;
13260 const char *cat = NULL;
13261
13262 if (!(cfg = ast_load_realtime_multientry("voicemail",
13263 "context", context, SENTINEL))) {
13264 return CLI_FAILURE;
13265 }
13266
13267 ast_cli(fd,
13268 "\n"
13269 "=============================================================\n"
13270 "=== Configured Voicemail Users ==============================\n"
13271 "=============================================================\n"
13272 "===\n");
13273
13274 while ((cat = ast_category_browse(cfg, cat))) {
13275 struct ast_variable *var = NULL;
13276 ast_cli(fd,
13277 "=== Mailbox ...\n"
13278 "===\n");
13279 for (var = ast_variable_browse(cfg, cat); var; var = var->next)
13280 ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
13281 ast_cli(fd,
13282 "===\n"
13283 "=== ---------------------------------------------------------\n"
13284 "===\n");
13285 }
13286
13287 ast_cli(fd,
13288 "=============================================================\n"
13289 "\n");
13290
13291 ast_config_destroy(cfg);
13292
13293 return CLI_SUCCESS;
13294}
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3622

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, voicemailpwcheck::context, NULL, SENTINEL, and var.

Referenced by handle_voicemail_show_users().

◆ start_poll_thread()

static void start_poll_thread ( void  )
static

Definition at line 13658 of file app_voicemail.c.

13659{
13660 int errcode;
13662
13663 poll_thread_run = 1;
13664
13665 if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
13666 ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
13667 }
13668}
struct ast_mwi_observer mwi_observer
static void * mb_poll_thread(void *data)
int ast_mwi_add_observer(struct ast_mwi_observer *observer)
Add an observer to receive MWI state related events.
Definition: mwi.c:301
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584

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

Referenced by actual_load_config().

◆ stop_poll_thread()

static void stop_poll_thread ( void  )
static

Definition at line 13670 of file app_voicemail.c.

13671{
13672 poll_thread_run = 0;
13673
13677
13678 pthread_join(poll_thread, NULL);
13680
13682}
#define ast_cond_signal(cond)
Definition: lock.h:203
void ast_mwi_remove_observer(struct ast_mwi_observer *observer)
Remove an MWI state observer.
Definition: mwi.c:307

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_mwi_remove_observer(), AST_PTHREADT_NULL, mwi_observer, NULL, poll_cond, poll_lock, poll_thread, and poll_thread_run.

Referenced by actual_load_config(), and unload_module().

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

1310{
1311 char *bufptr = buf;
1312 for (; *input; input++) {
1313 if (*input < 32) {
1314 continue;
1315 }
1316 *bufptr++ = *input;
1317 if (bufptr == buf + buflen - 1) {
1318 break;
1319 }
1320 }
1321 *bufptr = '\0';
1322 return buf;
1323}
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1570

References buf, and input().

Referenced by make_email_file(), and sendpage().

◆ substitute_escapes()

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

Definition at line 14171 of file app_voicemail.c.

14172{
14173 char *current;
14174
14175 /* Add 16 for fudge factor */
14176 struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
14177
14179
14180 /* Substitute strings \r, \n, and \t into the appropriate characters */
14181 for (current = (char *) value; *current; current++) {
14182 if (*current == '\\') {
14183 current++;
14184 if (!*current) {
14185 ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
14186 break;
14187 }
14188 switch (*current) {
14189 case '\\':
14190 ast_str_append(&str, 0, "\\");
14191 break;
14192 case 'r':
14193 ast_str_append(&str, 0, "\r");
14194 break;
14195 case 'n':
14196#ifdef IMAP_STORAGE
14197 if (!str->used || str->str[str->used - 1] != '\r') {
14198 ast_str_append(&str, 0, "\r");
14199 }
14200#endif
14201 ast_str_append(&str, 0, "\n");
14202 break;
14203 case 't':
14204 ast_str_append(&str, 0, "\t");
14205 break;
14206 default:
14207 ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
14208 break;
14209 }
14210 } else {
14211 ast_str_append(&str, 0, "%c", *current);
14212 }
14213 }
14214
14215 return ast_str_buffer(str);
14216}
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:909

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

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 15750 of file app_voicemail.c.

15751{
15752 int res;
15753
15760 res |= ast_manager_unregister("VoicemailUsersList");
15761 res |= ast_manager_unregister("VoicemailUserStatus");
15762 res |= ast_manager_unregister("VoicemailRefresh");
15763 res |= ast_manager_unregister("VoicemailBoxSummary");
15764 res |= ast_manager_unregister("VoicemailMove");
15765 res |= ast_manager_unregister("VoicemailRemove");
15766 res |= ast_manager_unregister("VoicemailForward");
15767#ifdef TEST_FRAMEWORK
15768 res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
15769 res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
15770 res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
15771 res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
15772 res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
15773 res |= AST_TEST_UNREGISTER(test_voicemail_vm_info);
15774#endif
15778#ifdef TEST_FRAMEWORK
15779 ast_uninstall_vm_test_functions();
15780#endif
15782
15783 ao2_container_unregister("voicemail_alias_mailbox_mappings");
15785 ao2_container_unregister("voicemail_mailbox_alias_mappings");
15787
15790
15792 ast_unload_realtime("voicemail");
15793 ast_unload_realtime("voicemail_data");
15794
15795#ifdef IMAP_STORAGE
15796 ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
15797#endif
15798 free_vm_users();
15799 free_vm_zones();
15800 return res;
15801}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8041
void ast_vm_greeter_unregister(const char *module_name)
Unregister the specified voicemail greeter provider.
Definition: main/app.c:511
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
Definition: main/app.c:400
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
const char * module_name
The name of the module that provides the voicemail functionality.
const char * module_name
The name of the module that provides the voicemail greeter functionality.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References alias_mailbox_mappings, 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_unload_realtime(), ast_unregister_application(), ast_vm_greeter_unregister(), ast_vm_unregister(), cli_voicemail, free_vm_users(), free_vm_zones(), inprocess_container, mailbox_alias_mappings, ast_vm_functions::module_name, ast_vm_greeter_functions::module_name, mwi_subscription_tps, NULL, playmsg_app, poll_thread, sayname_app, stop_poll_thread(), vm_greeter_table, vm_info_acf, vm_table, vmauthenticate_app, voicemail_app, and voicemailmain_app.

Referenced by load_module().

◆ valid_config()

static int valid_config ( const struct ast_config cfg)
inlinestatic

Check if configuration file is valid.

Definition at line 1899 of file app_voicemail.c.

1900{
1901 return cfg && cfg != CONFIG_STATUS_FILEINVALID;
1902}

References CONFIG_STATUS_FILEINVALID.

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

◆ vm_allocate_dh()

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

Definition at line 2153 of file app_voicemail.c.

2153 {
2154
2155 int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
2156
2157 /* remove old allocation */
2158 if (vms->deleted) {
2159 ast_free(vms->deleted);
2160 vms->deleted = NULL;
2161 }
2162 if (vms->heard) {
2163 ast_free(vms->heard);
2164 vms->heard = NULL;
2165 }
2166 vms->dh_arraysize = 0;
2167
2168 if (arraysize > 0) {
2169 if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
2170 return -1;
2171 }
2172 if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
2173 ast_free(vms->deleted);
2174 vms->deleted = NULL;
2175 return -1;
2176 }
2177 vms->dh_arraysize = arraysize;
2178 }
2179
2180 return 0;
2181}

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

Referenced by open_mailbox().

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

11284{
11285 int useadsi = 0, valid = 0, logretries = 0;
11286 char password[AST_MAX_EXTENSION], *passptr = NULL;
11287 struct ast_vm_user vmus, *vmu = NULL;
11288
11289 /* If ADSI is supported, setup login screen */
11290 adsi_begin(chan, &useadsi);
11291 if (!skipuser && useadsi)
11292 adsi_login(chan);
11293 if (!silent && !skipuser && ast_streamfile(chan, vm_login, ast_channel_language(chan))) {
11294 ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
11295 return -1;
11296 }
11297
11298 /* Authenticate them and get their mailbox/password */
11299
11300 while (!valid && (logretries < max_logins)) {
11301 /* Prompt for, and read in the username */
11302 if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
11303 ast_log(AST_LOG_WARNING, "Couldn't read username\n");
11304 return -1;
11305 }
11306 if (ast_strlen_zero(mailbox)) {
11307 if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
11308 ast_copy_string(mailbox, ast_channel_caller(chan)->id.number.str, mailbox_size);
11309 } else {
11310 ast_verb(3, "Username not entered\n");
11311 return -1;
11312 }
11313 } else if (mailbox[0] == '*') {
11314 /* user entered '*' */
11315 ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
11316 if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
11317 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11318 return -1;
11319 }
11320 ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
11321 mailbox[0] = '\0';
11322 }
11323
11324 if (useadsi)
11325 adsi_password(chan);
11326
11327 if (!ast_strlen_zero(prefix)) {
11328 char fullusername[80];
11329
11330 ast_copy_string(fullusername, prefix, sizeof(fullusername));
11331 strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
11332 ast_copy_string(mailbox, fullusername, mailbox_size);
11333 }
11334
11335 ast_debug(1, "Before find user for mailbox %s\n", mailbox);
11336 memset(&vmus, 0, sizeof(vmus));
11337 vmu = find_user(&vmus, context, mailbox);
11338 if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
11339 /* saved password is blank, so don't bother asking */
11340 password[0] = '\0';
11341 } else {
11343 if (!ast_check_hangup(chan)) {
11344 ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
11345 }
11346 free_user(vmu);
11347 return -1;
11348 }
11349 if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
11350 ast_log(AST_LOG_NOTICE, "Unable to read password\n");
11351 free_user(vmu);
11352 return -1;
11353 } else if (password[0] == '*') {
11354 /* user entered '*' */
11355 ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
11356 if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
11357 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11358 mailbox[0] = '*';
11359 free_user(vmu);
11360 return -1;
11361 }
11362 ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11363 mailbox[0] = '\0';
11364 /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
11365 free_user(vmu);
11366 vmu = NULL;
11367 }
11368 }
11369
11370 if (vmu) {
11371 passptr = vmu->password;
11372 if (passptr[0] == '-') passptr++;
11373 }
11374 if (vmu && !strcmp(passptr, password))
11375 valid++;
11376 else {
11377 ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
11378 if (!ast_strlen_zero(prefix))
11379 mailbox[0] = '\0';
11380 }
11381 logretries++;
11382 if (!valid) {
11383 if (skipuser || logretries >= max_logins) {
11384 if (ast_streamfile(chan, "vm-incorrect", ast_channel_language(chan))) {
11385 ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
11386 free_user(vmu);
11387 return -1;
11388 }
11389 if (ast_waitstream(chan, "")) { /* Channel is hung up */
11390 free_user(vmu);
11391 return -1;
11392 }
11393 } else {
11394 if (useadsi)
11395 adsi_login(chan);
11396 if (ast_streamfile(chan, "vm-incorrect-mailbox", ast_channel_language(chan))) {
11397 ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
11398 free_user(vmu);
11399 return -1;
11400 }
11401 }
11402 }
11403 }
11404 if (!valid && (logretries >= max_logins)) {
11405 ast_stopstream(chan);
11406 ast_play_and_wait(chan, "vm-goodbye");
11407 free_user(vmu);
11408 return -1;
11409 }
11410 if (vmu && !skipuser) {
11411 *res_vmu = *vmu;
11412 }
11413 return 0;
11414}
static void adsi_password(struct ast_channel *chan)
static void adsi_begin(struct ast_channel *chan, int *useadsi)
static void adsi_login(struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
static char prefix[MAX_PREFIX]
Definition: http.c:144

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

Referenced by vm_execmain(), and vmauthenticate().

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

11259{
11260 if (!strncasecmp(ast_channel_language(chan), "es", 2)) { /* SPANISH */
11261 return vm_browse_messages_es(chan, vms, vmu);
11262 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK */
11263 return vm_browse_messages_gr(chan, vms, vmu);
11264 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW */
11265 return vm_browse_messages_he(chan, vms, vmu);
11266 } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN */
11267 return vm_browse_messages_it(chan, vms, vmu);
11268 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE */
11269 return vm_browse_messages_ja(chan, vms, vmu);
11270 } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE */
11271 return vm_browse_messages_pt(chan, vms, vmu);
11272 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE */
11273 return vm_browse_messages_vi(chan, vms, vmu);
11274 } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) */
11275 return vm_browse_messages_zh(chan, vms, vmu);
11276 } else { /* Default to English syntax */
11277 return vm_browse_messages_en(chan, vms, vmu);
11278 }
11279}
static int vm_browse_messages_vi(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Vietnamese syntax for 'You have N messages' greeting.
static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Default English syntax for 'You have N messages' greeting.
static int vm_browse_messages_zh(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Chinese (Taiwan)syntax for 'You have N messages' greeting.
static int vm_browse_messages_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Portuguese syntax for 'You have N messages' greeting.
static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Spanish syntax for 'You have N messages' greeting.
static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Japanese syntax for 'You have N messages' greeting.
static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Italian syntax for 'You have N messages' greeting.
static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
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.

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

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

11071{
11072 int cmd = 0;
11073
11074 if (vms->lastmsg > -1) {
11075 cmd = play_message(chan, vmu, vms);
11076 } else {
11077 cmd = ast_play_and_wait(chan, "vm-youhave");
11078 if (!cmd)
11079 cmd = ast_play_and_wait(chan, "vm-no");
11080 if (!cmd) {
11081 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11082 cmd = ast_play_and_wait(chan, vms->fn);
11083 }
11084 if (!cmd)
11085 cmd = ast_play_and_wait(chan, "vm-messages");
11086 }
11087 return cmd;
11088}
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)

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

Referenced by vm_browse_messages().

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

11152{
11153 int cmd;
11154
11155 if (vms->lastmsg > -1) {
11156 cmd = play_message(chan, vmu, vms);
11157 } else {
11158 cmd = ast_play_and_wait(chan, "vm-youhaveno");
11159 if (!cmd)
11160 cmd = ast_play_and_wait(chan, "vm-messages");
11161 if (!cmd) {
11162 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11163 cmd = ast_play_and_wait(chan, vms->fn);
11164 }
11165 }
11166 return cmd;
11167}

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

Referenced by vm_browse_messages().

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

11019{
11020 int cmd = 0;
11021
11022 if (vms->lastmsg > -1) {
11023 cmd = play_message(chan, vmu, vms);
11024 } else {
11025 cmd = ast_play_and_wait(chan, "vm-youhaveno");
11026 if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
11027 if (!cmd) {
11028 snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
11029 cmd = ast_play_and_wait(chan, vms->fn);
11030 }
11031 if (!cmd)
11032 cmd = ast_play_and_wait(chan, "vm-messages");
11033 } else {
11034 if (!cmd)
11035 cmd = ast_play_and_wait(chan, "vm-messages");
11036 if (!cmd) {
11037 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11038 cmd = ast_play_and_wait(chan, vms->fn);
11039 }
11040 }
11041 }
11042 return cmd;
11043}

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

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

11047{
11048 int cmd = 0;
11049
11050 if (vms->lastmsg > -1) {
11051 cmd = play_message(chan, vmu, vms);
11052 } else {
11053 if (!strcasecmp(vms->fn, "INBOX")) {
11054 cmd = ast_play_and_wait(chan, "vm-nonewmessages");
11055 } else {
11056 cmd = ast_play_and_wait(chan, "vm-nomessages");
11057 }
11058 }
11059 return cmd;
11060}

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

Referenced by vm_browse_messages().

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

11099{
11100 int cmd;
11101
11102 if (vms->lastmsg > -1) {
11103 cmd = play_message(chan, vmu, vms);
11104 } else {
11105 cmd = ast_play_and_wait(chan, "vm-no");
11106 if (!cmd)
11107 cmd = ast_play_and_wait(chan, "vm-message");
11108 if (!cmd) {
11109 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11110 cmd = ast_play_and_wait(chan, vms->fn);
11111 }
11112 }
11113 return cmd;
11114}

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

Referenced by vm_browse_messages().

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

11125{
11126 int cmd = 0;
11127
11128 if (vms->lastmsg > -1) {
11129 cmd = play_message(chan, vmu, vms);
11130 } else {
11131 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11132 cmd = ast_play_and_wait(chan, vms->fn);
11133 if (!cmd)
11134 cmd = ast_play_and_wait(chan, "vm-messages");
11135 if (!cmd)
11136 cmd = ast_play_and_wait(chan, "jp-wa");
11137 if (!cmd)
11138 cmd = ast_play_and_wait(chan, "jp-arimasen");
11139 }
11140 return cmd;
11141}

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

Referenced by vm_browse_messages().

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

11178{
11179 int cmd;
11180
11181 if (vms->lastmsg > -1) {
11182 cmd = play_message(chan, vmu, vms);
11183 } else {
11184 cmd = ast_play_and_wait(chan, "vm-no");
11185 if (!cmd) {
11186 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11187 cmd = ast_play_and_wait(chan, vms->fn);
11188 }
11189 if (!cmd)
11190 cmd = ast_play_and_wait(chan, "vm-messages");
11191 }
11192 return cmd;
11193}

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

Referenced by vm_browse_messages().

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

11232{
11233 int cmd = 0;
11234
11235 if (vms->lastmsg > -1) {
11236 cmd = play_message(chan, vmu, vms);
11237 } else {
11238 cmd = ast_play_and_wait(chan, "vm-no");
11239 if (!cmd) {
11240 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11241 cmd = ast_play_and_wait(chan, vms->fn);
11242 }
11243 }
11244 return cmd;
11245}

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

Referenced by vm_browse_messages().

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

11204{
11205 int cmd;
11206
11207 if (vms->lastmsg > -1) {
11208 cmd = play_message(chan, vmu, vms);
11209 } else {
11210 cmd = ast_play_and_wait(chan, "vm-you");
11211 if (!cmd)
11212 cmd = ast_play_and_wait(chan, "vm-haveno");
11213 if (!cmd)
11214 cmd = ast_play_and_wait(chan, "vm-messages");
11215 if (!cmd) {
11216 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11217 cmd = ast_play_and_wait(chan, vms->fn);
11218 }
11219 }
11220 return cmd;
11221}

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

Referenced by vm_browse_messages().

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

1912{
1913 struct ast_config *cfg = NULL;
1914 struct ast_variable *var = NULL;
1915 struct ast_category *cat = NULL;
1916 char *category = NULL;
1917 const char *tmp = NULL;
1918 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
1919 char secretfn[PATH_MAX] = "";
1920 int found = 0;
1921
1922 if (!change_password_realtime(vmu, newpassword))
1923 return;
1924
1925 /* check if we should store the secret in the spool directory next to the messages */
1926 switch (vmu->passwordlocation) {
1927 case OPT_PWLOC_SPOOLDIR:
1928 snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
1929 if (write_password_to_file(secretfn, newpassword) == 0) {
1930 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
1931 ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
1932 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1933 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1934 break;
1935 } else {
1936 ast_log(LOG_WARNING, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1937 }
1938 /* Fall-through */
1940 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
1941 while ((category = ast_category_browse(cfg, category))) {
1942 if (!strcasecmp(category, vmu->context)) {
1943 char *value = NULL;
1944 char *new = NULL;
1945 if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
1946 ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
1947 break;
1948 }
1949 value = strstr(tmp, ",");
1950 if (!value) {
1951 new = ast_malloc(strlen(newpassword) + 1);
1952 sprintf(new, "%s", newpassword);
1953 } else {
1954 new = ast_malloc((strlen(value) + strlen(newpassword) + 1));
1955 sprintf(new, "%s%s", newpassword, value);
1956 }
1957 if (!(cat = ast_category_get(cfg, category, NULL))) {
1958 ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
1959 ast_free(new);
1960 break;
1961 }
1962 ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
1963 found = 1;
1964 ast_free(new);
1965 }
1966 }
1967 /* save the results */
1968 if (found) {
1969 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1970 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
1971 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
1972 ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "app_voicemail");
1973 ast_config_destroy(cfg);
1974 break;
1975 }
1976
1977 ast_config_destroy(cfg);
1978 }
1979 /* Fall-through */
1981 /* check users.conf and update the password stored for the mailbox */
1982 /* if no vmsecret entry exists create one. */
1983 if ((cfg = ast_config_load("users.conf", config_flags)) && valid_config(cfg)) {
1984 ast_debug(4, "we are looking for %s\n", vmu->mailbox);
1985 for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
1986 ast_debug(4, "users.conf: %s\n", category);
1987 if (!strcasecmp(category, vmu->mailbox)) {
1988 char new[strlen(newpassword) + 1];
1989 if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
1990 ast_debug(3, "looks like we need to make vmsecret!\n");
1991 var = ast_variable_new("vmsecret", newpassword, "");
1992 } else {
1993 var = NULL;
1994 }
1995
1996 sprintf(new, "%s", newpassword);
1997 if (!(cat = ast_category_get(cfg, category, NULL))) {
1998 ast_debug(4, "failed to get category!\n");
1999 ast_free(var);
2000 break;
2001 }
2002 if (!var) {
2003 ast_variable_update(cat, "vmsecret", new, NULL, 0);
2004 } else {
2006 }
2007 found = 1;
2008 break;
2009 }
2010 }
2011 /* save the results and clean things up */
2012 if (found) {
2013 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
2014 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
2015 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
2016 ast_config_text_file_save("users.conf", cfg, "app_voicemail");
2017 }
2018
2019 ast_config_destroy(cfg);
2020 }
2021 }
2022}
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
static int write_password_to_file(const char *secretfn, const char *password)
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:1533
@ CONFIG_FLAG_WITHCOMMENTS

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, LOG_WARNING, 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, VM_SPOOL_DIR, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser_setup(), and vm_options().

◆ vm_change_password_shell()

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

Definition at line 2024 of file app_voicemail.c.

2025{
2026 char buf[255];
2027 snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
2028 ast_debug(1, "External password: %s\n",buf);
2029 if (!ast_safe_system(buf)) {
2030 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
2031 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
2032 /* Reset the password in memory, too */
2033 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
2034 }
2035}

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

Referenced by vm_newuser_setup(), and vm_options().

◆ vm_check_password_shell()

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

Definition at line 1529 of file app_voicemail.c.

1530{
1531 int fds[2], pid = 0;
1532
1533 memset(buf, 0, len);
1534
1535 if (pipe(fds)) {
1536 snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
1537 } else {
1538 /* good to go*/
1539 pid = ast_safe_fork(0);
1540
1541 if (pid < 0) {
1542 /* ok maybe not */
1543 close(fds[0]);
1544 close(fds[1]);
1545 snprintf(buf, len, "FAILURE: Fork failed");
1546 } else if (pid) {
1547 /* parent */
1548 close(fds[1]);
1549 if (read(fds[0], buf, len) < 0) {
1550 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
1551 }
1552 close(fds[0]);
1553 } else {
1554 /* child */
1556 AST_APP_ARG(v)[20];
1557 );
1558 char *mycmd = ast_strdupa(command);
1559
1560 close(fds[0]);
1561 dup2(fds[1], STDOUT_FILENO);
1562 close(fds[1]);
1563 ast_close_fds_above_n(STDOUT_FILENO);
1564
1565 AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
1566
1567 execv(arg.v[0], arg.v);
1568 printf("FAILURE: %s", strerror(errno));
1569 _exit(0);
1570 }
1571 }
1572 return buf;
1573}
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:3197
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
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:3192

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, len(), and LOG_WARNING.

Referenced by check_password().

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

4874{
4875 char *txt;
4876 int txtsize = 0;
4877
4878 txtsize = (strlen(file) + 5)*sizeof(char);
4879 txt = ast_alloca(txtsize);
4880 /* Sprintf here would safe because we alloca'd exactly the right length,
4881 * but trying to eliminate all sprintf's anyhow
4882 */
4883 if (ast_check_realtime("voicemail_data")) {
4884 ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
4885 }
4886 snprintf(txt, txtsize, "%s.txt", file);
4887 unlink(txt);
4888 return ast_filedelete(file, NULL);
4889}

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

Referenced by copy_message(), and notify_new_message().

◆ vm_exec()

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

Definition at line 12724 of file app_voicemail.c.

12725{
12726 int res = 0;
12727 char *tmp;
12728 struct leave_vm_options leave_options;
12729 struct ast_flags flags = { 0 };
12730 char *opts[OPT_ARG_ARRAY_SIZE];
12732 AST_APP_ARG(argv0);
12733 AST_APP_ARG(argv1);
12734 );
12735
12736 memset(&leave_options, 0, sizeof(leave_options));
12737
12738 if (!ast_strlen_zero(data)) {
12739 tmp = ast_strdupa(data);
12741 if (args.argc == 2) {
12742 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
12743 return -1;
12746 int gain;
12747
12748 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
12749 ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
12750 return -1;
12751 } else {
12752 leave_options.record_gain = (signed char) gain;
12753 }
12754 }
12757 leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
12758 }
12759 }
12760 if (ast_test_flag(&flags, OPT_BEEP)) { /* Use custom beep (or none at all) */
12761 leave_options.beeptone = opts[OPT_ARG_BEEP_TONE];
12762 } else { /* Use default beep */
12763 leave_options.beeptone = "beep";
12764 }
12765 } else {
12766 char temp[256];
12767 res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
12768 if (res < 0)
12769 return res;
12770 if (ast_strlen_zero(temp))
12771 return 0;
12772 args.argv0 = ast_strdupa(temp);
12773 }
12774
12775 if (ast_channel_state(chan) != AST_STATE_UP) {
12778 } else {
12779 ast_answer(chan);
12780 }
12781 }
12782
12783 res = leave_voicemail(chan, args.argv0, &leave_options);
12784 if (res == 't') {
12785 ast_play_and_wait(chan, "vm-goodbye");
12786 res = 0;
12787 }
12788
12789 if (res == OPERATOR_EXIT) {
12790 res = 0;
12791 }
12792
12793 if (res == ERROR_LOCK_PATH) {
12794 ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
12795 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
12796 res = 0;
12797 }
12798
12799 return res;
12800}
static const struct ast_app_option vm_app_options[128]
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
enum ast_getdata_result 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:188
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:3056
@ AST_CONTROL_PROGRESS
unsigned int flags
Definition: utils.h:200

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, ast_flags::flags, 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_SILENT_IF_GREET, 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().

◆ vm_execmain()

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

Definition at line 11939 of file app_voicemail.c.

11940{
11941 /* XXX This is, admittedly, some pretty horrendous code. For some
11942 reason it just seemed a lot easier to do with GOTO's. I feel
11943 like I'm back in my GWBASIC days. XXX */
11944 int res = -1;
11945 int cmd = 0;
11946 int valid = 0;
11947 char prefixstr[80] ="";
11948 char ext_context[256]="";
11949 int box;
11950 int useadsi = 0;
11951 int skipuser = 0;
11952 struct vm_state vms = {{0}};
11953 struct ast_vm_user *vmu = NULL, vmus = {{0}};
11954 char *context = NULL;
11955 int silentexit = 0;
11956 struct ast_flags flags = { 0 };
11957 signed char record_gain = 0;
11958 int play_auto = 0;
11959 int play_folder = 0;
11960 int in_urgent = 0;
11961 int nodelete = 0;
11962#ifdef IMAP_STORAGE
11963 int deleted = 0;
11964#endif
11965
11966 /* Add the vm_state to the active list and keep it active */
11967 vms.lastmsg = -1;
11968
11969 ast_test_suite_event_notify("START", "Message: vm_execmain started");
11970 if (ast_channel_state(chan) != AST_STATE_UP) {
11971 ast_debug(1, "Before ast_answer\n");
11972 ast_answer(chan);
11973 }
11974
11975 if (!ast_strlen_zero(data)) {
11976 char *opts[OPT_ARG_ARRAY_SIZE];
11977 char *parse;
11979 AST_APP_ARG(argv0);
11980 AST_APP_ARG(argv1);
11981 );
11982
11983 parse = ast_strdupa(data);
11984
11986
11987 if (args.argc == 2) {
11988 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
11989 return -1;
11991 int gain;
11992 if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
11993 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
11994 ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
11995 return -1;
11996 } else {
11997 record_gain = (signed char) gain;
11998 }
11999 } else {
12000 ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
12001 }
12002 }
12004 play_auto = 1;
12005 if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
12006 /* See if it is a folder name first */
12007 if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
12008 if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
12009 play_folder = -1;
12010 }
12011 } else {
12012 play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
12013 }
12014 } else {
12015 ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
12016 }
12017 if (play_folder > 9 || play_folder < 0) {
12019 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
12020 opts[OPT_ARG_PLAYFOLDER]);
12021 play_folder = 0;
12022 }
12023 }
12025 nodelete = 1;
12026 }
12027 } else {
12028 /* old style options parsing */
12029 while (*(args.argv0)) {
12030 if (*(args.argv0) == 's')
12032 else if (*(args.argv0) == 'p')
12034 else
12035 break;
12036 (args.argv0)++;
12037 }
12038
12039 }
12040
12041 valid = ast_test_flag(&flags, OPT_SILENT);
12042
12043 if ((context = strchr(args.argv0, '@')))
12044 *context++ = '\0';
12045
12047 ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
12048 else
12049 ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
12050
12051 if (!ast_strlen_zero(vms.username)) {
12052 if ((vmu = find_user(&vmus, context ,vms.username))) {
12053 skipuser++;
12054 } else {
12055 ast_log(LOG_WARNING, "Mailbox '%s%s%s' doesn't exist\n", vms.username, context ? "@": "", context ? context : "");
12056 valid = 0;
12057 }
12058 } else {
12059 valid = 0;
12060 }
12061 }
12062
12063 if (!valid)
12064 res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
12065
12066 ast_debug(1, "After vm_authenticate\n");
12067
12068 if (vms.username[0] == '*') {
12069 ast_debug(1, "user pressed * in context '%s'\n", ast_channel_context(chan));
12070
12071 /* user entered '*' */
12072 if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) {
12073 ast_test_suite_event_notify("REDIRECT", "Message: redirecting user to 'a' extension");
12074 res = 0; /* prevent hangup */
12075 goto out;
12076 }
12077 }
12078
12079 if (!res) {
12080 valid = 1;
12081 if (!skipuser)
12082 vmu = &vmus;
12083 } else {
12084 res = 0;
12085 }
12086
12087 /* If ADSI is supported, setup login screen */
12088 adsi_begin(chan, &useadsi);
12089
12090 if (!valid) {
12091 goto out;
12092 }
12093 ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated");
12094
12095#ifdef IMAP_STORAGE
12096 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
12097 pthread_setspecific(ts_vmstate.key, &vms);
12098
12099 vms.interactive = 1;
12100 vms.updated = 1;
12101 if (vmu)
12102 ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
12103 vmstate_insert(&vms);
12104 init_vm_state(&vms);
12105#endif
12106
12107 /* Set language from config to override channel language */
12108 if (!ast_strlen_zero(vmu->language)) {
12109 ast_channel_lock(chan);
12110 ast_channel_language_set(chan, vmu->language);
12111 ast_channel_unlock(chan);
12112 }
12113
12114 /* Retrieve urgent, old and new message counts */
12115 ast_debug(1, "Before open_mailbox\n");
12116 res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
12117 if (res < 0)
12118 goto out;
12119 vms.oldmessages = vms.lastmsg + 1;
12120 ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
12121 /* check INBOX */
12122 res = open_mailbox(&vms, vmu, NEW_FOLDER);
12123 if (res < 0)
12124 goto out;
12125 vms.newmessages = vms.lastmsg + 1;
12126 ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
12127 /* Start in Urgent */
12128 in_urgent = 1;
12129 res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
12130 if (res < 0)
12131 goto out;
12132 vms.urgentmessages = vms.lastmsg + 1;
12133 ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
12134
12135 /* Select proper mailbox FIRST!! */
12136 if (play_auto) {
12137 ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages");
12138 if (vms.urgentmessages) {
12139 in_urgent = 1;
12140 res = open_mailbox(&vms, vmu, 11);
12141 } else {
12142 in_urgent = 0;
12143 res = open_mailbox(&vms, vmu, play_folder);
12144 }
12145 if (res < 0)
12146 goto out;
12147
12148 /* If there are no new messages, inform the user and hangup */
12149 if (vms.lastmsg == -1) {
12150 in_urgent = 0;
12151 cmd = vm_browse_messages(chan, &vms, vmu);
12152 res = 0;
12153 goto out;
12154 }
12155 } else {
12156 if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
12157 /* If we only have old messages start here */
12158 res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
12159 in_urgent = 0;
12160 play_folder = 1;
12161 if (res < 0)
12162 goto out;
12163 } else if (!vms.urgentmessages && vms.newmessages) {
12164 /* If we have new messages but none are urgent */
12165 in_urgent = 0;
12166 res = open_mailbox(&vms, vmu, NEW_FOLDER);
12167 if (res < 0)
12168 goto out;
12169 }
12170 }
12171
12172 if (useadsi)
12173 adsi_status(chan, &vms);
12174 res = 0;
12175
12176 /* Check to see if this is a new user */
12177 if (!strcasecmp(vmu->mailbox, vmu->password) &&
12179 if (ast_play_and_wait(chan, vm_newuser) == -1)
12180 ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
12181 cmd = vm_newuser_setup(chan, vmu, &vms, vmfmts, record_gain);
12182 if ((cmd == 't') || (cmd == '#')) {
12183 /* Timeout */
12184 ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out");
12185 res = 0;
12186 goto out;
12187 } else if (cmd < 0) {
12188 /* Hangup */
12189 ast_test_suite_event_notify("HANGUP", "Message: hangup detected");
12190 res = -1;
12191 goto out;
12192 }
12193 }
12194#ifdef IMAP_STORAGE
12195 ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
12196 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
12197 ast_debug(1, "*** QUOTA EXCEEDED!!\n");
12198 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
12199 }
12200 ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
12201 if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
12202 ast_log(AST_LOG_WARNING, "No more messages possible. User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
12203 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
12204 }
12205#endif
12206
12207 ast_test_suite_event_notify("INTRO", "Message: playing intro menu");
12208 if (play_auto) {
12209 cmd = '1';
12210 } else {
12211 cmd = vm_intro(chan, vmu, &vms);
12212 }
12213 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12214 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12215
12216 vms.repeats = 0;
12217 vms.starting = 1;
12218 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
12219 /* Run main menu */
12220 switch (cmd) {
12221 case '1': /* First message */
12222 vms.curmsg = 0;
12223 /* Fall through */
12224 case '5': /* Play current message */
12225 ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
12226 cmd = vm_browse_messages(chan, &vms, vmu);
12227 break;
12228 case '2': /* Change folders */
12229 ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder");
12230 if (useadsi)
12231 adsi_folders(chan, 0, "Change to folder...");
12232
12233 cmd = get_folder2(chan, "vm-changeto", 0);
12234 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12235 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12236 if (cmd == '#') {
12237 cmd = 0;
12238 } else if (cmd > 0) {
12239 cmd = cmd - '0';
12240 res = close_mailbox(&vms, vmu);
12241 if (res == ERROR_LOCK_PATH)
12242 goto out;
12243 /* If folder is not urgent, set in_urgent to zero! */
12244 if (cmd != 11) in_urgent = 0;
12245 res = open_mailbox(&vms, vmu, cmd);
12246 if (res < 0)
12247 goto out;
12248 play_folder = cmd;
12249 cmd = 0;
12250 }
12251 if (useadsi)
12252 adsi_status2(chan, &vms);
12253
12254 if (!cmd) {
12255 cmd = vm_play_folder_name(chan, vms.vmbox);
12256 }
12257
12258 vms.starting = 1;
12259 vms.curmsg = 0;
12260 break;
12261 case '3': /* Advanced options */
12262 ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");
12263 cmd = 0;
12264 vms.repeats = 0;
12265 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
12266 switch (cmd) {
12267 case '1': /* Reply */
12268 if (vms.lastmsg > -1 && !vms.starting) {
12269 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
12270 if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
12271 res = cmd;
12272 goto out;
12273 }
12274 } else {
12275 cmd = ast_play_and_wait(chan, "vm-sorry");
12276 }
12277 cmd = 't';
12278 break;
12279 case '2': /* Callback */
12280 if (!vms.starting)
12281 ast_verb(3, "Callback Requested\n");
12282 if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
12283 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
12284 if (cmd == 9) {
12285 silentexit = 1;
12286 goto out;
12287 } else if (cmd == ERROR_LOCK_PATH) {
12288 res = cmd;
12289 goto out;
12290 }
12291 } else {
12292 cmd = ast_play_and_wait(chan, "vm-sorry");
12293 }
12294 cmd = 't';
12295 break;
12296 case '3': /* Envelope */
12297 if (vms.lastmsg > -1 && !vms.starting) {
12298 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
12299 if (cmd == ERROR_LOCK_PATH) {
12300 res = cmd;
12301 goto out;
12302 }
12303 } else {
12304 cmd = ast_play_and_wait(chan, "vm-sorry");
12305 }
12306 cmd = 't';
12307 break;
12308 case '4': /* Dialout */
12309 if (!ast_strlen_zero(vmu->dialout)) {
12310 cmd = dialout(chan, vmu, NULL, vmu->dialout);
12311 if (cmd == 9) {
12312 silentexit = 1;
12313 goto out;
12314 }
12315 } else {
12316 cmd = ast_play_and_wait(chan, "vm-sorry");
12317 }
12318 cmd = 't';
12319 break;
12320
12321 case '5': /* Leave VoiceMail */
12322 if (ast_test_flag(vmu, VM_SVMAIL)) {
12323 cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
12324 if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
12325 res = cmd;
12326 goto out;
12327 }
12328 } else {
12329 cmd = ast_play_and_wait(chan, "vm-sorry");
12330 }
12331 cmd = 't';
12332 break;
12333
12334 case '*': /* Return to main menu */
12335 cmd = 't';
12336 break;
12337
12338 default:
12339 cmd = 0;
12340 if (!vms.starting) {
12341 cmd = ast_play_and_wait(chan, "vm-toreply");
12342 }
12343 if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
12344 cmd = ast_play_and_wait(chan, "vm-tocallback");
12345 }
12346 if (!cmd && !vms.starting) {
12347 cmd = ast_play_and_wait(chan, "vm-tohearenv");
12348 }
12349 if (!ast_strlen_zero(vmu->dialout) && !cmd) {
12350 cmd = ast_play_and_wait(chan, "vm-tomakecall");
12351 }
12352 if (ast_test_flag(vmu, VM_SVMAIL) && !cmd) {
12353 cmd = ast_play_and_wait(chan, "vm-leavemsg");
12354 }
12355 if (!cmd) {
12356 cmd = ast_play_and_wait(chan, "vm-starmain");
12357 }
12358 if (!cmd) {
12359 cmd = ast_waitfordigit(chan, 6000);
12360 }
12361 if (!cmd) {
12362 vms.repeats++;
12363 }
12364 if (vms.repeats > 3) {
12365 cmd = 't';
12366 }
12367 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12368 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12369 }
12370 }
12371 if (cmd == 't') {
12372 cmd = 0;
12373 vms.repeats = 0;
12374 }
12375 break;
12376 case '4': /* Go to the previous message */
12377 ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1);
12378 if (vms.curmsg > 0) {
12379 vms.curmsg--;
12380 cmd = play_message(chan, vmu, &vms);
12381 } else {
12382 /* Check if we were listening to new
12383 messages. If so, go to Urgent messages
12384 instead of saying "no more messages"
12385 */
12386 if (in_urgent == 0 && vms.urgentmessages > 0) {
12387 /* Check for Urgent messages */
12388 in_urgent = 1;
12389 res = close_mailbox(&vms, vmu);
12390 if (res == ERROR_LOCK_PATH)
12391 goto out;
12392 res = open_mailbox(&vms, vmu, 11); /* Open Urgent folder */
12393 if (res < 0)
12394 goto out;
12395 ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
12396 vms.curmsg = vms.lastmsg;
12397 if (vms.lastmsg < 0) {
12398 cmd = ast_play_and_wait(chan, "vm-nomore");
12399 }
12400 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12401 vms.curmsg = vms.lastmsg;
12402 cmd = play_message(chan, vmu, &vms);
12403 } else {
12404 cmd = ast_play_and_wait(chan, "vm-nomore");
12405 }
12406 }
12407 break;
12408 case '6': /* Go to the next message */
12409 ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1);
12410 if (vms.curmsg < vms.lastmsg) {
12411 vms.curmsg++;
12412 cmd = play_message(chan, vmu, &vms);
12413 } else {
12414 if (in_urgent && vms.newmessages > 0) {
12415 /* Check if we were listening to urgent
12416 * messages. If so, go to regular new messages
12417 * instead of saying "no more messages"
12418 */
12419 in_urgent = 0;
12420 res = close_mailbox(&vms, vmu);
12421 if (res == ERROR_LOCK_PATH)
12422 goto out;
12423 res = open_mailbox(&vms, vmu, NEW_FOLDER);
12424 if (res < 0)
12425 goto out;
12426 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12427 vms.curmsg = -1;
12428 if (vms.lastmsg < 0) {
12429 cmd = ast_play_and_wait(chan, "vm-nomore");
12430 }
12431 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12432 vms.curmsg = 0;
12433 cmd = play_message(chan, vmu, &vms);
12434 } else {
12435 cmd = ast_play_and_wait(chan, "vm-nomore");
12436 }
12437 }
12438 break;
12439 case '7': /* Delete the current message */
12440 if (!nodelete && vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
12441 vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
12442 if (useadsi)
12443 adsi_delete(chan, &vms);
12444 if (vms.deleted[vms.curmsg]) {
12445 if (play_folder == 0) {
12446 if (in_urgent) {
12447 vms.urgentmessages--;
12448 } else {
12449 vms.newmessages--;
12450 }
12451 }
12452 else if (play_folder == 1)
12453 vms.oldmessages--;
12454 cmd = ast_play_and_wait(chan, "vm-deleted");
12455 } else {
12456 if (play_folder == 0) {
12457 if (in_urgent) {
12458 vms.urgentmessages++;
12459 } else {
12460 vms.newmessages++;
12461 }
12462 }
12463 else if (play_folder == 1)
12464 vms.oldmessages++;
12465 cmd = ast_play_and_wait(chan, "vm-undeleted");
12466 }
12467 if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
12468 if (vms.curmsg < vms.lastmsg) {
12469 vms.curmsg++;
12470 cmd = play_message(chan, vmu, &vms);
12471 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12472 vms.curmsg = 0;
12473 cmd = play_message(chan, vmu, &vms);
12474 } else {
12475 /* Check if we were listening to urgent
12476 messages. If so, go to regular new messages
12477 instead of saying "no more messages"
12478 */
12479 if (in_urgent == 1) {
12480 /* Check for new messages */
12481 in_urgent = 0;
12482 res = close_mailbox(&vms, vmu);
12483 if (res == ERROR_LOCK_PATH)
12484 goto out;
12485 res = open_mailbox(&vms, vmu, NEW_FOLDER);
12486 if (res < 0)
12487 goto out;
12488 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12489 vms.curmsg = -1;
12490 if (vms.lastmsg < 0) {
12491 cmd = ast_play_and_wait(chan, "vm-nomore");
12492 }
12493 } else {
12494 cmd = ast_play_and_wait(chan, "vm-nomore");
12495 }
12496 }
12497 }
12498 } else /* Delete not valid if we haven't selected a message */
12499 cmd = 0;
12500#ifdef IMAP_STORAGE
12501 deleted = 1;
12502#endif
12503 break;
12504
12505 case '8': /* Forward the current message */
12506 if (vms.lastmsg > -1) {
12507 cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
12508 if (cmd == ERROR_LOCK_PATH) {
12509 res = cmd;
12510 goto out;
12511 }
12512 } else {
12513 /* Check if we were listening to urgent
12514 messages. If so, go to regular new messages
12515 instead of saying "no more messages"
12516 */
12517 if (in_urgent == 1 && vms.newmessages > 0) {
12518 /* Check for new messages */
12519 in_urgent = 0;
12520 res = close_mailbox(&vms, vmu);
12521 if (res == ERROR_LOCK_PATH)
12522 goto out;
12523 res = open_mailbox(&vms, vmu, NEW_FOLDER);
12524 if (res < 0)
12525 goto out;
12526 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12527 vms.curmsg = -1;
12528 if (vms.lastmsg < 0) {
12529 cmd = ast_play_and_wait(chan, "vm-nomore");
12530 }
12531 } else {
12532 cmd = ast_play_and_wait(chan, "vm-nomore");
12533 }
12534 }
12535 break;
12536 case '9': /* Save message to folder */
12537 ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
12538 if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
12539 /* No message selected */
12540 cmd = 0;
12541 break;
12542 }
12543 if (useadsi)
12544 adsi_folders(chan, 1, "Save to folder...");
12545 cmd = get_folder2(chan, "vm-savefolder", 1);
12546 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12547 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12548 box = 0; /* Shut up compiler */
12549 if (cmd == '#') {
12550 cmd = 0;
12551 break;
12552 } else if (cmd > 0) {
12553 box = cmd = cmd - '0';
12554 cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd, NULL, 0);
12555 if (cmd == ERROR_LOCK_PATH) {
12556 res = cmd;
12557 goto out;
12558#ifndef IMAP_STORAGE
12559 } else if (!cmd) {
12560 vms.deleted[vms.curmsg] = 1;
12561#endif
12562 } else {
12563 vms.deleted[vms.curmsg] = 0;
12564 vms.heard[vms.curmsg] = 0;
12565 }
12566 }
12567 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
12568 if (useadsi)
12569 adsi_message(chan, &vms);
12570 snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
12571 if (!cmd) {
12572 cmd = ast_play_and_wait(chan, "vm-message");
12573 if (!cmd)
12574 cmd = say_and_wait(chan, vms.curmsg + 1, ast_channel_language(chan));
12575 if (!cmd)
12576 cmd = ast_play_and_wait(chan, "vm-savedto");
12577 if (!cmd)
12578 cmd = vm_play_folder_name(chan, vms.fn);
12579 } else {
12580 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
12581 }
12583 if (vms.curmsg < vms.lastmsg) {
12584 vms.curmsg++;
12585 cmd = play_message(chan, vmu, &vms);
12586 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12587 vms.curmsg = 0;
12588 cmd = play_message(chan, vmu, &vms);
12589 } else {
12590 /* Check if we were listening to urgent
12591 messages. If so, go to regular new messages
12592 instead of saying "no more messages"
12593 */
12594 if (in_urgent == 1 && vms.newmessages > 0) {
12595 /* Check for new messages */
12596 in_urgent = 0;
12597 res = close_mailbox(&vms, vmu);
12598 if (res == ERROR_LOCK_PATH)
12599 goto out;
12600 res = open_mailbox(&vms, vmu, NEW_FOLDER);
12601 if (res < 0)
12602 goto out;
12603 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12604 vms.curmsg = -1;
12605 if (vms.lastmsg < 0) {
12606 cmd = ast_play_and_wait(chan, "vm-nomore");
12607 }
12608 } else {
12609 cmd = ast_play_and_wait(chan, "vm-nomore");
12610 }
12611 }
12612 }
12613 break;
12614 case '*': /* Help */
12615 if (!vms.starting) {
12616 if (!strncasecmp(ast_channel_language(chan), "ja", 2)) {
12617 cmd = vm_play_folder_name(chan, vms.vmbox);
12618 if (!cmd)
12619 cmd = ast_play_and_wait(chan, "jp-wa");
12620 if (!cmd)
12621 cmd = ast_play_and_wait(chan, "digits/1");
12622 if (!cmd)
12623 cmd = ast_play_and_wait(chan, "jp-wo");
12624 if (!cmd)
12625 cmd = ast_play_and_wait(chan, "silence/1");
12626 if (!cmd)
12627 cmd = ast_play_and_wait(chan, "vm-opts");
12628 if (!cmd)
12629 cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete);
12630 break;
12631 }
12632 cmd = ast_play_and_wait(chan, "vm-onefor");
12633 if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
12634 cmd = ast_play_and_wait(chan, "vm-for");
12635 }
12636 if (!cmd)
12637 cmd = vm_play_folder_name(chan, vms.vmbox);
12638 if (!cmd)
12639 cmd = ast_play_and_wait(chan, "vm-opts");
12640 if (!cmd)
12641 cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete);
12642 } else
12643 cmd = 0;
12644 break;
12645 case '0': /* Mailbox options */
12646 cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
12647 if (useadsi)
12648 adsi_status(chan, &vms);
12649 /* Reopen play_folder */
12650 res = open_mailbox(&vms, vmu, play_folder);
12651 if (res < 0) {
12652 goto out;
12653 }
12654 vms.starting = 1;
12655 break;
12656 default: /* Nothing */
12657 ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
12658 cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent, nodelete);
12659 break;
12660 }
12661 }
12662 if ((cmd == 't') || (cmd == '#')) {
12663 /* Timeout */
12664 res = 0;
12665 } else {
12666 /* Hangup */
12667 res = -1;
12668 }
12669
12670out:
12671 if (res > -1) {
12672 ast_stopstream(chan);
12673 adsi_goodbye(chan);
12674 if (valid && res != OPERATOR_EXIT) {
12675 if (silentexit)
12676 res = ast_play_and_wait(chan, "vm-dialout");
12677 else
12678 res = ast_play_and_wait(chan, "vm-goodbye");
12679 }
12680 if ((valid && res > 0) || res == OPERATOR_EXIT) {
12681 res = 0;
12682 }
12683 if (useadsi)
12685 }
12686 if (vmu)
12687 close_mailbox(&vms, vmu);
12688 if (valid) {
12689 int new = 0, old = 0, urgent = 0;
12690 snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
12691 /* Urgent flag not passwd to externnotify here */
12692 run_externnotify(vmu->context, vmu->mailbox, NULL);
12693 ast_app_inboxcount2(ext_context, &urgent, &new, &old);
12694 queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgent, new, old);
12695 }
12696#ifdef IMAP_STORAGE
12697 /* expunge message - use UID Expunge if supported on IMAP server*/
12698 ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
12699 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
12700 ast_mutex_lock(&vms.lock);
12701#ifdef HAVE_IMAP_TK2006
12702 if (LEVELUIDPLUS (vms.mailstream)) {
12703 mail_expunge_full(vms.mailstream, NIL, EX_UID);
12704 } else
12705#endif
12706 mail_expunge(vms.mailstream);
12707 ast_mutex_unlock(&vms.lock);
12708 }
12709 /* before we delete the state, we should copy pertinent info
12710 * back to the persistent model */
12711 if (vmu) {
12712 vmstate_delete(&vms);
12713 }
12714#endif
12715 if (vmu)
12716 free_user(vmu);
12717
12718#ifdef IMAP_STORAGE
12719 pthread_setspecific(ts_vmstate.key, NULL);
12720#endif
12721 return res;
12722}
int ast_adsi_unload_session(struct ast_channel *chan)
Definition: adsi.c:87
static void adsi_folders(struct ast_channel *chan, int start, char *label)
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
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 void adsi_status(struct ast_channel *chan, struct vm_state *vms)
static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
The advanced options within a message.
static int get_folder2(struct ast_channel *chan, char *fn, int start)
plays a prompt and waits for a keypress.
static void adsi_goodbye(struct ast_channel *chan)
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_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static void adsi_status2(struct ast_channel *chan, 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.
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8781
int urgentmessages
char context[80]
FILE * out
Definition: utils/frame.c:33

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(), vm_state::context, ast_vm_user::context, voicemailpwcheck::context, vm_state::curdir, vm_state::curmsg, vm_state::deleted, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, find_user(), ast_flags::flags, vm_state::fn, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, vm_state::heard, ast_vm_user::language, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), maxlogins, 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_READONLY, OPT_RECORDGAIN, OPT_SILENT, out, ast_vm_user::password, play_message(), queue_mwi_event(), vm_state::repeats, run_externnotify(), save_to_folder(), say_and_wait(), vm_state::starting, vm_state::urgentmessages, vm_state::username, vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser, vm_newuser_setup(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, VM_SVMAIL, vm_state::vmbox, and vmfmts.

Referenced by load_module().

◆ 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
flag

Presents a prompt for 1 to prepend the current message, 2 to forward the message without prepending, or * to return to the main menu.

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

Returns
zero on success, -1 on error.

Definition at line 7956 of file app_voicemail.c.

7958{
7959 int cmd = 0;
7960 int retries = 0, prepend_duration = 0, already_recorded = 0;
7961 char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
7962 char textfile[PATH_MAX];
7963 struct ast_config *msg_cfg;
7964 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
7965#ifndef IMAP_STORAGE
7966 signed char zero_gain = 0;
7967#else
7968 const char *msg_id = NULL;
7969#endif
7970 const char *duration_str;
7971
7972 /* Must always populate duration correctly */
7973 make_file(msgfile, sizeof(msgfile), curdir, curmsg);
7974 strcpy(textfile, msgfile);
7975 strcpy(backup, msgfile);
7976 strcpy(backup_textfile, msgfile);
7977 strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
7978 strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
7979 strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7980
7981 if ((msg_cfg = ast_config_load(textfile, config_flags)) && valid_config(msg_cfg) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
7982 *duration = atoi(duration_str);
7983 } else {
7984 *duration = 0;
7985 }
7986
7987 while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
7988 if (cmd)
7989 retries = 0;
7990 switch (cmd) {
7991 case '1':
7992
7993#ifdef IMAP_STORAGE
7994 /* Record new intro file */
7995 if (msg_cfg && msg_cfg != CONFIG_STATUS_FILEINVALID) {
7996 msg_id = ast_variable_retrieve(msg_cfg, "message", "msg_id");
7997 }
7998 make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
7999 strncat(vms->introfn, "intro", sizeof(vms->introfn));
8000 ast_play_and_wait(chan, "vm-record-prepend");
8001 ast_play_and_wait(chan, "beep");
8002 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);
8003 if (cmd == -1) {
8004 break;
8005 }
8006 cmd = 't';
8007#else
8008
8009 /* prepend a message to the current message, update the metadata and return */
8010
8011 make_file(msgfile, sizeof(msgfile), curdir, curmsg);
8012 strcpy(textfile, msgfile);
8013 strncat(textfile, ".txt", sizeof(textfile) - 1);
8014 *duration = 0;
8015
8016 /* if we can't read the message metadata, stop now */
8017 if (!valid_config(msg_cfg)) {
8018 cmd = 0;
8019 break;
8020 }
8021
8022 /* Back up the original file, so we can retry the prepend and restore it after forward. */
8023#ifndef IMAP_STORAGE
8024 if (already_recorded) {
8025 ast_filecopy(backup, msgfile, NULL);
8026 copy(backup_textfile, textfile);
8027 }
8028 else {
8029 ast_filecopy(msgfile, backup, NULL);
8030 copy(textfile, backup_textfile);
8031 }
8032#endif
8033 already_recorded = 1;
8034
8035 if (record_gain)
8036 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
8037
8038 cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
8039
8040 if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
8041 ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
8043 ast_filerename(backup, msgfile, NULL);
8044 }
8045
8046 if (record_gain)
8047 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
8048
8049
8050 if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
8051 *duration = atoi(duration_str);
8052
8053 if (prepend_duration) {
8054 struct ast_category *msg_cat;
8055 /* need enough space for a maximum-length message duration */
8056 char duration_buf[12];
8057
8058 *duration += prepend_duration;
8059 msg_cat = ast_category_get(msg_cfg, "message", NULL);
8060 snprintf(duration_buf, sizeof(duration_buf), "%ld", *duration);
8061 if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
8062 ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
8063 }
8064 }
8065
8066#endif
8067 break;
8068 case '2':
8069 /* NULL out introfile so we know there is no intro! */
8070#ifdef IMAP_STORAGE
8071 *vms->introfn = '\0';
8072#endif
8073 cmd = 't';
8074 break;
8075 case '*':
8076 cmd = '*';
8077 break;
8078 default:
8079 /* If time_out and return to menu, reset already_recorded */
8080 already_recorded = 0;
8081
8082 cmd = ast_play_and_wait(chan, "vm-forwardoptions");
8083 /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
8084 if (!cmd) {
8085 cmd = ast_play_and_wait(chan, "vm-starmain");
8086 /* "press star to return to the main menu" */
8087 }
8088 if (!cmd) {
8089 cmd = ast_waitfordigit(chan, 6000);
8090 }
8091 if (!cmd) {
8092 retries++;
8093 }
8094 if (retries > 3) {
8095 cmd = '*'; /* Let's cancel this beast */
8096 }
8097 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
8098 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
8099 }
8100 }
8101
8102 if (valid_config(msg_cfg))
8103 ast_config_destroy(msg_cfg);
8104 if (prepend_duration)
8105 *duration = prepend_duration;
8106
8107 if (already_recorded && cmd == -1) {
8108 /* restore original message if prepention cancelled */
8109 ast_filerename(backup, msgfile, NULL);
8110 rename(backup_textfile, textfile);
8111 }
8112
8113 if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */
8114 cmd = 0;
8115 return cmd;
8116}
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 'prepend' mode which works a li...
Definition: main/app.c:2149

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, maxsilence, NULL, PATH_MAX, play_record_review(), silencethreshold, valid_config(), vm_pls_try_again, and vm_prepend_timeout.

Referenced by forward_message().

◆ vm_index_to_foldername()

static const char * vm_index_to_foldername ( int  id)
static

Definition at line 2103 of file app_voicemail.c.

2104{
2105 return mbox(NULL, id);
2106}

References mbox(), and NULL.

◆ vm_instructions()

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

Definition at line 10690 of file app_voicemail.c.

10691{
10692 if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
10693 return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
10694 } else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
10695 return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
10696 } else { /* Default to ENGLISH */
10697 return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
10698 }
10699}
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)

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

Referenced by vm_execmain().

◆ 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,
int  nodelete 
)
static

Definition at line 10480 of file app_voicemail.c.

10481{
10482 int res = 0;
10483 /* Play instructions and wait for new command */
10484 while (!res) {
10485 if (vms->starting) {
10486 if (vms->lastmsg > -1) {
10487 if (skipadvanced)
10488 res = ast_play_and_wait(chan, "vm-onefor-full");
10489 else
10490 res = ast_play_and_wait(chan, "vm-onefor");
10491 if (!res)
10492 res = vm_play_folder_name(chan, vms->vmbox);
10493 }
10494 if (!res) {
10495 if (skipadvanced)
10496 res = ast_play_and_wait(chan, "vm-opts-full");
10497 else
10498 res = ast_play_and_wait(chan, "vm-opts");
10499 }
10500 } else {
10501 /* Added for additional help */
10502 if (skipadvanced) {
10503 res = ast_play_and_wait(chan, "vm-onefor-full");
10504 if (!res)
10505 res = vm_play_folder_name(chan, vms->vmbox);
10506 res = ast_play_and_wait(chan, "vm-opts-full");
10507 }
10508 /* Logic:
10509 * If the current message is not the first OR
10510 * if we're listening to the first new message and there are
10511 * also urgent messages, then prompt for navigation to the
10512 * previous message
10513 */
10514 if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
10515 res = ast_play_and_wait(chan, "vm-prev");
10516 }
10517 if (!res && !skipadvanced)
10518 res = ast_play_and_wait(chan, "vm-advopts");
10519 if (!res)
10520 res = ast_play_and_wait(chan, "vm-repeat");
10521 /* Logic:
10522 * If we're not listening to the last message OR
10523 * we're listening to the last urgent message and there are
10524 * also new non-urgent messages, then prompt for navigation
10525 * to the next message
10526 */
10527 if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
10528 (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
10529 res = ast_play_and_wait(chan, "vm-next");
10530 }
10531 if (!res) {
10532 int curmsg_deleted;
10533#ifdef IMAP_STORAGE
10534 ast_mutex_lock(&vms->lock);
10535#endif
10536 curmsg_deleted = vms->deleted[vms->curmsg];
10537#ifdef IMAP_STORAGE
10538 ast_mutex_unlock(&vms->lock);
10539#endif
10540 if (!nodelete) {
10541 if (!curmsg_deleted) {
10542 res = ast_play_and_wait(chan, "vm-delete");
10543 } else {
10544 res = ast_play_and_wait(chan, "vm-undelete");
10545 }
10546 }
10547 if (!res) {
10548 res = ast_play_and_wait(chan, "vm-toforward");
10549 }
10550 if (!res) {
10551 res = ast_play_and_wait(chan, "vm-savemessage");
10552 }
10553 }
10554 }
10555 if (!res) {
10556 res = ast_play_and_wait(chan, "vm-helpexit");
10557 }
10558 if (!res)
10559 res = ast_waitfordigit(chan, 6000);
10560 if (!res) {
10561 vms->repeats++;
10562 if (vms->repeats > 2) {
10563 res = 't';
10564 }
10565 }
10566 }
10567 return res;
10568}

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

◆ 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,
int  nodelete 
)
static

Definition at line 10570 of file app_voicemail.c.

10571{
10572 int res = 0;
10573 /* Play instructions and wait for new command */
10574 while (!res) {
10575 if (vms->starting) {
10576 if (vms->lastmsg > -1) {
10577 res = vm_play_folder_name(chan, vms->vmbox);
10578 if (!res)
10579 res = ast_play_and_wait(chan, "jp-wa");
10580 if (!res)
10581 res = ast_play_and_wait(chan, "digits/1");
10582 if (!res)
10583 res = ast_play_and_wait(chan, "jp-wo");
10584 if (!res)
10585 res = ast_play_and_wait(chan, "silence/1");
10586 }
10587 if (!res)
10588 res = ast_play_and_wait(chan, "vm-opts");
10589 } else {
10590 /* Added for additional help */
10591 if (skipadvanced) {
10592 res = vm_play_folder_name(chan, vms->vmbox);
10593 if (!res)
10594 res = ast_play_and_wait(chan, "jp-wa");
10595 if (!res)
10596 res = ast_play_and_wait(chan, "digits/1");
10597 if (!res)
10598 res = ast_play_and_wait(chan, "jp-wo");
10599 if (!res)
10600 res = ast_play_and_wait(chan, "silence/1");
10601 res = ast_play_and_wait(chan, "vm-opts-full");
10602 }
10603 /* Logic:
10604 * If the current message is not the first OR
10605 * if we're listening to the first new message and there are
10606 * also urgent messages, then prompt for navigation to the
10607 * previous message
10608 */
10609 if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
10610 res = ast_play_and_wait(chan, "vm-prev");
10611 }
10612 if (!res && !skipadvanced)
10613 res = ast_play_and_wait(chan, "vm-advopts");
10614 if (!res)
10615 res = ast_play_and_wait(chan, "vm-repeat");
10616 /* Logic:
10617 * If we're not listening to the last message OR
10618 * we're listening to the last urgent message and there are
10619 * also new non-urgent messages, then prompt for navigation
10620 * to the next message
10621 */
10622 if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
10623 (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
10624 res = ast_play_and_wait(chan, "vm-next");
10625 }
10626 if (!res) {
10627 int curmsg_deleted;
10628#ifdef IMAP_STORAGE
10629 ast_mutex_lock(&vms->lock);
10630#endif
10631 curmsg_deleted = vms->deleted[vms->curmsg];
10632#ifdef IMAP_STORAGE
10633 ast_mutex_unlock(&vms->lock);
10634#endif
10635 if (!curmsg_deleted) {
10636 res = ast_play_and_wait(chan, "vm-delete");
10637 } else {
10638 res = ast_play_and_wait(chan, "vm-undelete");
10639 }
10640 if (!res) {
10641 res = ast_play_and_wait(chan, "vm-toforward");
10642 }
10643 if (!res) {
10644 res = ast_play_and_wait(chan, "vm-savemessage");
10645 }
10646 }
10647 }
10648
10649 if (!res) {
10650 res = ast_play_and_wait(chan, "vm-helpexit");
10651 }
10652 if (!res)
10653 res = ast_waitfordigit(chan, 6000);
10654 if (!res) {
10655 vms->repeats++;
10656 if (vms->repeats > 2) {
10657 res = 't';
10658 }
10659 }
10660
10661 }
10662
10663 return res;
10664}

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

◆ 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,
int  nodelete 
)
static

Definition at line 10666 of file app_voicemail.c.

10667{
10668 int res = 0;
10669 /* Play instructions and wait for new command */
10670 while (!res) {
10671 if (vms->lastmsg > -1) {
10672 res = ast_play_and_wait(chan, "vm-listen");
10673 if (!res)
10674 res = vm_play_folder_name(chan, vms->vmbox);
10675 if (!res)
10676 res = ast_play_and_wait(chan, "press");
10677 if (!res)
10678 res = ast_play_and_wait(chan, "digits/1");
10679 }
10680 if (!res)
10681 res = ast_play_and_wait(chan, "vm-opts");
10682 if (!res) {
10683 vms->starting = 0;
10684 return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
10685 }
10686 }
10687 return res;
10688}

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

◆ vm_intro()

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

Definition at line 10412 of file app_voicemail.c.

10413{
10414 char prefile[256];
10415
10416 /* Notify the user that the temp greeting is set and give them the option to remove it */
10417 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10418 if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10419 RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10420 if (ast_fileexists(prefile, NULL, NULL) > 0) {
10421 ast_play_and_wait(chan, "vm-tempgreetactive");
10422 }
10423 DISPOSE(prefile, -1);
10424 }
10425
10426 /* Play voicemail intro - syntax is different for different languages */
10427 if (0) {
10428 return 0;
10429 } else if (!strncasecmp(ast_channel_language(chan), "cs", 2)) { /* CZECH syntax */
10430 return vm_intro_cs(chan, vms);
10431 } else if (!strncasecmp(ast_channel_language(chan), "cz", 2)) { /* deprecated CZECH syntax */
10432 static int deprecation_warning = 0;
10433 if (deprecation_warning++ % 10 == 0) {
10434 ast_log(LOG_WARNING, "cz is not a standard language code. Please switch to using cs instead.\n");
10435 }
10436 return vm_intro_cs(chan, vms);
10437 } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */
10438 return vm_intro_de(chan, vms);
10439 } else if (!strncasecmp(ast_channel_language(chan), "es", 2)) { /* SPANISH syntax */
10440 return vm_intro_es(chan, vms);
10441 } else if (!strncasecmp(ast_channel_language(chan), "fr", 2)) { /* FRENCH syntax */
10442 return vm_intro_fr(chan, vms);
10443 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */
10444 return vm_intro_gr(chan, vms);
10445 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW syntax */
10446 return vm_intro_he(chan, vms);
10447 } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC syntax */
10448 return vm_intro_is(chan, vms);
10449 } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */
10450 return vm_intro_it(chan, vms);
10451 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE syntax */
10452 return vm_intro_ja(chan, vms);
10453 } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */
10454 return vm_intro_nl(chan, vms);
10455 } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
10456 return vm_intro_no(chan, vms);
10457 } else if (!strncasecmp(ast_channel_language(chan), "da", 2)) { /* DANISH syntax */
10458 return vm_intro_da(chan, vms);
10459 } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
10460 return vm_intro_pl(chan, vms);
10461 } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* BRAZILIAN PORTUGUESE syntax */
10462 return vm_intro_pt_BR(chan, vms);
10463 } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE syntax */
10464 return vm_intro_pt(chan, vms);
10465 } else if (!strncasecmp(ast_channel_language(chan), "ru", 2)) { /* RUSSIAN syntax */
10466 return vm_intro_multilang(chan, vms, "n");
10467 } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
10468 return vm_intro_se(chan, vms);
10469 } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* UKRAINIAN syntax */
10470 return vm_intro_multilang(chan, vms, "n");
10471 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
10472 return vm_intro_vi(chan, vms);
10473 } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
10474 return vm_intro_zh(chan, vms);
10475 } else { /* Default to ENGLISH */
10476 return vm_intro_en(chan, vms);
10477 }
10478}
static int vm_intro_pl(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_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_intro_de(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_vi(struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_cs(struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_zh(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_en(struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_da(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_is(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_ja(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_it(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_no(struct ast_channel *chan, struct vm_state *vms)

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_da(), 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(), VM_SPOOL_DIR, and VM_TEMPGREETWARN.

Referenced by vm_execmain().

◆ vm_intro_cs()

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

Definition at line 10282 of file app_voicemail.c.

10283{
10284 int res;
10285 res = ast_play_and_wait(chan, "vm-youhave");
10286 if (!res) {
10287 if (vms->newmessages) {
10288 if (vms->newmessages == 1) {
10289 res = ast_play_and_wait(chan, "digits/jednu");
10290 } else {
10291 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10292 }
10293 if (!res) {
10294 if (vms->newmessages == 1)
10295 res = ast_play_and_wait(chan, "vm-novou");
10296 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
10297 res = ast_play_and_wait(chan, "vm-nove");
10298 if (vms->newmessages > 4)
10299 res = ast_play_and_wait(chan, "vm-novych");
10300 }
10301 if (vms->oldmessages && !res)
10302 res = ast_play_and_wait(chan, "vm-and");
10303 else if (!res) {
10304 if (vms->newmessages == 1)
10305 res = ast_play_and_wait(chan, "vm-zpravu");
10306 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
10307 res = ast_play_and_wait(chan, "vm-zpravy");
10308 if (vms->newmessages > 4)
10309 res = ast_play_and_wait(chan, "vm-zprav");
10310 }
10311 }
10312 if (!res && vms->oldmessages) {
10313 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10314 if (!res) {
10315 if (vms->oldmessages == 1)
10316 res = ast_play_and_wait(chan, "vm-starou");
10317 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
10318 res = ast_play_and_wait(chan, "vm-stare");
10319 if (vms->oldmessages > 4)
10320 res = ast_play_and_wait(chan, "vm-starych");
10321 }
10322 if (!res) {
10323 if (vms->oldmessages == 1)
10324 res = ast_play_and_wait(chan, "vm-zpravu");
10325 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
10326 res = ast_play_and_wait(chan, "vm-zpravy");
10327 if (vms->oldmessages > 4)
10328 res = ast_play_and_wait(chan, "vm-zprav");
10329 }
10330 }
10331 if (!res) {
10332 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10333 res = ast_play_and_wait(chan, "vm-no");
10334 if (!res)
10335 res = ast_play_and_wait(chan, "vm-zpravy");
10336 }
10337 }
10338 }
10339 return res;
10340}

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

◆ vm_intro_da()

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

Definition at line 9933 of file app_voicemail.c.

9934{
9935 /* Introduce messages they have */
9936 int res;
9937
9938 res = ast_play_and_wait(chan, "vm-youhave");
9939 if (res)
9940 return res;
9941
9942 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9943 res = ast_play_and_wait(chan, "vm-no");
9944 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9945 return res;
9946 }
9947
9948 if (vms->newmessages) {
9949 if ((vms->newmessages == 1)) {
9950 res = ast_play_and_wait(chan, "digits/1");
9951 res = res ? res : ast_play_and_wait(chan, "vm-INBOX");
9952 res = res ? res : ast_play_and_wait(chan, "vm-message");
9953 } else {
9954 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9955 res = res ? res : ast_play_and_wait(chan, "vm-INBOXs");
9956 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9957 }
9958 if (!res && vms->oldmessages)
9959 res = ast_play_and_wait(chan, "vm-and");
9960 }
9961 if (!res && vms->oldmessages) {
9962 if (vms->oldmessages == 1) {
9963 res = ast_play_and_wait(chan, "digits/1");
9964 res = res ? res : ast_play_and_wait(chan, "vm-Old");
9965 res = res ? res : ast_play_and_wait(chan, "vm-message");
9966 } else {
9967 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9968 res = res ? res : ast_play_and_wait(chan, "vm-Olds");
9969 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9970 }
9971 }
9972
9973 return res;
9974}

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

◆ vm_intro_de()

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

Definition at line 9978 of file app_voicemail.c.

9979{
9980 /* Introduce messages they have */
9981 int res;
9982 res = ast_play_and_wait(chan, "vm-youhave");
9983 if (!res) {
9984 if (vms->newmessages) {
9985 if (vms->newmessages == 1)
9986 res = ast_play_and_wait(chan, "digits/1F");
9987 else
9988 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9989 if (!res)
9990 res = ast_play_and_wait(chan, "vm-INBOX");
9991 if (vms->oldmessages && !res)
9992 res = ast_play_and_wait(chan, "vm-and");
9993 else if (!res) {
9994 if (vms->newmessages == 1)
9995 res = ast_play_and_wait(chan, "vm-message");
9996 else
9997 res = ast_play_and_wait(chan, "vm-messages");
9998 }
9999
10000 }
10001 if (!res && vms->oldmessages) {
10002 if (vms->oldmessages == 1)
10003 res = ast_play_and_wait(chan, "digits/1F");
10004 else
10005 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10006 if (!res)
10007 res = ast_play_and_wait(chan, "vm-Old");
10008 if (!res) {
10009 if (vms->oldmessages == 1)
10010 res = ast_play_and_wait(chan, "vm-message");
10011 else
10012 res = ast_play_and_wait(chan, "vm-messages");
10013 }
10014 }
10015 if (!res) {
10016 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10017 res = ast_play_and_wait(chan, "vm-no");
10018 if (!res)
10019 res = ast_play_and_wait(chan, "vm-messages");
10020 }
10021 }
10022 }
10023 return res;
10024}

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

◆ vm_intro_en()

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

Definition at line 9613 of file app_voicemail.c.

9614{
9615 int res;
9616
9617 /* Introduce messages they have */
9618 res = ast_play_and_wait(chan, "vm-youhave");
9619 if (!res) {
9620 if (vms->urgentmessages) {
9621 res = say_and_wait(chan, vms->urgentmessages, ast_channel_language(chan));
9622 if (!res)
9623 res = ast_play_and_wait(chan, "vm-Urgent");
9624 if ((vms->oldmessages || vms->newmessages) && !res) {
9625 res = ast_play_and_wait(chan, "vm-and");
9626 } else if (!res) {
9627 if (vms->urgentmessages == 1)
9628 res = ast_play_and_wait(chan, "vm-message");
9629 else
9630 res = ast_play_and_wait(chan, "vm-messages");
9631 }
9632 }
9633 if (vms->newmessages) {
9634 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9635 if (!res)
9636 res = ast_play_and_wait(chan, "vm-INBOX");
9637 if (vms->oldmessages && !res)
9638 res = ast_play_and_wait(chan, "vm-and");
9639 else if (!res) {
9640 if (vms->newmessages == 1)
9641 res = ast_play_and_wait(chan, "vm-message");
9642 else
9643 res = ast_play_and_wait(chan, "vm-messages");
9644 }
9645
9646 }
9647 if (!res && vms->oldmessages) {
9648 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9649 if (!res)
9650 res = ast_play_and_wait(chan, "vm-Old");
9651 if (!res) {
9652 if (vms->oldmessages == 1)
9653 res = ast_play_and_wait(chan, "vm-message");
9654 else
9655 res = ast_play_and_wait(chan, "vm-messages");
9656 }
9657 }
9658 if (!res) {
9659 if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
9660 res = ast_play_and_wait(chan, "vm-no");
9661 if (!res)
9662 res = ast_play_and_wait(chan, "vm-messages");
9663 }
9664 }
9665 }
9666 return res;
9667}

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

◆ vm_intro_es()

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

Definition at line 10027 of file app_voicemail.c.

10028{
10029 /* Introduce messages they have */
10030 int res;
10031 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10032 res = ast_play_and_wait(chan, "vm-youhaveno");
10033 if (!res)
10034 res = ast_play_and_wait(chan, "vm-messages");
10035 } else {
10036 res = ast_play_and_wait(chan, "vm-youhave");
10037 }
10038 if (!res) {
10039 if (vms->newmessages) {
10040 if (!res) {
10041 if (vms->newmessages == 1) {
10042 res = ast_play_and_wait(chan, "digits/1M");
10043 if (!res)
10044 res = ast_play_and_wait(chan, "vm-message");
10045 if (!res)
10046 res = ast_play_and_wait(chan, "vm-INBOXs");
10047 } else {
10048 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10049 if (!res)
10050 res = ast_play_and_wait(chan, "vm-messages");
10051 if (!res)
10052 res = ast_play_and_wait(chan, "vm-INBOX");
10053 }
10054 }
10055 if (vms->oldmessages && !res)
10056 res = ast_play_and_wait(chan, "vm-and");
10057 }
10058 if (vms->oldmessages) {
10059 if (!res) {
10060 if (vms->oldmessages == 1) {
10061 res = ast_play_and_wait(chan, "digits/1M");
10062 if (!res)
10063 res = ast_play_and_wait(chan, "vm-message");
10064 if (!res)
10065 res = ast_play_and_wait(chan, "vm-Olds");
10066 } else {
10067 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10068 if (!res)
10069 res = ast_play_and_wait(chan, "vm-messages");
10070 if (!res)
10071 res = ast_play_and_wait(chan, "vm-Old");
10072 }
10073 }
10074 }
10075 }
10076return res;
10077}

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

◆ vm_intro_fr()

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

Definition at line 10125 of file app_voicemail.c.

10126{
10127 /* Introduce messages they have */
10128 int res;
10129 res = ast_play_and_wait(chan, "vm-youhave");
10130 if (!res) {
10131 if (vms->newmessages) {
10132 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10133 if (!res)
10134 res = ast_play_and_wait(chan, "vm-INBOX");
10135 if (vms->oldmessages && !res)
10136 res = ast_play_and_wait(chan, "vm-and");
10137 else if (!res) {
10138 if (vms->newmessages == 1)
10139 res = ast_play_and_wait(chan, "vm-message");
10140 else
10141 res = ast_play_and_wait(chan, "vm-messages");
10142 }
10143
10144 }
10145 if (!res && vms->oldmessages) {
10146 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10147 if (!res)
10148 res = ast_play_and_wait(chan, "vm-Old");
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}

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

◆ vm_intro_gr()

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

Definition at line 9373 of file app_voicemail.c.

9374{
9375 int res = 0;
9376
9377 if (vms->newmessages) {
9378 res = ast_play_and_wait(chan, "vm-youhave");
9379 if (!res)
9381 if (!res) {
9382 if (vms->newmessages == 1) {
9383 res = ast_play_and_wait(chan, "vm-INBOX");
9384 if (!res)
9385 res = ast_play_and_wait(chan, "vm-message");
9386 } else {
9387 res = ast_play_and_wait(chan, "vm-INBOXs");
9388 if (!res)
9389 res = ast_play_and_wait(chan, "vm-messages");
9390 }
9391 }
9392 } else if (vms->oldmessages){
9393 res = ast_play_and_wait(chan, "vm-youhave");
9394 if (!res)
9396 if (vms->oldmessages == 1){
9397 res = ast_play_and_wait(chan, "vm-Old");
9398 if (!res)
9399 res = ast_play_and_wait(chan, "vm-message");
9400 } else {
9401 res = ast_play_and_wait(chan, "vm-Olds");
9402 if (!res)
9403 res = ast_play_and_wait(chan, "vm-messages");
9404 }
9405 } else if (!vms->oldmessages && !vms->newmessages)
9406 res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
9407 return res;
9408}

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

◆ vm_intro_he()

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

Definition at line 9507 of file app_voicemail.c.

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

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

◆ vm_intro_is()

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

Definition at line 9670 of file app_voicemail.c.

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

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

◆ vm_intro_it()

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

Definition at line 9739 of file app_voicemail.c.

9740{
9741 /* Introduce messages they have */
9742 int res;
9743 if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
9744 res = ast_play_and_wait(chan, "vm-no") ||
9745 ast_play_and_wait(chan, "vm-message");
9746 else
9747 res = ast_play_and_wait(chan, "vm-youhave");
9748 if (!res && vms->newmessages) {
9749 res = (vms->newmessages == 1) ?
9750 ast_play_and_wait(chan, "digits/un") ||
9751 ast_play_and_wait(chan, "vm-nuovo") ||
9752 ast_play_and_wait(chan, "vm-message") :
9753 /* 2 or more new messages */
9754 say_and_wait(chan, vms->newmessages, ast_channel_language(chan)) ||
9755 ast_play_and_wait(chan, "vm-nuovi") ||
9756 ast_play_and_wait(chan, "vm-messages");
9757 if (!res && vms->oldmessages)
9758 res = ast_play_and_wait(chan, "vm-and");
9759 }
9760 if (!res && vms->oldmessages) {
9761 res = (vms->oldmessages == 1) ?
9762 ast_play_and_wait(chan, "digits/un") ||
9763 ast_play_and_wait(chan, "vm-vecchio") ||
9764 ast_play_and_wait(chan, "vm-message") :
9765 /* 2 or more old messages */
9766 say_and_wait(chan, vms->oldmessages, ast_channel_language(chan)) ||
9767 ast_play_and_wait(chan, "vm-vecchi") ||
9768 ast_play_and_wait(chan, "vm-messages");
9769 }
9770 return res;
9771}

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

◆ vm_intro_ja()

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

Definition at line 9574 of file app_voicemail.c.

9575{
9576 /* Introduce messages they have */
9577 int res;
9578 if (vms->newmessages) {
9579 res = ast_play_and_wait(chan, "vm-INBOX");
9580 if (!res)
9581 res = ast_play_and_wait(chan, "vm-message");
9582 if (!res)
9583 res = ast_play_and_wait(chan, "jp-ga");
9584 if (!res)
9585 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9586 if (vms->oldmessages && !res)
9587 res = ast_play_and_wait(chan, "silence/1");
9588
9589 }
9590 if (vms->oldmessages) {
9591 res = ast_play_and_wait(chan, "vm-Old");
9592 if (!res)
9593 res = ast_play_and_wait(chan, "vm-message");
9594 if (!res)
9595 res = ast_play_and_wait(chan, "jp-ga");
9596 if (!res)
9597 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9598 }
9599 if (!vms->oldmessages && !vms->newmessages) {
9600 res = ast_play_and_wait(chan, "vm-messages");
9601 if (!res)
9602 res = ast_play_and_wait(chan, "jp-wa");
9603 if (!res)
9604 res = ast_play_and_wait(chan, "jp-arimasen");
9605 }
9606 else {
9607 res = ast_play_and_wait(chan, "jp-arimasu");
9608 }
9609 return res;
9610} /* Japanese */

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

Referenced by vm_intro().

◆ vm_intro_multilang()

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

Definition at line 9467 of file app_voicemail.c.

9468{
9469 int res;
9470 int lastnum = 0;
9471
9472 res = ast_play_and_wait(chan, "vm-youhave");
9473
9474 if (!res && vms->newmessages) {
9475 lastnum = vms->newmessages;
9476
9477 if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
9478 res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
9479 }
9480
9481 if (!res && vms->oldmessages) {
9482 res = ast_play_and_wait(chan, "vm-and");
9483 }
9484 }
9485
9486 if (!res && vms->oldmessages) {
9487 lastnum = vms->oldmessages;
9488
9489 if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
9490 res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
9491 }
9492 }
9493
9494 if (!res) {
9495 if (lastnum == 0) {
9496 res = ast_play_and_wait(chan, "vm-no");
9497 }
9498 if (!res) {
9499 res = ast_say_counted_noun(chan, lastnum, "vm-message");
9500 }
9501 }
9502
9503 return res;
9504}
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
int ast_say_counted_adjective(struct ast_channel *chan, int num, const char *adjective, const char *gender)

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

◆ vm_intro_nl()

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

Definition at line 10168 of file app_voicemail.c.

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 = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10176 if (!res) {
10177 if (vms->newmessages == 1)
10178 res = ast_play_and_wait(chan, "vm-INBOXs");
10179 else
10180 res = ast_play_and_wait(chan, "vm-INBOX");
10181 }
10182 if (vms->oldmessages && !res)
10183 res = ast_play_and_wait(chan, "vm-and");
10184 else if (!res) {
10185 if (vms->newmessages == 1)
10186 res = ast_play_and_wait(chan, "vm-message");
10187 else
10188 res = ast_play_and_wait(chan, "vm-messages");
10189 }
10190
10191 }
10192 if (!res && vms->oldmessages) {
10193 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10194 if (!res) {
10195 if (vms->oldmessages == 1)
10196 res = ast_play_and_wait(chan, "vm-Olds");
10197 else
10198 res = ast_play_and_wait(chan, "vm-Old");
10199 }
10200 if (!res) {
10201 if (vms->oldmessages == 1)
10202 res = ast_play_and_wait(chan, "vm-message");
10203 else
10204 res = ast_play_and_wait(chan, "vm-messages");
10205 }
10206 }
10207 if (!res) {
10208 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10209 res = ast_play_and_wait(chan, "vm-no");
10210 if (!res)
10211 res = ast_play_and_wait(chan, "vm-messages");
10212 }
10213 }
10214 }
10215 return res;
10216}

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

◆ vm_intro_no()

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

Definition at line 9889 of file app_voicemail.c.

9890{
9891 /* Introduce messages they have */
9892 int res;
9893
9894 res = ast_play_and_wait(chan, "vm-youhave");
9895 if (res)
9896 return res;
9897
9898 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9899 res = ast_play_and_wait(chan, "vm-no");
9900 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9901 return res;
9902 }
9903
9904 if (vms->newmessages) {
9905 if (vms->newmessages == 1) {
9906 res = ast_play_and_wait(chan, "digits/1");
9907 res = res ? res : ast_play_and_wait(chan, "vm-ny");
9908 res = res ? res : ast_play_and_wait(chan, "vm-message");
9909 } else {
9910 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9911 res = res ? res : ast_play_and_wait(chan, "vm-nye");
9912 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9913 }
9914 if (!res && vms->oldmessages)
9915 res = ast_play_and_wait(chan, "vm-and");
9916 }
9917 if (!res && vms->oldmessages) {
9918 if (vms->oldmessages == 1) {
9919 res = ast_play_and_wait(chan, "digits/1");
9920 res = res ? res : ast_play_and_wait(chan, "vm-gamel");
9921 res = res ? res : ast_play_and_wait(chan, "vm-message");
9922 } else {
9923 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9924 res = res ? res : ast_play_and_wait(chan, "vm-gamle");
9925 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9926 }
9927 }
9928
9929 return res;
9930}

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

◆ vm_intro_pl()

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

Definition at line 9774 of file app_voicemail.c.

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

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

Referenced by vm_intro().

◆ vm_intro_pt()

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

Definition at line 10219 of file app_voicemail.c.

10220{
10221 /* Introduce messages they have */
10222 int res;
10223 res = ast_play_and_wait(chan, "vm-youhave");
10224 if (!res) {
10225 if (vms->newmessages) {
10226 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10227 if (!res) {
10228 if (vms->newmessages == 1) {
10229 res = ast_play_and_wait(chan, "vm-message");
10230 if (!res)
10231 res = ast_play_and_wait(chan, "vm-INBOXs");
10232 } else {
10233 res = ast_play_and_wait(chan, "vm-messages");
10234 if (!res)
10235 res = ast_play_and_wait(chan, "vm-INBOX");
10236 }
10237 }
10238 if (vms->oldmessages && !res)
10239 res = ast_play_and_wait(chan, "vm-and");
10240 }
10241 if (!res && vms->oldmessages) {
10242 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10243 if (!res) {
10244 if (vms->oldmessages == 1) {
10245 res = ast_play_and_wait(chan, "vm-message");
10246 if (!res)
10247 res = ast_play_and_wait(chan, "vm-Olds");
10248 } else {
10249 res = ast_play_and_wait(chan, "vm-messages");
10250 if (!res)
10251 res = ast_play_and_wait(chan, "vm-Old");
10252 }
10253 }
10254 }
10255 if (!res) {
10256 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10257 res = ast_play_and_wait(chan, "vm-no");
10258 if (!res)
10259 res = ast_play_and_wait(chan, "vm-messages");
10260 }
10261 }
10262 }
10263 return res;
10264}

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

◆ vm_intro_pt_BR()

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

Definition at line 10080 of file app_voicemail.c.

10080 {
10081 /* Introduce messages they have */
10082 int res;
10083 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10084 res = ast_play_and_wait(chan, "vm-nomessages");
10085 return res;
10086 } else {
10087 res = ast_play_and_wait(chan, "vm-youhave");
10088 }
10089 if (vms->newmessages) {
10090 if (!res)
10091 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10092 if (vms->newmessages == 1) {
10093 if (!res)
10094 res = ast_play_and_wait(chan, "vm-message");
10095 if (!res)
10096 res = ast_play_and_wait(chan, "vm-INBOXs");
10097 } else {
10098 if (!res)
10099 res = ast_play_and_wait(chan, "vm-messages");
10100 if (!res)
10101 res = ast_play_and_wait(chan, "vm-INBOX");
10102 }
10103 if (vms->oldmessages && !res)
10104 res = ast_play_and_wait(chan, "vm-and");
10105 }
10106 if (vms->oldmessages) {
10107 if (!res)
10108 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10109 if (vms->oldmessages == 1) {
10110 if (!res)
10111 res = ast_play_and_wait(chan, "vm-message");
10112 if (!res)
10113 res = ast_play_and_wait(chan, "vm-Olds");
10114 } else {
10115 if (!res)
10116 res = ast_play_and_wait(chan, "vm-messages");
10117 if (!res)
10118 res = ast_play_and_wait(chan, "vm-Old");
10119 }
10120 }
10121 return res;
10122}

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

◆ vm_intro_se()

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

Definition at line 9845 of file app_voicemail.c.

9846{
9847 /* Introduce messages they have */
9848 int res;
9849
9850 res = ast_play_and_wait(chan, "vm-youhave");
9851 if (res)
9852 return res;
9853
9854 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
9855 res = ast_play_and_wait(chan, "vm-no");
9856 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9857 return res;
9858 }
9859
9860 if (vms->newmessages) {
9861 if (vms->newmessages == 1) {
9862 res = ast_play_and_wait(chan, "digits/ett");
9863 res = res ? res : ast_play_and_wait(chan, "vm-nytt");
9864 res = res ? res : ast_play_and_wait(chan, "vm-message");
9865 } else {
9866 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
9867 res = res ? res : ast_play_and_wait(chan, "vm-nya");
9868 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9869 }
9870 if (!res && vms->oldmessages)
9871 res = ast_play_and_wait(chan, "vm-and");
9872 }
9873 if (!res && vms->oldmessages) {
9874 if (vms->oldmessages == 1) {
9875 res = ast_play_and_wait(chan, "digits/ett");
9876 res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
9877 res = res ? res : ast_play_and_wait(chan, "vm-message");
9878 } else {
9879 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
9880 res = res ? res : ast_play_and_wait(chan, "vm-gamla");
9881 res = res ? res : ast_play_and_wait(chan, "vm-messages");
9882 }
9883 }
9884
9885 return res;
9886}

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

◆ vm_intro_vi()

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

Definition at line 10382 of file app_voicemail.c.

10383{
10384 int res;
10385
10386 /* Introduce messages they have */
10387 res = ast_play_and_wait(chan, "vm-youhave");
10388 if (!res) {
10389 if (vms->newmessages) {
10390 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10391 if (!res)
10392 res = ast_play_and_wait(chan, "vm-INBOX");
10393 if (vms->oldmessages && !res)
10394 res = ast_play_and_wait(chan, "vm-and");
10395 }
10396 if (!res && vms->oldmessages) {
10397 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10398 if (!res)
10399 res = ast_play_and_wait(chan, "vm-Old");
10400 }
10401 if (!res) {
10402 if (!vms->oldmessages && !vms->newmessages) {
10403 res = ast_play_and_wait(chan, "vm-no");
10404 if (!res)
10405 res = ast_play_and_wait(chan, "vm-message");
10406 }
10407 }
10408 }
10409 return res;
10410}

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

Referenced by vm_intro().

◆ vm_intro_zh()

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

Definition at line 10343 of file app_voicemail.c.

10344{
10345 int res;
10346 /* Introduce messages they have */
10347 res = ast_play_and_wait(chan, "vm-you");
10348
10349 if (!res && vms->newmessages) {
10350 res = ast_play_and_wait(chan, "vm-have");
10351 if (!res)
10352 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10353 if (!res)
10354 res = ast_play_and_wait(chan, "vm-tong");
10355 if (!res)
10356 res = ast_play_and_wait(chan, "vm-INBOX");
10357 if (vms->oldmessages && !res)
10358 res = ast_play_and_wait(chan, "vm-and");
10359 else if (!res)
10360 res = ast_play_and_wait(chan, "vm-messages");
10361 }
10362 if (!res && vms->oldmessages) {
10363 res = ast_play_and_wait(chan, "vm-have");
10364 if (!res)
10365 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10366 if (!res)
10367 res = ast_play_and_wait(chan, "vm-tong");
10368 if (!res)
10369 res = ast_play_and_wait(chan, "vm-Old");
10370 if (!res)
10371 res = ast_play_and_wait(chan, "vm-messages");
10372 }
10373 if (!res && !vms->oldmessages && !vms->newmessages) {
10374 res = ast_play_and_wait(chan, "vm-haveno");
10375 if (!res)
10376 res = ast_play_and_wait(chan, "vm-messages");
10377 }
10378 return res;
10379}

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

Referenced by vm_intro().

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

3869{
3870 switch (ast_lock_path(path)) {
3871 case AST_LOCK_TIMEOUT:
3872 return -1;
3873 default:
3874 return 0;
3875 }
3876}
@ AST_LOCK_TIMEOUT
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2604

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

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

16649{
16650 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
16651 struct vm_state vms;
16652 struct ast_vm_user *vmu = NULL, vmus;
16653 int res;
16654 int i;
16655 int this_index_only = -1;
16656 int open = 0;
16657 int inbox_index = get_folder_by_name("INBOX");
16658 int old_index = get_folder_by_name("Old");
16659 int urgent_index = get_folder_by_name("Urgent");
16660
16661 if (ast_strlen_zero(mailbox)) {
16662 ast_log(LOG_WARNING, "Cannot create a mailbox snapshot since no mailbox was specified\n");
16663 return NULL;
16664 }
16665
16666 memset(&vmus, 0, sizeof(vmus));
16667
16668 if (!(ast_strlen_zero(folder))) {
16669 /* find the folder index */
16670 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
16671 if (!strcasecmp(mailbox_folders[i], folder)) {
16672 this_index_only = i;
16673 break;
16674 }
16675 }
16676 if (this_index_only == -1) {
16677 /* Folder was specified and it did not match any folder in our list */
16678 return NULL;
16679 }
16680 }
16681
16682 if (!(vmu = find_user(&vmus, context, mailbox))) {
16683 ast_log(AST_LOG_WARNING, "Failed to create mailbox snapshot for unknown voicemail user %s@%s\n", mailbox, context);
16684 return NULL;
16685 }
16686
16687 if (!(mailbox_snapshot = ast_calloc(1, sizeof(*mailbox_snapshot)))) {
16688 ast_log(AST_LOG_ERROR, "Failed to allocate memory for mailbox snapshot\n");
16689 free_user(vmu);
16690 return NULL;
16691 }
16692
16693 if (!(mailbox_snapshot->snapshots = ast_calloc(ARRAY_LEN(mailbox_folders), sizeof(*mailbox_snapshot->snapshots)))) {
16694 ast_free(mailbox_snapshot);
16695 free_user(vmu);
16696 return NULL;
16697 }
16698
16699 mailbox_snapshot->folders = ARRAY_LEN(mailbox_folders);
16700
16701 for (i = 0; i < mailbox_snapshot->folders; i++) {
16702 int msg_folder_index = i;
16703
16704 /* We want this message in the snapshot if any of the following:
16705 * No folder was specified.
16706 * The specified folder matches the current folder.
16707 * The specified folder is INBOX AND we were asked to combine messages AND the current folder is either Old or Urgent.
16708 */
16709 if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
16710 continue;
16711 }
16712
16713 /* Make sure that Old or Urgent messages are marked as being in INBOX. */
16714 if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
16715 msg_folder_index = inbox_index;
16716 }
16717
16718 memset(&vms, 0, sizeof(vms));
16719 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
16720 vms.lastmsg = -1;
16721 open = 0;
16722
16723 /* open the mailbox state */
16724 if ((res = open_mailbox(&vms, vmu, i)) < 0) {
16725 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
16726 goto snapshot_cleanup;
16727 }
16728 open = 1;
16729
16730 /* Iterate through each msg, storing off info */
16731 if (vms.lastmsg != -1) {
16732 if ((vm_msg_snapshot_create(vmu, &vms, mailbox_snapshot, msg_folder_index, i, descending, sort_val))) {
16733 ast_log(LOG_WARNING, "Failed to create msg snapshots for %s@%s\n", mailbox, context);
16734 goto snapshot_cleanup;
16735 }
16736 }
16737
16738 /* close mailbox */
16739 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
16740 goto snapshot_cleanup;
16741 }
16742 open = 0;
16743 }
16744
16745snapshot_cleanup:
16746 if (vmu && open) {
16747 close_mailbox(&vms, vmu);
16748 }
16749
16750#ifdef IMAP_STORAGE
16751 if (vmu) {
16752 vmstate_delete(&vms);
16753 }
16754#endif
16755
16756 free_user(vmu);
16757 return mailbox_snapshot;
16758}
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.
struct ast_vm_mailbox_snapshot::@185 * snapshots

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

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

16761{
16762 int i;
16763 struct ast_vm_msg_snapshot *msg_snapshot;
16764
16765 for (i = 0; i < mailbox_snapshot->folders; i++) {
16766 while ((msg_snapshot = AST_LIST_REMOVE_HEAD(&mailbox_snapshot->snapshots[i], msg))) {
16767 msg_snapshot = vm_msg_snapshot_destroy(msg_snapshot);
16768 }
16769 }
16770 ast_free(mailbox_snapshot->snapshots);
16771 ast_free(mailbox_snapshot);
16772 return NULL;
16773}
static struct ast_vm_msg_snapshot * vm_msg_snapshot_destroy(struct ast_vm_msg_snapshot *msg_snapshot)

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

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

16863{
16864 struct vm_state from_vms;
16865 struct ast_vm_user *vmu = NULL, vmus;
16866 struct ast_vm_user *to_vmu = NULL, to_vmus;
16867 struct ast_config *msg_cfg;
16868 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
16869 char filename[PATH_MAX];
16870 int from_folder_index;
16871 int open = 0;
16872 int res = 0;
16873 int i;
16874 int *msg_nums;
16875
16876 if (ast_strlen_zero(from_mailbox) || ast_strlen_zero(to_mailbox)) {
16877 ast_log(LOG_WARNING, "Cannot forward message because either the from or to mailbox was not specified\n");
16878 return -1;
16879 }
16880
16881 if (!num_msgs) {
16882 ast_log(LOG_WARNING, "Invalid number of messages specified to forward: %zu\n", num_msgs);
16883 return -1;
16884 }
16885
16886 if (ast_strlen_zero(from_folder) || ast_strlen_zero(to_folder)) {
16887 ast_log(LOG_WARNING, "Cannot forward message because the from_folder or to_folder was not specified\n");
16888 return -1;
16889 }
16890
16891 memset(&vmus, 0, sizeof(vmus));
16892 memset(&to_vmus, 0, sizeof(to_vmus));
16893 memset(&from_vms, 0, sizeof(from_vms));
16894
16895 from_folder_index = get_folder_by_name(from_folder);
16896 if (from_folder_index == -1) {
16897 return -1;
16898 }
16899
16900 if (get_folder_by_name(to_folder) == -1) {
16901 return -1;
16902 }
16903
16904 if (!(vmu = find_user(&vmus, from_context, from_mailbox))) {
16905 ast_log(LOG_WARNING, "Can't find voicemail user to forward from (%s@%s)\n", from_mailbox, from_context);
16906 return -1;
16907 }
16908
16909 if (!(to_vmu = find_user(&to_vmus, to_context, to_mailbox))) {
16910 ast_log(LOG_WARNING, "Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
16911 free_user(vmu);
16912 return -1;
16913 }
16914
16915 ast_copy_string(from_vms.username, from_mailbox, sizeof(from_vms.username));
16916 from_vms.lastmsg = -1;
16917 open = 0;
16918
16919 /* open the mailbox state */
16920 if ((res = open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
16921 ast_log(LOG_WARNING, "Could not open mailbox %s\n", from_mailbox);
16922 res = -1;
16923 goto vm_forward_cleanup;
16924 }
16925
16926 open = 1;
16927
16928 if ((from_vms.lastmsg + 1) < num_msgs) {
16929 ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", from_folder, num_msgs);
16930 res = -1;
16931 goto vm_forward_cleanup;
16932 }
16933
16934 msg_nums = ast_alloca(sizeof(int) * num_msgs);
16935
16936 if ((res = message_range_and_existence_check(&from_vms, msg_ids, num_msgs, msg_nums, vmu) < 0)) {
16937 goto vm_forward_cleanup;
16938 }
16939
16940 /* Now we actually forward the messages */
16941 for (i = 0; i < num_msgs; i++) {
16942 int cur_msg = msg_nums[i];
16943 int duration = 0;
16944 const char *value;
16945
16946 make_file(from_vms.fn, sizeof(from_vms.fn), from_vms.curdir, cur_msg);
16947 snprintf(filename, sizeof(filename), "%s.txt", from_vms.fn);
16948 RETRIEVE(from_vms.curdir, cur_msg, vmu->mailbox, vmu->context);
16949 msg_cfg = ast_config_load(filename, config_flags);
16950 /* XXX This likely will not fail since we previously ensured that the
16951 * message we are looking for exists. However, there still could be some
16952 * circumstance where this fails, so atomicity is not guaranteed.
16953 */
16954 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
16955 DISPOSE(from_vms.curdir, cur_msg);
16956 continue;
16957 }
16958 if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
16959 duration = atoi(value);
16960 }
16961
16962 copy_message(NULL, vmu, from_folder_index, cur_msg, duration, to_vmu, vmfmts, from_vms.curdir, "", to_folder);
16963
16964 if (delete_old) {
16965 from_vms.deleted[cur_msg] = 1;
16966 }
16967 ast_config_destroy(msg_cfg);
16968 DISPOSE(from_vms.curdir, cur_msg);
16969 }
16970
16971 /* close mailbox */
16972 if ((res = close_mailbox(&from_vms, vmu) == ERROR_LOCK_PATH)) {
16973 res = -1;
16974 goto vm_forward_cleanup;
16975 }
16976 open = 0;
16977
16978vm_forward_cleanup:
16979 if (vmu && open) {
16980 close_mailbox(&from_vms, vmu);
16981 }
16982#ifdef IMAP_STORAGE
16983 if (vmu) {
16984 vmstate_delete(&from_vms);
16985 }
16986#endif
16987
16988 if (!res) {
16989 notify_new_state(to_vmu);
16990 }
16991
16992 free_user(vmu);
16993 free_user(to_vmu);
16994 return res;
16995}

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(), sip_to_pjsip::from_mailbox(), 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, value, and vmfmts.

Referenced by forward_message_from_mailbox(), and manager_voicemail_forward().

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

17003{
17004 struct vm_state vms;
17005 struct ast_vm_user *vmu = NULL, vmus;
17006 int old_folder_index;
17007 int new_folder_index;
17008 int open = 0;
17009 int res = 0;
17010 int i;
17011 int *old_msg_nums;
17012
17013 if (ast_strlen_zero(mailbox)) {
17014 ast_log(LOG_WARNING, "Cannot move message because no mailbox was specified\n");
17015 return -1;
17016 }
17017
17018 if (!num_msgs) {
17019 ast_log(LOG_WARNING, "Invalid number of messages specified to move: %zu\n", num_msgs);
17020 return -1;
17021 }
17022
17023 if (ast_strlen_zero(oldfolder) || ast_strlen_zero(newfolder)) {
17024 ast_log(LOG_WARNING, "Cannot move message because either oldfolder or newfolder was not specified\n");
17025 return -1;
17026 }
17027
17028 old_folder_index = get_folder_by_name(oldfolder);
17029 new_folder_index = get_folder_by_name(newfolder);
17030
17031 memset(&vmus, 0, sizeof(vmus));
17032 memset(&vms, 0, sizeof(vms));
17033
17034 if (old_folder_index == -1 || new_folder_index == -1) {
17035 return -1;
17036 }
17037
17038 if (!(vmu = find_user(&vmus, context, mailbox))) {
17039 return -1;
17040 }
17041
17042 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17043 vms.lastmsg = -1;
17044 open = 0;
17045
17046 /* open the mailbox state */
17047 if ((res = open_mailbox(&vms, vmu, old_folder_index)) < 0) {
17048 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17049 res = -1;
17050 goto vm_move_cleanup;
17051 }
17052
17053 open = 1;
17054
17055 if ((vms.lastmsg + 1) < num_msgs) {
17056 ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", oldfolder, num_msgs);
17057 res = -1;
17058 goto vm_move_cleanup;
17059 }
17060
17061 old_msg_nums = ast_alloca(sizeof(int) * num_msgs);
17062
17063 if ((res = message_range_and_existence_check(&vms, old_msg_ids, num_msgs, old_msg_nums, vmu)) < 0) {
17064 goto vm_move_cleanup;
17065 }
17066
17067 /* Now actually move the message */
17068 for (i = 0; i < num_msgs; ++i) {
17069 if (save_to_folder(vmu, &vms, old_msg_nums[i], new_folder_index, NULL, 0)) {
17070 res = -1;
17071 goto vm_move_cleanup;
17072 }
17073 vms.deleted[old_msg_nums[i]] = 1;
17074 }
17075
17076 /* close mailbox */
17077 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
17078 res = -1;
17079 goto vm_move_cleanup;
17080 }
17081 open = 0;
17082
17083vm_move_cleanup:
17084 if (vmu && open) {
17085 close_mailbox(&vms, vmu);
17086 }
17087#ifdef IMAP_STORAGE
17088 if (vmu) {
17089 vmstate_delete(&vms);
17090 }
17091#endif
17092
17093 if (!res) {
17094 notify_new_state(vmu);
17095 }
17096
17097 free_user(vmu);
17098 return res;
17099}

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

Referenced by manager_voicemail_move(), and move_message_from_mailbox().

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

17205{
17206 struct vm_state vms;
17207 struct ast_vm_user *vmu = NULL, vmus;
17208 int res = 0;
17209 int open = 0;
17210 int i;
17211 char filename[PATH_MAX];
17212 struct ast_config *msg_cfg;
17213 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
17214 int duration = 0;
17215 const char *value;
17216
17217 if (ast_strlen_zero(mailbox)) {
17218 ast_log(LOG_WARNING, "Cannot play message because no mailbox was specified\n");
17219 return -1;
17220 }
17221
17222 if (ast_strlen_zero(folder)) {
17223 ast_log(LOG_WARNING, "Cannot play message because no folder was specified\n");
17224 return -1;
17225 }
17226
17227 if (ast_strlen_zero(msg_id)) {
17228 ast_log(LOG_WARNING, "Cannot play message because no message number was specified\n");
17229 return -1;
17230 }
17231
17232 memset(&vmus, 0, sizeof(vmus));
17233 memset(&vms, 0, sizeof(vms));
17234
17235 if (ast_strlen_zero(context)) {
17236 context = "default";
17237 }
17238
17239 if (!(vmu = find_user(&vmus, context, mailbox))) {
17240 return -1;
17241 }
17242
17243 i = get_folder_by_name(folder);
17244 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17245 vms.lastmsg = -1;
17246 if ((res = open_mailbox(&vms, vmu, i)) < 0) {
17247 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17248 goto play2_msg_cleanup;
17249 }
17250 open = 1;
17251
17252 if (message_range_and_existence_check(&vms, &msg_id, 1, &vms.curmsg, vmu)) {
17253 res = -1;
17254 goto play2_msg_cleanup;
17255 }
17256
17257 /* Find the msg */
17258 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
17259 snprintf(filename, sizeof(filename), "%s.txt", vms.fn);
17260 RETRIEVE(vms.curdir, vms.curmsg, vmu->mailbox, vmu->context);
17261
17262 msg_cfg = ast_config_load(filename, config_flags);
17263 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
17264 DISPOSE(vms.curdir, vms.curmsg);
17265 res = -1;
17266 goto play2_msg_cleanup;
17267 }
17268 if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
17269 duration = atoi(value);
17270 }
17271 ast_config_destroy(msg_cfg);
17272
17273#ifdef IMAP_STORAGE
17274 /*IMAP storage stores any prepended message from a forward
17275 * as a separate file from the rest of the message
17276 */
17277 if (!ast_strlen_zero(vms.introfn) && ast_fileexists(vms.introfn, NULL, NULL) > 0) {
17278 wait_file(chan, &vms, vms.introfn);
17279 }
17280#endif
17281 if (cb) {
17282 cb(chan, vms.fn, duration);
17283 } else if ((wait_file(chan, &vms, vms.fn)) < 0) {
17284 ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms.fn);
17285 } else {
17286 res = 0;
17287 }
17288
17289 vms.heard[vms.curmsg] = 1;
17290
17291 /* cleanup configs and msg */
17292 DISPOSE(vms.curdir, vms.curmsg);
17293
17294play2_msg_cleanup:
17295 if (vmu && open) {
17296 close_mailbox(&vms, vmu);
17297 }
17298
17299#ifdef IMAP_STORAGE
17300 if (vmu) {
17301 vmstate_delete(&vms);
17302 }
17303#endif
17304
17305 if (!res) {
17306 notify_new_state(vmu);
17307 }
17308
17309 free_user(vmu);
17310 return res;
17311}

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_fileexists(), ast_log, AST_LOG_WARNING, ast_strlen_zero(), ast_variable_retrieve(), close_mailbox(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, voicemailpwcheck::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, LOG_WARNING, ast_vm_user::mailbox, voicemailpwcheck::mailbox, make_file(), message_range_and_existence_check(), notify_new_state(), NULL, open_mailbox(), PATH_MAX, RETRIEVE, vm_state::username, value, and wait_file().

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

17106{
17107 struct vm_state vms;
17108 struct ast_vm_user *vmu = NULL, vmus;
17109 int folder_index;
17110 int open = 0;
17111 int res = 0;
17112 int i;
17113 int *msg_nums;
17114
17115 if (ast_strlen_zero(mailbox)) {
17116 ast_log(LOG_WARNING, "Cannot remove message because no mailbox was specified\n");
17117 return -1;
17118 }
17119
17120 if (!num_msgs) {
17121 ast_log(LOG_WARNING, "Invalid number of messages specified to remove: %zu\n", num_msgs);
17122 return -1;
17123 }
17124
17125 if (ast_strlen_zero(folder)) {
17126 ast_log(LOG_WARNING, "Cannot remove message because no folder was specified\n");
17127 return -1;
17128 }
17129
17130 memset(&vmus, 0, sizeof(vmus));
17131 memset(&vms, 0, sizeof(vms));
17132
17133 folder_index = get_folder_by_name(folder);
17134 if (folder_index == -1) {
17135 ast_log(LOG_WARNING, "Could not remove msgs from unknown folder %s\n", folder);
17136 return -1;
17137 }
17138
17139 if (!(vmu = find_user(&vmus, context, mailbox))) {
17140 ast_log(LOG_WARNING, "Can't find voicemail user to remove msg from (%s@%s)\n", mailbox, context);
17141 return -1;
17142 }
17143
17144 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17145 vms.lastmsg = -1;
17146 open = 0;
17147
17148 /* open the mailbox state */
17149 if ((res = open_mailbox(&vms, vmu, folder_index)) < 0) {
17150 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17151 res = -1;
17152 goto vm_remove_cleanup;
17153 }
17154
17155 open = 1;
17156
17157 if ((vms.lastmsg + 1) < num_msgs) {
17158 ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", folder, num_msgs);
17159 res = -1;
17160 goto vm_remove_cleanup;
17161 }
17162
17163 msg_nums = ast_alloca(sizeof(int) * num_msgs);
17164
17165 if ((res = message_range_and_existence_check(&vms, msgs, num_msgs, msg_nums, vmu)) < 0) {
17166 goto vm_remove_cleanup;
17167 }
17168
17169 for (i = 0; i < num_msgs; i++) {
17170 vms.deleted[msg_nums[i]] = 1;
17171 }
17172
17173 /* close mailbox */
17174 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
17175 res = -1;
17176 ast_log(AST_LOG_ERROR, "Failed to close mailbox folder %s while removing msgs\n", folder);
17177 goto vm_remove_cleanup;
17178 }
17179 open = 0;
17180
17181vm_remove_cleanup:
17182 if (vmu && open) {
17183 close_mailbox(&vms, vmu);
17184 }
17185#ifdef IMAP_STORAGE
17186 if (vmu) {
17187 vmstate_delete(&vms);
17188 }
17189#endif
17190
17191 if (!res) {
17192 notify_new_state(vmu);
17193 }
17194
17195 free_user(vmu);
17196 return res;
17197}

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

Referenced by manager_voicemail_remove(), and remove_message_from_mailbox().

◆ vm_msg_snapshot_alloc()

static struct ast_vm_msg_snapshot * vm_msg_snapshot_alloc ( void  )
static

Definition at line 16460 of file app_voicemail.c.

16461{
16462 struct ast_vm_msg_snapshot *msg_snapshot;
16463
16464 if (!(msg_snapshot = ast_calloc(1, sizeof(*msg_snapshot)))) {
16465 return NULL;
16466 }
16467
16468 if (ast_string_field_init(msg_snapshot, 512)) {
16469 ast_free(msg_snapshot);
16470 return NULL;
16471 }
16472
16473 return msg_snapshot;
16474}
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

References ast_calloc, ast_free, ast_string_field_init, and NULL.

Referenced by vm_msg_snapshot_create().

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

16535{
16536 struct ast_vm_msg_snapshot *msg_snapshot;
16537 struct ast_vm_msg_snapshot *msg_snapshot_tmp;
16538 struct ast_config *msg_cfg;
16539 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
16540 char filename[PATH_MAX];
16541 const char *value;
16542
16543 for (vms->curmsg = 0; vms->curmsg <= vms->lastmsg; vms->curmsg++) {
16544 int inserted = 0;
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 msg_cfg = ast_config_load(filename, config_flags);
16550 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
16551 DISPOSE(vms->curdir, vms->curmsg);
16552 continue;
16553 }
16554
16555 /* Create the snapshot object */
16556 if (!(msg_snapshot = vm_msg_snapshot_alloc())) {
16557 ast_config_destroy(msg_cfg);
16558 return -1;
16559 }
16560
16561 /* Fill in the snapshot object */
16562 if ((value = ast_variable_retrieve(msg_cfg, "message", "msg_id"))) {
16563 ast_string_field_set(msg_snapshot, msg_id, value);
16564 } else {
16565 /* Message snapshots *really* should have a
16566 * message ID. Add one to the message config
16567 * if it does not already exist
16568 */
16569 char id[MSG_ID_LEN];
16570 if (!(add_message_id(msg_cfg, vms->curdir, vms->curmsg,
16571 filename, id, sizeof(id), vmu, mailbox_index))) {
16572 ast_string_field_set(msg_snapshot, msg_id, id);
16573 } else {
16574 ast_log(LOG_WARNING, "Unable to create a message ID for message %s/%d\n", vms->curdir, vms->curmsg);
16575 }
16576 }
16577 if ((value = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
16578 ast_string_field_set(msg_snapshot, callerid, value);
16579 }
16580 if ((value = ast_variable_retrieve(msg_cfg, "message", "callerchan"))) {
16581 ast_string_field_set(msg_snapshot, callerchan, value);
16582 }
16583 if ((value = ast_variable_retrieve(msg_cfg, "message", "exten"))) {
16584 ast_string_field_set(msg_snapshot, exten, value);
16585 }
16586 if ((value = ast_variable_retrieve(msg_cfg, "message", "origdate"))) {
16587 ast_string_field_set(msg_snapshot, origdate, value);
16588 }
16589 if ((value = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
16590 ast_string_field_set(msg_snapshot, origtime, value);
16591 }
16592 if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
16593 ast_string_field_set(msg_snapshot, duration, value);
16594 }
16595 if ((value = ast_variable_retrieve(msg_cfg, "message", "flag"))) {
16596 ast_string_field_set(msg_snapshot, flag, value);
16597 }
16598 msg_snapshot->msg_number = vms->curmsg;
16599 ast_string_field_set(msg_snapshot, folder_name, mailbox_folders[mailbox_index]);
16600
16601 /* store msg snapshot in mailbox snapshot */
16602 switch (sort_val) {
16603 default:
16605 if (descending) {
16606 AST_LIST_INSERT_HEAD(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
16607 } else {
16608 AST_LIST_INSERT_TAIL(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
16609 }
16610 inserted = 1;
16611 break;
16613 AST_LIST_TRAVERSE_SAFE_BEGIN(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot_tmp, msg) {
16614 int val = strcmp(msg_snapshot->origtime, msg_snapshot_tmp->origtime);
16615 if (descending && val >= 0) {
16616 AST_LIST_INSERT_BEFORE_CURRENT(msg_snapshot, msg);
16617 inserted = 1;
16618 break;
16619 } else if (!descending && val <= 0) {
16620 AST_LIST_INSERT_BEFORE_CURRENT(msg_snapshot, msg);
16621 inserted = 1;
16622 break;
16623 }
16624 }
16626 break;
16627 }
16628
16629 if (!inserted) {
16630 AST_LIST_INSERT_TAIL(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
16631 }
16632
16633 mailbox_snapshot->total_msg_num++;
16634
16635 /* cleanup configs and msg */
16636 ast_config_destroy(msg_cfg);
16637 DISPOSE(vms->curdir, vms->curmsg);
16638 }
16639
16640 return 0;
16641}
static struct ast_vm_msg_snapshot * vm_msg_snapshot_alloc(void)
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)
@ AST_VM_SNAPSHOT_SORT_BY_TIME
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:599
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
const ast_string_field origtime

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, vm_state::fn, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, mailbox_folders, 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().

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

16477{
16478 ast_string_field_free_memory(msg_snapshot);
16479 ast_free(msg_snapshot);
16480
16481 return NULL;
16482}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ast_free, ast_string_field_free_memory, and NULL.

Referenced by vm_mailbox_snapshot_destroy().

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

10702{
10703 int cmd = 0;
10704 int duration = 0;
10705 int tries = 0;
10706 char newpassword[80] = "";
10707 char newpassword2[80] = "";
10708 char prefile[PATH_MAX] = "";
10709 unsigned char buf[256];
10710 int bytes = 0;
10711
10712 ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
10713 if (ast_adsi_available(chan)) {
10714 bytes += adsi_logo(buf + bytes);
10715 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
10716 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
10717 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
10718 bytes += ast_adsi_voice_mode(buf + bytes, 0);
10720 }
10721
10722 /* If forcename is set, have the user record their name */
10723 if (ast_test_flag(vmu, VM_FORCENAME)) {
10724 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
10725 if (ast_fileexists(prefile, NULL, NULL) < 1) {
10726 cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10727 if (cmd < 0 || cmd == 't' || cmd == '#')
10728 return cmd;
10729 }
10730 }
10731
10732 /* If forcegreetings is set, have the user record their greetings */
10733 if (ast_test_flag(vmu, VM_FORCEGREET)) {
10734 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
10735 if (ast_fileexists(prefile, NULL, NULL) < 1) {
10736 cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10737 if (cmd < 0 || cmd == 't' || cmd == '#')
10738 return cmd;
10739 }
10740
10741 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
10742 if (ast_fileexists(prefile, NULL, NULL) < 1) {
10743 cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10744 if (cmd < 0 || cmd == 't' || cmd == '#')
10745 return cmd;
10746 }
10747 }
10748
10749 /*
10750 * Change the password last since new users will be able to skip over any steps this one comes before
10751 * by hanging up and calling back to voicemail main since the password is used to verify new user status.
10752 */
10753 for (;;) {
10754 newpassword[1] = '\0';
10755 newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
10756 if (cmd == '#')
10757 newpassword[0] = '\0';
10758 if (cmd < 0 || cmd == 't' || cmd == '#')
10759 return cmd;
10760 cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
10761 if (cmd < 0 || cmd == 't' || cmd == '#')
10762 return cmd;
10763 cmd = check_password(vmu, newpassword); /* perform password validation */
10764 if (cmd != 0) {
10765 ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
10767 } else {
10768 newpassword2[1] = '\0';
10769 newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
10770 if (cmd == '#')
10771 newpassword2[0] = '\0';
10772 if (cmd < 0 || cmd == 't' || cmd == '#')
10773 return cmd;
10774 cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
10775 if (cmd < 0 || cmd == 't' || cmd == '#')
10776 return cmd;
10777 if (!strcmp(newpassword, newpassword2))
10778 break;
10779 ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
10780 cmd = ast_play_and_wait(chan, vm_mismatch);
10781 }
10782 if (++tries == 3)
10783 return -1;
10784 if (cmd != 0) {
10786 }
10787 }
10789 vm_change_password(vmu, newpassword);
10791 vm_change_password_shell(vmu, newpassword);
10792
10793 ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
10794 cmd = ast_play_and_wait(chan, vm_passchanged);
10795
10796 return cmd;
10797}
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)

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, buf, check_password(), ast_vm_user::context, ext_pass_cmd, maxgreet, NULL, PATH_MAX, play_record_review(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, vm_state::username, vm_change_password(), vm_change_password_shell(), VM_FORCEGREET, VM_FORCENAME, vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, vm_reenterpassword, and VM_SPOOL_DIR.

Referenced by vm_execmain().

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

10800{
10801 int cmd = 0;
10802 int retries = 0;
10803 int duration = 0;
10804 char newpassword[80] = "";
10805 char newpassword2[80] = "";
10806 char prefile[PATH_MAX] = "";
10807 unsigned char buf[256];
10808 int bytes = 0;
10809
10810 ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
10811 if (ast_adsi_available(chan)) {
10812 bytes += adsi_logo(buf + bytes);
10813 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
10814 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
10815 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
10816 bytes += ast_adsi_voice_mode(buf + bytes, 0);
10818 }
10819 while ((cmd >= 0) && (cmd != 't')) {
10820 if (cmd)
10821 retries = 0;
10822 switch (cmd) {
10823 case '1': /* Record your unavailable message */
10824 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
10825 cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10826 break;
10827 case '2': /* Record your busy message */
10828 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
10829 cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10830 break;
10831 case '3': /* Record greeting */
10832 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
10833 cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10834 break;
10835 case '4': /* manage the temporary greeting */
10836 cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
10837 break;
10838 case '5': /* change password */
10839 if (vmu->password[0] == '-') {
10840 cmd = ast_play_and_wait(chan, "vm-no");
10841 break;
10842 }
10843 newpassword[1] = '\0';
10844 newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
10845 if (cmd == '#')
10846 newpassword[0] = '\0';
10847 else {
10848 if (cmd < 0)
10849 break;
10850 if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
10851 break;
10852 }
10853 }
10854 cmd = check_password(vmu, newpassword); /* perform password validation */
10855 if (cmd != 0) {
10856 ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
10858 if (!cmd) {
10860 }
10861 break;
10862 }
10863 newpassword2[1] = '\0';
10864 newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
10865 if (cmd == '#')
10866 newpassword2[0] = '\0';
10867 else {
10868 if (cmd < 0)
10869 break;
10870
10871 if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
10872 break;
10873 }
10874 }
10875 if (strcmp(newpassword, newpassword2)) {
10876 ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
10877 cmd = ast_play_and_wait(chan, vm_mismatch);
10878 if (!cmd) {
10880 }
10881 break;
10882 }
10883
10885 vm_change_password(vmu, newpassword);
10886 }
10888 vm_change_password_shell(vmu, newpassword);
10889 }
10890
10891 ast_debug(1, "User %s set password to %s of length %d\n",
10892 vms->username, newpassword, (int) strlen(newpassword));
10893 cmd = ast_play_and_wait(chan, vm_passchanged);
10894 break;
10895 case '*':
10896 cmd = 't';
10897 break;
10898 default:
10899 cmd = 0;
10900 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10901 RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10902 if (ast_fileexists(prefile, NULL, NULL)) {
10903 cmd = ast_play_and_wait(chan, "vm-tmpexists");
10904 }
10905 DISPOSE(prefile, -1);
10906 if (!cmd) {
10907 cmd = ast_play_and_wait(chan, "vm-options");
10908 }
10909 if (!cmd) {
10910 cmd = ast_waitfordigit(chan, 6000);
10911 }
10912 if (!cmd) {
10913 retries++;
10914 }
10915 if (retries > 3) {
10916 cmd = 't';
10917 }
10918 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
10919 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
10920 }
10921 }
10922 if (cmd == 't')
10923 cmd = 0;
10924 return cmd;
10925}
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'.

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(), buf, check_password(), ast_vm_user::context, DISPOSE, ext_pass_cmd, ast_vm_user::mailbox, maxgreet, NULL, ast_vm_user::password, PATH_MAX, play_record_review(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, RETRIEVE, vm_state::username, vm_change_password(), vm_change_password_shell(), vm_invalid_password, vm_mismatch, vm_newpassword, vm_passchanged, vm_pls_try_again, vm_reenterpassword, VM_SPOOL_DIR, and vm_tempgreeting().

Referenced by vm_execmain().

◆ vm_play_folder_name()

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

Definition at line 9334 of file app_voicemail.c.

9335{
9336 int cmd;
9337
9338 if ( !strncasecmp(ast_channel_language(chan), "it", 2) ||
9339 !strncasecmp(ast_channel_language(chan), "es", 2) ||
9340 !strncasecmp(ast_channel_language(chan), "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
9341 cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
9342 return cmd ? cmd : ast_play_and_wait(chan, box);
9343 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {
9344 return vm_play_folder_name_gr(chan, box);
9345 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* Hebrew syntax */
9346 return ast_play_and_wait(chan, box);
9347 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
9348 return vm_play_folder_name_ja(chan, box);
9349 } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
9350 return vm_play_folder_name_pl(chan, box);
9351 } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* Ukrainian syntax */
9352 return vm_play_folder_name_ua(chan, box);
9353 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
9354 return ast_play_and_wait(chan, box);
9355 } else { /* Default English */
9356 cmd = ast_play_and_wait(chan, box);
9357 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
9358 }
9359}
static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua(struct ast_channel *chan, char *box)
static int vm_play_folder_name_ja(struct ast_channel *chan, char *box)

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

◆ vm_play_folder_name_gr()

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

Definition at line 9274 of file app_voicemail.c.

9275{
9276 int cmd;
9277 char *buf;
9278
9279 buf = ast_alloca(strlen(box) + 2);
9280 strcpy(buf, box);
9281 strcat(buf, "s");
9282
9283 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
9284 cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
9285 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
9286 } else {
9287 cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
9288 return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
9289 }
9290}

References ast_alloca, ast_play_and_wait(), and buf.

Referenced by vm_play_folder_name().

◆ vm_play_folder_name_ja()

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

Definition at line 9292 of file app_voicemail.c.

9293{
9294 int cmd;
9295
9296 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9297 cmd = ast_play_and_wait(chan, box);
9298 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9299 } else {
9300 cmd = ast_play_and_wait(chan, box);
9301 return cmd;
9302 }
9303}

References ast_play_and_wait().

Referenced by vm_play_folder_name().

◆ vm_play_folder_name_pl()

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

Definition at line 9305 of file app_voicemail.c.

9306{
9307 int cmd;
9308
9309 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9310 if (!strcasecmp(box, "vm-INBOX"))
9311 cmd = ast_play_and_wait(chan, "vm-new-e");
9312 else
9313 cmd = ast_play_and_wait(chan, "vm-old-e");
9314 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9315 } else {
9316 cmd = ast_play_and_wait(chan, "vm-messages");
9317 return cmd ? cmd : ast_play_and_wait(chan, box);
9318 }
9319}

References ast_play_and_wait().

Referenced by vm_play_folder_name().

◆ vm_play_folder_name_ua()

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

Definition at line 9321 of file app_voicemail.c.

9322{
9323 int cmd;
9324
9325 if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
9326 cmd = ast_play_and_wait(chan, "vm-messages");
9327 return cmd ? cmd : ast_play_and_wait(chan, box);
9328 } else {
9329 cmd = ast_play_and_wait(chan, box);
9330 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9331 }
9332}

References ast_play_and_wait().

Referenced by vm_play_folder_name().

◆ vm_playmsgexec()

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

Definition at line 11521 of file app_voicemail.c.

11522{
11523 char *parse;
11524 char *mailbox = NULL;
11525 char *context = NULL;
11526 int res;
11527
11530 AST_APP_ARG(msg_id);
11531 );
11532
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 return -1;
11540 }
11541
11542 parse = ast_strdupa(data);
11544
11545 if (ast_strlen_zero(args.mailbox) || ast_strlen_zero(args.msg_id)) {
11546 return -1;
11547 }
11548
11549 if ((context = strchr(args.mailbox, '@'))) {
11550 *context++ = '\0';
11551 }
11552 mailbox = args.mailbox;
11553
11554 res = play_message_by_id(chan, mailbox, context, args.msg_id);
11555 pbx_builtin_setvar_helper(chan, "VOICEMAIL_PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS");
11556
11557 return 0;
11558}
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.

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(), voicemailpwcheck::context, voicemailpwcheck::mailbox, NULL, pbx_builtin_setvar_helper(), and play_message_by_id().

Referenced by load_module().

◆ vm_sayname()

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

Definition at line 15077 of file app_voicemail.c.

15078{
15079 char *context;
15080 char *mailbox;
15081
15082 if (ast_strlen_zero(mailbox_id)
15083 || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
15084 return -1;
15085 }
15086 return sayname(chan, mailbox, context);
15087}
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)

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

◆ 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_gain

This is option 4 from the mailbox options menu. This function manages the following promptings: 1: play / record / review the temporary greeting. : invokes play_record_review(). 2: remove (delete) the temporary greeting. *: return to the main menu.

Returns
zero on success, -1 on error.

Definition at line 10943 of file app_voicemail.c.

10944{
10945 int cmd = 0;
10946 int retries = 0;
10947 int duration = 0;
10948 char prefile[PATH_MAX] = "";
10949 unsigned char buf[256];
10950 int bytes = 0;
10951
10952 if (ast_adsi_available(chan)) {
10953 bytes += adsi_logo(buf + bytes);
10954 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
10955 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
10956 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
10957 bytes += ast_adsi_voice_mode(buf + bytes, 0);
10959 }
10960
10961 ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
10962 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10963 while ((cmd >= 0) && (cmd != 't')) {
10964 if (cmd)
10965 retries = 0;
10966 RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10967 if (ast_fileexists(prefile, NULL, NULL) <= 0) {
10968 cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10969 if (cmd == -1) {
10970 break;
10971 }
10972 cmd = 't';
10973 } else {
10974 switch (cmd) {
10975 case '1':
10976 cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
10977 break;
10978 case '2':
10979 DELETE(prefile, -1, prefile, vmu);
10980 ast_play_and_wait(chan, "vm-tempremoved");
10981 cmd = 't';
10982 break;
10983 case '*':
10984 cmd = 't';
10985 break;
10986 default:
10987 cmd = ast_play_and_wait(chan,
10988 ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
10989 "vm-tempgreeting2" : "vm-tempgreeting");
10990 if (!cmd) {
10991 cmd = ast_waitfordigit(chan, 6000);
10992 }
10993 if (!cmd) {
10994 retries++;
10995 }
10996 if (retries > 3) {
10997 cmd = 't';
10998 }
10999 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
11000 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
11001 }
11002 }
11003 DISPOSE(prefile, -1);
11004 }
11005 if (cmd == 't')
11006 cmd = 0;
11007 return cmd;
11008}

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(), buf, ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, maxgreet, NULL, PATH_MAX, play_record_review(), RETRIEVE, vm_state::username, and VM_SPOOL_DIR.

Referenced by vm_options().

◆ vmauthenticate()

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

Definition at line 13216 of file app_voicemail.c.

13217{
13218 char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
13219 struct ast_vm_user vmus = {{0}};
13220 char *options = NULL;
13221 int silent = 0, skipuser = 0;
13222 int res = -1;
13223
13224 if (data) {
13225 s = ast_strdupa(data);
13226 user = strsep(&s, ",");
13227 options = strsep(&s, ",");
13228 if (user) {
13229 s = user;
13230 user = strsep(&s, "@");
13231 context = strsep(&s, "");
13232 if (!ast_strlen_zero(user))
13233 skipuser++;
13235 }
13236 }
13237
13238 if (options) {
13239 silent = (strchr(options, 's')) != NULL;
13240 }
13241
13242 if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
13243 pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
13244 pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
13245 ast_play_and_wait(chan, "auth-thankyou");
13246 res = 0;
13247 } else if (mailbox[0] == '*') {
13248 /* user entered '*' */
13249 if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) {
13250 res = 0; /* prevent hangup */
13251 }
13252 }
13253
13254 return res;
13255}
static char user[512]
structure to hold users read from users.conf

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, voicemailpwcheck::context, voicemailpwcheck::mailbox, NULL, options, pbx_builtin_setvar_helper(), strsep(), user, and vm_authenticate().

Referenced by load_module().

◆ vmsayname_exec()

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

Definition at line 15139 of file app_voicemail.c.

15140{
15141 char *context;
15142 char *mailbox;
15143 int res;
15144
15145 if (ast_strlen_zero(data)
15147 ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
15148 return -1;
15149 }
15150
15151 if ((res = sayname(chan, mailbox, context)) < 0) {
15152 ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", mailbox, context);
15153 res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
15154 if (!res) {
15156 }
15157 }
15158
15159 return res;
15160}
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:8271
@ AST_SAY_CASE_NONE
Definition: say.h:182

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(), voicemailpwcheck::context, LOG_WARNING, voicemailpwcheck::mailbox, sayname(), and separate_mailbox().

Referenced by load_module().

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

4976{
4977 const struct vm_zone *z = NULL;
4978 struct timeval t = ast_tvnow();
4979
4980 /* Does this user have a timezone specified? */
4981 if (!ast_strlen_zero(vmu->zonetag)) {
4982 /* Find the zone in the list */
4984 AST_LIST_TRAVERSE(&zones, z, list) {
4985 if (!strcmp(z->name, vmu->zonetag))
4986 break;
4987 }
4989 }
4990 ast_localtime(&t, tm, z ? z->timezone : NULL);
4991 return tm;
4992}

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

◆ wait_file()

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

Definition at line 8625 of file app_voicemail.c.

8626{
8627 ast_test_suite_event_notify("PLAYVOICE", "Message: Playing %s", file);
8629}
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:1465

References ast_control_streamfile(), ast_test_suite_event_notify, make_ari_stubs::file, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, NULL, and skipms.

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

◆ wait_file2()

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

Definition at line 8617 of file app_voicemail.c.

8618{
8619 int res;
8620 if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
8621 ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file);
8622 return res;
8623}

References AST_DIGIT_ANY, ast_log, AST_LOG_WARNING, ast_stream_and_wait(), and make_ari_stubs::file.

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

◆ write_password_to_file()

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

Definition at line 15106 of file app_voicemail.c.

15106 {
15107 struct ast_config *conf;
15108 struct ast_category *cat;
15109 struct ast_variable *var;
15110 int res = -1;
15111
15112 if (!(conf = ast_config_new())) {
15113 ast_log(LOG_ERROR, "Error creating new config structure\n");
15114 return res;
15115 }
15116 if (!(cat = ast_category_new("general", "", 1))) {
15117 ast_log(LOG_ERROR, "Error creating new category structure\n");
15119 return res;
15120 }
15121 if (!(var = ast_variable_new("password", password, ""))) {
15122 ast_log(LOG_ERROR, "Error creating new variable structure\n");
15125 return res;
15126 }
15129 if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
15130 res = 0;
15131 } else {
15132 ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
15133 }
15134
15136 return res;
15137}
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
Definition: extconf.c:2788
void ast_category_destroy(struct ast_category *cat)
Definition: extconf.c:2845
All configuration options for http media cache.

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

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

Definition at line 17323 of file app_voicemail.c.

◆ addesc

char* addesc = "Comedian Mail"
static

Definition at line 1034 of file app_voicemail.c.

Referenced by adsi_load_vmail().

◆ adsifdn

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

Definition at line 1157 of file app_voicemail.c.

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

◆ adsisec

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

Definition at line 1158 of file app_voicemail.c.

Referenced by actual_load_config(), and adsi_load_vmail().

◆ adsiver

int adsiver = 1
static

Definition at line 1159 of file app_voicemail.c.

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

◆ alias_mailbox_mappings

struct ao2_container* alias_mailbox_mappings
static

◆ aliasescontext

char aliasescontext[MAX_VM_CONTEXT_LEN]
static

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 17323 of file app_voicemail.c.

◆ callcontext

char callcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1143 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

◆ charset

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

Definition at line 1155 of file app_voicemail.c.

◆ cidinternalcontexts

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static

Definition at line 1146 of file app_voicemail.c.

Referenced by actual_load_config(), and play_message_callerid().

◆ cli_voicemail

struct ast_cli_entry cli_voicemail[]
static

Definition at line 13499 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

◆ dialcontext

char dialcontext[AST_MAX_CONTEXT] = ""
static

◆ emailbody

char* emailbody
static

◆ emaildateformat

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

Definition at line 1160 of file app_voicemail.c.

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

◆ emailsubject

char* emailsubject
static

Definition at line 1150 of file app_voicemail.c.

Referenced by actual_load_config(), and make_email_file().

◆ exitcontext

char exitcontext[AST_MAX_CONTEXT] = ""
static

◆ ext_pass_check_cmd

char ext_pass_check_cmd[128]
static

Definition at line 1014 of file app_voicemail.c.

Referenced by actual_load_config(), and check_password().

◆ ext_pass_cmd

char ext_pass_cmd[128]
static

◆ externnotify

char externnotify[160]
static

Definition at line 1058 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

◆ fromstring

char fromstring[100]
static

Definition at line 1153 of file app_voicemail.c.

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

◆ globalflags

struct ast_flags globalflags = {0}
static

◆ inprocess_container

struct ao2_container* inprocess_container

Definition at line 1244 of file app_voicemail.c.

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

◆ listen_control_forward_key

char listen_control_forward_key[12]
static

Definition at line 1109 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_pause_key

char listen_control_pause_key[12]
static

Definition at line 1111 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_restart_key

char listen_control_restart_key[12]
static

Definition at line 1112 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_reverse_key

char listen_control_reverse_key[12]
static

Definition at line 1110 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_stop_key

char listen_control_stop_key[12]
static

Definition at line 1113 of file app_voicemail.c.

Referenced by actual_load_config(), and wait_file().

◆ locale

char locale[20]
static

◆ mailbox_alias_mappings

struct ao2_container* mailbox_alias_mappings
static

◆ mailbox_folders

const char* const mailbox_folders[]
static

◆ mailcmd

char mailcmd[160] = SENDMAIL
static

Definition at line 1057 of file app_voicemail.c.

Referenced by actual_load_config(), append_vmu_info_astman(), sendmail(), and sendpage().

◆ maxdeletedmsg

int maxdeletedmsg
static

Definition at line 1054 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

◆ maxgreet

int maxgreet
static

◆ maxlogins

int maxlogins = 3
static

Definition at line 1066 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_execmain().

◆ maxmsg

int maxmsg = MAXMSG
static

Definition at line 1053 of file app_voicemail.c.

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

◆ maxsilence

int maxsilence
static

◆ minpassword

int minpassword = MINPASSWORD
static

Definition at line 1067 of file app_voicemail.c.

Referenced by actual_load_config(), and check_password().

◆ msg_id_incrementor

int msg_id_incrementor
static

Definition at line 3881 of file app_voicemail.c.

Referenced by generate_msg_id().

◆ mwi_observer

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

Definition at line 13653 of file app_voicemail.c.

Referenced by start_poll_thread(), and stop_poll_thread().

◆ mwi_subscription_tps

struct ast_taskprocessor* mwi_subscription_tps
static

◆ my_umask

int my_umask
static

◆ pagerbody

char* pagerbody
static

Definition at line 1151 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

◆ pagerdateformat

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

Definition at line 1161 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

◆ pagerfromstring

char pagerfromstring[100]
static

Definition at line 1154 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

◆ pagersubject

char* pagersubject
static

Definition at line 1152 of file app_voicemail.c.

Referenced by actual_load_config(), and sendpage().

◆ passwordlocation

int passwordlocation
static

Definition at line 1068 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

◆ playmsg_app

char* playmsg_app = "VoiceMailPlayMsg"
static

Definition at line 1044 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

◆ poll_cond

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static

Definition at line 1081 of file app_voicemail.c.

Referenced by mb_poll_thread(), and stop_poll_thread().

◆ poll_freq

unsigned int poll_freq = DEFAULT_POLL_FREQ
static

Polling frequency

Definition at line 1078 of file app_voicemail.c.

Referenced by actual_load_config(), and mb_poll_thread().

◆ poll_lock

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

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

Referenced by actual_load_config().

◆ poll_thread

pthread_t poll_thread = AST_PTHREADT_NULL
static

◆ poll_thread_run

unsigned char poll_thread_run
static

Definition at line 1083 of file app_voicemail.c.

Referenced by mb_poll_thread(), start_poll_thread(), and stop_poll_thread().

◆ pwdchange

int pwdchange = PWDCHANGE_INTERNAL
static

Definition at line 1020 of file app_voicemail.c.

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

◆ saydurationminfo

int saydurationminfo = 2
static

Definition at line 1140 of file app_voicemail.c.

Referenced by actual_load_config(), and populate_defaults().

◆ sayname_app

char* sayname_app = "VMSayName"
static

Definition at line 1046 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

◆ serveremail

char serveremail[80] = ASTERISK_USERNAME
static

◆ silencethreshold

int silencethreshold = 128
static

◆ skipms

int skipms = 3000
static

◆ smdi_iface

struct ast_smdi_interface* smdi_iface = NULL
static

Definition at line 1059 of file app_voicemail.c.

Referenced by actual_load_config(), and run_externnotify().

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

Referenced by actual_load_config().

◆ vm_app_options

const struct ast_app_option vm_app_options[128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'S' ] = { .flag = OPT_SILENT_IF_GREET }, [ '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 }, [ 'r' ] = { .flag = OPT_READONLY }, }
static

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

Referenced by load_module(), and unload_module().

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

Referenced by load_module(), and unload_module().

◆ vm_invalid_password

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

Definition at line 1123 of file app_voicemail.c.

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

◆ vm_login

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

Definition at line 1116 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_authenticate().

◆ vm_mismatch

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

Definition at line 1122 of file app_voicemail.c.

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

◆ vm_newpassword

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

Definition at line 1119 of file app_voicemail.c.

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

◆ vm_newuser

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

Definition at line 1117 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_execmain().

◆ vm_passchanged

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

Definition at line 1120 of file app_voicemail.c.

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

◆ vm_password

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

Definition at line 1118 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_authenticate().

◆ vm_pls_try_again

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

◆ vm_prepend_timeout

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

Definition at line 1136 of file app_voicemail.c.

Referenced by actual_load_config(), and vm_forwardoptions().

◆ vm_reenterpassword

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

Definition at line 1121 of file app_voicemail.c.

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

◆ VM_SPOOL_DIR

char VM_SPOOL_DIR[PATH_MAX]
static

◆ vm_table

const struct ast_vm_functions vm_table
static

◆ vmauthenticate_app

char* vmauthenticate_app = "VMAuthenticate"
static

Definition at line 1042 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

◆ vmfmts

char vmfmts[80] = "wav"
static

◆ vmmaxsecs

int vmmaxsecs
static

Definition at line 1063 of file app_voicemail.c.

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

◆ vmminsecs

int vmminsecs
static

Definition at line 1062 of file app_voicemail.c.

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

◆ voicemail_app

char* voicemail_app = "VoiceMail"
static

Definition at line 1037 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

◆ voicemailmain_app

char* voicemailmain_app = "VoiceMailMain"
static

Definition at line 1040 of file app_voicemail.c.

Referenced by load_module(), and unload_module().

◆ volgain

double volgain
static

Definition at line 1061 of file app_voicemail.c.

Referenced by actual_load_config(), and 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 1050 of file app_voicemail.c.

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