Asterisk - The Open Source Telephony Project GIT-master-f36a736
Data Structures | Macros | Enumerations | Functions | Variables
app_voicemail_odbc.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_odbc.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 COUNT(a, b)   count_messages(a,b)
 
#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 LAST_MSG_INDEX(a)   last_message_index(a)
 
#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 MSGFILE_LEN   (7)
 
#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_ODBC_AUDIO_ON_DISK   (1 << 21)
 
#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_odbc.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_odbc.c.

◆ CHUNKSIZE

#define CHUNKSIZE   65536

Definition at line 635 of file app_voicemail_odbc.c.

◆ COMMAND_TIMEOUT

#define COMMAND_TIMEOUT   5000

Definition at line 631 of file app_voicemail_odbc.c.

◆ COPY

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

Definition at line 1014 of file app_voicemail_odbc.c.

◆ COUNT

#define COUNT (   a,
  b 
)    count_messages(a,b)

Definition at line 1007 of file app_voicemail_odbc.c.

◆ DEFAULT_LISTEN_CONTROL_FORWARD_KEY

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 643 of file app_voicemail_odbc.c.

◆ DEFAULT_LISTEN_CONTROL_PAUSE_KEY

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 645 of file app_voicemail_odbc.c.

◆ DEFAULT_LISTEN_CONTROL_RESTART_KEY

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 646 of file app_voicemail_odbc.c.

◆ DEFAULT_LISTEN_CONTROL_REVERSE_KEY

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 644 of file app_voicemail_odbc.c.

◆ DEFAULT_LISTEN_CONTROL_STOP_KEY

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 647 of file app_voicemail_odbc.c.

◆ DEFAULT_POLL_FREQ

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 1085 of file app_voicemail_odbc.c.

◆ DELETE

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

Definition at line 1015 of file app_voicemail_odbc.c.

◆ DISPOSE

#define DISPOSE (   a,
  b 
)

Definition at line 1010 of file app_voicemail_odbc.c.

◆ ENDL

#define ENDL   "\n"

Definition at line 665 of file app_voicemail_odbc.c.

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

Definition at line 694 of file app_voicemail_odbc.c.

◆ ERROR_MAX_MSGS

#define ERROR_MAX_MSGS   -101

Definition at line 695 of file app_voicemail_odbc.c.

◆ EXISTS

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

Definition at line 1012 of file app_voicemail_odbc.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 785 of file app_voicemail_odbc.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_odbc.c.

◆ LAST_MSG_INDEX

#define LAST_MSG_INDEX (   a)    last_message_index(a)

Definition at line 1008 of file app_voicemail_odbc.c.

◆ MAPPING_BUCKETS

#define MAPPING_BUCKETS   511

Definition at line 1108 of file app_voicemail_odbc.c.

◆ MAX_DATETIME_FORMAT

#define MAX_DATETIME_FORMAT   512

Definition at line 668 of file app_voicemail_odbc.c.

◆ MAX_MAIL_BODY_CONTENT_SIZE

#define MAX_MAIL_BODY_CONTENT_SIZE   134217728L

Definition at line 655 of file app_voicemail_odbc.c.

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 669 of file app_voicemail_odbc.c.

◆ MAX_VM_CONTEXT_LEN

#define MAX_VM_CONTEXT_LEN   (AST_MAX_CONTEXT)

Definition at line 886 of file app_voicemail_odbc.c.

◆ MAX_VM_MAILBOX_LEN

#define MAX_VM_MAILBOX_LEN   (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)

Definition at line 888 of file app_voicemail_odbc.c.

◆ MAX_VM_MBOX_ID_LEN

#define MAX_VM_MBOX_ID_LEN   (AST_MAX_EXTENSION)

Definition at line 885 of file app_voicemail_odbc.c.

◆ MAXMSG

#define MAXMSG   100

Definition at line 657 of file app_voicemail_odbc.c.

◆ MAXMSGLIMIT

#define MAXMSGLIMIT   9999

Definition at line 658 of file app_voicemail_odbc.c.

◆ MINPASSWORD

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 660 of file app_voicemail_odbc.c.

◆ MSG_ID_LEN

#define MSG_ID_LEN   256

Definition at line 4017 of file app_voicemail_odbc.c.

◆ MSGFILE_LEN

#define MSGFILE_LEN   (7)

Length of the message file name: msgXXXX

Definition at line 698 of file app_voicemail_odbc.c.

◆ OPERATOR_EXIT

#define OPERATOR_EXIT   300

Definition at line 696 of file app_voicemail_odbc.c.

◆ PWDCHANGE_EXTERNAL

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 1028 of file app_voicemail_odbc.c.

◆ PWDCHANGE_INTERNAL

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 1027 of file app_voicemail_odbc.c.

◆ RENAME

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

Definition at line 1013 of file app_voicemail_odbc.c.

◆ RETRIEVE

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

Definition at line 1009 of file app_voicemail_odbc.c.

◆ SENDMAIL

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

Definition at line 652 of file app_voicemail_odbc.c.

◆ SMDI_MWI_WAIT_TIMEOUT

#define SMDI_MWI_WAIT_TIMEOUT   1000 /* 1 second */

Definition at line 629 of file app_voicemail_odbc.c.

◆ STORE

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

Definition at line 1011 of file app_voicemail_odbc.c.

◆ tdesc

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 1037 of file app_voicemail_odbc.c.

◆ UPDATE_MSG_ID

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

Definition at line 1016 of file app_voicemail_odbc.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_odbc.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_odbc.c.

◆ VM_ATTACH

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 682 of file app_voicemail_odbc.c.

◆ VM_DELETE

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 683 of file app_voicemail_odbc.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_odbc.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_odbc.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_odbc.c.

◆ VM_FORCEGREET

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 679 of file app_voicemail_odbc.c.

◆ VM_FORCENAME

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 678 of file app_voicemail_odbc.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_odbc.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_odbc.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_odbc.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_odbc.c.

◆ VM_ODBC_AUDIO_ON_DISK

#define VM_ODBC_AUDIO_ON_DISK   (1 << 21)

When using ODBC, leave the message and greeting recordings on disk instead of moving them into the table

Definition at line 692 of file app_voicemail_odbc.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_odbc.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_odbc.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_odbc.c.

◆ VM_SAYCID

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 673 of file app_voicemail_odbc.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_odbc.c.

◆ VM_SEARCH

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 685 of file app_voicemail_odbc.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_odbc.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_odbc.c.

◆ VM_TEMPGREETWARN

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 686 of file app_voicemail_odbc.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 940 of file app_voicemail_odbc.c.

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 637 of file app_voicemail_odbc.c.

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0777

Definition at line 633 of file app_voicemail_odbc.c.

◆ VOICEMAIL_FILE_MODE

#define VOICEMAIL_FILE_MODE   0666

Definition at line 634 of file app_voicemail_odbc.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 700 of file app_voicemail_odbc.c.

700 {
701 NEW_FOLDER = 0,
702 OLD_FOLDER = 1,
703 WORK_FOLDER = 2,
704 FAMILY_FOLDER = 3,
705 FRIENDS_FOLDER = 4,
707};
@ 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 725 of file app_voicemail_odbc.c.

725 {
730 /* This *must* be the last value in this enum! */
732};
@ 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 709 of file app_voicemail_odbc.c.

709 {
710 OPT_SILENT = (1 << 0),
711 OPT_BUSY_GREETING = (1 << 1),
712 OPT_UNAVAIL_GREETING = (1 << 2),
713 OPT_RECORDGAIN = (1 << 3),
714 OPT_PREPEND_MAILBOX = (1 << 4),
715 OPT_AUTOPLAY = (1 << 6),
716 OPT_DTMFEXIT = (1 << 7),
717 OPT_MESSAGE_Urgent = (1 << 8),
718 OPT_MESSAGE_PRIORITY = (1 << 9),
719 OPT_EARLYM_GREETING = (1 << 10),
720 OPT_BEEP = (1 << 11),
721 OPT_SILENT_IF_GREET = (1 << 12),
722 OPT_READONLY = (1 << 13),
723};
@ 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 734 of file app_voicemail_odbc.c.

734 {
738};
@ 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 6434 of file app_voicemail_odbc.c.

6435{
6436 DIR *dir;
6437 struct dirent *de;
6438 char fn[256];
6439 int ret = 0;
6440 struct alias_mailbox_mapping *mapping;
6441 char *c;
6442 char *m;
6443
6444 /* If no mailbox, return immediately */
6446 return 0;
6447
6448 if (ast_strlen_zero(folder))
6449 folder = "INBOX";
6451 context = "default";
6452
6453 c = (char *)context;
6454 m = (char *)mailbox;
6455
6457 char tmp[MAX_VM_MAILBOX_LEN];
6458
6459 snprintf(tmp, MAX_VM_MAILBOX_LEN, "%s@%s", mailbox, context);
6461 if (mapping) {
6462 separate_mailbox(ast_strdupa(mapping->mailbox), &m, &c);
6463 ao2_ref(mapping, -1);
6464 }
6465 }
6466
6467 snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, c, m, folder);
6468
6469 if (!(dir = opendir(fn)))
6470 return 0;
6471
6472 while ((de = readdir(dir))) {
6473 if (!strncasecmp(de->d_name, "msg", 3)) {
6474 if (shortcircuit) {
6475 ret = 1;
6476 break;
6477 } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
6478 ret++;
6479 }
6480 }
6481 }
6482
6483 closedir(dir);
6484
6485 return ret;
6486}
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 17811 of file app_voicemail_odbc.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 17811 of file app_voicemail_odbc.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 13601 of file app_voicemail_odbc.c.

13602{
13603 struct ast_vm_user svm;
13604 struct ast_vm_user *vmu = NULL;
13605 char *parse;
13606 char *mailbox;
13607 char *context;
13608 int res = 0;
13609
13611 AST_APP_ARG(mailbox_context);
13612 AST_APP_ARG(attribute);
13613 AST_APP_ARG(folder);
13614 );
13615
13616 buf[0] = '\0';
13617
13618 if (ast_strlen_zero(args)) {
13619 ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13620 return -1;
13621 }
13622
13623 parse = ast_strdupa(args);
13624 AST_STANDARD_APP_ARGS(arg, parse);
13625
13626 if (ast_strlen_zero(arg.mailbox_context)
13627 || ast_strlen_zero(arg.attribute)
13628 || separate_mailbox(ast_strdupa(arg.mailbox_context), &mailbox, &context)) {
13629 ast_log(LOG_ERROR, "VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13630 return -1;
13631 }
13632
13633 memset(&svm, 0, sizeof(svm));
13634 vmu = find_user(&svm, context, mailbox);
13635
13636 if (!strncasecmp(arg.attribute, "exists", 5)) {
13637 ast_copy_string(buf, vmu ? "1" : "0", len);
13638 free_user(vmu);
13639 return 0;
13640 }
13641
13642 if (vmu) {
13643 if (!strncasecmp(arg.attribute, "password", 8)) {
13645 } else if (!strncasecmp(arg.attribute, "fullname", 8)) {
13647 } else if (!strncasecmp(arg.attribute, "email", 5)) {
13648 ast_copy_string(buf, vmu->email, len);
13649 } else if (!strncasecmp(arg.attribute, "pager", 5)) {
13650 ast_copy_string(buf, vmu->pager, len);
13651 } else if (!strncasecmp(arg.attribute, "language", 8)) {
13653 } else if (!strncasecmp(arg.attribute, "locale", 6)) {
13654 ast_copy_string(buf, vmu->locale, len);
13655 } else if (!strncasecmp(arg.attribute, "tz", 2)) {
13657 } else if (!strncasecmp(arg.attribute, "count", 5)) {
13658 char *mailbox_id;
13659
13660 mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2);
13661 sprintf(mailbox_id, "%s@%s", mailbox, context);/* Safe */
13662
13663 /* If mbxfolder is empty messagecount will default to INBOX */
13664 res = messagecount(mailbox_id, arg.folder);
13665 if (res < 0) {
13666 ast_log(LOG_ERROR, "Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
13667 free_user(vmu);
13668 return -1;
13669 }
13670 snprintf(buf, len, "%d", res);
13671 } else {
13672 ast_log(LOG_ERROR, "Unknown attribute '%s' for VM_INFO\n", arg.attribute);
13673 free_user(vmu);
13674 return -1;
13675 }
13676 free_user(vmu);
13677 }
13678
13679 return 0;
13680}
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 14836 of file app_voicemail_odbc.c.

14837{
14838 struct ast_vm_user *current;
14839 char *cat;
14840 const char *val;
14841 char *q, *stringp, *tmp;
14842 int x;
14843 unsigned int tmpadsi[4];
14844 char secretfn[PATH_MAX] = "";
14845 long tps_queue_low;
14846 long tps_queue_high;
14847
14848#ifdef IMAP_STORAGE
14849 ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
14850#endif
14851 /* set audio control prompts */
14857
14858#ifdef IMAP_STORAGE
14859 ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
14860#endif
14861
14862 /* Free all the users structure */
14863 free_vm_users();
14864
14865 /* Free all the zones structure */
14866 free_vm_zones();
14867
14868 /* Remove all aliases */
14871
14873
14874 memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
14875 memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
14876
14877 if (cfg) {
14878 /* General settings */
14879
14880 if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
14881 val = "default";
14883
14884 aliasescontext[0] = '\0';
14885 val = ast_variable_retrieve(cfg, "general", "aliasescontext");
14887
14888 /* Attach voice message to mail message ? */
14889 if (!(val = ast_variable_retrieve(cfg, "general", "attach")))
14890 val = "yes";
14892
14893 if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
14894 val = "no";
14896
14897 volgain = 0.0;
14898 if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
14899 sscanf(val, "%30lf", &volgain);
14900
14901#ifdef ODBC_STORAGE
14902 strcpy(odbc_database, "asterisk");
14903 if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
14904 ast_copy_string(odbc_database, val, sizeof(odbc_database));
14905 }
14906
14907 strcpy(odbc_table, "voicemessages");
14908 if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
14909 ast_copy_string(odbc_table, val, sizeof(odbc_table));
14910 }
14911 odbc_table_len = strlen(odbc_table);
14912
14914 if (!(val = ast_variable_retrieve(cfg, "general", "odbc_audio_on_disk")))
14915 val = "no";
14917
14918#endif
14919 /* Mail command */
14920 strcpy(mailcmd, SENDMAIL);
14921 if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
14922 ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
14923
14924 maxsilence = 0;
14925 if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
14926 maxsilence = atoi(val);
14927 if (maxsilence > 0)
14928 maxsilence *= 1000;
14929 }
14930
14931 if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
14932 maxmsg = MAXMSG;
14933 } else {
14934 maxmsg = atoi(val);
14935 if (maxmsg < 0) {
14936 ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
14937 maxmsg = MAXMSG;
14938 } else if (maxmsg > MAXMSGLIMIT) {
14939 ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
14941 }
14942 }
14943
14944 if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
14945 maxdeletedmsg = 0;
14946 } else {
14947 if (sscanf(val, "%30d", &x) == 1)
14948 maxdeletedmsg = x;
14949 else if (ast_true(val))
14951 else
14952 maxdeletedmsg = 0;
14953
14954 if (maxdeletedmsg < 0) {
14955 ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
14957 } else if (maxdeletedmsg > MAXMSGLIMIT) {
14958 ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
14960 }
14961 }
14962
14963 /* Load date format config for voicemail mail */
14964 if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
14966 }
14967
14968 /* Load date format config for voicemail pager mail */
14969 if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
14971 }
14972
14973 /* External password changing command */
14974 if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
14977 } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
14980 }
14981
14982 /* External password validation command */
14983 if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
14985 ast_debug(1, "found externpasscheck: %s\n", ext_pass_check_cmd);
14986 }
14987
14988#ifdef IMAP_STORAGE
14989 /* IMAP server address */
14990 if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
14991 ast_copy_string(imapserver, val, sizeof(imapserver));
14992 } else {
14993 ast_copy_string(imapserver, "localhost", sizeof(imapserver));
14994 }
14995 /* IMAP server port */
14996 if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
14997 ast_copy_string(imapport, val, sizeof(imapport));
14998 } else {
14999 ast_copy_string(imapport, "143", sizeof(imapport));
15000 }
15001 /* IMAP server flags */
15002 if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
15003 ast_copy_string(imapflags, val, sizeof(imapflags));
15004 }
15005 /* IMAP server master username */
15006 if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
15007 ast_copy_string(authuser, val, sizeof(authuser));
15008 }
15009 /* IMAP server master password */
15010 if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
15011 ast_copy_string(authpassword, val, sizeof(authpassword));
15012 }
15013 /* Expunge on exit */
15014 if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
15015 if (ast_false(val))
15016 expungeonhangup = 0;
15017 else
15018 expungeonhangup = 1;
15019 } else {
15020 expungeonhangup = 1;
15021 }
15022 /* IMAP voicemail folder */
15023 if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
15024 ast_copy_string(imapfolder, val, sizeof(imapfolder));
15025 } else {
15026 ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
15027 }
15028 if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
15029 ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
15030 }
15031 if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
15032 imapgreetings = ast_true(val);
15033 } else {
15034 imapgreetings = 0;
15035 }
15036 if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
15037 ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
15038 } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
15039 /* Also support greetingsfolder as documented in voicemail.conf.sample */
15040 ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
15041 } else {
15042 ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
15043 }
15044 if ((val = ast_variable_retrieve(cfg, "general", "imap_poll_logout"))) {
15045 imap_poll_logout = ast_true(val);
15046 } else {
15047 imap_poll_logout = 0;
15048 }
15049
15050 /* There is some very unorthodox casting done here. This is due
15051 * to the way c-client handles the argument passed in. It expects a
15052 * void pointer and casts the pointer directly to a long without
15053 * first dereferencing it. */
15054 if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
15055 mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
15056 } else {
15057 mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
15058 }
15059
15060 if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
15061 mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
15062 } else {
15063 mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
15064 }
15065
15066 if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
15067 mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
15068 } else {
15069 mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
15070 }
15071
15072 if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
15073 mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
15074 } else {
15075 mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
15076 }
15077
15078 /* Increment configuration version */
15079 imapversion++;
15080#endif
15081 /* External voicemail notify application */
15082 if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
15084 ast_debug(1, "found externnotify: %s\n", externnotify);
15085 } else {
15086 externnotify[0] = '\0';
15087 }
15088
15089 /* SMDI voicemail notification */
15090 if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
15091 ast_debug(1, "Enabled SMDI voicemail notification\n");
15092 if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
15094 } else {
15095 ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
15096 smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
15097 }
15098 if (!smdi_iface) {
15099 ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
15100 }
15101 }
15102
15103 /* Silence treshold */
15105 if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
15106 silencethreshold = atoi(val);
15107
15108 if (!(val = ast_variable_retrieve(cfg, "general", "serveremail")))
15111
15112 vmmaxsecs = 0;
15113 if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
15114 if (sscanf(val, "%30d", &x) == 1) {
15115 vmmaxsecs = x;
15116 } else {
15117 ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
15118 }
15119 } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
15120 static int maxmessage_deprecate = 0;
15121 if (maxmessage_deprecate == 0) {
15122 maxmessage_deprecate = 1;
15123 ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
15124 }
15125 if (sscanf(val, "%30d", &x) == 1) {
15126 vmmaxsecs = x;
15127 } else {
15128 ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
15129 }
15130 }
15131
15132 vmminsecs = 0;
15133 if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
15134 if (sscanf(val, "%30d", &x) == 1) {
15135 vmminsecs = x;
15136 if (maxsilence / 1000 >= vmminsecs) {
15137 ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
15138 }
15139 } else {
15140 ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
15141 }
15142 } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
15143 static int maxmessage_deprecate = 0;
15144 if (maxmessage_deprecate == 0) {
15145 maxmessage_deprecate = 1;
15146 ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
15147 }
15148 if (sscanf(val, "%30d", &x) == 1) {
15149 vmminsecs = x;
15150 if (maxsilence / 1000 >= vmminsecs) {
15151 ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
15152 }
15153 } else {
15154 ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
15155 }
15156 }
15157
15158 val = ast_variable_retrieve(cfg, "general", "format");
15159 if (!val) {
15160 val = "wav";
15161 } else {
15162 tmp = ast_strdupa(val);
15164 if (!val) {
15165 ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
15166 val = "wav";
15167 }
15168 }
15169 ast_copy_string(vmfmts, val, sizeof(vmfmts));
15170
15171 skipms = 3000;
15172 if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
15173 if (sscanf(val, "%30d", &x) == 1) {
15174 maxgreet = x;
15175 } else {
15176 ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
15177 }
15178 }
15179
15180 if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
15181 if (sscanf(val, "%30d", &x) == 1) {
15182 skipms = x;
15183 } else {
15184 ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
15185 }
15186 }
15187
15188 maxlogins = 3;
15189 if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
15190 if (sscanf(val, "%30d", &x) == 1) {
15191 maxlogins = x;
15192 } else {
15193 ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
15194 }
15195 }
15196
15198 if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
15199 if (sscanf(val, "%30d", &x) == 1) {
15200 minpassword = x;
15201 } else {
15202 ast_log(AST_LOG_WARNING, "Invalid minimum password length. Default to %d\n", minpassword);
15203 }
15204 }
15205
15206 /* Force new user to record name ? */
15207 if (!(val = ast_variable_retrieve(cfg, "general", "forcename")))
15208 val = "no";
15210
15211 /* Force new user to record greetings ? */
15212 if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings")))
15213 val = "no";
15215
15216 if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
15217 ast_debug(1, "VM_CID Internal context string: %s\n", val);
15218 stringp = ast_strdupa(val);
15219 for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
15220 if (!ast_strlen_zero(stringp)) {
15221 q = strsep(&stringp, ",");
15222 while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
15223 q++;
15225 ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
15226 } else {
15227 cidinternalcontexts[x][0] = '\0';
15228 }
15229 }
15230 }
15231 if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
15232 ast_debug(1, "VM Review Option disabled globally\n");
15233 val = "no";
15234 }
15236
15237 if (!(val = ast_variable_retrieve(cfg, "general", "leaveurgent"))){
15238 val = "yes";
15239 } else if (ast_false(val)) {
15240 ast_debug(1, "VM leave urgent messages disabled globally\n");
15241 val = "no";
15242 }
15244
15245 /* Temporary greeting reminder */
15246 if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
15247 ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
15248 val = "no";
15249 } else {
15250 ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
15251 }
15253 if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
15254 ast_debug(1, "VM next message wrap disabled globally\n");
15255 val = "no";
15256 }
15258
15259 if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
15260 ast_debug(1, "VM Operator break disabled globally\n");
15261 val = "no";
15262 }
15264
15265 if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
15266 ast_debug(1, "VM CID Info before msg disabled globally\n");
15267 val = "no";
15268 }
15270
15271 if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
15272 ast_debug(1, "Send Voicemail msg disabled globally\n");
15273 val = "no";
15274 }
15276
15277 if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
15278 ast_debug(1, "ENVELOPE before msg enabled globally\n");
15279 val = "yes";
15280 }
15282
15283 if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
15284 ast_debug(1, "Move Heard enabled globally\n");
15285 val = "yes";
15286 }
15288
15289 if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
15290 ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
15291 val = "no";
15292 }
15294
15295 if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
15296 ast_debug(1, "Duration info before msg enabled globally\n");
15297 val = "yes";
15298 }
15300
15301 saydurationminfo = 2;
15302 if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
15303 if (sscanf(val, "%30d", &x) == 1) {
15304 saydurationminfo = x;
15305 } else {
15306 ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
15307 }
15308 }
15309
15310 if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
15311 ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
15312 val = "no";
15313 }
15315
15316 if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
15318 ast_debug(1, "found dialout context: %s\n", dialcontext);
15319 } else {
15320 dialcontext[0] = '\0';
15321 }
15322
15323 if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
15325 ast_debug(1, "found callback context: %s\n", callcontext);
15326 } else {
15327 callcontext[0] = '\0';
15328 }
15329
15330 if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
15332 ast_debug(1, "found operator context: %s\n", exitcontext);
15333 } else {
15334 exitcontext[0] = '\0';
15335 }
15336
15337 /* load password sounds configuration */
15338 if ((val = ast_variable_retrieve(cfg, "general", "vm-login")))
15340 if ((val = ast_variable_retrieve(cfg, "general", "vm-newuser")))
15342 if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
15344 if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
15346 if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
15348 if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
15350 if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
15352 if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
15354 if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
15356 }
15357 if ((val = ast_variable_retrieve(cfg, "general", "vm-prepend-timeout"))) {
15359 }
15360 /* load configurable audio prompts */
15361 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
15363 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
15365 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
15367 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
15369 if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
15371
15372 if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory")))
15373 val = "no";
15375
15376 if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
15377 val = "voicemail.conf";
15378 }
15379 if (!(strcmp(val, "spooldir"))) {
15381 } else {
15383 }
15384
15386 if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
15387 if (sscanf(val, "%30u", &poll_freq) != 1) {
15389 ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
15390 }
15391 }
15392
15393 poll_mailboxes = 0;
15394 if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
15396
15397 memset(fromstring, 0, sizeof(fromstring));
15398 memset(pagerfromstring, 0, sizeof(pagerfromstring));
15399 strcpy(charset, "ISO-8859-1");
15400 if (emailbody) {
15402 emailbody = NULL;
15403 }
15404 if (emailsubject) {
15407 }
15408 if (pagerbody) {
15410 pagerbody = NULL;
15411 }
15412 if (pagersubject) {
15415 }
15416 if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
15418 if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
15420 if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
15422 if ((val = ast_variable_retrieve(cfg, "general", "charset")))
15424 if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
15425 sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
15426 for (x = 0; x < 4; x++) {
15427 memcpy(&adsifdn[x], &tmpadsi[x], 1);
15428 }
15429 }
15430 if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
15431 sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
15432 for (x = 0; x < 4; x++) {
15433 memcpy(&adsisec[x], &tmpadsi[x], 1);
15434 }
15435 }
15436 if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
15437 if (atoi(val)) {
15438 adsiver = atoi(val);
15439 }
15440 }
15441 if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
15443 }
15444 if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
15445 ast_copy_string(locale, val, sizeof(locale));
15446 }
15447 if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
15449 }
15450 if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
15452 }
15453 if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
15455 }
15456 if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
15458 }
15459
15460 tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
15461 if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_high"))) {
15462 if (sscanf(val, "%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
15463 ast_log(AST_LOG_WARNING, "Invalid the taskprocessor high water alert trigger level '%s'\n", val);
15464 tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;
15465 }
15466 }
15467 tps_queue_low = -1;
15468 if ((val = ast_variable_retrieve(cfg, "general", "tps_queue_low"))) {
15469 if (sscanf(val, "%30ld", &tps_queue_low) != 1 ||
15470 tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
15471 ast_log(AST_LOG_WARNING, "Invalid the taskprocessor low water clear alert level '%s'\n", val);
15472 tps_queue_low = -1;
15473 }
15474 }
15475 if (ast_taskprocessor_alert_set_levels(mwi_subscription_tps, tps_queue_low, tps_queue_high)) {
15476 ast_log(AST_LOG_WARNING, "Failed to set alert levels for voicemail taskprocessor.\n");
15477 }
15478
15479 /* load mailboxes from users.conf */
15480 if (ucfg) {
15481 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15482 if (!strcasecmp(cat, "general")) {
15483 continue;
15484 }
15485 if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
15486 continue;
15487 if ((current = find_or_create(userscontext, cat))) {
15490 ast_copy_string(current->context, userscontext, sizeof(current->context));
15491 if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
15492 current->passwordlocation = OPT_PWLOC_USERSCONF;
15493 }
15494
15495 switch (current->passwordlocation) {
15496 case OPT_PWLOC_SPOOLDIR:
15497 snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
15498 read_password_from_file(secretfn, current->password, sizeof(current->password));
15499 }
15500 }
15501 }
15502 }
15503
15504 /* load mailboxes from voicemail.conf */
15505
15506 /*
15507 * Aliases must be loaded before users or the aliases won't be notified
15508 * if there's existing voicemail in the user mailbox.
15509 */
15510 load_aliases(cfg);
15511
15512 load_zonemessages(cfg);
15513
15514 load_users(cfg);
15515
15517
15522
15523 return 0;
15524 } else {
15526 ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
15527 return 0;
15528 }
15529}
static char pagerfromstring[100]
static char vm_password[80]
static char vm_invalid_password[80]
#define VM_SEARCH
#define VM_ODBC_AUDIO_ON_DISK
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:784
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:774
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_ODBC_AUDIO_ON_DISK, 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 5733 of file app_voicemail_odbc.c.

5734{
5735 char fname[PATH_MAX] = "";
5736 char sox_gain_tmpdir[PATH_MAX];
5737 char *file_to_delete = NULL, *dir_to_delete = NULL;
5738 int res;
5739 char altfname[PATH_MAX] = "";
5740 int altused = 0;
5741 char altformat[80] = "";
5742 char *c = NULL;
5743
5744 /* Eww. We want formats to tell us their own MIME type */
5745 char *mime_type = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
5746
5747 /* Users of multiple file formats need special attention. */
5748 snprintf(fname, sizeof(fname), "%s.%s", attach, format);
5749 if (!ast_file_is_readable(fname)) {
5750 ast_copy_string(altformat, vmfmts, sizeof(altformat));
5751 c = strchr(altformat, '|');
5752 if (c) {
5753 *c = '\0';
5754 }
5755 ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s - trying first/alternate format %s\n", fname, strerror(errno), altformat);
5756 snprintf(altfname, sizeof(altfname), "%s.%s", attach, altformat);
5757 if (!ast_file_is_readable(altfname)) {
5758 ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s - alternate format %s failure\n", altfname, strerror(errno), altformat);
5759 } else {
5760 altused = 1;
5761 }
5762 }
5763
5764 /* This 'while' loop will only execute once. We use it so that we can 'break' */
5765 while (vmu->volgain < -.001 || vmu->volgain > .001 || altused) {
5766 char tmpdir[PATH_MAX];
5767
5768 create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
5769
5770 res = snprintf(sox_gain_tmpdir, sizeof(sox_gain_tmpdir), "%s/vm-gain-XXXXXX", tmpdir);
5771 if (res >= sizeof(sox_gain_tmpdir)) {
5772 ast_log(LOG_ERROR, "Failed to create temporary directory path %s: Out of buffer space\n", tmpdir);
5773 break;
5774 }
5775
5776 if (mkdtemp(sox_gain_tmpdir)) {
5777 int soxstatus = 0;
5778 char sox_gain_cmd[PATH_MAX];
5779
5780 ast_debug(3, "sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
5781
5782 /* Save for later */
5783 dir_to_delete = sox_gain_tmpdir;
5784
5785 res = snprintf(fname, sizeof(fname), "%s/output.%s", sox_gain_tmpdir, format);
5786 if (res >= sizeof(fname)) {
5787 ast_log(LOG_ERROR, "Failed to create filename buffer for %s/output.%s: Too long\n", sox_gain_tmpdir, format);
5788 break;
5789 }
5790
5791 if (!altused) {
5792 res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
5793 vmu->volgain, attach, format, fname);
5794 } else {
5795 if (!strcasecmp(format, "wav")) {
5796 if (vmu->volgain < -.001 || vmu->volgain > .001) {
5797 res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s -e signed-integer -b 16 %s",
5798 vmu->volgain, attach, altformat, fname);
5799 } else {
5800 res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox %s.%s -e signed-integer -b 16 %s",
5801 attach, altformat, fname);
5802 }
5803 } else {
5804 if (vmu->volgain < -.001 || vmu->volgain > .001) {
5805 res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
5806 vmu->volgain, attach, altformat, fname);
5807 } else {
5808 res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox %s.%s %s",
5809 attach, altformat, fname);
5810 }
5811 }
5812 }
5813
5814 if (res >= sizeof(sox_gain_cmd)) {
5815 ast_log(LOG_ERROR, "Failed to generate sox command, out of buffer space\n");
5816 break;
5817 }
5818
5819 soxstatus = ast_safe_system(sox_gain_cmd);
5820 if (!soxstatus) {
5821 /* Save for later */
5822 file_to_delete = fname;
5823 ast_debug(3, "VOLGAIN: Stored at: %s - Level: %.4f - Mailbox: %s\n", fname, vmu->volgain, mailbox);
5824 } else {
5825 ast_log(LOG_WARNING, "Sox failed to re-encode %s: %s (have you installed support for all sox file formats?)\n",
5826 fname,
5827 soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
5828 ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
5829 }
5830 }
5831
5832 break;
5833 }
5834
5835 if (!file_to_delete) {
5836 res = snprintf(fname, sizeof(fname), "%s.%s", attach, format);
5837 if (res >= sizeof(fname)) {
5838 ast_log(LOG_ERROR, "Failed to create filename buffer for %s.%s: Too long\n", attach, format);
5839 return -1;
5840 }
5841 }
5842
5843 fprintf(p, "--%s" ENDL, bound);
5844 if (msgnum > -1)
5845 fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, mime_type, format, filename);
5846 else
5847 fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, mime_type, format, greeting_attachment, format);
5848 fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
5849 fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
5850 if (msgnum > -1)
5851 fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
5852 else
5853 fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
5855 if (last)
5856 fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
5857
5858 if (file_to_delete) {
5859 unlink(file_to_delete);
5860 }
5861
5862 if (dir_to_delete) {
5863 rmdir(dir_to_delete);
5864 }
5865
5866 return 0;
5867}
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 13273 of file app_voicemail_odbc.c.

13274{
13275 struct ast_variable *var;
13276 struct ast_category *cat;
13277 generate_msg_id(id);
13278
13279 var = ast_variable_new("msg_id", id, "");
13280 if (!var) {
13281 return -1;
13282 }
13283
13284 cat = ast_category_get(msg_cfg, "message", NULL);
13285 if (!cat) {
13286 ast_log(LOG_ERROR, "Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
13288 return -1;
13289 }
13290
13292
13293 if (ast_config_text_file_save(filename, msg_cfg, "app_voicemail")) {
13294 ast_log(LOG_WARNING, "Unable to update %s to have a message ID\n", filename);
13295 return -1;
13296 }
13297
13298 UPDATE_MSG_ID(dir, msg, id, vmu, msg_cfg, folder);
13299 return 0;
13300}
#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:2716
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:1120
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 7851 of file app_voicemail_odbc.c.

7852{
7853 int x;
7854 if (!ast_adsi_available(chan))
7855 return;
7856 x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
7857 if (x < 0) {
7858 *useadsi = 0;
7860 return;
7861 }
7862 if (!x) {
7863 if (adsi_load_vmail(chan, useadsi)) {
7864 ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
7865 return;
7866 }
7867 } else
7868 *useadsi = 1;
7869}
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:891
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 8050 of file app_voicemail_odbc.c.

8051{
8052 int bytes = 0;
8053 unsigned char buf[256];
8054 unsigned char keys[8];
8055
8056 int x;
8057
8058 if (!ast_adsi_available(chan))
8059 return;
8060
8061 /* New meaning for keys */
8062 for (x = 0; x < 5; x++)
8063 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
8064
8065 keys[6] = 0x0;
8066 keys[7] = 0x0;
8067
8068 if (!vms->curmsg) {
8069 /* No prev key, provide "Folder" instead */
8070 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
8071 }
8072 if (vms->curmsg >= vms->lastmsg) {
8073 /* If last message ... */
8074 if (vms->curmsg) {
8075 /* but not only message, provide "Folder" instead */
8076 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
8077 } else {
8078 /* Otherwise if only message, leave blank */
8079 keys[3] = 1;
8080 }
8081 }
8082
8083 /* If deleted, show "undeleted" */
8084#ifdef IMAP_STORAGE
8085 ast_mutex_lock(&vms->lock);
8086#endif
8087 if (vms->deleted[vms->curmsg]) {
8088 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
8089 }
8090#ifdef IMAP_STORAGE
8091 ast_mutex_unlock(&vms->lock);
8092#endif
8093
8094 /* Except "Exit" */
8095 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
8096 bytes += ast_adsi_set_keys(buf + bytes, keys);
8097 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8098
8100}
#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 7919 of file app_voicemail_odbc.c.

7920{
7921 unsigned char buf[256];
7922 int bytes = 0;
7923 unsigned char keys[8];
7924 int x, y;
7925
7926 if (!ast_adsi_available(chan))
7927 return;
7928
7929 for (x = 0; x < 5; x++) {
7930 y = ADSI_KEY_APPS + 12 + start + x;
7931 if (y > ADSI_KEY_APPS + 12 + 4)
7932 y = 0;
7933 keys[x] = ADSI_KEY_SKT | y;
7934 }
7935 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
7936 keys[6] = 0;
7937 keys[7] = 0;
7938
7939 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
7940 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
7941 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7942 bytes += ast_adsi_set_keys(buf + bytes, keys);
7943 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7944
7946}
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 8205 of file app_voicemail_odbc.c.

8206{
8207 unsigned char buf[256];
8208 int bytes = 0;
8209
8210 if (!ast_adsi_available(chan))
8211 return;
8212 bytes += adsi_logo(buf + bytes);
8213 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
8214 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
8215 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
8216 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8217
8219}
#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 7722 of file app_voicemail_odbc.c.

7723{
7724 unsigned char buf[256];
7725 int bytes = 0;
7726 int x;
7727 char num[5];
7728
7729 *useadsi = 0;
7730 bytes += ast_adsi_data_mode(buf + bytes);
7732
7733 bytes = 0;
7734 bytes += adsi_logo(buf);
7735 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
7736#ifdef DISPLAY
7737 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
7738#endif
7739 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7740 bytes += ast_adsi_data_mode(buf + bytes);
7742
7744 bytes = 0;
7745 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
7746 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
7747 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7748 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7750 return 0;
7751 }
7752
7753#ifdef DISPLAY
7754 /* Add a dot */
7755 bytes = 0;
7756 bytes += ast_adsi_logo(buf);
7757 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
7758 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
7759 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7761#endif
7762 bytes = 0;
7763 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
7764 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
7765 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advanced", "3", 1);
7766 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
7767 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
7768 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
7770
7771#ifdef DISPLAY
7772 /* Add another dot */
7773 bytes = 0;
7774 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
7775 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7776
7777 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7779#endif
7780
7781 bytes = 0;
7782 /* These buttons we load but don't use yet */
7783 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
7784 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
7785 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
7786 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
7787 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
7788 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
7790
7791#ifdef DISPLAY
7792 /* Add another dot */
7793 bytes = 0;
7794 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
7795 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7797#endif
7798
7799 bytes = 0;
7800 for (x = 0; x < 5; x++) {
7801 snprintf(num, sizeof(num), "%d", x);
7802 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
7803 }
7804 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
7806
7807#ifdef DISPLAY
7808 /* Add another dot */
7809 bytes = 0;
7810 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
7811 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7813#endif
7814
7815 if (ast_adsi_end_download(chan)) {
7816 bytes = 0;
7817 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
7818 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
7819 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7820 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7822 return 0;
7823 }
7824 bytes = 0;
7825 bytes += ast_adsi_download_disconnect(buf + bytes);
7826 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7828
7829 ast_debug(1, "Done downloading scripts...\n");
7830
7831#ifdef DISPLAY
7832 /* Add last dot */
7833 bytes = 0;
7834 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
7835 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7836#endif
7837 ast_debug(1, "Restarting session...\n");
7838
7839 bytes = 0;
7840 /* Load the session now */
7841 if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
7842 *useadsi = 1;
7843 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
7844 } else
7845 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
7846
7848 return 0;
7849}
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 7871 of file app_voicemail_odbc.c.

7872{
7873 unsigned char buf[256];
7874 int bytes = 0;
7875 unsigned char keys[8];
7876 int x;
7877 if (!ast_adsi_available(chan))
7878 return;
7879
7880 for (x = 0; x < 8; x++)
7881 keys[x] = 0;
7882 /* Set one key for next */
7883 keys[3] = ADSI_KEY_APPS + 3;
7884
7885 bytes += adsi_logo(buf + bytes);
7886 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
7887 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
7888 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7889 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
7890 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
7891 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
7892 bytes += ast_adsi_set_keys(buf + bytes, keys);
7893 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7895}
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 7714 of file app_voicemail_odbc.c.

7715{
7716 int bytes = 0;
7717 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
7718 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
7719 return bytes;
7720}

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

7949{
7950 int bytes = 0;
7951 unsigned char buf[256];
7952 char buf1[256], buf2[256];
7953 char fn2[PATH_MAX];
7954
7955 char cid[256] = "";
7956 char *val;
7957 char *name, *num;
7958 char datetime[21] = "";
7959 FILE *f;
7960
7961 unsigned char keys[8];
7962
7963 int x;
7964
7965 if (!ast_adsi_available(chan))
7966 return;
7967
7968 /* Retrieve important info */
7969 snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
7970 f = fopen(fn2, "r");
7971 if (f) {
7972 while (!feof(f)) {
7973 if (!fgets((char *) buf, sizeof(buf), f)) {
7974 continue;
7975 }
7976 if (!feof(f)) {
7977 char *stringp = NULL;
7978 stringp = (char *) buf;
7979 strsep(&stringp, "=");
7980 val = strsep(&stringp, "=");
7981 if (!ast_strlen_zero(val)) {
7982 if (!strcmp((char *) buf, "callerid"))
7983 ast_copy_string(cid, val, sizeof(cid));
7984 if (!strcmp((char *) buf, "origdate"))
7985 ast_copy_string(datetime, val, sizeof(datetime));
7986 }
7987 }
7988 }
7989 fclose(f);
7990 }
7991 /* New meaning for keys */
7992 for (x = 0; x < 5; x++)
7993 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
7994 keys[6] = 0x0;
7995 keys[7] = 0x0;
7996
7997 if (!vms->curmsg) {
7998 /* No prev key, provide "Folder" instead */
7999 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
8000 }
8001 if (vms->curmsg >= vms->lastmsg) {
8002 /* If last message ... */
8003 if (vms->curmsg) {
8004 /* but not only message, provide "Folder" instead */
8005 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
8006 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8007
8008 } else {
8009 /* Otherwise if only message, leave blank */
8010 keys[3] = 1;
8011 }
8012 }
8013
8014 if (!ast_strlen_zero(cid)) {
8015 ast_callerid_parse(cid, &name, &num);
8016 if (!name)
8017 name = num;
8018 } else {
8019 name = "Unknown Caller";
8020 }
8021
8022 /* If deleted, show "undeleted" */
8023#ifdef IMAP_STORAGE
8024 ast_mutex_lock(&vms->lock);
8025#endif
8026 if (vms->deleted[vms->curmsg]) {
8027 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
8028 }
8029#ifdef IMAP_STORAGE
8030 ast_mutex_unlock(&vms->lock);
8031#endif
8032
8033 /* Except "Exit" */
8034 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
8035 snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
8036 strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
8037 snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
8038
8039 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
8040 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
8041 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
8042 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
8043 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
8044 bytes += ast_adsi_set_keys(buf + bytes, keys);
8045 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8046
8048}
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1162
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 7897 of file app_voicemail_odbc.c.

7898{
7899 unsigned char buf[256];
7900 int bytes = 0;
7901 unsigned char keys[8];
7902 int x;
7903 if (!ast_adsi_available(chan))
7904 return;
7905
7906 for (x = 0; x < 8; x++)
7907 keys[x] = 0;
7908 /* Set one key for next */
7909 keys[3] = ADSI_KEY_APPS + 3;
7910
7911 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
7912 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
7913 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
7914 bytes += ast_adsi_set_keys(buf + bytes, keys);
7915 bytes += ast_adsi_voice_mode(buf + bytes, 0);
7917}

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 8102 of file app_voicemail_odbc.c.

8103{
8104 unsigned char buf[256] = "";
8105 char buf1[256] = "", buf2[256] = "";
8106 int bytes = 0;
8107 unsigned char keys[8];
8108 int x;
8109
8110 char *newm = (vms->newmessages == 1) ? "message" : "messages";
8111 char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
8112 if (!ast_adsi_available(chan))
8113 return;
8114 if (vms->newmessages) {
8115 snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
8116 if (vms->oldmessages) {
8117 strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
8118 snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
8119 } else {
8120 snprintf(buf2, sizeof(buf2), "%s.", newm);
8121 }
8122 } else if (vms->oldmessages) {
8123 snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
8124 snprintf(buf2, sizeof(buf2), "%s.", oldm);
8125 } else {
8126 strcpy(buf1, "You have no messages.");
8127 buf2[0] = ' ';
8128 buf2[1] = '\0';
8129 }
8130 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
8131 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
8132 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
8133
8134 for (x = 0; x < 6; x++)
8135 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
8136 keys[6] = 0;
8137 keys[7] = 0;
8138
8139 /* Don't let them listen if there are none */
8140 if (vms->lastmsg < 0)
8141 keys[0] = 1;
8142 bytes += ast_adsi_set_keys(buf + bytes, keys);
8143
8144 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8145
8147}
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 8149 of file app_voicemail_odbc.c.

8150{
8151 unsigned char buf[256] = "";
8152 char buf1[256] = "", buf2[256] = "";
8153 int bytes = 0;
8154 unsigned char keys[8];
8155 int x;
8156
8157 char *mess = (vms->lastmsg == 0) ? "message" : "messages";
8158
8159 if (!ast_adsi_available(chan))
8160 return;
8161
8162 /* Original command keys */
8163 for (x = 0; x < 6; x++)
8164 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
8165
8166 keys[6] = 0;
8167 keys[7] = 0;
8168
8169 if ((vms->lastmsg + 1) < 1)
8170 keys[0] = 0;
8171
8172 snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
8173 strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
8174
8175 if (vms->lastmsg + 1)
8176 snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
8177 else
8178 strcpy(buf2, "no messages.");
8179 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
8180 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
8181 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
8182 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
8183 bytes += ast_adsi_set_keys(buf + bytes, keys);
8184
8185 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8186
8188
8189}

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 16490 of file app_voicemail_odbc.c.

16491{
16492 int res = 0;
16493 char filename[PATH_MAX];
16494 struct ast_config *msg_cfg = NULL;
16495 const char *origtime, *context;
16496 char *name, *num;
16497 int retries = 0;
16498 char *cid;
16499 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
16500
16501 vms->starting = 0;
16502
16503 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
16504
16505 /* Retrieve info from VM attribute file */
16506 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
16507 RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
16508 msg_cfg = ast_config_load(filename, config_flags);
16509 DISPOSE(vms->curdir, vms->curmsg);
16510 if (!valid_config(msg_cfg)) {
16511 ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
16512 return 0;
16513 }
16514
16515 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
16516 ast_config_destroy(msg_cfg);
16517 return 0;
16518 }
16519
16520 cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
16521
16522 context = ast_variable_retrieve(msg_cfg, "message", "context");
16523 switch (option) {
16524 case 3: /* Play message envelope */
16525 if (!res) {
16526 res = play_message_datetime(chan, vmu, origtime, filename);
16527 }
16528 if (!res) {
16529 res = play_message_callerid(chan, vms, cid, context, 0, 1);
16530 }
16531
16532 res = 't';
16533 break;
16534
16535 case 2: /* Call back */
16536
16537 if (ast_strlen_zero(cid))
16538 break;
16539
16540 ast_callerid_parse(cid, &name, &num);
16541 while ((res > -1) && (res != 't')) {
16542 switch (res) {
16543 case '1':
16544 if (num) {
16545 /* Dial the CID number */
16546 res = dialout(chan, vmu, num, vmu->callback);
16547 if (res) {
16548 ast_config_destroy(msg_cfg);
16549 return 9;
16550 }
16551 } else {
16552 res = '2';
16553 }
16554 break;
16555
16556 case '2':
16557 /* Want to enter a different number, can only do this if there's a dialout context for this user */
16558 if (!ast_strlen_zero(vmu->dialout)) {
16559 res = dialout(chan, vmu, NULL, vmu->dialout);
16560 if (res) {
16561 ast_config_destroy(msg_cfg);
16562 return 9;
16563 }
16564 } else {
16565 ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
16566 res = ast_play_and_wait(chan, "vm-sorry");
16567 }
16568 ast_config_destroy(msg_cfg);
16569 return res;
16570 case '*':
16571 res = 't';
16572 break;
16573 case '3':
16574 case '4':
16575 case '5':
16576 case '6':
16577 case '7':
16578 case '8':
16579 case '9':
16580 case '0':
16581
16582 res = ast_play_and_wait(chan, "vm-sorry");
16583 retries++;
16584 break;
16585 default:
16586 if (num) {
16587 ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
16588 res = ast_play_and_wait(chan, "vm-num-i-have");
16589 if (!res)
16590 res = play_message_callerid(chan, vms, num, vmu->context, 1, 1);
16591 if (!res)
16592 res = ast_play_and_wait(chan, "vm-tocallnum");
16593 /* Only prompt for a caller-specified number if there is a dialout context specified */
16594 if (!ast_strlen_zero(vmu->dialout)) {
16595 if (!res)
16596 res = ast_play_and_wait(chan, "vm-calldiffnum");
16597 }
16598 } else {
16599 res = ast_play_and_wait(chan, "vm-nonumber");
16600 if (!ast_strlen_zero(vmu->dialout)) {
16601 if (!res)
16602 res = ast_play_and_wait(chan, "vm-toenternumber");
16603 }
16604 }
16605 if (!res) {
16606 res = ast_play_and_wait(chan, "vm-star-cancel");
16607 }
16608 if (!res) {
16609 res = ast_waitfordigit(chan, 6000);
16610 }
16611 if (!res) {
16612 retries++;
16613 if (retries > 3) {
16614 res = 't';
16615 }
16616 }
16617 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
16618 isprint(res) ? res : '?', isprint(res) ? res : '?');
16619 break;
16620
16621 }
16622 if (res == 't')
16623 res = 0;
16624 else if (res == '*')
16625 res = -1;
16626 }
16627 break;
16628
16629 case 1: /* Reply */
16630 /* Send reply directly to sender */
16631 if (ast_strlen_zero(cid))
16632 break;
16633
16634 ast_callerid_parse(cid, &name, &num);
16635 if (!num) {
16636 ast_verb(3, "No CID number available, no reply sent\n");
16637 if (!res)
16638 res = ast_play_and_wait(chan, "vm-nonumber");
16639 ast_config_destroy(msg_cfg);
16640 return res;
16641 } else {
16642 struct ast_vm_user vmu2, *vmu3;
16643 memset(&vmu2, 0, sizeof(vmu2));
16644 vmu3 = find_user(&vmu2, vmu->context, num);
16645 if (vmu3) {
16646 struct leave_vm_options leave_options;
16647 char mailbox[AST_MAX_EXTENSION * 2 + 2];
16648 snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
16649
16650 ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
16651
16652 memset(&leave_options, 0, sizeof(leave_options));
16653 leave_options.record_gain = record_gain;
16654 leave_options.beeptone = "beep";
16655 res = leave_voicemail(chan, mailbox, &leave_options);
16656 if (!res)
16657 res = 't';
16658 ast_config_destroy(msg_cfg);
16659 free_user(vmu3);
16660 return res;
16661 } else {
16662 /* Sender has no mailbox, can't reply */
16663 ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
16664 ast_play_and_wait(chan, "vm-nobox");
16665 res = 't';
16666 ast_config_destroy(msg_cfg);
16667 return res;
16668 }
16669 }
16670 res = 0;
16671
16672 break;
16673 }
16674
16675 ast_config_destroy(msg_cfg);
16676
16677#ifndef IMAP_STORAGE
16678 if (!res) {
16679 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
16680 vms->heard[msg] = 1;
16681 res = wait_file(chan, vms, vms->fn);
16682 }
16683#endif
16684 return res;
16685}
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:3194
#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 14744 of file app_voicemail_odbc.c.

14745{
14746 struct alias_mailbox_mapping *mapping;
14747 size_t from_len = strlen(alias) + 1;
14748 size_t to_len = strlen(mailbox) + 1;
14749
14750 mapping = ao2_alloc(sizeof(*mapping) + from_len + to_len, NULL);
14751 if (!mapping) {
14752 return NULL;
14753 }
14754 mapping->alias = mapping->buf;
14755 mapping->mailbox = mapping->buf + from_len;
14756 ast_copy_string(mapping->alias, alias, from_len); /* Safe */
14757 ast_copy_string(mapping->mailbox, mailbox, to_len); /* Safe */
14758
14759 return mapping;
14760}
#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 13342 of file app_voicemail_odbc.c.

13343{
13344 /* Assumes lock is already held */
13345 char *tmp;
13346 char *stringp;
13347 char *s;
13348 struct ast_vm_user *vmu;
13349 char mailbox_full[MAX_VM_MAILBOX_LEN];
13350 int new = 0, old = 0, urgent = 0;
13351 char secretfn[PATH_MAX] = "";
13352
13353 tmp = ast_strdupa(data);
13354
13355 if (!(vmu = find_or_create(context, box)))
13356 return -1;
13357
13358 populate_defaults(vmu);
13359
13360 stringp = tmp;
13361 if ((s = strsep(&stringp, ","))) {
13362 if (!ast_strlen_zero(s) && s[0] == '*') {
13363 ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
13364 "\n\tmust be reset in voicemail.conf.\n", box);
13365 }
13366 /* assign password regardless of validity to prevent NULL password from being assigned */
13367 ast_copy_string(vmu->password, s, sizeof(vmu->password));
13368 }
13369 if (stringp && (s = strsep(&stringp, ","))) {
13370 ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
13371 }
13372 if (stringp && (s = strsep(&stringp, ","))) {
13373 vmu->email = ast_strdup(s);
13374 }
13375 if (stringp && (s = strsep(&stringp, ","))) {
13376 ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
13377 }
13378 if (stringp) {
13379 apply_options(vmu, stringp);
13380 }
13381
13382 switch (vmu->passwordlocation) {
13383 case OPT_PWLOC_SPOOLDIR:
13384 snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
13385 read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
13386 }
13387
13388 snprintf(mailbox_full, MAX_VM_MAILBOX_LEN, "%s%s%s",
13389 box,
13390 ast_strlen_zero(context) ? "" : "@",
13391 context);
13392
13393 inboxcount2(mailbox_full, &urgent, &new, &old);
13394#ifdef IMAP_STORAGE
13395 imap_logout(mailbox_full);
13396#endif
13397 queue_mwi_event(NULL, mailbox_full, urgent, new, old);
13398
13399 return 0;
13400}
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 14283 of file app_voicemail_odbc.c.

14289{
14290 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
14291 struct ast_vm_msg_snapshot *msg;
14292 int nummessages = 0;
14293 int i;
14294
14295 /* Take a snapshot of the mailbox */
14296 mailbox_snapshot = ast_vm_mailbox_snapshot_create(vmu->mailbox, vmu->context, NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0);
14297 if (!mailbox_snapshot) {
14298 ast_log(LOG_ERROR, "Could not append voicemail box info for box %s@%s.",
14299 vmu->mailbox, vmu->context);
14300 return 0;
14301 }
14302
14303 astman_send_listack(s, m, "Voicemail box detail will follow", "start");
14304 /* walk through each folder's contents and append info for each message */
14305 for (i = 0; i < mailbox_snapshot->folders; i++) {
14306 AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) {
14307 astman_append(s,
14308 "Event: %s\r\n"
14309 "%s"
14310 "Folder: %s\r\n"
14311 "CallerID: %s\r\n"
14312 "Date: %s\r\n"
14313 "Duration: %s\r\n"
14314 "Flag: %s\r\n"
14315 "ID: %s\r\n"
14316 "\r\n",
14317 event_name,
14318 actionid,
14319 msg->folder_name,
14320 msg->callerid,
14321 msg->origdate,
14322 msg->duration,
14323 msg->flag,
14324 msg->msg_id
14325 );
14326 nummessages++;
14327 }
14328 }
14329
14330 /* done, destroy. */
14331 mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
14332 astman_send_list_complete_start(s, m, "VoicemailBoxDetailComplete", nummessages);
14334
14335 return 1;
14336}
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:2011
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:2047
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
@ 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 14159 of file app_voicemail_odbc.c.

14165{
14166 int new;
14167 int old;
14168 char *mailbox;
14169 int ret;
14170
14171 if((s == NULL) || (vmu == NULL) || (event_name == NULL) || (actionid == NULL)) {
14172 ast_log(LOG_ERROR, "Wrong input parameter.");
14173 return 0;
14174 }
14175
14176 /* create mailbox string */
14177 if (!ast_strlen_zero(vmu->context)) {
14178 ret = ast_asprintf(&mailbox, "%s@%s", vmu->mailbox, vmu->context);
14179 } else {
14180 ret = ast_asprintf(&mailbox, "%s", vmu->mailbox);
14181 }
14182 if (ret == -1) {
14183 ast_log(LOG_ERROR, "Could not create mailbox string. err[%s]\n", strerror(errno));
14184 return 0;
14185 }
14186
14187 /* get mailbox count */
14188 ret = inboxcount(mailbox, &new, &old);
14190 if (ret == -1) {
14191 ast_log(LOG_ERROR, "Could not get mailbox count. user[%s], context[%s]\n",
14192 vmu->mailbox ?: "", vmu->context ?: "");
14193 return 0;
14194 }
14195
14196 astman_append(s,
14197 "Event: %s\r\n"
14198 "%s"
14199 "VMContext: %s\r\n"
14200 "VoiceMailbox: %s\r\n"
14201 "Fullname: %s\r\n"
14202 "Email: %s\r\n"
14203 "Pager: %s\r\n"
14204 "ServerEmail: %s\r\n"
14205 "FromString: %s\r\n"
14206 "MailCommand: %s\r\n"
14207 "Language: %s\r\n"
14208 "TimeZone: %s\r\n"
14209 "Callback: %s\r\n"
14210 "Dialout: %s\r\n"
14211 "UniqueID: %s\r\n"
14212 "ExitContext: %s\r\n"
14213 "SayDurationMinimum: %d\r\n"
14214 "SayEnvelope: %s\r\n"
14215 "SayCID: %s\r\n"
14216 "AttachMessage: %s\r\n"
14217 "AttachmentFormat: %s\r\n"
14218 "DeleteMessage: %s\r\n"
14219 "VolumeGain: %.2f\r\n"
14220 "CanReview: %s\r\n"
14221 "CanMarkUrgent: %s\r\n"
14222 "CallOperator: %s\r\n"
14223 "MaxMessageCount: %d\r\n"
14224 "MaxMessageLength: %d\r\n"
14225 "NewMessageCount: %d\r\n"
14226 "OldMessageCount: %d\r\n"
14227#ifdef IMAP_STORAGE
14228 "IMAPUser: %s\r\n"
14229 "IMAPServer: %s\r\n"
14230 "IMAPPort: %s\r\n"
14231 "IMAPFlags: %s\r\n"
14232#endif
14233 "\r\n",
14234
14235 event_name,
14236 actionid,
14237 vmu->context,
14238 vmu->mailbox,
14239 vmu->fullname,
14240 vmu->email,
14241 vmu->pager,
14244 mailcmd,
14245 vmu->language,
14246 vmu->zonetag,
14247 vmu->callback,
14248 vmu->dialout,
14249 vmu->uniqueid,
14250 vmu->exit,
14251 vmu->saydurationm,
14252 ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
14253 ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
14254 ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
14255 vmu->attachfmt,
14256 ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
14257 vmu->volgain,
14258 ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
14259 ast_test_flag(vmu, VM_MARK_URGENT) ? "Yes" : "No",
14260 ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
14261 vmu->maxmsg,
14262 vmu->maxsecs,
14263 new,
14264 old
14265#ifdef IMAP_STORAGE
14266 ,
14267 vmu->imapuser,
14268 vmu->imapserver,
14269 vmu->imapport,
14270 vmu->imapflags
14271#endif
14272 );
14273
14274 return 1;
14275
14276}
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 1525 of file app_voicemail_odbc.c.

1526{
1527 int x;
1528 if (!strcasecmp(var, "attach")) {
1530 } else if (!strcasecmp(var, "attachfmt")) {
1531 ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
1532 } else if (!strcasecmp(var, "attachextrecs")) {
1534 } else if (!strcasecmp(var, "serveremail")) {
1535 ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
1536 } else if (!strcasecmp(var, "fromstring")) {
1537 ast_copy_string(vmu->fromstring, value, sizeof(vmu->fromstring));
1538 } else if (!strcasecmp(var, "emailbody")) {
1539 ast_free(vmu->emailbody);
1541 } else if (!strcasecmp(var, "emailsubject")) {
1542 ast_free(vmu->emailsubject);
1544 } else if (!strcasecmp(var, "language")) {
1545 ast_copy_string(vmu->language, value, sizeof(vmu->language));
1546 } else if (!strcasecmp(var, "tz")) {
1547 ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
1548 } else if (!strcasecmp(var, "locale")) {
1549 ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
1550#ifdef IMAP_STORAGE
1551 } else if (!strcasecmp(var, "imapuser")) {
1552 ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
1553 vmu->imapversion = imapversion;
1554 } else if (!strcasecmp(var, "imapserver")) {
1555 ast_copy_string(vmu->imapserver, value, sizeof(vmu->imapserver));
1556 vmu->imapversion = imapversion;
1557 } else if (!strcasecmp(var, "imapport")) {
1558 ast_copy_string(vmu->imapport, value, sizeof(vmu->imapport));
1559 vmu->imapversion = imapversion;
1560 } else if (!strcasecmp(var, "imapflags")) {
1561 ast_copy_string(vmu->imapflags, value, sizeof(vmu->imapflags));
1562 vmu->imapversion = imapversion;
1563 } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
1564 ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
1565 vmu->imapversion = imapversion;
1566 } else if (!strcasecmp(var, "imapfolder")) {
1567 ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
1568 vmu->imapversion = imapversion;
1569 } else if (!strcasecmp(var, "imapvmshareid")) {
1570 ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
1571 vmu->imapversion = imapversion;
1572#endif
1573 } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
1575 } else if (!strcasecmp(var, "saycid")){
1577 } else if (!strcasecmp(var, "sendvoicemail")){
1579 } else if (!strcasecmp(var, "review")){
1581 } else if (!strcasecmp(var, "leaveurgent")){
1583 } else if (!strcasecmp(var, "tempgreetwarn")){
1585 } else if (!strcasecmp(var, "messagewrap")){
1587 } else if (!strcasecmp(var, "operator")) {
1589 } else if (!strcasecmp(var, "envelope")){
1591 } else if (!strcasecmp(var, "moveheard")){
1593 } else if (!strcasecmp(var, "sayduration")){
1595 } else if (!strcasecmp(var, "saydurationm")){
1596 if (sscanf(value, "%30d", &x) == 1) {
1597 vmu->saydurationm = x;
1598 } else {
1599 ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
1600 }
1601 } else if (!strcasecmp(var, "forcename")){
1603 } else if (!strcasecmp(var, "forcegreetings")){
1605 } else if (!strcasecmp(var, "callback")) {
1606 ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
1607 } else if (!strcasecmp(var, "dialout")) {
1608 ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
1609 } else if (!strcasecmp(var, "exitcontext")) {
1610 ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
1611 } else if (!strcasecmp(var, "minsecs")) {
1612 if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
1613 vmu->minsecs = x;
1614 } else {
1615 ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1616 vmu->minsecs = vmminsecs;
1617 }
1618 } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
1619 vmu->maxsecs = atoi(value);
1620 if (vmu->maxsecs <= 0) {
1621 ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
1622 vmu->maxsecs = vmmaxsecs;
1623 } else {
1624 vmu->maxsecs = atoi(value);
1625 }
1626 if (!strcasecmp(var, "maxmessage"))
1627 ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1628 } else if (!strcasecmp(var, "maxmsg")) {
1629 vmu->maxmsg = atoi(value);
1630 /* Accept maxmsg=0 (Greetings only voicemail) */
1631 if (vmu->maxmsg < 0) {
1632 ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
1633 vmu->maxmsg = MAXMSG;
1634 } else if (vmu->maxmsg > MAXMSGLIMIT) {
1635 ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
1636 vmu->maxmsg = MAXMSGLIMIT;
1637 }
1638 } else if (!strcasecmp(var, "nextaftercmd")) {
1640 } else if (!strcasecmp(var, "backupdeleted")) {
1641 if (sscanf(value, "%30d", &x) == 1)
1642 vmu->maxdeletedmsg = x;
1643 else if (ast_true(value))
1644 vmu->maxdeletedmsg = MAXMSG;
1645 else
1646 vmu->maxdeletedmsg = 0;
1647
1648 if (vmu->maxdeletedmsg < 0) {
1649 ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
1650 vmu->maxdeletedmsg = MAXMSG;
1651 } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
1652 ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
1654 }
1655 } else if (!strcasecmp(var, "volgain")) {
1656 sscanf(value, "%30lf", &vmu->volgain);
1657 } else if (!strcasecmp(var, "passwordlocation")) {
1658 if (!strcasecmp(value, "spooldir")) {
1660 } else {
1662 }
1663 } else if (!strcasecmp(var, "options")) {
1664 apply_options(vmu, value);
1665 }
1666}
#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, ast_vm_user::maxmsg, 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 1784 of file app_voicemail_odbc.c.

1785{
1786 char *stringp;
1787 char *s;
1788 char *var, *value;
1789 stringp = ast_strdupa(options);
1790 while ((s = strsep(&stringp, "|"))) {
1791 value = s;
1792 if ((var = strsep(&value, "=")) && value) {
1793 apply_option(vmu, var, value);
1794 }
1795 }
1796}
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 1803 of file app_voicemail_odbc.c.

1804{
1805 for (; var; var = var->next) {
1806 if (!strcasecmp(var->name, "vmsecret")) {
1807 ast_copy_string(retval->password, var->value, sizeof(retval->password));
1808 } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
1809 if (ast_strlen_zero(retval->password)) {
1810 if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
1811 ast_log(LOG_WARNING, "Invalid password detected for mailbox %s. The password"
1812 "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
1813 } else {
1814 ast_copy_string(retval->password, var->value, sizeof(retval->password));
1815 }
1816 }
1817 } else if (!strcasecmp(var->name, "uniqueid")) {
1818 ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
1819 } else if (!strcasecmp(var->name, "pager")) {
1820 ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
1821 } else if (!strcasecmp(var->name, "email")) {
1822 ast_free(retval->email);
1823 retval->email = ast_strdup(var->value);
1824 } else if (!strcasecmp(var->name, "fullname")) {
1825 ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
1826 } else if (!strcasecmp(var->name, "context")) {
1827 ast_copy_string(retval->context, var->value, sizeof(retval->context));
1828 } else if (!strcasecmp(var->name, "emailsubject")) {
1829 ast_free(retval->emailsubject);
1830 retval->emailsubject = ast_strdup(substitute_escapes(var->value));
1831 } else if (!strcasecmp(var->name, "emailbody")) {
1832 ast_free(retval->emailbody);
1833 retval->emailbody = ast_strdup(substitute_escapes(var->value));
1834#ifdef IMAP_STORAGE
1835 } else if (!strcasecmp(var->name, "imapuser")) {
1836 ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
1837 retval->imapversion = imapversion;
1838 } else if (!strcasecmp(var->name, "imapserver")) {
1839 ast_copy_string(retval->imapserver, var->value, sizeof(retval->imapserver));
1840 retval->imapversion = imapversion;
1841 } else if (!strcasecmp(var->name, "imapport")) {
1842 ast_copy_string(retval->imapport, var->value, sizeof(retval->imapport));
1843 retval->imapversion = imapversion;
1844 } else if (!strcasecmp(var->name, "imapflags")) {
1845 ast_copy_string(retval->imapflags, var->value, sizeof(retval->imapflags));
1846 retval->imapversion = imapversion;
1847 } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
1848 ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
1849 retval->imapversion = imapversion;
1850 } else if (!strcasecmp(var->name, "imapfolder")) {
1851 ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
1852 retval->imapversion = imapversion;
1853 } else if (!strcasecmp(var->name, "imapvmshareid")) {
1854 ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
1855 retval->imapversion = imapversion;
1856#endif
1857 } else
1858 apply_option(retval, var->name, var->value);
1859 }
1860}
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 17811 of file app_voicemail_odbc.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 5378 of file app_voicemail_odbc.c.

5379{
5380 struct ast_str *tmp = ast_str_alloca(80);
5381 int first_section = 1;
5382
5384 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
5385 for (; *start; start++) {
5386 int need_encoding = 0;
5387 if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
5388 need_encoding = 1;
5389 }
5390 if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
5391 (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
5392 (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
5393 (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
5394 /* Start new line */
5395 ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
5396 ast_str_set(&tmp, -1, "=?%s?Q?", charset);
5397 first_section = 0;
5398 }
5399 if (need_encoding && *start == ' ') {
5400 ast_str_append(&tmp, -1, "_");
5401 } else if (need_encoding) {
5402 ast_str_append(&tmp, -1, "=%hhX", *start);
5403 } else {
5404 ast_str_append(&tmp, -1, "%c", *start);
5405 }
5406 }
5407 ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
5408 return ast_str_buffer(*end);
5409}
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 5306 of file app_voicemail_odbc.c.

5307{
5308 const char *ptr;
5309
5310 /* We're only ever passing 0 to maxlen, so short output isn't possible */
5311 ast_str_set(buf, maxlen, "\"");
5312 for (ptr = from; *ptr; ptr++) {
5313 if (*ptr == '"' || *ptr == '\\') {
5314 ast_str_append(buf, maxlen, "\\%c", *ptr);
5315 } else {
5316 ast_str_append(buf, maxlen, "%c", *ptr);
5317 }
5318 }
5319 ast_str_append(buf, maxlen, "\"");
5320
5321 return ast_str_buffer(*buf);
5322}

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 1762 of file app_voicemail_odbc.c.

1763{
1764 int res = -1;
1765 if (!strcmp(vmu->password, password)) {
1766 /* No change (but an update would return 0 rows updated, so we opt out here) */
1767 return 0;
1768 }
1769
1770 if (strlen(password) > 10) {
1771 ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
1772 }
1773 if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
1774 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
1775 ast_copy_string(vmu->password, password, sizeof(vmu->password));
1776 res = 0;
1777 }
1778 return res;
1779}
#define SENTINEL
Definition: compiler.h:87
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3710
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: main/config.c:3564

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 5351 of file app_voicemail_odbc.c.

5352{
5353 for (; *str; str++) {
5354 if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
5355 return 1;
5356 }
5357 }
5358 return 0;
5359}
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 1721 of file app_voicemail_odbc.c.

1722{
1723 /* check minimum length */
1724 if (strlen(password) < minpassword)
1725 return 1;
1726 /* check that password does not contain '*' character */
1727 if (!ast_strlen_zero(password) && password[0] == '*')
1728 return 1;
1730 char cmd[255], buf[255];
1731
1732 ast_debug(1, "Verify password policies for %s\n", password);
1733
1734 snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
1735 if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
1736 ast_debug(5, "Result: %s\n", buf);
1737 if (!strncasecmp(buf, "VALID", 5)) {
1738 ast_debug(3, "Passed password check: '%s'\n", buf);
1739 return 0;
1740 } else if (!strncasecmp(buf, "FAILURE", 7)) {
1741 ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
1742 return 0;
1743 } else {
1744 ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
1745 return 1;
1746 }
1747 }
1748 }
1749 return 0;
1750}
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 9573 of file app_voicemail_odbc.c.

9574{
9575 int x = 0;
9576 int last_msg_idx = 0;
9577
9578#ifndef IMAP_STORAGE
9579 int res = 0, nummsg;
9580 char fn2[PATH_MAX];
9581#endif
9582 SCOPE_ENTER(3, "user: %s dir: %s msg: %d\n",
9583 vms->username, vms->curdir, vms->curmsg);
9584
9585 if (vms->lastmsg <= -1) {
9586 ast_trace(-1, "No messages in mailbox\n");
9587 goto done;
9588 }
9589
9590 vms->curmsg = -1;
9591#ifndef IMAP_STORAGE
9592 /* Get the deleted messages fixed */
9593 if (vm_lock_path(vms->curdir)) {
9594 SCOPE_EXIT_RTN_VALUE(ERROR_LOCK_PATH, "Could not open mailbox %s: mailbox is locked\n", vms->curdir);
9595 }
9596
9597 /* update count as message may have arrived while we've got mailbox open */
9598 last_msg_idx = LAST_MSG_INDEX(vms->curdir);
9599 if (last_msg_idx != vms->lastmsg) {
9600 ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
9601 }
9602
9603 /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
9604 for (x = 0; x < last_msg_idx + 1; x++) {
9605 if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
9606 /* Save this message. It's not in INBOX or hasn't been heard */
9607 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
9608 if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
9609 break;
9610 }
9611 vms->curmsg++;
9612 make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
9613 if (strcmp(vms->fn, fn2)) {
9614 SCOPE_CALL(-1, RENAME, vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
9615 }
9616 } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
9617 /* Move to old folder before deleting */
9618 res = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, vms, x, 1, NULL, 0);
9619 if (res == ERROR_LOCK_PATH || res == ERROR_MAX_MSGS) {
9620 /* If save failed do not delete the message */
9621 ast_log(AST_LOG_WARNING, "Save failed. Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
9622 vms->deleted[x] = 0;
9623 vms->heard[x] = 0;
9624 --x;
9625 }
9626 } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
9627 /* Move to deleted folder */
9628 res = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, vms, x, 10, NULL, 0);
9629 if (res == ERROR_LOCK_PATH) {
9630 ast_trace(-1, "Unable to lock path. Not moving message to deleted folder.\n");
9631 /* If save failed do not delete the message */
9632 vms->deleted[x] = 0;
9633 vms->heard[x] = 0;
9634 --x;
9635 }
9636 } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
9637 /* If realtime storage enabled - we should explicitly delete this message,
9638 cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
9639 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
9640 res = SCOPE_CALL_WITH_INT_RESULT(-1, EXISTS, vms->curdir, x, vms->fn, NULL);
9641 if (res) {
9642 SCOPE_CALL(-1, DELETE, vms->curdir, x, vms->fn, vmu);
9643 }
9644 }
9645 }
9646
9647 /* Delete ALL remaining messages */
9648 nummsg = x - 1;
9649 for (x = vms->curmsg + 1; x <= nummsg; x++) {
9650 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
9651 res = SCOPE_CALL_WITH_INT_RESULT(-1, EXISTS, vms->curdir, x, vms->fn, NULL);
9652 if (res) {
9653 SCOPE_CALL(-1, DELETE, vms->curdir, x, vms->fn, vmu);
9654 }
9655 }
9656 ast_unlock_path(vms->curdir);
9657#else /* defined(IMAP_STORAGE) */
9658 ast_mutex_lock(&vms->lock);
9659 if (vms->deleted) {
9660 /* Since we now expunge after each delete, deleting in reverse order
9661 * ensures that no reordering occurs between each step. */
9662 last_msg_idx = vms->dh_arraysize;
9663 for (x = last_msg_idx - 1; x >= 0; x--) {
9664 if (vms->deleted[x]) {
9665 ast_debug(3, "IMAP delete of %d\n", x);
9666 DELETE(vms->curdir, x, vms->fn, vmu);
9667 }
9668 }
9669 }
9670#endif
9671
9672done:
9673 if (vms->deleted) {
9674 ast_free(vms->deleted);
9675 vms->deleted = NULL;
9676 }
9677 if (vms->heard) {
9678 ast_free(vms->heard);
9679 vms->heard = NULL;
9680 }
9681 vms->dh_arraysize = 0;
9682#ifdef IMAP_STORAGE
9683 ast_mutex_unlock(&vms->lock);
9684#endif
9685
9686 SCOPE_EXIT_RTN_VALUE(0, "Done\n");
9687}
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)
#define LAST_MSG_INDEX(a)
#define ERROR_MAX_MSGS
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_CALL_WITH_INT_RESULT(level, __funcname,...)
#define SCOPE_CALL(level, __funcname,...)
#define ast_trace(level,...)
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2630
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3545
char username[80]
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_trace, 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_MSG_INDEX, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, NULL, PATH_MAX, RENAME, save_to_folder(), SCOPE_CALL, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, vm_state::username, 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 12191 of file app_voicemail_odbc.c.

12192{
12193 const char *word = a->word;
12194 int pos = a->pos;
12195 int state = a->n;
12196 int which = 0;
12197 int wordlen;
12198 struct ast_vm_user *vmu;
12199 const char *context = "", *mailbox = "", *folder = "", *id = "";
12200 char *ret = NULL;
12201
12202 if (pos > maxpos) {
12203 /* If the passed in pos is above the max, return NULL to avoid 'over-filling' the cli */
12204 return NULL;
12205 }
12206
12207 /* if we are in pos 2 or pos 6 in 'forward' mode */
12208 if (pos == 2 || (pos == 6 && maxpos == 8)) {
12209 /* find users */
12210 wordlen = strlen(word);
12212 AST_LIST_TRAVERSE(&users, vmu, list) {
12213 if (!strncasecmp(word, vmu->mailbox , wordlen)) {
12214 if (mailbox && strcmp(mailbox, vmu->mailbox) && ++which > state) {
12215 ret = ast_strdup(vmu->mailbox);
12217 return ret;
12218 }
12219 mailbox = vmu->mailbox;
12220 }
12221 }
12223 } else if (pos == 3 || pos == 7) {
12224 /* find contexts that match the user */
12225 mailbox = (pos == 3) ? a->argv[2] : a->argv[6];
12226 wordlen = strlen(word);
12228 AST_LIST_TRAVERSE(&users, vmu, list) {
12229 if (!strncasecmp(word, vmu->context, wordlen) && !strcasecmp(mailbox, vmu->mailbox)) {
12230 if (context && strcmp(context, vmu->context) && ++which > state) {
12231 ret = ast_strdup(vmu->context);
12233 return ret;
12234 }
12235 context = vmu->context;
12236 }
12237 }
12239 } else if (pos == 4 || pos == 8 || (pos == 6 && maxpos == 6) ) {
12240 int i;
12241 /* Walk through the standard folders */
12242 wordlen = strlen(word);
12243 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
12244 if (folder && !strncasecmp(word, mailbox_folders[i], wordlen) && ++which > state) {
12245 return ast_strdup(mailbox_folders[i]);
12246 }
12247 folder = mailbox_folders[i];
12248 }
12249 } else if (pos == 5) {
12250 /* find messages in the folder */
12251 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
12252 struct ast_vm_msg_snapshot *msg;
12253 mailbox = a->argv[2];
12254 context = a->argv[3];
12255 folder = a->argv[4];
12256 wordlen = strlen(word);
12257
12258 /* Take a snapshot of the mailbox and snag the individual info */
12259 if ((mailbox_snapshot = ast_vm_mailbox_snapshot_create(mailbox, context, folder, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0))) {
12260 int i;
12261 /* we are only requesting the one folder, but we still need to know it's index */
12262 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
12263 if (!strcasecmp(mailbox_folders[i], folder)) {
12264 break;
12265 }
12266 }
12267 AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) {
12268 if (id && !strncasecmp(word, msg->msg_id, wordlen) && ++which > state) {
12269 ret = ast_strdup(msg->msg_id);
12270 break;
12271 }
12272 id = msg->msg_id;
12273 }
12274 /* done, destroy. */
12275 mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
12276 }
12277 }
12278
12279 return ret;
12280}
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 12101 of file app_voicemail_odbc.c.

12102{
12103 const char *word = a->word;
12104 int pos = a->pos;
12105 int state = a->n;
12106 int which = 0;
12107 int wordlen;
12108 struct ast_vm_user *vmu;
12109 const char *context = "", *mailbox = "";
12110 char *ret = NULL;
12111
12112 /* 0 - voicemail; 1 - show; 2 - mailbox; 3 - <mailbox>; 4 - <context> */
12113 if (pos == 3) {
12114 wordlen = strlen(word);
12116 AST_LIST_TRAVERSE(&users, vmu, list) {
12117 if (!strncasecmp(word, vmu->mailbox , wordlen)) {
12118 if (mailbox && strcmp(mailbox, vmu->mailbox) && ++which > state) {
12119 ret = ast_strdup(vmu->mailbox);
12121 return ret;
12122 }
12123 mailbox = vmu->mailbox;
12124 }
12125 }
12127 } else if (pos == 4) {
12128 /* Only display contexts that match the user in pos 3 */
12129 const char *box = a->argv[3];
12130 wordlen = strlen(word);
12132 AST_LIST_TRAVERSE(&users, vmu, list) {
12133 if (!strncasecmp(word, vmu->context, wordlen) && !strcasecmp(box, vmu->mailbox)) {
12134 if (context && strcmp(context, vmu->context) && ++which > state) {
12135 ret = ast_strdup(vmu->context);
12137 return ret;
12138 }
12139 context = vmu->context;
12140 }
12141 }
12143 }
12144
12145 return ret;
12146}

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 13767 of file app_voicemail_odbc.c.

13768{
13769 int which = 0;
13770 int wordlen;
13771 struct ast_vm_user *vmu;
13772 const char *context = "";
13773 char *ret;
13774
13775 /* 0 - voicemail; 1 - show; 2 - users; 3 - for; 4 - <context> */
13776 if (pos > 4)
13777 return NULL;
13778 wordlen = strlen(word);
13780 AST_LIST_TRAVERSE(&users, vmu, list) {
13781 if (!strncasecmp(word, vmu->context, wordlen)) {
13782 if (context && strcmp(context, vmu->context) && ++which > state) {
13783 ret = ast_strdup(vmu->context);
13785 return ret;
13786 }
13787 /* ignore repeated contexts ? */
13788 context = vmu->context;
13789 }
13790 }
13792 return NULL;
13793}

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 5103 of file app_voicemail_odbc.c.

5104{
5105 int ifd;
5106 int ofd;
5107 int res = -1;
5108 int len;
5109 char buf[4096];
5110
5111#ifdef HARDLINK_WHEN_POSSIBLE
5112 /* Hard link if possible; saves disk space & is faster */
5113 if (!link(infile, outfile)) {
5114 return 0;
5115 }
5116#endif
5117
5118 if ((ifd = open(infile, O_RDONLY)) < 0) {
5119 ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
5120 return -1;
5121 }
5122
5123 if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
5124 ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
5125 close(ifd);
5126 return -1;
5127 }
5128
5129 for (;;) {
5130 int wrlen;
5131
5132 len = read(ifd, buf, sizeof(buf));
5133 if (!len) {
5134 res = 0;
5135 break;
5136 }
5137
5138 if (len < 0) {
5139 ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
5140 break;
5141 }
5142
5143 wrlen = write(ofd, buf, len);
5144 if (errno == ENOMEM || errno == ENOSPC || wrlen != len) {
5145 ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, wrlen, len, strerror(errno));
5146 break;
5147 }
5148 }
5149
5150 close(ifd);
5151 close(ofd);
5152 if (res) {
5153 unlink(outfile);
5154 }
5155
5156 return res;
5157}
#define VOICEMAIL_FILE_MODE

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

Referenced by copy_plain_file(), 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 6343 of file app_voicemail_odbc.c.

6346{
6347 char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
6348 const char *frombox = mbox(vmu, imbox);
6349 const char *userfolder;
6350 int recipmsgnum;
6351 int res = 0;
6352 SCOPE_ENTER(3, "mb: %s imb: %d msgnum: %d recip: %s dir: %s dest_folder: %s",
6353 vmu->mailbox, imbox, msgnum, recip->mailbox, dir, dest_folder);
6354
6355 ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
6356
6357 if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
6358 userfolder = "Urgent";
6359 } else if (!ast_strlen_zero(dest_folder)) {
6360 userfolder = dest_folder;
6361 } else {
6362 userfolder = "INBOX";
6363 }
6364
6365 create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
6366 ast_trace(-1, "todir: %s\n", todir);
6367
6368 if (!dir)
6369 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
6370 else
6371 ast_copy_string(fromdir, dir, sizeof(fromdir));
6372
6373 ast_trace(-1, "fromdir: %s\n", fromdir);
6374
6375 make_file(frompath, sizeof(frompath), fromdir, msgnum);
6376 ast_trace(-1, "frompath: %s\n", frompath);
6377
6378 make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
6379 ast_trace(-1, "todir: %s\n", todir);
6380
6381 if (vm_lock_path(todir)) {
6383 }
6384
6385 recipmsgnum = LAST_MSG_INDEX(todir) + 1;
6386 ast_trace(-1, "recip msgnum: %d\n", recipmsgnum);
6387
6388 if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
6389 int exists = 0;
6390
6391 make_file(topath, sizeof(topath), todir, recipmsgnum);
6392 ast_trace(-1, "topath: %s\n", topath);
6393
6394 exists = SCOPE_CALL_WITH_INT_RESULT(-1, EXISTS, fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : "");
6395 if (exists) {
6396 SCOPE_CALL(-1, COPY, fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
6397 } else {
6398 SCOPE_CALL(-1, copy_plain_file,frompath, topath);
6399 SCOPE_CALL(-1, STORE, todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL);
6400 SCOPE_CALL(-1, vm_delete, topath);
6401
6402 }
6403 } else {
6404 ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
6405 res = -1;
6406 }
6407 ast_unlock_path(todir);
6408 if (chan) {
6409 struct ast_party_caller *caller = ast_channel_caller(chan);
6410 notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
6411 S_COR(caller->id.number.valid, caller->id.number.str, NULL),
6412 S_COR(caller->id.name.valid, caller->id.name.str, NULL),
6413 flag);
6414 }
6415
6416 SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res);
6417}
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
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:157
#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:420
struct ast_party_id id
Caller party ID.
Definition: channel.h:422
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:281
char * str
Subscriber name (Malloced)
Definition: channel.h:266
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293

References ast_channel_caller(), ast_channel_language(), ast_copy_string(), ast_log, AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_trace, ast_unlock_path(), ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, exists(), ast_party_caller::id, inprocess_count(), LAST_MSG_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, SCOPE_CALL, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, 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 5168 of file app_voicemail_odbc.c.

5169{
5170 char frompath2[PATH_MAX], topath2[PATH_MAX];
5171 struct ast_variable *tmp, *var = NULL;
5172 const char *origmailbox = "", *context = "", *exten = "";
5173 const char *priority = "", *callerchan = "", *callerid = "", *origdate = "";
5174 const char *origtime = "", *category = "", *duration = "";
5175
5176 ast_filecopy(frompath, topath, NULL);
5177 snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
5178 snprintf(topath2, sizeof(topath2), "%s.txt", topath);
5179
5180 if (ast_check_realtime("voicemail_data")) {
5181 var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
5182 /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
5183 for (tmp = var; tmp; tmp = tmp->next) {
5184 if (!strcasecmp(tmp->name, "origmailbox")) {
5185 origmailbox = tmp->value;
5186 } else if (!strcasecmp(tmp->name, "context")) {
5187 context = tmp->value;
5188 } else if (!strcasecmp(tmp->name, "exten")) {
5189 exten = tmp->value;
5190 } else if (!strcasecmp(tmp->name, "priority")) {
5191 priority = tmp->value;
5192 } else if (!strcasecmp(tmp->name, "callerchan")) {
5193 callerchan = tmp->value;
5194 } else if (!strcasecmp(tmp->name, "callerid")) {
5195 callerid = tmp->value;
5196 } else if (!strcasecmp(tmp->name, "origdate")) {
5197 origdate = tmp->value;
5198 } else if (!strcasecmp(tmp->name, "origtime")) {
5199 origtime = tmp->value;
5200 } else if (!strcasecmp(tmp->name, "category")) {
5201 category = tmp->value;
5202 } else if (!strcasecmp(tmp->name, "duration")) {
5203 duration = tmp->value;
5204 }
5205 }
5206 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);
5207 }
5208 copy(frompath2, topath2);
5210}
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:3755
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3521

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 5003 of file app_voicemail_odbc.c.

5004{
5005
5006 int vmcount = 0;
5007 DIR *vmdir = NULL;
5008 struct dirent *vment = NULL;
5009
5010 if (vm_lock_path(dir))
5011 return ERROR_LOCK_PATH;
5012
5013 if ((vmdir = opendir(dir))) {
5014 while ((vment = readdir(vmdir))) {
5015 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
5016 vmcount++;
5017 }
5018 }
5019 closedir(vmdir);
5020 }
5021 ast_unlock_path(dir);
5022
5023 return vmcount;
5024}

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

◆ 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 2219 of file app_voicemail_odbc.c.

2220{
2221 mode_t mode = VOICEMAIL_DIR_MODE;
2222 int res;
2223
2224 make_dir(dest, len, context, ext, folder);
2225 if ((res = ast_mkdir(dest, mode))) {
2226 ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
2227 return -1;
2228 }
2229 return 0;
2230}
#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 16418 of file app_voicemail_odbc.c.

16419{
16420 int cmd = 0;
16421 char destination[80] = "";
16422 int retries = 0;
16423
16424 if (!num) {
16425 ast_verb(3, "Destination number will be entered manually\n");
16426 while (retries < 3 && cmd != 't') {
16427 destination[1] = '\0';
16428 destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
16429 if (!cmd)
16430 destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
16431 if (!cmd)
16432 destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
16433 if (!cmd) {
16434 cmd = ast_waitfordigit(chan, 6000);
16435 if (cmd)
16436 destination[0] = cmd;
16437 }
16438 if (!cmd) {
16439 retries++;
16440 } else {
16441
16442 if (cmd < 0)
16443 return 0;
16444 if (cmd == '*') {
16445 ast_verb(3, "User hit '*' to cancel outgoing call\n");
16446 return 0;
16447 }
16448 if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0)
16449 retries++;
16450 else
16451 cmd = 't';
16452 }
16453 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
16454 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
16455 }
16456 if (retries >= 3) {
16457 return 0;
16458 }
16459
16460 } else {
16461 ast_verb(3, "Destination number is CID number '%s'\n", num);
16462 ast_copy_string(destination, num, sizeof(destination));
16463 }
16464
16465 if (!ast_strlen_zero(destination)) {
16466 if (destination[strlen(destination) -1 ] == '*')
16467 return 0;
16468 ast_verb(3, "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, ast_channel_context(chan));
16469 ast_channel_exten_set(chan, destination);
16470 ast_channel_context_set(chan, outgoing_context);
16471 ast_channel_priority_set(chan, 0);
16472 return 9;
16473 }
16474 return 0;
16475}
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:6577

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 13302 of file app_voicemail_odbc.c.

13303{
13304 struct ast_vm_user *vmu;
13305
13306 if (!ast_strlen_zero(box) && box[0] == '*') {
13307 ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character. The '*' character,"
13308 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
13309 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
13310 "\n\tand will be ignored.\n", box, context);
13311 return NULL;
13312 }
13313
13314 AST_LIST_TRAVERSE(&users, vmu, list) {
13315 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
13316 if (strcasecmp(vmu->context, context)) {
13317 ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
13318 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
13319 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
13320 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
13321 }
13322 ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
13323 return NULL;
13324 }
13325 if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
13326 ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
13327 return NULL;
13328 }
13329 }
13330
13331 if (!(vmu = ast_calloc(1, sizeof(*vmu))))
13332 return NULL;
13333
13334 ast_copy_string(vmu->context, context, sizeof(vmu->context));
13335 ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
13336
13338
13339 return vmu;
13340}
#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 1935 of file app_voicemail_odbc.c.

1936{
1937 /* This function could be made to generate one from a database, too */
1938 struct ast_vm_user *vmu = NULL, *cur;
1940
1942 context = "default";
1943
1944 AST_LIST_TRAVERSE(&users, cur, list) {
1945#ifdef IMAP_STORAGE
1946 if (cur->imapversion != imapversion) {
1947 continue;
1948 }
1949#endif
1950 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
1951 break;
1952 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1953 break;
1954 }
1955 if (cur) {
1956 /* Make a copy, so that on a reload, we have no race */
1957 if ((vmu = (ivm ? ivm : ast_calloc(1, sizeof(*vmu))))) {
1958 ast_free(vmu->email);
1959 ast_free(vmu->emailbody);
1960 ast_free(vmu->emailsubject);
1961 *vmu = *cur;
1962 vmu->email = ast_strdup(cur->email);
1963 vmu->emailbody = ast_strdup(cur->emailbody);
1964 vmu->emailsubject = ast_strdup(cur->emailsubject);
1965 ast_set2_flag(vmu, !ivm, VM_ALLOCED);
1966 AST_LIST_NEXT(vmu, list) = NULL;
1967 }
1968 }
1970 if (!vmu) {
1971 vmu = find_user_realtime(ivm, context, mailbox);
1972 }
1973 if (!vmu && !ast_strlen_zero(aliasescontext)) {
1974 struct alias_mailbox_mapping *mapping;
1975 char *search_string = ast_alloca(MAX_VM_MAILBOX_LEN);
1976
1977 snprintf(search_string, MAX_VM_MAILBOX_LEN, "%s%s%s",
1978 mailbox,
1979 ast_strlen_zero(context) ? "" : "@",
1980 S_OR(context, ""));
1981
1982 mapping = ao2_find(alias_mailbox_mappings, search_string, OBJ_SEARCH_KEY);
1983 if (mapping) {
1984 char *search_mailbox = NULL;
1985 char *search_context = NULL;
1986
1987 separate_mailbox(ast_strdupa(mapping->mailbox), &search_mailbox, &search_context);
1988 ao2_ref(mapping, -1);
1989 vmu = find_user(ivm, search_mailbox, search_context);
1990 }
1991 }
1992
1993 return vmu;
1994}
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 1894 of file app_voicemail_odbc.c.

1895{
1896 struct ast_variable *var;
1897 struct ast_vm_user *retval;
1898
1899 if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
1900 if (ivm) {
1901 memset(retval, 0, sizeof(*retval));
1902 }
1904 if (!ivm) {
1906 }
1907 if (mailbox) {
1908 ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
1909 }
1911 var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
1912 } else {
1913 var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
1914 }
1915 if (var) {
1918 } else {
1919 if (!ivm)
1921 retval = NULL;
1922 }
1923 }
1924 return retval;
1925}
#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 8686 of file app_voicemail_odbc.c.

8687{
8688#ifdef IMAP_STORAGE
8689 int todircount = 0;
8690 struct vm_state *dstvms;
8691#endif
8692 char username[70]="";
8693 char fn[PATH_MAX]; /* for playback of name greeting */
8694 char ecodes[16] = "#";
8695 int res = 0, cmd = 0;
8696 struct ast_vm_user *receiver = NULL, *vmtmp;
8698 char *stringp;
8699 const char *s;
8700 const char mailbox_context[256];
8701 int saved_messages = 0;
8702 int valid_extensions = 0;
8703 char *dir;
8704 int curmsg;
8705 char urgent_str[7] = "";
8706 int prompt_played = 0;
8707#ifndef IMAP_STORAGE
8708 char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
8709#endif
8710 SCOPE_ENTER(3, "%s: user: %s dir: %s msg: %d\n", ast_channel_name(chan),
8711 vms->username, vms->curdir, vms->curmsg);
8712
8714 ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
8715 }
8716
8717 if (vms == NULL) {
8718 SCOPE_EXIT_RTN_VALUE(-1, "vms is NULL\n");
8719 }
8720 dir = vms->curdir;
8721 curmsg = vms->curmsg;
8722
8723 ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
8724 while (!res && !valid_extensions) {
8725 int use_directory = 0;
8727 int done = 0;
8728 int retries = 0;
8729 cmd = 0;
8730 while ((cmd >= 0) && !done ){
8731 if (cmd)
8732 retries = 0;
8733 switch (cmd) {
8734 case '1':
8735 use_directory = 0;
8736 done = 1;
8737 break;
8738 case '2':
8739 use_directory = 1;
8740 done = 1;
8741 break;
8742 case '*':
8743 cmd = 't';
8744 done = 1;
8745 break;
8746 default:
8747 /* Press 1 to enter an extension press 2 to use the directory */
8748 cmd = ast_play_and_wait(chan, "vm-forward");
8749 if (!cmd) {
8750 cmd = ast_waitfordigit(chan, 3000);
8751 }
8752 if (!cmd) {
8753 retries++;
8754 }
8755 if (retries > 3) {
8756 cmd = 't';
8757 done = 1;
8758 }
8759 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
8760 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
8761 }
8762 }
8763 if (cmd < 0 || cmd == 't')
8764 break;
8765 }
8766
8767 if (use_directory) {
8768 /* use app_directory */
8769
8770 struct ast_app* directory_app;
8771
8772 directory_app = pbx_findapp("Directory");
8773 if (directory_app) {
8774 char vmcontext[256];
8775 char old_context[strlen(ast_channel_context(chan)) + 1];
8776 char old_exten[strlen(ast_channel_exten(chan)) + 1];
8777 int old_priority;
8778 /* make backup copies */
8779 strcpy(old_context, ast_channel_context(chan)); /* safe */
8780 strcpy(old_exten, ast_channel_exten(chan)); /* safe */
8781 old_priority = ast_channel_priority(chan);
8782
8783 /* call the Directory, changes the channel */
8784 snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
8785 res = pbx_exec(chan, directory_app, vmcontext);
8786
8787 ast_copy_string(username, ast_channel_exten(chan), sizeof(username));
8788
8789 /* restore the old context, exten, and priority */
8790 ast_channel_context_set(chan, old_context);
8791 ast_channel_exten_set(chan, old_exten);
8792 ast_channel_priority_set(chan, old_priority);
8793 } else {
8794 ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
8796 }
8797 } else {
8798 /* Ask for an extension */
8799 res = ast_streamfile(chan, "vm-extension", ast_channel_language(chan)); /* "extension" */
8800 prompt_played++;
8801 if (res || prompt_played > 4)
8802 break;
8803 if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#")) < 0)
8804 break;
8805 }
8806
8807 /* start all over if no username */
8808 if (ast_strlen_zero(username))
8809 continue;
8810 stringp = username;
8811 s = strsep(&stringp, "*");
8812 /* start optimistic */
8813 valid_extensions = 1;
8814 while (s) {
8815 snprintf((char*)mailbox_context, sizeof(mailbox_context), "%s@%s", s, context ? context : "default");
8816 if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
8817 int oldmsgs;
8818 int newmsgs;
8819 int capacity;
8820
8821 if (inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
8822 ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
8823 /* Shouldn't happen, but allow trying another extension if it does */
8824 res = ast_play_and_wait(chan, "pbx-invalid");
8825 valid_extensions = 0;
8826 break;
8827 }
8828#ifdef IMAP_STORAGE
8829 if (!(dstvms = get_vm_state_by_mailbox(s, context, 0))) {
8830 if (!(dstvms = create_vm_state_from_user(receiver))) {
8831 ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
8832 /* Shouldn't happen, but allow trying another extension if it does */
8833 res = ast_play_and_wait(chan, "pbx-invalid");
8834 valid_extensions = 0;
8835 break;
8836 }
8837 }
8838 check_quota(dstvms, imapfolder);
8839 if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
8840 ast_log(LOG_NOTICE, "Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
8841 res = ast_play_and_wait(chan, "vm-mailboxfull");
8842 valid_extensions = 0;
8843 while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8844 inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8845 free_user(vmtmp);
8846 }
8847 break;
8848 }
8849#endif
8850 capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
8851 if ((newmsgs + oldmsgs) >= capacity) {
8852 ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
8853 res = ast_play_and_wait(chan, "vm-mailboxfull");
8854 valid_extensions = 0;
8855 while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8856 inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8857 free_user(vmtmp);
8858 }
8859 inprocess_count(receiver->mailbox, receiver->context, -1);
8860 break;
8861 }
8862 AST_LIST_INSERT_HEAD(&extensions, receiver, list);
8863 } else {
8864 /* XXX Optimization for the future. When we encounter a single bad extension,
8865 * bailing out on all of the extensions may not be the way to go. We should
8866 * probably just bail on that single extension, then allow the user to enter
8867 * several more. XXX
8868 */
8869 while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
8870 free_user(receiver);
8871 }
8872 ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", mailbox_context);
8873 /* "I am sorry, that's not a valid extension. Please try again." */
8874 res = ast_play_and_wait(chan, "pbx-invalid");
8875 valid_extensions = 0;
8876 break;
8877 }
8878
8879 /* play name if available, else play extension number */
8880 snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
8881 SCOPE_CALL(-1, RETRIEVE, fn, -1, s, receiver->context);
8882 if (ast_fileexists(fn, NULL, NULL) > 0) {
8883 res = ast_stream_and_wait(chan, fn, ecodes);
8884 if (res) {
8885 SCOPE_CALL(-1, DISPOSE, fn, -1);
8886 return res;
8887 }
8888 } else {
8889 res = ast_say_digit_str(chan, s, ecodes, ast_channel_language(chan));
8890 }
8891 SCOPE_CALL(-1, DISPOSE, fn, -1);
8892
8893 s = strsep(&stringp, "*");
8894 }
8895 /* break from the loop of reading the extensions */
8896 if (valid_extensions)
8897 break;
8898 }
8899 /* check if we're clear to proceed */
8900 if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
8901 return res;
8902 if (is_new_message == 1) {
8903 struct leave_vm_options leave_options;
8904 char mailbox[AST_MAX_EXTENSION * 2 + 2];
8905 snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
8906
8907 /* Send VoiceMail */
8908 memset(&leave_options, 0, sizeof(leave_options));
8909 leave_options.record_gain = record_gain;
8910 leave_options.beeptone = "beep";
8911 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, leave_voicemail, chan, mailbox, &leave_options);
8912 } else {
8913 /* Forward VoiceMail */
8914 long duration = 0;
8915 struct vm_state vmstmp;
8916 int copy_msg_result = 0;
8917#ifdef IMAP_STORAGE
8918 char filename[PATH_MAX];
8919 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8920 const char *msg_id = NULL;
8921 struct ast_config *msg_cfg;
8922#endif
8923 memcpy(&vmstmp, vms, sizeof(vmstmp));
8924
8925 SCOPE_CALL(-1, RETRIEVE, dir, curmsg, sender->mailbox, sender->context);
8926#ifdef IMAP_STORAGE
8927 make_file(filename, sizeof(filename), dir, curmsg);
8928 strncat(filename, ".txt", sizeof(filename) - strlen(filename) - 1);
8929 msg_cfg = ast_config_load(filename, config_flags);
8930 if (msg_cfg && msg_cfg == CONFIG_STATUS_FILEINVALID) {
8931 msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
8932 ast_config_destroy(msg_cfg);
8933 }
8934#endif
8935
8936 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, vm_forwardoptions, chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
8937 if (!cmd) {
8938 AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
8939#ifdef IMAP_STORAGE
8940 int attach_user_voicemail;
8941 char *myserveremail = serveremail;
8942
8943 /* get destination mailbox */
8944 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
8945 if (!dstvms) {
8946 dstvms = create_vm_state_from_user(vmtmp);
8947 }
8948 if (dstvms) {
8949 init_mailstream(dstvms, 0);
8950 if (!dstvms->mailstream) {
8951 ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
8952 } else {
8953 copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
8954 run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str);
8955 }
8956 } else {
8957 ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
8958 }
8959 if (!ast_strlen_zero(vmtmp->serveremail))
8960 myserveremail = vmtmp->serveremail;
8961 attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
8962 /* NULL category for IMAP storage */
8963 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
8964 dstvms->curbox,
8965 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
8966 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
8967 vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
8968 NULL, urgent_str, msg_id);
8969#else
8970 copy_msg_result = SCOPE_CALL_WITH_INT_RESULT(-1, copy_message, chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL);
8971#endif
8972 saved_messages++;
8974 inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
8975 free_user(vmtmp);
8976 if (res)
8977 break;
8978 }
8980 if (saved_messages > 0 && !copy_msg_result) {
8981 /* give confirmation that the message was saved */
8982 /* commented out since we can't forward batches yet
8983 if (saved_messages == 1)
8984 res = ast_play_and_wait(chan, "vm-message");
8985 else
8986 res = ast_play_and_wait(chan, "vm-messages");
8987 if (!res)
8988 res = ast_play_and_wait(chan, "vm-saved"); */
8989 res = ast_play_and_wait(chan, "vm-msgforwarded");
8990 }
8991#ifndef IMAP_STORAGE
8992 else {
8993 /* with IMAP, mailbox full warning played by imap_check_limits */
8994 res = ast_play_and_wait(chan, "vm-mailboxfull");
8995 }
8996 /* Restore original message without prepended message if backup exists */
8997 make_file(msgfile, sizeof(msgfile), dir, curmsg);
8998 strcpy(textfile, msgfile);
8999 strcpy(backup, msgfile);
9000 strcpy(backup_textfile, msgfile);
9001 strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
9002 strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
9003 strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
9004 if (ast_fileexists(backup, NULL, NULL) > 0) {
9005 ast_filerename(backup, msgfile, NULL);
9006 rename(backup_textfile, textfile);
9007 }
9008#endif
9009 }
9010 SCOPE_CALL(-1, DISPOSE, dir, curmsg);
9011#ifndef IMAP_STORAGE
9012 if (cmd) { /* assuming hangup, cleanup backup file */
9013 make_file(msgfile, sizeof(msgfile), dir, curmsg);
9014 strcpy(textfile, msgfile);
9015 strcpy(backup_textfile, msgfile);
9016 strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
9017 strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
9018 rename(backup_textfile, textfile);
9019 }
9020#endif
9021 }
9022
9023 /* If anything failed above, we still have this list to free */
9024 while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
9025 inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
9026 free_user(vmtmp);
9027 }
9028 SCOPE_EXIT_RTN_VALUE(res ? res : cmd, "Done. res: %d cmd: %d\n", res, cmd);
9029}
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.
const char * ast_channel_name(const struct ast_channel *chan)
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:8281
ast_app: A registered application
Definition: pbx_app.c:45
Number structure.
Definition: app_followme.c:154
#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_name(), 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, SCOPE_CALL, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, 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 12046 of file app_voicemail_odbc.c.

12047{
12048 const char *from_mailbox = a->argv[2];
12049 const char *from_context = a->argv[3];
12050 const char *from_folder = a->argv[4];
12051 const char *id[] = { a->argv[5] };
12052 const char *to_mailbox = a->argv[6];
12053 const char *to_context = a->argv[7];
12054 const char *to_folder = a->argv[8];
12055 int ret = vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0);
12056 if (ret) {
12057 ast_cli(a->fd, "Error forwarding message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
12058 id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
12059 } else {
12060 ast_cli(a->fd, "Forwarded message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
12061 id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
12062 }
12063 return ret;
12064}
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 2279 of file app_voicemail_odbc.c.

2280{
2281 if (!vmu) {
2282 return;
2283 }
2284
2285 if (!ast_strlen_zero(vmu->mailbox)) {
2287 }
2288
2289 free_user(vmu);
2290}
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 14621 of file app_voicemail_odbc.c.

14622{
14623 struct ast_vm_user *current;
14625 while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
14628 }
14630}
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 14633 of file app_voicemail_odbc.c.

14634{
14635 struct vm_zone *zcur;
14637 while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
14638 free_zone(zcur);
14640}
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 6122 of file app_voicemail_odbc.c.

6123{
6124 ast_free(z);
6125}

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 6664 of file app_voicemail_odbc.c.

6665{
6666 /* msg id is time of msg_id generation plus an incrementing value
6667 * called each time a new msg_id is generated. This should achieve uniqueness,
6668 * but only in single system solutions.
6669 */
6670 unsigned int unique_counter = ast_atomic_fetchadd_int(&msg_id_incrementor, +1);
6671 snprintf(dst, MSG_ID_LEN, "%ld-%08x", (long) time(NULL), unique_counter);
6672}
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 6078 of file app_voicemail_odbc.c.

6079{
6080 struct ast_tm tm;
6081 struct timeval t = ast_tvnow();
6082
6083 ast_localtime(&t, &tm, "UTC");
6084
6085 return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
6086}
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 8225 of file app_voicemail_odbc.c.

8226{
8227 int x;
8228 int d;
8229 char fn[PATH_MAX];
8230 d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
8231 if (d)
8232 return d;
8233 for (x = start; x < 5; x++) { /* For all folders */
8234 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
8235 return d;
8236 d = ast_play_and_wait(chan, "vm-for"); /* "for" */
8237 if (d)
8238 return d;
8239 snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
8240
8241 /* The inbox folder can have its name changed under certain conditions
8242 * so this checks if the sound file exists for the inbox folder name and
8243 * if it doesn't, plays the default name instead. */
8244 if (x == 0) {
8245 if (ast_fileexists(fn, NULL, NULL)) {
8246 d = vm_play_folder_name(chan, fn);
8247 } else {
8248 ast_verb(4, "Failed to find file %s; falling back to INBOX\n", fn);
8249 d = vm_play_folder_name(chan, "vm-INBOX");
8250 }
8251 } else {
8252 ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
8253 d = vm_play_folder_name(chan, fn);
8254 }
8255
8256 if (d)
8257 return d;
8258 d = ast_waitfordigit(chan, 500);
8259 if (d)
8260 return d;
8261 }
8262
8263 d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
8264 if (d)
8265 return d;
8266 d = ast_waitfordigit(chan, 4000);
8267 return d;
8268}
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:8257
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 8310 of file app_voicemail_odbc.c.

8311{
8312 int res = 0;
8313 int loops = 0;
8314
8315 res = ast_play_and_wait(chan, fn); /* Folder name */
8316 while (((res < '0') || (res > '9')) &&
8317 (res != '#') && (res >= 0) &&
8318 loops < 4) {
8319 /* res = get_folder(chan, 0); */
8320 if (!strcasecmp(ast_channel_language(chan), "ja")) { /* Japanese syntax */
8321 res = get_folder_ja(chan, 0);
8322 } else { /* Default syntax */
8323 res = get_folder(chan, 0);
8324 }
8325 loops++;
8326 }
8327 if (loops == 4) { /* give up */
8328 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
8329 return '#';
8330 }
8331 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
8332 isprint(res) ? res : '?', isprint(res) ? res : '?');
8333 return res;
8334}
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 2248 of file app_voicemail_odbc.c.

2249{
2250 size_t i;
2251
2252 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
2253 if (strcasecmp(name, mailbox_folders[i]) == 0) {
2254 return i;
2255 }
2256 }
2257
2258 return -1;
2259}

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 8271 of file app_voicemail_odbc.c.

8272{
8273 int x;
8274 int d;
8275 char fn[256];
8276 for (x = start; x < 5; x++) { /* For all folders */
8277 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL))) {
8278 return d;
8279 }
8280 snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
8281 d = vm_play_folder_name(chan, fn);
8282 if (d) {
8283 return d;
8284 }
8285 d = ast_waitfordigit(chan, 500);
8286 if (d) {
8287 return d;
8288 }
8289 }
8290 d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
8291 if (d) {
8292 return d;
8293 }
8294 d = ast_waitfordigit(chan, 4000);
8295 return d;
8296}

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 12282 of file app_voicemail_odbc.c.

12283{
12284 switch (cmd) {
12285 case CLI_INIT:
12286 e->command = "voicemail forward";
12287 e->usage =
12288 "Usage: voicemail forward <from_mailbox> <from_context> <from_folder> <messageid> <to_mailbox> <to_context> <to_folder>\n"
12289 " Forward message <messageid> in mailbox <mailbox>@<context> <from_folder>\n"
12290 " to mailbox <mailbox>@<context> <to_folder>\n";
12291 return NULL;
12292 case CLI_GENERATE:
12294 case CLI_HANDLER:
12295 break;
12296 }
12297
12298 if (a->argc != 9) {
12299 return CLI_SHOWUSAGE;
12300 }
12301
12303 return CLI_FAILURE;
12304 }
12305
12306 return CLI_SUCCESS;
12307}
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 12309 of file app_voicemail_odbc.c.

12310{
12311 switch (cmd) {
12312 case CLI_INIT:
12313 e->command = "voicemail move";
12314 e->usage =
12315 "Usage: voicemail move <mailbox> <context> <from_folder> <messageid> <to_folder>\n"
12316 " Move message <messageid> in mailbox <mailbox>&<context> from <from_folder> to <to_folder>\n";
12317 return NULL;
12318 case CLI_GENERATE:
12320 case CLI_HANDLER:
12321 break;
12322 }
12323
12324 if (a->argc != 7) {
12325 return CLI_SHOWUSAGE;
12326 }
12327
12329 return CLI_FAILURE;
12330 }
12331
12332 return CLI_SUCCESS;
12333}
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 13948 of file app_voicemail_odbc.c.

13949{
13950 switch (cmd) {
13951 case CLI_INIT:
13952 e->command = "voicemail reload";
13953 e->usage =
13954 "Usage: voicemail reload\n"
13955 " Reload voicemail configuration\n";
13956 return NULL;
13957 case CLI_GENERATE:
13958 return NULL;
13959 }
13960
13961 if (a->argc != 2)
13962 return CLI_SHOWUSAGE;
13963
13964 ast_cli(a->fd, "Reloading voicemail configuration...\n");
13965 load_config(1);
13966
13967 return CLI_SUCCESS;
13968}
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 12335 of file app_voicemail_odbc.c.

12336{
12337 switch (cmd) {
12338 case CLI_INIT:
12339 e->command = "voicemail remove";
12340 e->usage =
12341 "Usage: voicemail remove <mailbox> <context> <from_folder> <messageid>\n"
12342 " Remove message <messageid> from <from_folder> in mailbox <mailbox>@<context>\n";
12343 return NULL;
12344 case CLI_GENERATE:
12346 case CLI_HANDLER:
12347 break;
12348 }
12349
12350 if (a->argc != 6) {
12351 return CLI_SHOWUSAGE;
12352 }
12353
12355 return CLI_FAILURE;
12356 }
12357
12358 return CLI_SUCCESS;
12359}
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 13908 of file app_voicemail_odbc.c.

13909{
13910 struct ao2_iterator aliases;
13911 struct alias_mailbox_mapping *mapping;
13912#define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"
13913 char *res = CLI_SUCCESS;
13914
13915 switch (cmd) {
13916 case CLI_INIT:
13917 e->command = "voicemail show aliases";
13918 e->usage =
13919 "Usage: voicemail show aliases\n"
13920 " Lists mailbox aliases\n";
13921 return NULL;
13922 case CLI_GENERATE:
13923 return NULL;
13924 }
13925
13926 if (a->argc != 3)
13927 return CLI_SHOWUSAGE;
13928
13930 ast_cli(a->fd, "Aliases are not enabled\n");
13931 return res;
13932 }
13933
13934 ast_cli(a->fd, "Aliases context: %s\n", aliasescontext);
13935 ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, "Alias", "Mailbox");
13936
13938 while ((mapping = ao2_iterator_next(&aliases))) {
13939 ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, mapping->alias, mapping->mailbox);
13940 ao2_ref(mapping, -1);
13941 }
13943
13944 return res;
13945}
#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 12148 of file app_voicemail_odbc.c.

12149{
12150 switch (cmd) {
12151 case CLI_INIT:
12152 e->command = "voicemail show mailbox";
12153 e->usage =
12154 "Usage: voicemail show mailbox <mailbox> <context>\n"
12155 " Show contents of mailbox <mailbox>@<context>\n";
12156 return NULL;
12157 case CLI_GENERATE:
12159 case CLI_HANDLER:
12160 break;
12161 }
12162
12163 if (a->argc != 5) {
12164 return CLI_SHOWUSAGE;
12165 }
12166
12168 return CLI_FAILURE;
12169 }
12170
12171 return CLI_SUCCESS;
12172}
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 13796 of file app_voicemail_odbc.c.

13797{
13798 struct ast_vm_user *vmu;
13799#define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
13800 const char *context = NULL;
13801 int users_counter = 0;
13802
13803 switch (cmd) {
13804 case CLI_INIT:
13805 e->command = "voicemail show users [for]";
13806 e->usage =
13807 "Usage: voicemail show users [for <context>]\n"
13808 " Lists all mailboxes currently set up\n";
13809 return NULL;
13810 case CLI_GENERATE:
13811 return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
13812 }
13813
13814 if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
13815 return CLI_SHOWUSAGE;
13816 if (a->argc == 5) {
13817 if (strcmp(a->argv[3],"for"))
13818 return CLI_SHOWUSAGE;
13819 context = a->argv[4];
13820 }
13821
13822 if (ast_check_realtime("voicemail")) {
13823 if (!context) {
13824 ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
13825 return CLI_SHOWUSAGE;
13826 }
13827 return show_users_realtime(a->fd, context);
13828 }
13829
13831 if (AST_LIST_EMPTY(&users)) {
13832 ast_cli(a->fd, "There are no voicemail users currently defined\n");
13834 return CLI_FAILURE;
13835 }
13836 if (!context) {
13837 ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
13838 } else {
13839 int count = 0;
13840 AST_LIST_TRAVERSE(&users, vmu, list) {
13841 if (!strcmp(context, vmu->context)) {
13842 count++;
13843 break;
13844 }
13845 }
13846 if (count) {
13847 ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
13848 } else {
13849 ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
13851 return CLI_FAILURE;
13852 }
13853 }
13854 AST_LIST_TRAVERSE(&users, vmu, list) {
13855 int newmsgs = 0, oldmsgs = 0;
13856 char count[12], tmp[256] = "";
13857
13858 if (!context || !strcmp(context, vmu->context)) {
13859 snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
13860 inboxcount(tmp, &newmsgs, &oldmsgs);
13861 snprintf(count, sizeof(count), "%d", newmsgs);
13862 ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
13863 users_counter++;
13864 }
13865 }
13867 ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
13868 return CLI_SUCCESS;
13869}
#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 13872 of file app_voicemail_odbc.c.

13873{
13874 struct vm_zone *zone;
13875#define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
13876 char *res = CLI_SUCCESS;
13877
13878 switch (cmd) {
13879 case CLI_INIT:
13880 e->command = "voicemail show zones";
13881 e->usage =
13882 "Usage: voicemail show zones\n"
13883 " Lists zone message formats\n";
13884 return NULL;
13885 case CLI_GENERATE:
13886 return NULL;
13887 }
13888
13889 if (a->argc != 3)
13890 return CLI_SHOWUSAGE;
13891
13893 if (!AST_LIST_EMPTY(&zones)) {
13894 ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
13895 AST_LIST_TRAVERSE(&zones, zone, list) {
13896 ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
13897 }
13898 } else {
13899 ast_cli(a->fd, "There are no voicemail zones currently defined\n");
13900 res = CLI_FAILURE;
13901 }
13903
13904 return res;
13905}
#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 6497 of file app_voicemail_odbc.c.

6498{
6499 char tmp[256], *tmp2 = tmp, *box, *context;
6500 ast_copy_string(tmp, mailbox, sizeof(tmp));
6501 if (ast_strlen_zero(folder)) {
6502 folder = "INBOX";
6503 }
6504 while ((box = strsep(&tmp2, ",&"))) {
6505 if ((context = strchr(box, '@')))
6506 *context++ = '\0';
6507 else
6508 context = "default";
6509 if (__has_voicemail(context, box, folder, 1))
6510 return 1;
6511 /* If we are checking INBOX, we should check Urgent as well */
6512 if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
6513 return 1;
6514 }
6515 }
6516 return 0;
6517}
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().

◆ inboxcount()

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

Definition at line 6597 of file app_voicemail_odbc.c.

6598{
6599 int urgentmsgs = 0;
6600 int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
6601 if (newmsgs) {
6602 *newmsgs += urgentmsgs;
6603 }
6604 return res;
6605}

References inboxcount2(), and voicemailpwcheck::mailbox.

Referenced by append_vmu_info_astman(), 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 6527 of file app_voicemail_odbc.c.

6528{
6529 char tmp[256];
6530 char *context;
6531
6532 /* If no mailbox, return immediately */
6533 if (ast_strlen_zero(mailbox)) {
6534 return 0;
6535 }
6536
6537 if (newmsgs) {
6538 *newmsgs = 0;
6539 }
6540 if (oldmsgs) {
6541 *oldmsgs = 0;
6542 }
6543 if (urgentmsgs) {
6544 *urgentmsgs = 0;
6545 }
6546
6547 if (strchr(mailbox, ',')) {
6548 int tmpnew, tmpold, tmpurgent;
6549 char *mb, *cur;
6550
6551 ast_copy_string(tmp, mailbox, sizeof(tmp));
6552 mb = tmp;
6553 while ((cur = strsep(&mb, ", "))) {
6554 if (!ast_strlen_zero(cur)) {
6555 if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL)) {
6556 return -1;
6557 } else {
6558 if (newmsgs) {
6559 *newmsgs += tmpnew;
6560 }
6561 if (oldmsgs) {
6562 *oldmsgs += tmpold;
6563 }
6564 if (urgentmsgs) {
6565 *urgentmsgs += tmpurgent;
6566 }
6567 }
6568 }
6569 }
6570 return 0;
6571 }
6572
6573 ast_copy_string(tmp, mailbox, sizeof(tmp));
6574
6575 if ((context = strchr(tmp, '@'))) {
6576 *context++ = '\0';
6577 } else {
6578 context = "default";
6579 }
6580
6581 if (newmsgs) {
6582 *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
6583 }
6584 if (oldmsgs) {
6585 *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
6586 }
6587 if (urgentmsgs) {
6588 *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
6589 }
6590
6591 return 0;
6592}

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

Referenced by append_mailbox(), 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 1267 of file app_voicemail_odbc.c.

1268{
1269 struct inprocess *i = obj, *j = arg;
1270 if (strcmp(i->mailbox, j->mailbox)) {
1271 return 0;
1272 }
1273 return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
1274}
@ 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 1276 of file app_voicemail_odbc.c.

1277{
1278 int context_len = strlen(context) + 1;
1279 int mailbox_len = strlen(mailbox) + 1;
1280 struct inprocess *i, *arg = ast_alloca(sizeof(*arg) + context_len + mailbox_len);
1281 arg->context = arg->mailbox + mailbox_len;
1282 ast_copy_string(arg->mailbox, mailbox, mailbox_len); /* SAFE */
1283 ast_copy_string(arg->context, context, context_len); /* SAFE */
1285 if ((i = ao2_find(inprocess_container, arg, 0))) {
1286 int ret = ast_atomic_fetchadd_int(&i->count, delta);
1288 ao2_ref(i, -1);
1289 return ret;
1290 }
1291 if (delta < 0) {
1292 ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
1293 }
1294 if (!(i = ao2_alloc(sizeof(*i) + context_len + mailbox_len, NULL))) {
1296 return 0;
1297 }
1298 i->context = i->mailbox + mailbox_len;
1299 ast_copy_string(i->mailbox, mailbox, mailbox_len); /* SAFE */
1300 ast_copy_string(i->context, context, context_len); /* SAFE */
1301 i->count = delta;
1304 ao2_ref(i, -1);
1305 return 0;
1306}
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 1261 of file app_voicemail_odbc.c.

1262{
1263 const struct inprocess *i = obj;
1264 return atoi(i->mailbox);
1265}

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 6088 of file app_voicemail_odbc.c.

6089{
6090 int res;
6091 char fn[PATH_MAX];
6092 char dest[PATH_MAX];
6093
6094 snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
6095
6096 if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
6097 ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
6098 return -1;
6099 }
6100
6101 RETRIEVE(fn, -1, ext, context);
6102 if (ast_fileexists(fn, NULL, NULL) > 0) {
6103 res = ast_stream_and_wait(chan, fn, ecodes);
6104 if (res) {
6105 DISPOSE(fn, -1);
6106 return res;
6107 }
6108 } else {
6109 /* Dispose just in case */
6110 DISPOSE(fn, -1);
6111 res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
6112 if (res)
6113 return res;
6114 res = ast_say_digit_str(chan, ext, ecodes, ast_channel_language(chan));
6115 if (res)
6116 return res;
6117 }
6118 res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
6119 return res;
6120}

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 1869 of file app_voicemail_odbc.c.

1870{
1871 int i;
1872 char *local_key = ast_strdupa(key);
1873
1874 for (i = 0; i < strlen(key); ++i) {
1875 if (!strchr(VALID_DTMF, *local_key)) {
1876 ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
1877 return 0;
1878 }
1879 local_key++;
1880 }
1881 return 1;
1882}
#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 5056 of file app_voicemail_odbc.c.

5057{
5058 int x;
5059 unsigned char map[MAXMSGLIMIT] = "";
5060 DIR *msgdir;
5061 struct dirent *msgdirent;
5062 int msgdirint;
5063 char extension[4];
5064 int stopcount = 0;
5065
5066 /* Reading the entire directory into a file map scales better than
5067 * doing a stat repeatedly on a predicted sequence. I suspect this
5068 * is partially due to stat(2) internally doing a readdir(2) itself to
5069 * find each file. */
5070 if (!(msgdir = opendir(dir))) {
5071 return -1;
5072 }
5073
5074 while ((msgdirent = readdir(msgdir))) {
5075 if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
5076 map[msgdirint] = 1;
5077 stopcount++;
5078 ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
5079 }
5080 }
5081 closedir(msgdir);
5082
5083 for (x = 0; x < MAXMSGLIMIT && stopcount; x++) {
5084 stopcount -= map[x];
5085 }
5086
5087 return x - 1;
5088}
structure to hold extensions

References ast_debug, and MAXMSGLIMIT.

◆ leave_voicemail()

static int leave_voicemail ( struct ast_channel chan,
char *  ext,
struct leave_vm_options options 
)
static

Prompts the user and records a voicemail to a mailbox.

Parameters
chan
ext
optionsOPT_BUSY_GREETING, OPT_UNAVAIL_GREETING
Returns
zero on success, -1 on error.

Definition at line 6996 of file app_voicemail_odbc.c.

6997{
6998#ifdef IMAP_STORAGE
6999 int newmsgs, oldmsgs;
7000#endif
7001 char txtfile[PATH_MAX];
7002 char tmptxtfile[PATH_MAX];
7003 struct vm_state *vms = NULL;
7004 char callerid[256];
7005 FILE *txt;
7006 char date[256];
7007 int txtdes;
7008 int res = 0;
7009 int msgnum;
7010 int duration = 0;
7011 int sound_duration = 0;
7012 int ouseexten = 0;
7013 int greeting_only = 0;
7014 char tmpdur[16];
7015 char priority[16];
7016 char origtime[16];
7017 char dir[PATH_MAX];
7018 char tmpdir[PATH_MAX];
7019 char fn[PATH_MAX];
7020 char prefile[PATH_MAX] = "";
7021 char tempfile[PATH_MAX] = "";
7022 char ext_context[256] = "";
7023 char fmt[80];
7024 char *context;
7025 char ecodes[17] = "#";
7026 struct ast_str *tmp = ast_str_create(16);
7027 char *tmpptr;
7028 struct ast_vm_user *vmu;
7029 struct ast_vm_user svm;
7030 const char *category = NULL;
7031 const char *code;
7032 const char *alldtmf = "0123456789ABCD*#";
7033 char flag[80];
7034 SCOPE_ENTER(3, "%s: %s\n", ast_channel_name(chan), ext);
7035
7036 if (!tmp) {
7037 SCOPE_EXIT_RTN_VALUE(-1, "Failed to allocate memory for tmp\n");
7038 }
7039
7040 ast_str_set(&tmp, 0, "%s", ext);
7042 if ((context = strchr(ext, '@'))) {
7043 *context++ = '\0';
7044 tmpptr = strchr(context, '&');
7045 } else {
7046 tmpptr = strchr(ext, '&');
7047 }
7048
7049 if (tmpptr)
7050 *tmpptr++ = '\0';
7051
7052 ast_channel_lock(chan);
7053 if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
7054 category = ast_strdupa(category);
7055 }
7056 ast_channel_unlock(chan);
7057
7059 ast_copy_string(flag, "Urgent", sizeof(flag));
7061 ast_copy_string(flag, "PRIORITY", sizeof(flag));
7062 } else {
7063 flag[0] = '\0';
7064 }
7065
7066 ast_debug(3, "Before find_user\n");
7067 memset(&svm, 0, sizeof(svm));
7068 if (!(vmu = find_user(&svm, context, ext))) {
7069 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7070 ast_free(tmp);
7072 "%s: Exten: %s: No entry in voicemail config file for '%s'\n", ast_channel_name(chan), ext, ext);
7073 }
7074
7075 /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
7076 if (vmu->maxmsg == 0) {
7077 greeting_only = 1;
7079 }
7080
7081 /* Setup pre-file if appropriate */
7082 if (strcmp(vmu->context, "default"))
7083 snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
7084 else
7085 ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
7086
7087 /* Set the path to the prefile. Will be one of
7088 VM_SPOOL_DIRcontext/ext/busy
7089 VM_SPOOL_DIRcontext/ext/unavail
7090 Depending on the flag set in options.
7091 */
7093 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
7095 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
7096 }
7097 ast_trace(-1, "prefile: %s\n", prefile);
7098 /* Set the path to the tmpfile as
7099 VM_SPOOL_DIR/context/ext/temp
7100 and attempt to create the folder structure.
7101 */
7102 snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
7103 ast_trace(-1, "tempfile: %s\n", tempfile);
7104 if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
7105 free_user(vmu);
7106 ast_free(tmp);
7108 "%s: Exten: %s: Failed to make directory (%s)\n", ast_channel_name(chan), ext, tempfile);
7109 }
7110 SCOPE_CALL(-1, RETRIEVE, tempfile, -1, vmu->mailbox, vmu->context);
7111 if (ast_fileexists(tempfile, NULL, NULL) > 0) {
7112 ast_copy_string(prefile, tempfile, sizeof(prefile));
7113 ast_trace(-1, "new prefile: %s\n", prefile);
7114 }
7115
7116 SCOPE_CALL(-1, DISPOSE, tempfile, -1);
7117
7118 /* It's easier just to try to make it than to check for its existence */
7119#ifndef IMAP_STORAGE
7120 create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
7121#else
7122 snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
7123 if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
7124 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
7125 }
7126#endif
7127
7128 /* Check current context for special extensions */
7129 if (ast_test_flag(vmu, VM_OPERATOR)) {
7130 if (!ast_strlen_zero(vmu->exit)) {
7131 if (ast_exists_extension(chan, vmu->exit, "o", 1,
7132 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
7133 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
7134 ouseexten = 1;
7135 }
7136 } else if (ast_exists_extension(chan, ast_channel_context(chan), "o", 1,
7137 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
7138 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
7139 ouseexten = 1;
7140 }
7141 }
7142
7143 if (!ast_strlen_zero(vmu->exit)) {
7144 if (ast_exists_extension(chan, vmu->exit, "a", 1,
7145 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
7146 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
7147 }
7148 } else if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
7149 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
7150 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
7151 }
7152
7154 for (code = alldtmf; *code; code++) {
7155 char e[2] = "";
7156 e[0] = *code;
7157 if (strchr(ecodes, e[0]) == NULL
7158 && ast_canmatch_extension(chan,
7159 (!ast_strlen_zero(options->exitcontext) ? options->exitcontext : ast_channel_context(chan)),
7160 e, 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
7161 strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
7162 }
7163 }
7164 }
7165
7166 /* Play the beginning intro if desired */
7167 if (!ast_strlen_zero(prefile)) {
7168#if defined(ODBC_STORAGE)
7169 int success = SCOPE_CALL_WITH_INT_RESULT(-1, RETRIEVE, prefile, -1, ext, context);
7170#elif defined(IMAP_STORAGE)
7171 SCOPE_CALL(-1, RETRIEVE, prefile, -1, ext, context);
7172#endif
7173
7174 if (ast_fileexists(prefile, NULL, NULL) > 0) {
7175 if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1) {
7176 /* We know we have a greeting at this point, so squelch the instructions
7177 * if that is what is being asked of us */
7180 }
7181 res = ast_waitstream(chan, ecodes);
7182 }
7183#ifdef ODBC_STORAGE
7184 if (success == -1) {
7185 /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
7186 ast_trace(-1, "Greeting '%s' not retrieved from database, but found in file storage. Inserting into database\n", prefile);
7187 SCOPE_CALL(-1, odbc_store_message, prefile, vmu->mailbox, vmu->context, -1);
7188 }
7189#endif
7190 } else {
7191 ast_trace(-1, "%s doesn't exist, doing what we can\n", prefile);
7192 res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
7193 }
7194 SCOPE_CALL(-1, DISPOSE, prefile, -1);
7195 if (res < 0) {
7196 free_user(vmu);
7197 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7198 ast_free(tmp);
7199 SCOPE_EXIT_RTN_VALUE(-1, "Hang up during prefile playback\n");
7200 }
7201 }
7202 if (res == '#') {
7203 /* On a '#' we skip the instructions */
7205 res = 0;
7206 }
7207 if (!res && !ast_test_flag(options, OPT_SILENT)) {
7208 res = ast_stream_and_wait(chan, INTRO, ecodes);
7209 if (res == '#') {
7211 res = 0;
7212 }
7213 }
7214 if (res > 0)
7215 ast_stopstream(chan);
7216 /* Check for a '*' here in case the caller wants to escape from voicemail to something
7217 other than the operator -- an automated attendant or mailbox login for example */
7218 if (res == '*') {
7219 ast_channel_exten_set(chan, "a");
7220 if (!ast_strlen_zero(vmu->exit)) {
7221 ast_channel_context_set(chan, vmu->exit);
7222 }
7223 ast_channel_priority_set(chan, 0);
7224 free_user(vmu);
7225 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
7226 ast_free(tmp);
7227 SCOPE_EXIT_RTN_VALUE(0, "User escaped with '*'\n");
7228 }
7229
7230 /* Check for a '0' here */
7231 if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
7232 transfer:
7233 if (ouseexten) {
7234 ast_channel_exten_set(chan, "o");
7235 if (!ast_strlen_zero(vmu->exit)) {
7236 ast_channel_context_set(chan, vmu->exit);
7237 }
7238 ast_play_and_wait(chan, "transfer");
7239 ast_channel_priority_set(chan, 0);
7240 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
7241 }
7242 free_user(vmu);
7243 ast_free(tmp);
7244 SCOPE_EXIT_RTN_VALUE(OPERATOR_EXIT, "User escaped with '0'\n");
7245 }
7246
7247 /* Allow all other digits to exit Voicemail and return to the dialplan */
7248 if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
7249 if (!ast_strlen_zero(options->exitcontext)) {
7250 ast_channel_context_set(chan, options->exitcontext);
7251 }
7252 free_user(vmu);
7253 ast_free(tmp);
7254 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
7255 SCOPE_EXIT_RTN_VALUE(res, "User escaped back to dialplan '%c'\n", res);
7256 }
7257
7258 if (greeting_only) {
7259 ast_debug(3, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
7260 pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
7261 res = 0;
7262 goto leave_vm_out;
7263 }
7264
7265 if (res < 0) {
7266 free_user(vmu);
7267 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7268 ast_free(tmp);
7269 SCOPE_EXIT_RTN_VALUE(-1, "Other error '%d'\n", res);
7270 }
7271 /* The meat of recording the message... All the announcements and beeps have been played*/
7272 if (ast_channel_state(chan) != AST_STATE_UP) {
7273 ast_answer(chan);
7274 }
7275 ast_copy_string(fmt, vmfmts, sizeof(fmt));
7276 if (!ast_strlen_zero(fmt)) {
7277 char msg_id[MSG_ID_LEN] = "";
7278 msgnum = 0;
7279
7280#ifdef IMAP_STORAGE
7281 /* Is ext a mailbox? */
7282 /* must open stream for this user to get info! */
7283 res = inboxcount(ext_context, &newmsgs, &oldmsgs);
7284 if (res < 0) {
7285 ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
7286 free_user(vmu);
7287 ast_free(tmp);
7288 return -1;
7289 }
7290 if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
7291 /* It is possible under certain circumstances that inboxcount did not
7292 * create a vm_state when it was needed. This is a catchall which will
7293 * rarely be used.
7294 */
7295 if (!(vms = create_vm_state_from_user(vmu))) {
7296 ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
7297 free_user(vmu);
7298 ast_free(tmp);
7299 return -1;
7300 }
7301 }
7302 vms->newmessages++;
7303
7304 /* here is a big difference! We add one to it later */
7305 msgnum = newmsgs + oldmsgs;
7306 ast_debug(3, "Messagecount set to %d\n", msgnum);
7307 snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
7308 /* set variable for compatibility */
7309 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
7310
7311 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
7312 goto leave_vm_out;
7313 }
7314#else
7315 if (COUNT(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
7316 res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
7317 if (!res)
7318 res = ast_waitstream(chan, "");
7319 ast_log(AST_LOG_WARNING, "No more messages possible\n");
7320 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7321 inprocess_count(vmu->mailbox, vmu->context, -1);
7322 goto leave_vm_out;
7323 }
7324
7325#endif
7326 snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
7327 ast_trace(-1, "Tempfile: %s\n", tmptxtfile);
7328 txtdes = mkstemp(tmptxtfile);
7329 chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
7330 if (txtdes < 0) {
7331 res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
7332 if (!res)
7333 res = ast_waitstream(chan, "");
7334 ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
7335 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7336 inprocess_count(vmu->mailbox, vmu->context, -1);
7337 goto leave_vm_out;
7338 }
7339
7340 /* Now play the beep once we have the message number for our next message. */
7341 if (res >= 0) {
7342 /* Unless we're *really* silent, try to send the beep */
7343 /* Play default or custom beep, unless no beep desired */
7344 if (!ast_strlen_zero(options->beeptone)) {
7345 res = ast_stream_and_wait(chan, options->beeptone, "");
7346 }
7347 }
7348
7349 /* Store information in real-time storage */
7350 if (ast_check_realtime("voicemail_data")) {
7351 snprintf(priority, sizeof(priority), "%d", ast_channel_priority(chan));
7352 snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
7353 get_date(date, sizeof(date));
7354 ast_callerid_merge(callerid, sizeof(callerid),
7355 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
7356 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
7357 "Unknown");
7358 ast_store_realtime("voicemail_data",
7359 "origmailbox", ext,
7360 "context", ast_channel_context(chan),
7361 "exten", ast_channel_exten(chan),
7362 "priority", priority,
7363 "callerchan", ast_channel_name(chan),
7364 "callerid", callerid,
7365 "origdate", date,
7366 "origtime", origtime,
7367 "category", S_OR(category, ""),
7368 "filename", tmptxtfile,
7369 SENTINEL);
7370 }
7371
7372 /* Store information */
7373 txt = fdopen(txtdes, "w+");
7374 if (txt) {
7375 generate_msg_id(msg_id);
7376 get_date(date, sizeof(date));
7377 ast_callerid_merge(callerid, sizeof(callerid),
7378 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
7379 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
7380 "Unknown");
7381 fprintf(txt,
7382 ";\n"
7383 "; Message Information file\n"
7384 ";\n"
7385 "[message]\n"
7386 "origmailbox=%s\n"
7387 "context=%s\n"
7388 "exten=%s\n"
7389 "rdnis=%s\n"
7390 "priority=%d\n"
7391 "callerchan=%s\n"
7392 "callerid=%s\n"
7393 "origdate=%s\n"
7394 "origtime=%ld\n"
7395 "category=%s\n"
7396 "msg_id=%s\n",
7397 ext,
7398 ast_channel_context(chan),
7399 ast_channel_exten(chan),
7400 S_COR(ast_channel_redirecting(chan)->from.number.valid,
7401 ast_channel_redirecting(chan)->from.number.str, "unknown"),
7403 ast_channel_name(chan),
7404 callerid,
7405 date, (long) time(NULL),
7406 category ? category : "",
7407 msg_id);
7408 ast_trace(-1, "Saving txt file mbox: %s msg_id: %s\n", ext, msg_id);
7409 } else {
7410 ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
7411 inprocess_count(vmu->mailbox, vmu->context, -1);
7412 if (ast_check_realtime("voicemail_data")) {
7413 ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
7414 }
7415 res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan));
7416 goto leave_vm_out;
7417 }
7418
7419 res = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id, 0);
7420
7421 /* At this point, either we were instructed to make the message Urgent
7422 by arguments to VoiceMail or during the review process by the person
7423 leaving the message. So we update the directory where we want this
7424 message to go. */
7425 if (!strcmp(flag, "Urgent")) {
7426 create_dirpath(dir, sizeof(dir), vmu->context, ext, "Urgent");
7427 }
7428
7429 if (txt) {
7430 fprintf(txt, "flag=%s\n", flag);
7431 if (sound_duration < vmu->minsecs) {
7432 fclose(txt);
7433 ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->minsecs);
7434 ast_filedelete(tmptxtfile, NULL);
7435 unlink(tmptxtfile);
7436 if (ast_check_realtime("voicemail_data")) {
7437 ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
7438 }
7439 inprocess_count(vmu->mailbox, vmu->context, -1);
7440 } else {
7441 fprintf(txt, "duration=%d\n", duration);
7442 fclose(txt);
7443 if (vm_lock_path(dir)) {
7444 ast_log(AST_LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
7445 /* Delete files */
7446 ast_filedelete(tmptxtfile, NULL);
7447 unlink(tmptxtfile);
7448 inprocess_count(vmu->mailbox, vmu->context, -1);
7449 } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
7450 ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
7451 unlink(tmptxtfile);
7452 ast_unlock_path(dir);
7453 inprocess_count(vmu->mailbox, vmu->context, -1);
7454 if (ast_check_realtime("voicemail_data")) {
7455 ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
7456 }
7457 } else {
7458#ifndef IMAP_STORAGE
7459 msgnum = LAST_MSG_INDEX(dir) + 1;
7460#endif
7461 make_file(fn, sizeof(fn), dir, msgnum);
7462
7463 /* assign a variable with the name of the voicemail file */
7464#ifndef IMAP_STORAGE
7465 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
7466#else
7467 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
7468#endif
7469
7470 snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
7471
7472 ast_trace(-1, "Renaming recordings '%s' -> fn '%s'\n", tmptxtfile, fn);
7473 /* ast_filerename renames the recordings but not the txt file */
7474 ast_filerename(tmptxtfile, fn, NULL);
7475
7476 ast_trace(-1, "Renaming txt file '%s' -> fn '%s'\n", tmptxtfile, txtfile);
7477 rename(tmptxtfile, txtfile);
7478 inprocess_count(vmu->mailbox, vmu->context, -1);
7479
7480 /* Properly set permissions on voicemail text descriptor file.
7481 Unfortunately mkstemp() makes this file 0600 on most unix systems. */
7482 if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
7483 ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
7484
7485 ast_unlock_path(dir);
7486 if (ast_check_realtime("voicemail_data")) {
7487 snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
7488 ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
7489 }
7490 /* We must store the file first, before copying the message, because
7491 * ODBC storage does the entire copy with SQL.
7492 */
7493 if (ast_fileexists(fn, NULL, NULL) > 0) {
7494 SCOPE_CALL(-1, STORE, dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag, msg_id);
7495 }
7496
7497 /* Are there to be more recipients of this message? */
7498 while (tmpptr) {
7499 struct ast_vm_user recipu, *recip;
7500 char *exten, *cntx;
7501
7502 exten = strsep(&tmpptr, "&");
7503 cntx = strchr(exten, '@');
7504 if (cntx) {
7505 *cntx = '\0';
7506 cntx++;
7507 }
7508 memset(&recipu, 0, sizeof(recipu));
7509 if ((recip = find_user(&recipu, cntx, exten))) {
7510 copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag, NULL);
7511 free_user(recip);
7512 }
7513 }
7514
7515 /* Notification needs to happen after the copy, though. */
7516 if (ast_fileexists(fn, NULL, NULL)) {
7517#ifdef IMAP_STORAGE
7518 notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
7519 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
7520 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
7521 flag);
7522#else
7523 notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
7524 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
7525 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL),
7526 flag);
7527#endif
7528 }
7529
7530 /* Disposal needs to happen after the optional move and copy */
7531 if (ast_fileexists(fn, NULL, NULL)) {
7532 SCOPE_CALL(-1, DISPOSE, dir, msgnum);
7533 }
7534 }
7535 }
7536 } else {
7537 inprocess_count(vmu->mailbox, vmu->context, -1);
7538 }
7539 if (res == '0') {
7540 goto transfer;
7541 } else if (res > 0 && res != 't')
7542 res = 0;
7543
7544 if (sound_duration < vmu->minsecs)
7545 /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
7546 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
7547 else
7548 pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
7549 } else
7550 ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
7551leave_vm_out:
7552 free_user(vmu);
7553
7554#ifdef IMAP_STORAGE
7555 /* expunge message - use UID Expunge if supported on IMAP server*/
7556 ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
7557 if (expungeonhangup == 1 && vms->mailstream != NULL) {
7558 ast_mutex_lock(&vms->lock);
7559#ifdef HAVE_IMAP_TK2006
7560 if (LEVELUIDPLUS (vms->mailstream)) {
7561 mail_expunge_full(vms->mailstream, NIL, EX_UID);
7562 } else
7563#endif
7564 mail_expunge(vms->mailstream);
7565 ast_mutex_unlock(&vms->lock);
7566 }
7567#endif
7568
7569 ast_free(tmp);
7570 SCOPE_EXIT_RTN_VALUE(res, "Done: '%d'\n", res);
7571}
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
#define COUNT(a, b)
#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:1273
static int transfer(void *data)
Definition: chan_pjsip.c:2132
#define ast_channel_lock(chan)
Definition: channel.h:2968
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2824
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
Definition: main/config.c:3791
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: main/config.c:3674
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_trace, ast_unlock_path(), ast_update_realtime(), ast_verb, ast_waitstream(), ast_vm_user::context, voicemailpwcheck::context, copy_message(), COUNT, 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_MSG_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, SCOPE_CALL, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, 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 14762 of file app_voicemail_odbc.c.

14763{
14764 struct ast_variable *var;
14765
14767 return;
14768 }
14770 while (var) {
14771 struct alias_mailbox_mapping *mapping = alias_mailbox_mapping_create(var->name, var->value);
14772 if (mapping) {
14775 ao2_ref(mapping, -1);
14776 }
14777 var = var->next;
14778 }
14779}
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 14730 of file app_voicemail_odbc.c.

14731{
14732 return load_config_force(reload, 0);
14733}
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 14689 of file app_voicemail_odbc.c.

14690{
14691 struct ast_config *cfg, *ucfg;
14692 struct ast_flags config_flags = { reload && !force ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14693 int res;
14694
14695 ast_unload_realtime("voicemail");
14696 ast_unload_realtime("voicemail_data");
14697
14698 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
14699 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
14700 return 0;
14701 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
14702 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
14703 ucfg = NULL;
14704 }
14706 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
14707 ast_config_destroy(ucfg);
14708 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
14709 return 0;
14710 }
14711 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
14712 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
14713 return 0;
14714 } else {
14716 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
14717 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
14718 ucfg = NULL;
14719 }
14720 }
14721
14722 res = actual_load_config(reload, cfg, ucfg);
14723
14724 ast_config_destroy(cfg);
14725 ast_config_destroy(ucfg);
14726
14727 return res;
14728}
#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:3591
#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 16304 of file app_voicemail_odbc.c.

16305{
16306 int res;
16307 my_umask = umask(0);
16308 umask(my_umask);
16309
16312 if (!inprocess_container) {
16314 }
16315
16317 alias_mailbox_mapping_hash_fn, NULL, alias_mailbox_mapping_cmp_fn);
16319 ast_log(LOG_ERROR, "Unable to create alias_mailbox_mappings container\n");
16322 }
16323 res = ao2_container_register("voicemail_alias_mailbox_mappings", alias_mailbox_mappings, print_mappings);
16324 if (res) {
16325 ast_log(LOG_ERROR, "Unable to register alias_mailbox_mappings container\n");
16329 }
16330
16332 mailbox_alias_mapping_hash_fn, NULL, mailbox_alias_mapping_cmp_fn);
16334 ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");
16336 ao2_container_unregister("voicemail_alias_mailbox_mappings");
16339 }
16340 res = ao2_container_register("voicemail_mailbox_alias_mappings", mailbox_alias_mappings, print_mappings);
16341 if (res) {
16342 ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");
16344 ao2_container_unregister("voicemail_alias_mailbox_mappings");
16348 }
16349
16350 /* compute the location of the voicemail spool directory */
16351 snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
16352
16353 if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
16354 ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor. MWI will not work\n");
16355 }
16356
16357 if ((res = load_config(0))) {
16358 unload_module();
16360 }
16361
16375#ifdef TEST_FRAMEWORK
16376 res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
16377 res |= AST_TEST_REGISTER(test_voicemail_msgcount);
16378 res |= AST_TEST_REGISTER(test_voicemail_vmuser);
16379 res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
16380 res |= AST_TEST_REGISTER(test_voicemail_load_config);
16381 res |= AST_TEST_REGISTER(test_voicemail_vm_info);
16382#endif
16383
16384 if (res) {
16385 ast_log(LOG_ERROR, "Failure registering applications, functions or tests\n");
16386 unload_module();
16388 }
16389
16390 /* ast_vm_register may return DECLINE if another module registered for vm */
16391 res = ast_vm_register(&vm_table);
16392 if (res) {
16393 ast_log(LOG_ERROR, "Failure registering as a voicemail provider\n");
16394 unload_module();
16396 }
16397
16398 /* ast_vm_greeter_register may return DECLINE if another module registered as a greeter */
16400 if (res) {
16401 ast_log(LOG_ERROR, "Failure registering as a greeter provider\n");
16402 unload_module();
16404 }
16405
16407
16408#ifdef TEST_FRAMEWORK
16409 ast_install_vm_test_functions(vm_test_create_user, vm_test_destroy_user);
16410#endif
16411
16412 ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
16413 ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
16414
16416}
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:640
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 14816 of file app_voicemail_odbc.c.

14817{
14818 struct ast_variable *var;
14819 char *cat = NULL;
14820
14821 while ((cat = ast_category_browse(cfg, cat))) {
14822 if (strcasecmp(cat, "general") == 0
14823 || strcasecmp(cat, aliasescontext) == 0
14824 || strcasecmp(cat, "zonemessages") == 0) {
14825 continue;
14826 }
14827
14828 var = ast_variable_browse(cfg, cat);
14829 while (var) {
14830 append_mailbox(cat, var->name, var->value);
14831 var = var->next;
14832 }
14833 }
14834}
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 14781 of file app_voicemail_odbc.c.

14782{
14783 struct ast_variable *var;
14784
14785 var = ast_variable_browse(cfg, "zonemessages");
14786 while (var) {
14787 if (var->value) {
14788 struct vm_zone *z;
14789 char *msg_format, *tzone;
14790 char storage[strlen(var->value) + 1];
14791
14792 z = ast_malloc(sizeof(*z));
14793 if (!z) {
14794 return;
14795 }
14796
14797 strcpy(storage, var->value); /* safe */
14798 msg_format = storage;
14799 tzone = strsep(&msg_format, "|,");
14800 if (msg_format) {
14801 ast_copy_string(z->name, var->name, sizeof(z->name));
14802 ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
14807 } else {
14808 ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
14809 ast_free(z);
14810 }
14811 }
14812 var = var->next;
14813 }
14814}
#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 2189 of file app_voicemail_odbc.c.

2190{
2191 return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
2192}

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 5434 of file app_voicemail_odbc.c.

5453{
5454 char date[256];
5455 char host[MAXHOSTNAMELEN] = "";
5456 char who[256];
5457 char bound[256];
5458 char dur[256];
5459 struct ast_tm tm;
5460 char enc_cidnum[256] = "", enc_cidname[256] = "";
5461 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
5462 char *greeting_attachment;
5463 char filename[256];
5464 int first_line;
5465 char *emailsbuf;
5466 char *email;
5467
5468 if (!str1 || !str2) {
5469 ast_free(str1);
5470 ast_free(str2);
5471 return;
5472 }
5473
5474 if (cidnum) {
5475 strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
5476 }
5477 if (cidname) {
5478 strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
5479 }
5480 gethostname(host, sizeof(host) - 1);
5481
5482 if (strchr(srcemail, '@')) {
5483 ast_copy_string(who, srcemail, sizeof(who));
5484 } else {
5485 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
5486 }
5487
5488 greeting_attachment = strrchr(ast_strdupa(attach), '/');
5489 if (greeting_attachment) {
5490 *greeting_attachment++ = '\0';
5491 }
5492
5493 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
5494 ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
5495 fprintf(p, "Date: %s" ENDL, date);
5496
5497 /* Set date format for voicemail mail */
5498 ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
5499
5501 struct ast_channel *ast;
5502 char *e_fromstring = !ast_strlen_zero(vmu->fromstring) ? vmu->fromstring : fromstring;
5503 if ((ast = ast_dummy_channel_alloc())) {
5504 char *ptr;
5505 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5506 ast_str_substitute_variables(&str1, 0, ast, e_fromstring);
5507
5508 if (check_mime(ast_str_buffer(str1))) {
5509 first_line = 1;
5510 ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
5511 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5512 *ptr = '\0';
5513 fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
5514 first_line = 0;
5515 /* Substring is smaller, so this will never grow */
5516 ast_str_set(&str2, 0, "%s", ptr + 1);
5517 }
5518 fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
5519 } else {
5520 fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
5521 }
5522 ast = ast_channel_unref(ast);
5523 } else {
5524 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5525 }
5526 } else {
5527 fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
5528 }
5529
5530 emailsbuf = ast_strdupa(vmu->email);
5531 fprintf(p, "To:");
5532 first_line = 1;
5533 while ((email = strsep(&emailsbuf, "|"))) {
5534 char *next = emailsbuf;
5535 if (check_mime(vmu->fullname)) {
5536 char *ptr;
5537 ast_str_encode_mime(&str2, 0, vmu->fullname, first_line ? strlen("To: ") : 0, strlen(email) + 3 + (next ? strlen(",") : 0));
5538 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5539 *ptr = '\0';
5540 fprintf(p, " %s" ENDL, ast_str_buffer(str2));
5541 /* Substring is smaller, so this will never grow */
5542 ast_str_set(&str2, 0, "%s", ptr + 1);
5543 }
5544 fprintf(p, " %s <%s>%s" ENDL, ast_str_buffer(str2), email, next ? "," : "");
5545 } else {
5546 fprintf(p, " %s <%s>%s" ENDL, ast_str_quote(&str2, 0, vmu->fullname), email, next ? "," : "");
5547 }
5548 first_line = 0;
5549 }
5550
5551 if (msgnum <= -1) {
5552 fprintf(p, "Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
5554 char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
5555 struct ast_channel *ast;
5556 if ((ast = ast_dummy_channel_alloc())) {
5557 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5558 ast_str_substitute_variables(&str1, 0, ast, e_subj);
5559 if (check_mime(ast_str_buffer(str1))) {
5560 char *ptr;
5561 first_line = 1;
5562 ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
5563 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5564 *ptr = '\0';
5565 fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5566 first_line = 0;
5567 /* Substring is smaller, so this will never grow */
5568 ast_str_set(&str2, 0, "%s", ptr + 1);
5569 }
5570 fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
5571 } else {
5572 fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
5573 }
5574 ast = ast_channel_unref(ast);
5575 } else {
5576 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5577 }
5578 } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
5579 if (ast_strlen_zero(flag)) {
5580 fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5581 } else {
5582 fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
5583 }
5584 } else {
5585 if (ast_strlen_zero(flag)) {
5586 fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5587 } else {
5588 fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
5589 }
5590 }
5591
5592 fprintf(p, "Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
5593 (unsigned int) ast_random(), mailbox, (int) getpid(), host);
5594 if (imap) {
5595 /* additional information needed for IMAP searching */
5596 fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
5597 /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
5598 fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
5599 fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
5600#ifdef IMAP_STORAGE
5601 fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
5602#else
5603 fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
5604#endif
5605 /* flag added for Urgent */
5606 fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, S_OR(flag, ""));
5607 fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan ? ast_channel_priority(chan) : 0);
5608 fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
5609 fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
5610 fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
5611 if (!ast_strlen_zero(category)) {
5612 fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
5613 } else {
5614 fprintf(p, "X-Asterisk-VM-Category: " ENDL);
5615 }
5616 fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
5617 fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
5618 fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
5619 fprintf(p, "X-Asterisk-VM-Message-ID: %s" ENDL, msg_id);
5620 }
5621 if (!ast_strlen_zero(cidnum)) {
5622 fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
5623 }
5624 if (!ast_strlen_zero(cidname)) {
5625 fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
5626 }
5627 fprintf(p, "MIME-Version: 1.0" ENDL);
5628 if (attach_user_voicemail) {
5629 /* Something unique. */
5630 snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%u", msgnum + 1, mailbox,
5631 (int) getpid(), (unsigned int) ast_random());
5632
5633 fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
5634 fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
5635 fprintf(p, "--%s" ENDL, bound);
5636 }
5637 fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
5638 if (msgnum <= -1) {
5639 fprintf(p, "This message is to let you know that your greeting '%s' was changed on %s." ENDL
5640 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
5641 greeting_attachment, date);
5642 } else if (emailbody || vmu->emailbody) {
5643 char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
5644 struct ast_channel *ast;
5645 if ((ast = ast_dummy_channel_alloc())) {
5646 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5647 ast_str_substitute_variables(&str1, 0, ast, e_body);
5648#ifdef IMAP_STORAGE
5649 {
5650 /* Convert body to native line terminators for IMAP backend */
5651 char *line = ast_str_buffer(str1), *next;
5652 do {
5653 /* Terminate line before outputting it to the file */
5654 if ((next = strchr(line, '\n'))) {
5655 *next++ = '\0';
5656 }
5657 fprintf(p, "%s" ENDL, line);
5658 line = next;
5659 } while (!ast_strlen_zero(line));
5660 }
5661#else
5662 fprintf(p, "%s" ENDL, ast_str_buffer(str1));
5663#endif
5664 ast = ast_channel_unref(ast);
5665 } else {
5666 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5667 }
5668 } else {
5669 if (strcmp(vmu->mailbox, mailbox)) {
5670 /* Forwarded type */
5671 struct ast_config *msg_cfg;
5672 const char *v;
5673 int inttime;
5674 char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
5675 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
5676 /* Retrieve info from VM attribute file */
5677 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
5678 make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
5679 if (strlen(fromfile) < sizeof(fromfile) - 5) {
5680 strcat(fromfile, ".txt");
5681 }
5682 if ((msg_cfg = ast_config_load(fromfile, config_flags)) && valid_config(msg_cfg)) {
5683 if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
5684 ast_copy_string(origcallerid, v, sizeof(origcallerid));
5685 }
5686
5687 /* You might be tempted to do origdate, except that a) it's in the wrong
5688 * format, and b) it's missing for IMAP recordings. */
5689 if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
5690 struct timeval tv = { inttime, };
5691 struct ast_tm tm;
5692 ast_localtime(&tv, &tm, NULL);
5693 ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
5694 }
5695 fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
5696 " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
5697 "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
5698 " chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
5699 msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
5700 date, origcallerid, origdate);
5701 ast_config_destroy(msg_cfg);
5702 } else {
5703 goto plain_message;
5704 }
5705 } else {
5706plain_message:
5707 fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
5708 "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
5709 "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
5710 ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
5711 (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
5712 }
5713 }
5714
5715 if (imap || attach_user_voicemail) {
5716 if (!ast_strlen_zero(attach2)) {
5717 snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
5718 ast_debug(5, "creating second attachment filename %s\n", filename);
5719 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
5720 snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
5721 ast_debug(5, "creating attachment filename %s\n", filename);
5722 add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5723 } else {
5724 snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
5725 ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
5726 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5727 }
5728 }
5729 ast_free(str1);
5730 ast_free(str2);
5731}
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:3004
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1328
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 2206 of file app_voicemail_odbc.c.

2207{
2208 return snprintf(dest, len, "%s/msg%04d", dir, num);
2209}

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 14463 of file app_voicemail_odbc.c.

14464{
14465 struct ast_vm_user *vmu = NULL;
14466 const char *id = astman_get_header(m, "ActionID");
14467 char actionid[128];
14468 struct ast_vm_user svm;
14469
14470 const char *context = astman_get_header(m, "Context");
14471 const char *mailbox = astman_get_header(m, "Mailbox");
14472
14474 astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters.");
14475 return 0;
14476 }
14477
14478 actionid[0] = '\0';
14479 if (!ast_strlen_zero(id)) {
14480 snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
14481 }
14482
14483 /* find user */
14484 memset(&svm, 0, sizeof(svm));
14485 vmu = find_user(&svm, context, mailbox);
14486 if (!vmu) {
14487 /* could not find it */
14488 astman_send_ack(s, m, "There is no voicemail user matching the given user.");
14489 return 0;
14490 }
14491
14492 /* Append the mailbox details */
14493 if (!append_vmbox_info_astman(s, m, vmu, "VoicemailBoxDetail", actionid)) {
14494 astman_send_error(s, m, "Unable to get mailbox info for the given user.");
14495 }
14496
14497 free_user(vmu);
14498 return 0;
14499}
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:1969
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630

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 14422 of file app_voicemail_odbc.c.

14423{
14424 struct ast_vm_user *vmu = NULL;
14425 const char *id = astman_get_header(m, "ActionID");
14426 char actionid[128];
14427 int num_users = 0;
14428 int ret;
14429
14430 actionid[0] = '\0';
14431 if (!ast_strlen_zero(id)) {
14432 snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
14433 }
14434
14436
14437 if (AST_LIST_EMPTY(&users)) {
14438 astman_send_ack(s, m, "There are no voicemail users currently defined.");
14440 return RESULT_SUCCESS;
14441 }
14442
14443 astman_send_listack(s, m, "Voicemail user list will follow", "start");
14444
14445 AST_LIST_TRAVERSE(&users, vmu, list) {
14446 /* append vmu info event */
14447 ret = append_vmu_info_astman(s, vmu, "VoicemailUserEntry", actionid);
14448 if(ret == 0) {
14449 ast_log(LOG_ERROR, "Could not append voicemail user info.");
14450 continue;
14451 }
14452 ++num_users;
14453 }
14454
14455 astman_send_list_complete_start(s, m, "VoicemailUserEntryComplete", num_users);
14457
14459
14460 return RESULT_SUCCESS;
14461}
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 14338 of file app_voicemail_odbc.c.

14339{
14340 const char *context = astman_get_header(data, "Context");
14341 const char *mailbox = astman_get_header(data, "Mailbox");
14342 const char *at;
14343
14344 if (!ast_strlen_zero(mwi_state->uniqueid)) {
14345 if (
14346 /* First case: everything matches */
14348 /* Second case: match the mailbox only */
14350 (at = strchr(mwi_state->uniqueid, '@')) &&
14351 strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0) ||
14352 /* Third case: match the context only */
14354 (at = strchr(mwi_state->uniqueid, '@')) &&
14355 strcmp(context, at + 1) == 0) ||
14356 /* Final case: match an exact specified mailbox */
14358 (at = strchr(mwi_state->uniqueid, '@')) &&
14359 strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0 &&
14360 strcmp(context, at + 1) == 0)
14361 ) {
14362 poll_subscribed_mailbox(mwi_state, NULL);
14363 }
14364 }
14365
14366 return 0;
14367}
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 14376 of file app_voicemail_odbc.c.

14377{
14378 struct ast_vm_user *vmu = NULL;
14379 const char *id = astman_get_header(m, "ActionID");
14380 char actionid[128];
14381 struct ast_vm_user svm;
14382 int ret;
14383
14384 const char *context = astman_get_header(m, "Context");
14385 const char *mailbox = astman_get_header(m, "Mailbox");
14386
14388 astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters.");
14389 return RESULT_SUCCESS;
14390 }
14391
14392 actionid[0] = '\0';
14393 if (!ast_strlen_zero(id)) {
14394 snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
14395 }
14396
14397 /* find user */
14398 memset(&svm, 0, sizeof(svm));
14399 vmu = find_user(&svm, context, mailbox);
14400 if (!vmu) {
14401 /* could not find it */
14402 astman_send_ack(s, m, "There is no voicemail user of the given info.");
14403 return RESULT_SUCCESS;
14404 }
14405
14406 astman_send_listack(s, m, "Voicemail user detail will follow", "start");
14407
14408 /* append vmu info event */
14409 ret = append_vmu_info_astman(s, vmu, "VoicemailUserDetail", actionid);
14410 free_user(vmu);
14411 if(ret == 0) {
14412 ast_log(LOG_ERROR, "Could not append voicemail user info.");
14413 }
14414
14415 astman_send_list_complete_start(s, m, "VoicemailUserDetailComplete", 1);
14417
14418 return RESULT_SUCCESS;
14419}

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 14572 of file app_voicemail_odbc.c.

14573{
14574 const char *from_mailbox = astman_get_header(m, "Mailbox");
14575 const char *from_context = astman_get_header(m, "Context");
14576 const char *from_folder = astman_get_header(m, "Folder");
14577 const char *id[] = { astman_get_header(m, "ID") };
14578 const char *to_mailbox = astman_get_header(m, "ToMailbox");
14579 const char *to_context = astman_get_header(m, "ToContext");
14580 const char *to_folder = astman_get_header(m, "ToFolder");
14581
14583 astman_send_error(s, m, "Mailbox not specified, required");
14584 return 0;
14585 }
14586 if (ast_strlen_zero(from_context)) {
14587 astman_send_error(s, m, "Context not specified, required");
14588 return 0;
14589 }
14590 if (ast_strlen_zero(from_folder)) {
14591 astman_send_error(s, m, "Folder not specified, required");
14592 return 0;
14593 }
14594 if (ast_strlen_zero(id[0])) {
14595 astman_send_error(s, m, "ID not specified, required");
14596 return 0;
14597 }
14598 if (ast_strlen_zero(to_mailbox)) {
14599 astman_send_error(s, m, "ToMailbox not specified, required");
14600 return 0;
14601 }
14602 if (ast_strlen_zero(to_context)) {
14603 astman_send_error(s, m, "ToContext not specified, required");
14604 return 0;
14605 }
14606 if (ast_strlen_zero(to_folder)) {
14607 astman_send_error(s, m, "ToFolder not specified, required");
14608 return 0;
14609 }
14610
14611 if (vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0)) {
14612 astman_send_ack(s, m, "Message forward failed\n");
14613 } else {
14614 astman_send_ack(s, m, "Message forward successful\n");
14615 }
14616
14617 return 0;
14618}

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 14501 of file app_voicemail_odbc.c.

14502{
14503 const char *mailbox = astman_get_header(m, "Mailbox");
14504 const char *context = astman_get_header(m, "Context");
14505 const char *from_folder = astman_get_header(m, "Folder");
14506 const char *id[] = { astman_get_header(m, "ID") };
14507 const char *to_folder = astman_get_header(m, "ToFolder");
14508
14509 if (ast_strlen_zero(mailbox)) {
14510 astman_send_error(s, m, "Mailbox not specified, required");
14511 return 0;
14512 }
14513 if (ast_strlen_zero(context)) {
14514 astman_send_error(s, m, "Context not specified, required");
14515 return 0;
14516 }
14517 if (ast_strlen_zero(from_folder)) {
14518 astman_send_error(s, m, "Folder not specified, required");
14519 return 0;
14520 }
14521 if (ast_strlen_zero(id[0])) {
14522 astman_send_error(s, m, "ID not specified, required");
14523 return 0;
14524 }
14525 if (ast_strlen_zero(to_folder)) {
14526 astman_send_error(s, m, "ToFolder not specified, required");
14527 return 0;
14528 }
14529
14530 if (vm_msg_move(mailbox, context, 1, from_folder, id, to_folder)) {
14531 astman_send_ack(s, m, "Message move failed\n");
14532 } else {
14533 astman_send_ack(s, m, "Message move successful\n");
14534 }
14535
14536 return 0;
14537}
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 14369 of file app_voicemail_odbc.c.

14370{
14372 astman_send_ack(s, m, "Refresh sent");
14373 return RESULT_SUCCESS;
14374}
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 14539 of file app_voicemail_odbc.c.

14540{
14541 const char *mailbox = astman_get_header(m, "Mailbox");
14542 const char *context = astman_get_header(m, "Context");
14543 const char *folder = astman_get_header(m, "Folder");
14544 const char *id[] = { astman_get_header(m, "ID") };
14545
14546 if (ast_strlen_zero(mailbox)) {
14547 astman_send_error(s, m, "Mailbox not specified, required");
14548 return 0;
14549 }
14550 if (ast_strlen_zero(context)) {
14551 astman_send_error(s, m, "Context not specified, required");
14552 return 0;
14553 }
14554 if (ast_strlen_zero(folder)) {
14555 astman_send_error(s, m, "Folder not specified, required");
14556 return 0;
14557 }
14558 if (ast_strlen_zero(id[0])) {
14559 astman_send_error(s, m, "ID not specified, required");
14560 return 0;
14561 }
14562
14563 if (vm_msg_remove(mailbox, context, 1, folder, id)) {
14564 astman_send_ack(s, m, "Message remove failed\n");
14565 } else {
14566 astman_send_ack(s, m, "Message remove successful\n");
14567 }
14568
14569 return 0;
14570}
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 14006 of file app_voicemail_odbc.c.

14007{
14008 while (poll_thread_run) {
14009 struct timespec ts = { 0, };
14010 struct timeval wait;
14011
14013
14014 if (!poll_thread_run) {
14015 break;
14016 }
14017
14019 ts.tv_sec = wait.tv_sec;
14020 ts.tv_nsec = wait.tv_usec * 1000;
14021
14025 }
14026
14027 return NULL;
14028}
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 2232 of file app_voicemail_odbc.c.

2233{
2234#ifdef IMAP_STORAGE
2235 if (vmu && id == 0) {
2236 return vmu->imapfolder;
2237 }
2238#endif
2239 return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
2240}
enum queue_result id
Definition: app_queue.c:1667

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 17282 of file app_voicemail_odbc.c.

17283{
17284 int i;
17285 int res = 0;
17286 for (i = 0; i < num_msgs; ++i) {
17287 const char *msg_id = msg_ids[i];
17288 int found = 0;
17289 for (vms->curmsg = 0; vms->curmsg <= vms->lastmsg; vms->curmsg++) {
17290 const char *other_msg_id;
17291 char filename[PATH_MAX];
17292 struct ast_config *msg_cfg;
17293 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
17294
17295 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
17296 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
17297 RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
17298 msg_cfg = ast_config_load(filename, config_flags);
17299 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
17300 DISPOSE(vms->curdir, vms->curmsg);
17301 res = -1;
17302 goto done;
17303 }
17304
17305 other_msg_id = ast_variable_retrieve(msg_cfg, "message", "msg_id");
17306
17307 if (!ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
17308 /* Message found. We can get out of this inner loop
17309 * and move on to the next message to find
17310 */
17311 found = 1;
17312 msg_nums[i] = vms->curmsg;
17313 ast_config_destroy(msg_cfg);
17314 DISPOSE(vms->curdir, vms->curmsg);
17315 break;
17316 }
17317 ast_config_destroy(msg_cfg);
17318 DISPOSE(vms->curdir, vms->curmsg);
17319 }
17320 if (!found) {
17321 /* If we can't find one of the message IDs requested, then OH NO! */
17322 res = -1;
17323 goto done;
17324 }
17325 }
17326
17327done:
17328 return res;
17329}

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 6421 of file app_voicemail_odbc.c.

6422{
6423 char *context;
6424 char *mailbox;
6425
6426 if (ast_strlen_zero(mailbox_id)
6427 || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
6428 return 0;
6429 }
6430
6431 return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
6432}

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

Referenced by acf_vm_info().

◆ move_message_from_mailbox()

static int move_message_from_mailbox ( struct ast_cli_args a)
static

Definition at line 12066 of file app_voicemail_odbc.c.

12067{
12068 const char *mailbox = a->argv[2];
12069 const char *context = a->argv[3];
12070 const char *from_folder = a->argv[4];
12071 const char *id[] = { a->argv[5] };
12072 const char *to_folder = a->argv[6];
12073 int ret = vm_msg_move(mailbox, context, 1, from_folder, id, to_folder);
12074 if (ret) {
12075 ast_cli(a->fd, "Error moving message %s from mailbox %s@%s %s to %s\n",
12076 id[0], mailbox, context, from_folder, to_folder);
12077 } else {
12078 ast_cli(a->fd, "Moved message %s from mailbox %s@%s %s to %s\n",
12079 id[0], mailbox, context, from_folder, to_folder);
12080 }
12081 return ret;
12082}

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 6688 of file app_voicemail_odbc.c.

6689{
6690 /* voicemail recipient structure */
6691 struct ast_vm_user *recipient; /* points to svm once it's been created */
6692 struct ast_vm_user svm; /* struct storing the voicemail recipient */
6693
6694 /* File paths */
6695 char tmpdir[PATH_MAX]; /* directory temp files are stored in */
6696 char tmptxtfile[PATH_MAX]; /* tmp file for voicemail txt file */
6697 char desttxtfile[PATH_MAX]; /* final destination for txt file */
6698 char tmpaudiofile[PATH_MAX]; /* tmp file where audio is stored */
6699 char dir[PATH_MAX]; /* destination for tmp files on completion */
6700 char destination[PATH_MAX]; /* destination with msgXXXX. Basically <dir>/msgXXXX */
6701
6702 /* stuff that only seems to be needed for IMAP */
6703 #ifdef IMAP_STORAGE
6704 struct vm_state *vms = NULL;
6705 char ext_context[256] = "";
6706 int newmsgs = 0;
6707 int oldmsgs = 0;
6708 #endif
6709
6710 /* miscellaneous operational variables */
6711 int res = 0; /* Used to store error codes from functions */
6712 int txtdes /* File descriptor for the text file used to write the voicemail info */;
6713 FILE *txt; /* FILE pointer to text file used to write the voicemail info */
6714 char date[256]; /* string used to hold date of the voicemail (only used for ODBC) */
6715 int msgnum; /* the 4 digit number designated to the voicemail */
6716 int duration = 0; /* Length of the audio being recorded in seconds */
6717 struct ast_filestream *recording_fs; /*used to read the recording to get duration data */
6718
6719 /* We aren't currently doing anything with category, since it comes from a channel variable and
6720 * this function doesn't use channels, but this function could add that as an argument later. */
6721 const char *category = NULL; /* pointless for now */
6722 char msg_id[MSG_ID_LEN];
6723
6724 /* Start by checking to see if the file actually exists... */
6725 if (!(ast_fileexists(recdata->recording_file, recdata->recording_ext, NULL))) {
6726 ast_log(LOG_ERROR, "File: %s not found.\n", recdata->recording_file);
6727 return -1;
6728 }
6729
6730 memset(&svm, 0, sizeof(svm));
6731 if (!(recipient = find_user(&svm, recdata->context, recdata->mailbox))) {
6732 ast_log(LOG_ERROR, "No entry in voicemail config file for '%s@%s'\n", recdata->mailbox, recdata->context);
6733 return -1;
6734 }
6735
6736 /* determine duration in seconds */
6737 if ((recording_fs = ast_readfile(recdata->recording_file, recdata->recording_ext, NULL, 0, 0, VOICEMAIL_DIR_MODE))) {
6738 if (!ast_seekstream(recording_fs, 0, SEEK_END)) {
6739 long framelength = ast_tellstream(recording_fs);
6740 int sample_rate = ast_ratestream(recording_fs);
6741 if (sample_rate) {
6742 duration = (int) (framelength / sample_rate);
6743 } else {
6744 ast_log(LOG_ERROR,"Unable to determine sample rate of recording %s\n", recdata->recording_file);
6745 }
6746 }
6747 ast_closestream(recording_fs);
6748 }
6749
6750 /* If the duration was below the minimum duration for the user, let's just drop the whole thing now */
6751 if (duration < recipient->minsecs) {
6752 ast_log(LOG_NOTICE, "Copying recording to voicemail %s@%s skipped because duration was shorter than "
6753 "minmessage of recipient\n", recdata->mailbox, recdata->context);
6754 return -1;
6755 }
6756
6757 /* Note that this number must be dropped back to a net sum of zero before returning from this function */
6758
6759 if ((res = create_dirpath(tmpdir, sizeof(tmpdir), recipient->context, recdata->mailbox, "tmp"))) {
6760 ast_log(LOG_ERROR, "Failed to make directory.\n");
6761 }
6762
6763 snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
6764 txtdes = mkstemp(tmptxtfile);
6765 if (txtdes < 0) {
6766 chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
6767 /* Something screwed up. Abort. */
6768 ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
6769 free_user(recipient);
6770 return -1;
6771 }
6772
6773 /* Store information */
6774 txt = fdopen(txtdes, "w+");
6775 if (txt) {
6776 generate_msg_id(msg_id);
6777 get_date(date, sizeof(date));
6778 fprintf(txt,
6779 ";\n"
6780 "; Message Information file\n"
6781 ";\n"
6782 "[message]\n"
6783 "origmailbox=%s\n"
6784 "context=%s\n"
6785 "exten=%s\n"
6786 "rdnis=Unknown\n"
6787 "priority=%d\n"
6788 "callerchan=%s\n"
6789 "callerid=%s\n"
6790 "origdate=%s\n"
6791 "origtime=%ld\n"
6792 "category=%s\n"
6793 "msg_id=%s\n"
6794 "flag=\n" /* flags not supported in copy from file yet */
6795 "duration=%d\n", /* Don't have any reliable way to get duration of file. */
6796
6797 recdata->mailbox,
6798 S_OR(recdata->call_context, ""),
6799 S_OR(recdata->call_extension, ""),
6800 recdata->call_priority,
6801 S_OR(recdata->call_callerchan, "Unknown"),
6802 S_OR(recdata->call_callerid, "Unknown"),
6803 date, (long) time(NULL),
6804 S_OR(category, ""),
6805 msg_id,
6806 duration);
6807
6808 /* Since we are recording from a file, we shouldn't need to do anything else with
6809 * this txt file */
6810 fclose(txt);
6811
6812 } else {
6813 ast_log(LOG_WARNING, "Error opening text file for output\n");
6814 if (ast_check_realtime("voicemail_data")) {
6815 ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
6816 }
6817 free_user(recipient);
6818 return -1;
6819 }
6820
6821 /* At this point, the actual creation of a voicemail message should be finished.
6822 * Now we just need to copy the files being recorded into the receiving folder. */
6823
6824 create_dirpath(dir, sizeof(dir), recipient->context, recipient->mailbox, recdata->folder);
6825
6826#ifdef IMAP_STORAGE
6827 /* make recipient info into an inboxcount friendly string */
6828 snprintf(ext_context, sizeof(ext_context), "%s@%s", recipient->mailbox, recipient->context);
6829
6830 /* Is ext a mailbox? */
6831 /* must open stream for this user to get info! */
6832 res = inboxcount(ext_context, &newmsgs, &oldmsgs);
6833 if (res < 0) {
6834 ast_log(LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
6835 free_user(recipient);
6836 unlink(tmptxtfile);
6837 return -1;
6838 }
6839 if (!(vms = get_vm_state_by_mailbox(recipient->mailbox, recipient->context, 0))) {
6840 /* It is possible under certain circumstances that inboxcount did not
6841 * create a vm_state when it was needed. This is a catchall which will
6842 * rarely be used.
6843 */
6844 if (!(vms = create_vm_state_from_user(recipient))) {
6845 ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
6846 free_user(recipient);
6847 unlink(tmptxtfile);
6848 return -1;
6849 }
6850 }
6851 vms->newmessages++;
6852
6853 /* here is a big difference! We add one to it later */
6854 msgnum = newmsgs + oldmsgs;
6855 ast_debug(3, "Messagecount set to %d\n", msgnum);
6856 snprintf(destination, sizeof(destination), "%simap/msg%s%04d", VM_SPOOL_DIR, recipient->mailbox, msgnum);
6857
6858 /* Check to see if we have enough room in the mailbox. If not, spit out an error and end
6859 * Note that imap_check_limits raises inprocess_count if successful */
6860 if ((res = imap_check_limits(NULL, vms, recipient, msgnum))) {
6861 ast_log(LOG_NOTICE, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context);
6862 inprocess_count(recipient->mailbox, recipient->context, -1);
6863 free_user(recipient);
6864 unlink(tmptxtfile);
6865 return -1;
6866 }
6867
6868#else
6869
6870 /* Check to see if the mailbox is full for ODBC/File storage */
6871 ast_debug(3, "mailbox = %d : inprocess = %d\n", COUNT(recipient, dir),
6872 inprocess_count(recipient->mailbox, recipient->context, 0));
6873 if (COUNT(recipient, dir) > recipient->maxmsg - inprocess_count(recipient->mailbox, recipient->context, +1)) {
6874 ast_log(AST_LOG_WARNING, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context);
6875 inprocess_count(recipient->mailbox, recipient->context, -1);
6876 free_user(recipient);
6877 unlink(tmptxtfile);
6878 return -1;
6879 }
6880
6881 msgnum = LAST_MSG_INDEX(dir) + 1;
6882#endif
6883
6884 /* Lock the directory receiving the voicemail since we want it to still exist when we attempt to copy the voicemail.
6885 * We need to unlock it before we return. */
6886 if (vm_lock_path(dir)) {
6887 ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6888 /* Delete files */
6889 ast_filedelete(tmptxtfile, NULL);
6890 unlink(tmptxtfile);
6891 free_user(recipient);
6892 return -1;
6893 }
6894
6895 make_file(destination, sizeof(destination), dir, msgnum);
6896
6897 make_file(tmpaudiofile, sizeof(tmpaudiofile), tmpdir, msgnum);
6898
6899 if (ast_filecopy(recdata->recording_file, tmpaudiofile, recdata->recording_ext)) {
6900 ast_log(LOG_ERROR, "Audio file failed to copy to tmp dir. Probably low disk space.\n");
6901
6902 inprocess_count(recipient->mailbox, recipient->context, -1);
6903 ast_unlock_path(dir);
6904 free_user(recipient);
6905 unlink(tmptxtfile);
6906 return -1;
6907 }
6908
6909 /* Alright, try to copy to the destination folder now. */
6910 if (ast_filerename(tmpaudiofile, destination, recdata->recording_ext)) {
6911 ast_log(LOG_ERROR, "Audio file failed to move to destination directory. Permissions/Overlap?\n");
6912 inprocess_count(recipient->mailbox, recipient->context, -1);
6913 ast_unlock_path(dir);
6914 free_user(recipient);
6915 unlink(tmptxtfile);
6916 return -1;
6917 }
6918
6919 snprintf(desttxtfile, sizeof(desttxtfile), "%s.txt", destination);
6920 rename(tmptxtfile, desttxtfile);
6921
6922 if (chmod(desttxtfile, VOICEMAIL_FILE_MODE) < 0) {
6923 ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", desttxtfile, strerror(errno));
6924 }
6925
6926
6927 ast_unlock_path(dir);
6928 inprocess_count(recipient->mailbox, recipient->context, -1);
6929
6930 /* If we copied something, we should store it either to ODBC or IMAP if we are using those. The STORE macro allows us
6931 * 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
6932 * time to create the voicemail database entry. */
6933 if (ast_fileexists(destination, NULL, NULL) > 0) {
6934 struct ast_channel *chan = NULL;
6935 char fmt[80];
6936 char clid[80];
6937 char cidnum[80], cidname[80];
6938 int send_email;
6939
6940 if (ast_check_realtime("voicemail_data")) {
6941 get_date(date, sizeof(date));
6942 ast_store_realtime("voicemail_data",
6943 "origmailbox", recdata->mailbox,
6944 "context", S_OR(recdata->context, ""),
6945 "exten", S_OR(recdata->call_extension, ""),
6946 "priority", recdata->call_priority,
6947 "callerchan", S_OR(recdata->call_callerchan, "Unknown"),
6948 "callerid", S_OR(recdata->call_callerid, "Unknown"),
6949 "origdate", date,
6950 "origtime", time(NULL),
6951 "category", S_OR(category, ""),
6952 "filename", tmptxtfile,
6953 "duration", duration,
6954 SENTINEL);
6955 }
6956
6957 STORE(dir, recipient->mailbox, recipient->context, msgnum, NULL, recipient, fmt, 0, vms, "", msg_id);
6958
6959 send_email = ast_test_flag(recipient, VM_EMAIL_EXT_RECS);
6960
6961 if (send_email) {
6962 /* Send an email if possible, fall back to just notifications if not. */
6963 ast_copy_string(fmt, recdata->recording_ext, sizeof(fmt));
6964 ast_copy_string(clid, recdata->call_callerid, sizeof(clid));
6965 ast_callerid_split(clid, cidname, sizeof(cidname), cidnum, sizeof(cidnum));
6966
6967 /* recdata->call_callerchan itself no longer exists, so we can't use the real channel. Use a dummy one. */
6968 chan = ast_dummy_channel_alloc();
6969 }
6970 if (chan) {
6971 notify_new_message(chan, recipient, NULL, msgnum, duration, fmt, cidnum, cidname, "");
6972 ast_channel_unref(chan);
6973 } else {
6974 if (send_email) { /* We tried and failed. */
6975 ast_log(LOG_WARNING, "Failed to allocate dummy channel, email will not be sent\n");
6976 }
6977 notify_new_state(recipient);
6978 }
6979 }
6980
6981 free_user(recipient);
6982 unlink(tmptxtfile);
6983 return 0;
6984}
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:1292
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, create_dirpath(), errno, find_user(), ast_vm_recording_data::folder, free_user(), generate_msg_id(), get_date(), inboxcount(), inprocess_count(), LAST_MSG_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 14113 of file app_voicemail_odbc.c.

14114{
14115 void *data = ast_mwi_subscriber_data(sub);
14116
14117 /* Don't bump data's reference. We'll just use the one returned above */
14119 /* A reference was returned for data when retrieving, so remove it on error */
14120 ao2_ref(data, -1);
14121 }
14122}
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 14106 of file app_voicemail_odbc.c.

14107{
14109 ao2_ref(data, -1);
14110 return 0;
14111}

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 14095 of file app_voicemail_odbc.c.

14096{
14097 void *data = ast_mwi_subscriber_data(sub);
14098
14099 /* Don't bump data's reference. We'll just use the one returned above */
14101 /* A reference was returned for data when retrieving, so remove it on error */
14102 ao2_ref(data, -1);
14103 }
14104}
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 14076 of file app_voicemail_odbc.c.

14077{
14078 struct ast_mwi_state *mwi_state = data;
14079
14080 /*
14081 * Go ahead and clear the implicit MWI publisher here to avoid a leak. If a backing
14082 * configuration is available it'll re-initialize (reset the cached state) on its
14083 * next publish.
14084 */
14086
14087#ifdef IMAP_STORAGE
14088 imap_close_subscribed_mailbox(mwi_state, NULL);
14089#endif
14090
14091 ao2_ref(mwi_state, -1);
14092 return 0;
14093}
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 8572 of file app_voicemail_odbc.c.

8573{
8574 char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
8575 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8576 const char *category;
8577 char *myserveremail = serveremail;
8578
8579 ast_channel_lock(chan);
8580 if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
8581 category = ast_strdupa(category);
8582 }
8583 ast_channel_unlock(chan);
8584
8585#ifndef IMAP_STORAGE
8586 make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
8587#else
8588 snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
8589#endif
8590 make_file(fn, sizeof(fn), todir, msgnum);
8591 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
8592
8593 if (!ast_strlen_zero(vmu->attachfmt)) {
8594 if (strstr(fmt, vmu->attachfmt))
8595 fmt = vmu->attachfmt;
8596 else
8597 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);
8598 }
8599
8600 /* Attach only the first format */
8601 fmt = ast_strdupa(fmt);
8602 stringp = fmt;
8603 strsep(&stringp, "|");
8604
8605 if (!ast_strlen_zero(vmu->serveremail))
8606 myserveremail = vmu->serveremail;
8607
8608 if (!ast_strlen_zero(vmu->email)) {
8609 int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
8610 char *msg_id = NULL;
8611#ifdef IMAP_STORAGE
8612 struct ast_config *msg_cfg;
8613 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8614 char filename[PATH_MAX];
8615
8616 snprintf(filename, sizeof(filename), "%s.txt", fn);
8617 msg_cfg = ast_config_load(filename, config_flags);
8618 if (msg_cfg && msg_cfg != CONFIG_STATUS_FILEINVALID) {
8619 msg_id = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "msg_id"));
8620 ast_config_destroy(msg_cfg);
8621 }
8622#endif
8623
8624 if (attach_user_voicemail)
8625 RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
8626
8627 /* XXX possible imap issue, should category be NULL XXX */
8628 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);
8629
8630 if (attach_user_voicemail)
8631 DISPOSE(todir, msgnum);
8632 }
8633
8634 if (!ast_strlen_zero(vmu->pager)) {
8635 sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
8636 }
8637
8638 if (ast_test_flag(vmu, VM_DELETE))
8639 DELETE(todir, msgnum, fn, vmu);
8640
8641 /* Leave voicemail for someone */
8642 if (ast_app_has_voicemail(ext_context, NULL))
8643 ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
8644
8645 queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgentmsgs, newmsgs, oldmsgs);
8646 run_externnotify(vmu->context, vmu->mailbox, flag);
8647
8648#ifdef IMAP_STORAGE
8649 vm_delete(fn); /* Delete the file, but not the IMAP message */
8650 if (ast_test_flag(vmu, VM_DELETE)) { /* Delete the IMAP message if delete = yes */
8651 vm_imap_delete(NULL, vms->curmsg, vmu);
8652 vms->newmessages--; /* Fix new message count */
8653 }
8654#endif
8655
8656 return 0;
8657}
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 17331 of file app_voicemail_odbc.c.

17332{
17333 int new = 0, old = 0, urgent = 0;
17334 char ext_context[1024];
17335
17336 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
17337 run_externnotify(vmu->context, vmu->mailbox, NULL);
17338 ast_app_inboxcount2(ext_context, &urgent, &new, &old);
17339 queue_mwi_event(NULL, ext_context, urgent, new, old);
17340}

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 9519 of file app_voicemail_odbc.c.

9520{
9521 int count_msg, last_msg;
9522 SCOPE_ENTER(3, "user: %s dir: %s msg: %d box %d\n",
9523 vms->username, vms->curdir, vms->curmsg, box);
9524
9525 ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
9526
9527 /* Rename the member vmbox HERE so that we don't try to return before
9528 * we know what's going on.
9529 */
9530 snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
9531
9532 /* Faster to make the directory than to check if it exists. */
9533 create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
9534
9535 /* traverses directory using readdir (or select query for ODBC) */
9536 count_msg = COUNT(vmu, vms->curdir);
9537 if (count_msg < 0) {
9538 SCOPE_EXIT_RTN_VALUE(count_msg, "msgs: %d\n", count_msg);
9539 } else {
9540 vms->lastmsg = count_msg - 1;
9541 }
9542
9543 if (vm_allocate_dh(vms, vmu, count_msg)) {
9544 SCOPE_EXIT_RTN_VALUE(-1, "failed to allocate dh\n");
9545 }
9546
9547 /*
9548 The following test is needed in case sequencing gets messed up.
9549 There appears to be more than one way to mess up sequence, so
9550 we will not try to find all of the root causes--just fix it when
9551 detected.
9552 */
9553
9554 if (vm_lock_path(vms->curdir)) {
9555 SCOPE_EXIT_LOG_RTN_VALUE(ERROR_LOCK_PATH, AST_LOG_ERROR, "Could not open mailbox %s: mailbox is locked\n", vms->curdir);
9556 }
9557
9558 /* for local storage, checks directory for messages up to MAXMSGLIMIT */
9559 last_msg = LAST_MSG_INDEX(vms->curdir);
9560 ast_unlock_path(vms->curdir);
9561
9562 if (last_msg < -1) {
9563 SCOPE_EXIT_RTN_VALUE(last_msg, "last msg: %d\n", last_msg);
9564 } else if (vms->lastmsg != last_msg) {
9565 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);
9566 resequence_mailbox(vmu, vms->curdir, count_msg);
9567 }
9568
9569 SCOPE_EXIT_RTN_VALUE(0, "Done\n");
9570}
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, create_dirpath(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, ERROR_LOCK_PATH, LAST_MSG_INDEX, vm_state::lastmsg, LOG_NOTICE, ast_vm_user::maxmsg, mbox(), resequence_mailbox(), SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, 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 9265 of file app_voicemail_odbc.c.

9266{
9267 int res = 0;
9268 char filename[PATH_MAX], *cid;
9269 const char *origtime, *context, *category, *duration, *flag;
9270 struct ast_config *msg_cfg;
9271 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
9272 SCOPE_ENTER(3, "%s: user: %s dir: %s msg: %d\n", ast_channel_name(chan),
9273 vms->username, vms->curdir, vms->curmsg);
9274
9275 vms->starting = 0;
9276 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
9277 adsi_message(chan, vms);
9278 if (!vms->curmsg) {
9279 res = wait_file2(chan, vms, "vm-first"); /* "First" */
9280 } else if (vms->curmsg == vms->lastmsg) {
9281 res = wait_file2(chan, vms, "vm-last"); /* "last" */
9282 }
9283
9284 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
9285 SCOPE_CALL(-1, RETRIEVE, vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
9286 msg_cfg = ast_config_load(filename, config_flags);
9287 if (!valid_config(msg_cfg)) {
9288 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
9289 return 0;
9290 }
9291 flag = ast_variable_retrieve(msg_cfg, "message", "flag");
9292
9293 /* Play the word urgent if we are listening to urgent messages */
9294 if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
9295 res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
9296 }
9297
9298 if (!res) {
9299 /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
9300 /* POLISH syntax */
9301 if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
9302 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
9303 int ten, one;
9304 char nextmsg[256];
9305 ten = (vms->curmsg + 1) / 10;
9306 one = (vms->curmsg + 1) % 10;
9307
9308 if (vms->curmsg < 20) {
9309 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
9310 res = wait_file2(chan, vms, nextmsg);
9311 } else {
9312 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
9313 res = wait_file2(chan, vms, nextmsg);
9314 if (one > 0) {
9315 if (!res) {
9316 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
9317 res = wait_file2(chan, vms, nextmsg);
9318 }
9319 }
9320 }
9321 }
9322 if (!res)
9323 res = wait_file2(chan, vms, "vm-message");
9324 /* HEBREW syntax */
9325 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
9326 if (!vms->curmsg) {
9327 res = wait_file2(chan, vms, "vm-message");
9328 res = wait_file2(chan, vms, "vm-first");
9329 } else if (vms->curmsg == vms->lastmsg) {
9330 res = wait_file2(chan, vms, "vm-message");
9331 res = wait_file2(chan, vms, "vm-last");
9332 } else {
9333 res = wait_file2(chan, vms, "vm-message");
9334 res = wait_file2(chan, vms, "vm-number");
9335 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9336 }
9337 /* ICELANDIC syntax */
9338 } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) {
9339 res = wait_file2(chan, vms, "vm-message");
9340 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
9341 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "n");
9342 }
9343 /* VIETNAMESE syntax */
9344 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
9345 if (!vms->curmsg) {
9346 res = wait_file2(chan, vms, "vm-message");
9347 res = wait_file2(chan, vms, "vm-first");
9348 } else if (vms->curmsg == vms->lastmsg) {
9349 res = wait_file2(chan, vms, "vm-message");
9350 res = wait_file2(chan, vms, "vm-last");
9351 } else {
9352 res = wait_file2(chan, vms, "vm-message");
9353 res = wait_file2(chan, vms, "vm-number");
9354 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9355 }
9356 } else {
9357 if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
9358 res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
9359 } else { /* DEFAULT syntax */
9360 res = wait_file2(chan, vms, "vm-message");
9361 }
9362 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
9363 if (!res) {
9364 ast_test_suite_event_notify("PLAYBACK", "Message: message number");
9365 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
9366 }
9367 }
9368 }
9369 }
9370
9371 if (!valid_config(msg_cfg)) {
9372 SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
9373 }
9374
9375 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
9376 SCOPE_CALL(-1, DISPOSE, vms->curdir, vms->curmsg);
9377 ast_config_destroy(msg_cfg);
9378 SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "No origtime?!\n");
9379 }
9380
9381 cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
9382 duration = ast_variable_retrieve(msg_cfg, "message", "duration");
9383 category = ast_variable_retrieve(msg_cfg, "message", "category");
9384
9385 context = ast_variable_retrieve(msg_cfg, "message", "context");
9386 if (!res) {
9387 res = play_message_category(chan, category);
9388 }
9389 if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
9390 res = play_message_datetime(chan, vmu, origtime, filename);
9391 }
9392 if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
9393 res = play_message_callerid(chan, vms, cid, context, 0, 0);
9394 }
9395 if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
9396 res = play_message_duration(chan, vms, duration, vmu->saydurationm);
9397 }
9398 /* Allow pressing '1' to skip envelope / callerid */
9399 if (res == '1') {
9400 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
9401 res = 0;
9402 }
9403 ast_config_destroy(msg_cfg);
9404
9405 if (!res) {
9406 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
9407#ifdef IMAP_STORAGE
9408 ast_mutex_lock(&vms->lock);
9409#endif
9410 vms->heard[vms->curmsg] = 1;
9411#ifdef IMAP_STORAGE
9412 ast_mutex_unlock(&vms->lock);
9413 /*IMAP storage stores any prepended message from a forward
9414 * as a separate file from the rest of the message
9415 */
9416 if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
9417 wait_file(chan, vms, vms->introfn);
9418 }
9419#endif
9420 if ((res = wait_file(chan, vms, vms->fn)) < 0) {
9421 ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
9422 res = 0;
9423 }
9424 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
9425 isprint(res) ? res : '?', isprint(res) ? res : '?');
9426 }
9427 SCOPE_CALL(-1, DISPOSE, vms->curdir, vms->curmsg);
9428 SCOPE_EXIT_RTN_VALUE(res, "Done: RC: %d\n", res);
9429}
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_channel_name(), 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, SCOPE_CALL, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, vm_state::starting, vm_state::username, 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 11881 of file app_voicemail_odbc.c.

11882{
11883 struct vm_state vms;
11884 struct ast_vm_user *vmu = NULL, vmus;
11885 int res = 0;
11886 int open = 0;
11887 int played = 0;
11888 int i;
11889
11890 memset(&vmus, 0, sizeof(vmus));
11891 memset(&vms, 0, sizeof(vms));
11892
11893 if (!(vmu = find_user(&vmus, context, mailbox))) {
11894 goto play_msg_cleanup;
11895 }
11896
11897 /* Iterate through every folder, find the msg, and play it */
11898 for (i = 0; i < ARRAY_LEN(mailbox_folders) && !played; i++) {
11899 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
11900 vms.lastmsg = -1;
11901
11902 /* open the mailbox state */
11903 if ((res = open_mailbox(&vms, vmu, i)) < 0) {
11904 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
11905 res = -1;
11906 goto play_msg_cleanup;
11907 }
11908 open = 1;
11909
11910 /* play msg if it exists in this mailbox */
11911 if ((vms.lastmsg != -1) && !(play_message_by_id_helper(chan, vmu, &vms, msg_id))) {
11912 played = 1;
11913 }
11914
11915 /* close mailbox */
11916 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
11917 res = -1;
11918 goto play_msg_cleanup;
11919 }
11920 open = 0;
11921 }
11922
11923play_msg_cleanup:
11924 if (!played) {
11925 res = -1;
11926 }
11927
11928 if (vmu && open) {
11929 close_mailbox(&vms, vmu);
11930 }
11931
11932#ifdef IMAP_STORAGE
11933 if (vmu) {
11934 vmstate_delete(&vms);
11935 }
11936#endif
11937
11938 free_user(vmu);
11939
11940 return res;
11941}
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 11838 of file app_voicemail_odbc.c.

11842{
11843 if (message_range_and_existence_check(vms, &msg_id, 1, &vms->curmsg, vmu)) {
11844 return -1;
11845 }
11846 /* Found the msg, so play it back */
11847
11848 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
11849
11850#ifdef IMAP_STORAGE
11851 /*IMAP storage stores any prepended message from a forward
11852 * as a separate file from the rest of the message
11853 */
11854 if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
11855 wait_file(chan, vms, vms->introfn);
11856 }
11857#endif
11858 RETRIEVE(vms->curdir,vms->curmsg,vmu->mailbox, vmu->context);
11859
11860 if ((wait_file(chan, vms, vms->fn)) < 0) {
11861 ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
11862 } else {
11863#ifdef IMAP_STORAGE
11864 ast_mutex_lock(&vms->lock);
11865#endif
11866 vms->heard[vms->curmsg] = 1;
11867#ifdef IMAP_STORAGE
11868 ast_mutex_unlock(&vms->lock);
11869#endif
11870 }
11871 DISPOSE(vms->curdir, vms->curmsg);
11872 return 0;
11873}
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 9138 of file app_voicemail_odbc.c.

9139{
9140 int res = 0;
9141 int i;
9142 char *callerid, *name;
9143 char prefile[PATH_MAX] = "";
9144
9145 /* If voicemail cid is not enabled, or we didn't get cid or context from
9146 * the attribute file, leave now.
9147 *
9148 * TODO Still need to change this so that if this function is called by the
9149 * message envelope (and someone is explicitly requesting to hear the CID),
9150 * it does not check to see if CID is enabled in the config file.
9151 */
9152 if ((cid == NULL)||(context == NULL))
9153 return res;
9154
9155 /* Strip off caller ID number from name */
9156 ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
9157 ast_callerid_parse(cid, &name, &callerid);
9158 if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
9159 /* Check for internal contexts and only */
9160 /* say extension when the call didn't come from an internal context in the list */
9161 for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
9162 ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
9163 if ((strcmp(cidinternalcontexts[i], context) == 0))
9164 break;
9165 }
9166 if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
9167 if (!res) {
9168 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
9169 if (!ast_strlen_zero(prefile)) {
9170 /* See if we can find a recorded name for this callerid
9171 * and if found, use that instead of saying number. */
9172 if (ast_fileexists(prefile, NULL, NULL) > 0) {
9173 ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
9174 if (!callback)
9175 res = wait_file2(chan, vms, "vm-from");
9176 res = ast_stream_and_wait(chan, prefile, "");
9177 } else {
9178 ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
9179 /* Say "from extension" as one saying to sound smoother */
9180 if (!callback)
9181 res = wait_file2(chan, vms, "vm-from-extension");
9182 res = ast_say_digit_str(chan, callerid, "", ast_channel_language(chan));
9183 }
9184 }
9185 }
9186 } else if (!res) {
9187 ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
9188 /* If there is a recording for this numeric callerid then play that */
9189 if (!callback) {
9190 /* See if we can find a recorded name for this person instead of their extension number */
9191 snprintf(prefile, sizeof(prefile), "%s/recordings/callerids/%s", ast_config_AST_SPOOL_DIR, callerid);
9192 if (!saycidnumber && ast_fileexists(prefile, NULL, NULL) > 0) {
9193 ast_verb(3, "Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
9194 wait_file2(chan, vms, "vm-from");
9195 res = ast_stream_and_wait(chan, prefile, "");
9196 ast_verb(3, "Played recorded name result '%d'\n", res);
9197 } else {
9198 /* Since this is all nicely figured out, why not say "from phone number" in this case" */
9199 wait_file2(chan, vms, "vm-from-phonenumber");
9200 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
9201 }
9202 } else {
9203 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, ast_channel_language(chan));
9204 }
9205 }
9206 } else {
9207 /* Number unknown */
9208 ast_debug(1, "VM-CID: From an unknown number\n");
9209 /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
9210 res = wait_file2(chan, vms, "vm-unknown-caller");
9211 }
9212 return res;
9213}

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 9045 of file app_voicemail_odbc.c.

9046{
9047 int res = 0;
9048
9049 if (!ast_strlen_zero(category))
9050 res = ast_play_and_wait(chan, category);
9051
9052 if (res) {
9053 ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
9054 res = 0;
9055 }
9056
9057 return res;
9058}

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 9060 of file app_voicemail_odbc.c.

9061{
9062 int res = 0;
9063 struct vm_zone *the_zone = NULL;
9064 time_t t;
9065
9066 if (ast_get_time_t(origtime, &t, 0, NULL)) {
9067 ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
9068 return 0;
9069 }
9070
9071 /* Does this user have a timezone specified? */
9072 if (!ast_strlen_zero(vmu->zonetag)) {
9073 /* Find the zone in the list */
9074 struct vm_zone *z;
9077 if (!strcmp(z->name, vmu->zonetag)) {
9078 the_zone = z;
9079 break;
9080 }
9081 }
9083 }
9084
9085/* No internal variable parsing for now, so we'll comment it out for the time being */
9086#if 0
9087 /* Set the DIFF_* variables */
9088 ast_localtime(&t, &time_now, NULL);
9089 tv_now = ast_tvnow();
9090 ast_localtime(&tv_now, &time_then, NULL);
9091
9092 /* Day difference */
9093 if (time_now.tm_year == time_then.tm_year)
9094 snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
9095 else
9096 snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
9097 pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
9098
9099 /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
9100#endif
9101 if (the_zone) {
9102 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), the_zone->msg_format, the_zone->timezone);
9103 } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */
9104 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
9105 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */
9106 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q H 'digits/kai' M ", NULL);
9107 } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC syntax */
9108 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
9109 } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */
9110 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);
9111 } else if (!strcasecmp(ast_channel_language(chan),"ja")) { /* Japanese syntax */
9112 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "PHM q 'jp-ni' 'vm-received'", NULL);
9113 } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */
9114 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/nl-om' HM", NULL);
9115 } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
9116 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
9117 } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
9118 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q HM", NULL);
9119 } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* Brazilian PORTUGUESE syntax */
9120 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);
9121 } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
9122 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' dB 'digits/at' k 'and' M", NULL);
9123 } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
9124 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "qR 'vm-received'", NULL);
9125 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
9126 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);
9127 } else {
9128 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' IMp", NULL);
9129 }
9130#if 0
9131 pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
9132#endif
9133 return res;
9134}
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 9215 of file app_voicemail_odbc.c.

9216{
9217 int res = 0;
9218 int durationm;
9219 int durations;
9220 /* Verify that we have a duration for the message */
9221 if (duration == NULL)
9222 return res;
9223
9224 /* Convert from seconds to minutes */
9225 durations = atoi(duration);
9226 durationm = (durations / 60);
9227
9228 ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
9229
9230 if ((!res) && (durationm >= minduration)) {
9231 res = wait_file2(chan, vms, "vm-duration");
9232
9233 /* POLISH syntax */
9234 if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
9235 div_t num = div(durationm, 10);
9236
9237 if (durationm == 1) {
9238 res = ast_play_and_wait(chan, "digits/1z");
9239 res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
9240 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9241 if (num.rem == 2) {
9242 if (!num.quot) {
9243 res = ast_play_and_wait(chan, "digits/2-ie");
9244 } else {
9245 res = say_and_wait(chan, durationm - 2 , ast_channel_language(chan));
9246 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
9247 }
9248 } else {
9249 res = say_and_wait(chan, durationm, ast_channel_language(chan));
9250 }
9251 res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
9252 } else {
9253 res = say_and_wait(chan, durationm, ast_channel_language(chan));
9254 res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
9255 }
9256 /* DEFAULT syntax */
9257 } else {
9258 res = ast_say_number(chan, durationm, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
9259 res = wait_file2(chan, vms, "vm-minutes");
9260 }
9261 }
9262 return res;
9263}
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 16687 of file app_voicemail_odbc.c.

16690{
16691 /* Record message & let caller review or re-record it, or set options if applicable */
16692 int res = 0;
16693 int cmd = 0;
16694 int max_attempts = 3;
16695 int attempts = 0;
16696 int recorded = 0;
16697 int msg_exists = 0;
16698 signed char zero_gain = 0;
16699 char tempfile[PATH_MAX];
16700 char *acceptdtmf = "#";
16701 char *canceldtmf = "";
16702 int canceleddtmf = 0;
16703 SCOPE_ENTER(3, "%s: rf: %s fmt: %s type: %s vmu: %s\n",
16704 ast_channel_name(chan), recordfile, fmt, outsidecaller ? "msg" : "greeting",
16705 vmu->mailbox);
16706 /* Note that urgent and private are for flagging messages as such in the future */
16707
16708 /* barf if no pointer passed to store duration in */
16709 if (duration == NULL) {
16710 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING, "%s\n", "Error play_record_review called without duration pointer\n");
16711 }
16712
16713 if (!outsidecaller)
16714 snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
16715 else
16716 ast_copy_string(tempfile, recordfile, sizeof(tempfile));
16717
16718 cmd = '3'; /* Want to start by recording */
16719
16720 while ((cmd >= 0) && (cmd != 't')) {
16721 switch (cmd) {
16722 case '1':
16723 if (!msg_exists) {
16724 /* In this case, 1 is to record a message */
16725 cmd = '3';
16726 break;
16727 } else {
16728 /* Otherwise 1 is to save the existing message */
16729 ast_verb(3, "Saving message as is\n");
16730 if (!outsidecaller) {
16731 ast_trace(-1, "Renaming greeting '%s' to '%s'\n", tempfile, recordfile);
16732 ast_filerename(tempfile, recordfile, NULL);
16733 }
16734 if (!forwardintro) {
16735 ast_stream_and_wait(chan, "vm-msgsaved", "");
16736 }
16737 if (!outsidecaller) {
16738 /* Saves to IMAP server only if imapgreeting=yes */
16739 ast_trace(-1, "Saving greeting '%s'\n", recordfile);
16740 SCOPE_CALL(-1, STORE, recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id);
16741 SCOPE_CALL(-1, DISPOSE, recordfile, -1);
16742 }
16743 cmd = 't';
16744 SCOPE_EXIT_RTN_VALUE(res, "Message saved to %s\n", recordfile);
16745 }
16746 case '2':
16747 /* Review */
16748 ast_verb(3, "Reviewing the message\n");
16749 ast_trace(-1, "Reviewing '%s'\n", tempfile);
16750 cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
16751 break;
16752 case '3':
16753 msg_exists = 0;
16754 /* Record */
16755 if (recorded == 1)
16756 ast_verb(3, "Re-recording the message\n");
16757 else
16758 ast_verb(3, "Recording the message\n");
16759
16760 if (recorded && outsidecaller) {
16761 if (forwardintro) {
16762 cmd = ast_play_and_wait(chan, "vm-record-prepend");
16763 } else {
16764 cmd = ast_play_and_wait(chan, INTRO);
16765 }
16766 cmd = ast_play_and_wait(chan, "beep");
16767 }
16768 if (cmd == -1) {
16769 /* User has hung up, no options to give */
16770 ast_filedelete(tempfile, NULL);
16771 SCOPE_EXIT_RTN_VALUE(cmd, "User hung up before message could be rerecorded. Deleted '%s'\n", tempfile);
16772 }
16773 recorded = 1;
16774 /* 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 */
16775 if (record_gain)
16776 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
16777 if (ast_test_flag(vmu, VM_OPERATOR))
16778 canceldtmf = "0";
16779 ast_trace(-1, "Recording '%s'\n", tempfile);
16780 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);
16781 if (strchr(canceldtmf, cmd)) {
16782 /* need this flag here to distinguish between pressing '0' during message recording or after */
16783 canceleddtmf = 1;
16784 }
16785 if (record_gain)
16786 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
16787 if (cmd == -1) {
16788 /* User has hung up, no options to give */
16789 if (!outsidecaller) {
16790 /* user was recording a greeting and they hung up, so let's delete the recording. */
16791 ast_filedelete(tempfile, NULL);
16792 }
16793 SCOPE_EXIT_RTN_VALUE(cmd, "User hung up after recording. %s %s\n",
16794 outsidecaller ? "Saved message " : "Deleted greeting \n", tempfile);
16795 }
16796 if (cmd == '0') {
16797 break;
16798 } else if (cmd == '*') {
16799 break;
16800#if 0
16801 } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
16802 /* Message is too short */
16803 ast_verb(3, "Message too short\n");
16804 cmd = ast_play_and_wait(chan, "vm-tooshort");
16805 cmd = ast_filedelete(tempfile, NULL);
16806 break;
16807 } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
16808 /* Message is all silence */
16809 ast_verb(3, "Nothing recorded\n");
16810 cmd = ast_filedelete(tempfile, NULL);
16811 cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
16812 if (!cmd)
16813 cmd = ast_play_and_wait(chan, "vm-speakup");
16814 break;
16815#endif
16816 } else {
16817 /* If all is well, a message exists */
16818 msg_exists = 1;
16819 cmd = 0;
16820 }
16821 break;
16822 case '4':
16823 if (outsidecaller && ast_test_flag(vmu, VM_MARK_URGENT)) { /* only mark vm messages */
16824 /* Mark Urgent */
16825 if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
16826 ast_verb(3, "marking message as Urgent\n");
16827 res = ast_play_and_wait(chan, "vm-marked-urgent");
16828 strcpy(flag, "Urgent");
16829 } else if (flag) {
16830 ast_verb(3, "UNmarking message as Urgent\n");
16831 res = ast_play_and_wait(chan, "vm-marked-nonurgent");
16832 strcpy(flag, "");
16833 } else {
16834 ast_play_and_wait(chan, "vm-sorry");
16835 }
16836 cmd = 0;
16837 } else {
16838 cmd = ast_play_and_wait(chan, "vm-sorry");
16839 }
16840 break;
16841 case '5':
16842 case '6':
16843 case '7':
16844 case '8':
16845 case '9':
16846 case '*':
16847 case '#':
16848 cmd = ast_play_and_wait(chan, "vm-sorry");
16849 break;
16850#if 0
16851/* XXX Commented out for the moment because of the dangers of deleting
16852 a message while recording (can put the message numbers out of sync) */
16853 case '*':
16854 /* Cancel recording, delete message, offer to take another message*/
16855 cmd = ast_play_and_wait(chan, "vm-deleted");
16856 cmd = ast_filedelete(tempfile, NULL);
16857 if (outsidecaller) {
16858 res = vm_exec(chan, NULL);
16859 return res;
16860 }
16861 else
16862 return 1;
16863#endif
16864 case '0':
16865 if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
16866 cmd = ast_play_and_wait(chan, "vm-sorry");
16867 break;
16868 }
16869 if (msg_exists || recorded) {
16870 ast_trace(-1, "Reviewing '%s'\n", tempfile);
16871 cmd = ast_play_and_wait(chan, "vm-saveoper");
16872 if (!cmd)
16873 cmd = ast_waitfordigit(chan, 3000);
16874 if (cmd == '1') {
16875 ast_trace(-1, "Saving '%s' to '%s'\n", tempfile, recordfile);
16876 ast_filerename(tempfile, recordfile, NULL);
16877 ast_play_and_wait(chan, "vm-msgsaved");
16878 cmd = '0';
16879 } else if (cmd == '4') {
16880 if (flag) {
16881 ast_play_and_wait(chan, "vm-marked-urgent");
16882 strcpy(flag, "Urgent");
16883 }
16884 ast_play_and_wait(chan, "vm-msgsaved");
16885 cmd = '0';
16886 } else {
16887 ast_trace(-1, "Deleting '%s'\n", tempfile);
16888 ast_play_and_wait(chan, "vm-deleted");
16889 SCOPE_CALL(-1, DELETE, tempfile, -1, tempfile, vmu);
16890 SCOPE_CALL(-1, DISPOSE, tempfile, -1);
16891 cmd = '0';
16892 }
16893 }
16894 return cmd;
16895 default:
16896 /* If the caller is an outside caller and the review option is enabled or it's forward intro
16897 allow them to review the message, but let the owner of the box review
16898 their OGM's */
16899 if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro) {
16900 SCOPE_EXIT_RTN_VALUE(cmd, "Done. Outside caller, review not set, no forwardintro\n");
16901 }
16902 if (msg_exists) {
16903 cmd = ast_play_and_wait(chan, "vm-review");
16904 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_MARK_URGENT)) {
16905 if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
16906 cmd = ast_play_and_wait(chan, "vm-review-urgent");
16907 } else if (flag) {
16908 cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
16909 }
16910 }
16911 } else {
16912 cmd = ast_play_and_wait(chan, "vm-torerecord");
16913 if (!cmd)
16914 cmd = ast_waitfordigit(chan, 600);
16915 }
16916
16917 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
16918 cmd = ast_play_and_wait(chan, "vm-reachoper");
16919 if (!cmd)
16920 cmd = ast_waitfordigit(chan, 600);
16921 }
16922#if 0
16923 if (!cmd)
16924 cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
16925#endif
16926 if (!cmd)
16927 cmd = ast_waitfordigit(chan, 6000);
16928 if (!cmd) {
16929 attempts++;
16930 }
16931 if (attempts > max_attempts) {
16932 cmd = 't';
16933 }
16934 }
16935 }
16936 if (!outsidecaller && (cmd == -1 || cmd == 't')) {
16937 /* Hang up or timeout, so delete the recording. */
16938 ast_trace(-1, "Deleting '%s' on hangup or timeout\n", tempfile);
16939 ast_filedelete(tempfile, NULL);
16940 }
16941
16942 if (cmd != 't' && outsidecaller)
16943 ast_play_and_wait(chan, "vm-goodbye");
16944
16945 SCOPE_EXIT_RTN_VALUE(cmd, "Done\n");
16946}
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:7444
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:2149
@ AST_RECORD_IF_EXISTS_OVERWRITE
#define AST_OPTION_RXGAIN

References ast_channel_name(), ast_channel_setoption(), ast_copy_string(), AST_DIGIT_ANY, ast_filedelete(), ast_filerename(), 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_trace, ast_verb, ast_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, INTRO, LOG_WARNING, ast_vm_user::mailbox, maxsilence, NULL, PATH_MAX, leave_vm_options::record_gain, SCOPE_CALL, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, 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 13981 of file app_voicemail_odbc.c.

13982{
13983 int new = 0, old = 0, urgent = 0;
13984
13985 if (!mwi_state) {
13986 /* This should only occur due to allocation failure of a default mwi state object */
13987 return 0;
13988 }
13989
13990 inboxcount2(mwi_state->uniqueid, &urgent, &new, &old);
13991
13992#ifdef IMAP_STORAGE
13993 if (imap_poll_logout) {
13994 imap_logout(mwi_state->uniqueid);
13995 }
13996#endif
13997
13998 if (urgent != mwi_state->urgent_msgs || new != mwi_state->new_msgs || old != mwi_state->old_msgs) {
13999 queue_mwi_event(NULL, mwi_state->uniqueid, urgent, new, old);
14000 run_externnotify(NULL, mwi_state->uniqueid, NULL);
14001 }
14002
14003 return 0;
14004}
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 1478 of file app_voicemail_odbc.c.

1479{
1482 if (saydurationminfo) {
1484 }
1485 ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
1486 ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
1487 ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
1488 ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
1489 ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
1490 if (vmminsecs) {
1491 vmu->minsecs = vmminsecs;
1492 }
1493 if (vmmaxsecs) {
1494 vmu->maxsecs = vmmaxsecs;
1495 }
1496 if (maxmsg) {
1497 vmu->maxmsg = maxmsg;
1498 }
1499 if (maxdeletedmsg) {
1501 }
1502 vmu->volgain = volgain;
1503 ast_free(vmu->email);
1504 vmu->email = NULL;
1505 ast_free(vmu->emailsubject);
1506 vmu->emailsubject = NULL;
1507 ast_free(vmu->emailbody);
1508 vmu->emailbody = NULL;
1509#ifdef IMAP_STORAGE
1510 ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
1511 ast_copy_string(vmu->imapserver, imapserver, sizeof(vmu->imapserver));
1512 ast_copy_string(vmu->imapport, imapport, sizeof(vmu->imapport));
1513 ast_copy_string(vmu->imapflags, imapflags, sizeof(vmu->imapflags));
1514#endif
1515}
#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 5244 of file app_voicemail_odbc.c.

5245{
5246 char callerid[256];
5247 char num[12];
5248 char fromdir[256], fromfile[256];
5249 struct ast_config *msg_cfg;
5250 const char *origcallerid, *origtime;
5251 char origcidname[80], origcidnum[80], origdate[80];
5252 int inttime;
5253 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
5254
5255 /* Prepare variables for substitution in email body and subject */
5256 pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
5257 pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
5258 snprintf(num, sizeof(num), "%d", msgnum);
5259 pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
5260 pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
5261 pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
5262 pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
5263 ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
5264 pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
5265 pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
5266 pbx_builtin_setvar_helper(ast, "VM_DATE", date);
5267 pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
5268 pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
5269
5270 /* Retrieve info from VM attribute file */
5271 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
5272 make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
5273 if (strlen(fromfile) < sizeof(fromfile) - 5) {
5274 strcat(fromfile, ".txt");
5275 }
5276 if (!(msg_cfg = ast_config_load(fromfile, config_flags)) || !(valid_config(msg_cfg))) {
5277 ast_debug(1, "Config load for message text file '%s' failed\n", fromfile);
5278 return;
5279 }
5280
5281 if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
5282 pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
5283 ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
5284 pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
5285 pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
5286 }
5287
5288 if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
5289 struct timeval tv = { inttime, };
5290 struct ast_tm tm;
5291 ast_localtime(&tv, &tm, NULL);
5292 ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
5293 pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
5294 }
5295 ast_config_destroy(msg_cfg);
5296}

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 16280 of file app_voicemail_odbc.c.

16281{
16282 struct alias_mailbox_mapping *mapping = v_obj;
16283
16284 if (!mapping) {
16285 return;
16286 }
16287 prnt(where, "Alias: %s Mailbox: %s", mapping->alias, mapping->mailbox);
16288}

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 8527 of file app_voicemail_odbc.c.

8528{
8529 char *mailbox;
8530 char *context;
8531
8533 return;
8534 }
8535
8536 ast_debug(3, "Queueing event for mailbox %s New: %d Old: %d\n", box, new + urgent, old);
8537 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8538
8540 struct ao2_iterator *aliases;
8541 struct mailbox_alias_mapping *mapping;
8542
8544 while ((mapping = ao2_iterator_next(aliases))) {
8545 char alias[strlen(mapping->alias) + 1];
8546 strcpy(alias, mapping->alias); /* safe */
8547 mailbox = NULL;
8548 context = NULL;
8549 ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);
8551 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8552 ao2_ref(mapping, -1);
8553 }
8555 }
8556}
#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 15568 of file app_voicemail_odbc.c.

15568 {
15569 struct ast_config *pwconf;
15570 struct ast_flags config_flags = { 0 };
15571
15572 pwconf = ast_config_load(secretfn, config_flags);
15573 if (valid_config(pwconf)) {
15574 const char *val = ast_variable_retrieve(pwconf, "general", "password");
15575 if (val) {
15576 ast_copy_string(password, val, passwordlen);
15577 ast_config_destroy(pwconf);
15578 return;
15579 }
15580 ast_config_destroy(pwconf);
15581 }
15582 ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
15583}

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 16222 of file app_voicemail_odbc.c.

16223{
16224 return load_config(1);
16225}

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 12084 of file app_voicemail_odbc.c.

12085{
12086 const char *mailbox = a->argv[2];
12087 const char *context = a->argv[3];
12088 const char *folder = a->argv[4];
12089 const char *id[] = { a->argv[5] };
12090 int ret = vm_msg_remove(mailbox, context, 1, folder, id);
12091 if (ret) {
12092 ast_cli(a->fd, "Error removing message %s from mailbox %s@%s %s\n",
12093 id[0], mailbox, context, folder);
12094 } else {
12095 ast_cli(a->fd, "Removed message %s from mailbox %s@%s %s\n",
12096 id[0], mailbox, context, folder);
12097 }
12098 return ret;
12099}

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 5033 of file app_voicemail_odbc.c.

5034{
5035 char stxt[PATH_MAX];
5036 char dtxt[PATH_MAX];
5037 ast_filerename(sfn, dfn, NULL);
5038 snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
5039 snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
5040 if (ast_check_realtime("voicemail_data")) {
5041 ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
5042 }
5043 rename(stxt, dtxt);
5044}

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 7574 of file app_voicemail_odbc.c.

7575{
7576 /* we know the actual number of messages, so stop process when number is hit */
7577
7578 int x, dest;
7579 char sfn[PATH_MAX];
7580 char dfn[PATH_MAX];
7581
7582 if (vm_lock_path(dir)) {
7583 return ERROR_LOCK_PATH;
7584 }
7585
7586 for (x = 0, dest = 0; dest != stopcount && x < MAXMSGLIMIT; x++) {
7587 make_file(sfn, sizeof(sfn), dir, x);
7588 if (EXISTS(dir, x, sfn, NULL)) {
7589
7590 if (x != dest) {
7591 make_file(dfn, sizeof(dfn), dir, dest);
7592 RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
7593 }
7594
7595 dest++;
7596 }
7597 }
7598 ast_unlock_path(dir);
7599
7600 return dest;
7601}

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 2006 of file app_voicemail_odbc.c.

2007{
2008 /* This function could be made to generate one from a database, too */
2009 struct ast_vm_user *cur;
2010 int res = -1;
2012 AST_LIST_TRAVERSE(&users, cur, list) {
2013 if ((!context || !strcasecmp(context, cur->context)) &&
2014 (!strcasecmp(mailbox, cur->mailbox)))
2015 break;
2016 }
2017 if (cur) {
2018 ast_copy_string(cur->password, newpass, sizeof(cur->password));
2019 res = 0;
2020 }
2022 if (!res) {
2023 struct ast_json *json_object;
2024
2025 json_object = ast_json_pack("{s: s, s: s, s: s}",
2026 "Context", S_OR(context, "default"),
2027 "Mailbox", mailbox,
2028 "NewPassword", newpass);
2029 ast_manager_publish_event("VoicemailPasswordChange", EVENT_FLAG_SYSTEM | EVENT_FLAG_USER, json_object);
2030 ast_json_unref(json_object);
2031 }
2032 return res;
2033}
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:637
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 6607 of file app_voicemail_odbc.c.

6608{
6609 char arguments[255];
6610 char ext_context[256] = "";
6611 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6612 struct ast_smdi_mwi_message *mwi_msg;
6613
6615 snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
6616 else
6617 ast_copy_string(ext_context, extension, sizeof(ext_context));
6618
6619 if (smdi_iface) {
6620 if (ast_app_has_voicemail(ext_context, NULL))
6622 else
6624
6626 ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
6627 if (!strncmp(mwi_msg->cause, "INV", 3))
6628 ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
6629 else if (!strncmp(mwi_msg->cause, "BLK", 3))
6630 ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
6631 ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
6632 ao2_ref(mwi_msg, -1);
6633 } else {
6634 ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
6635 }
6636 }
6637
6639 if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6640 ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
6641 } else {
6642 snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
6643 externnotify, S_OR(context, "\"\""),
6644 extension, newvoicemails,
6645 oldvoicemails, urgentvoicemails);
6646 ast_debug(1, "Executing %s\n", arguments);
6647 ast_safe_system(arguments);
6648 }
6649 }
6650}
#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 7611 of file app_voicemail_odbc.c.

7612{
7613#ifdef IMAP_STORAGE
7614 /* we must use mbox(x) folder names, and copy the message there */
7615 /* simple. huh? */
7616 char sequence[10];
7617 char mailbox[256];
7618 int res;
7619 int curr_mbox;
7620
7621 /* get the real IMAP message number for this message */
7622 snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
7623
7624 ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
7625 ast_mutex_lock(&vms->lock);
7626 /* if save to Old folder, put in INBOX as read */
7627 if (box == OLD_FOLDER) {
7628 mail_setflag(vms->mailstream, sequence, "\\Seen");
7629 } else if (box == NEW_FOLDER) {
7630 mail_clearflag(vms->mailstream, sequence, "\\Seen");
7631 }
7632 if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
7633 ast_mutex_unlock(&vms->lock);
7634 return 0;
7635 }
7636
7637 /* get the current mailbox so that we can point the mailstream back to it later */
7638 curr_mbox = get_folder_by_name(vms->curbox);
7639
7640 /* Create the folder if it doesn't exist */
7641 imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
7642 if (vms->mailstream && !mail_status(vms->mailstream, mailbox, SA_UIDNEXT)) {
7643 if (mail_create(vms->mailstream, mailbox) != NIL) {
7644 ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
7645 }
7646 }
7647
7648 /* restore previous mbox stream */
7649 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
7650 ast_log(AST_LOG_ERROR, "IMAP mailstream is NULL or can't init_mailstream\n");
7651 res = -1;
7652 } else {
7653 if (move) {
7654 res = !mail_move(vms->mailstream, sequence, (char *) mbox(vmu, box));
7655 } else {
7656 res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
7657 }
7658 }
7659 ast_mutex_unlock(&vms->lock);
7660 return res;
7661#else
7662 char *dir = vms->curdir;
7663 char *username = vms->username;
7664 char *context = vmu->context;
7665 char sfn[PATH_MAX];
7666 char dfn[PATH_MAX];
7667 char ddir[PATH_MAX];
7668 const char *dbox = mbox(vmu, box);
7669 int x, i;
7670 SCOPE_ENTER(3, "dir: %s msg: %d box: %d dbox: %s move? %d \n", dir, msg, box, dbox, move);
7671
7672 create_dirpath(ddir, sizeof(ddir), context, username, dbox);
7673 ast_trace(-1, "ddir: %s\n", ddir);
7674
7675 if (vm_lock_path(ddir)) {
7676 SCOPE_EXIT_RTN_VALUE(ERROR_LOCK_PATH, "Failed to lock path %s\n", ddir);
7677 }
7678
7679 x = LAST_MSG_INDEX(ddir) + 1;
7680
7681 if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
7682 ast_trace(-1, "Deleting message %d\n", msg);
7683 x--;
7684 for (i = 1; i <= x; i++) {
7685 /* Push files down a "slot". The oldest file (msg0000) will be deleted. */
7686 make_file(sfn, sizeof(sfn), ddir, i);
7687 make_file(dfn, sizeof(dfn), ddir, i - 1);
7688 if (EXISTS(ddir, i, sfn, NULL)) {
7689 SCOPE_CALL(-1, RENAME, ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
7690 } else
7691 break;
7692 }
7693 } else {
7694 if (x >= vmu->maxmsg) {
7695 ast_unlock_path(ddir);
7696 SCOPE_EXIT_RTN_VALUE(ERROR_MAX_MSGS, "Max messages reached\n");
7697 }
7698 }
7699 make_file(sfn, sizeof(sfn), dir, msg);
7700 make_file(dfn, sizeof(dfn), ddir, x);
7701 if (strcmp(sfn, dfn)) {
7702 ast_trace(-1, "Copying message '%s' to '%s'\n", sfn, dfn);
7703 SCOPE_CALL(-1, COPY, dir, msg, ddir, x, username, context, sfn, dfn);
7704 }
7705 ast_unlock_path(ddir);
7706
7707 if (newmsg) {
7708 *newmsg = x;
7709 }
7710 SCOPE_EXIT_RTN_VALUE(0, "Done\n");
7711#endif
7712}
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_trace, 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_MSG_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, SCOPE_CALL, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, 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 15531 of file app_voicemail_odbc.c.

15532{
15533 int res = -1;
15534 char dir[PATH_MAX];
15535 snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
15536 ast_debug(2, "About to try retrieving name file %s\n", dir);
15537 RETRIEVE(dir, -1, mailbox, context);
15538 if (ast_fileexists(dir, NULL, NULL)) {
15539 res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
15540 }
15541 DISPOSE(dir, -1);
15542 return res;
15543}

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 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 5869 of file app_voicemail_odbc.c.

5886{
5887 FILE *p = NULL;
5888 char tmp[80] = "/tmp/astmail-XXXXXX";
5889 char tmp2[256];
5890 char *stringp;
5891
5892 if (vmu && ast_strlen_zero(vmu->email)) {
5893 ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
5894 return(0);
5895 }
5896
5897 /* Mail only the first format */
5898 format = ast_strdupa(format);
5899 stringp = format;
5900 strsep(&stringp, "|");
5901
5902 if (!strcmp(format, "wav49"))
5903 format = "WAV";
5904 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));
5905 /* Make a temporary file instead of piping directly to sendmail, in case the mail
5906 command hangs */
5908 ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
5909 return -1;
5910 } else {
5911 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);
5912 fclose(p);
5913 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5914 ast_safe_system(tmp2);
5915 ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
5916 }
5917 return 0;
5918}
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_name, 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 5920 of file app_voicemail_odbc.c.

5921{
5922 char enc_cidnum[256], enc_cidname[256];
5923 char date[256];
5924 char host[MAXHOSTNAMELEN] = "";
5925 char who[256];
5926 char dur[PATH_MAX];
5927 char tmp[80] = "/tmp/astmail-XXXXXX";
5928 char tmp2[PATH_MAX];
5929 struct ast_tm tm;
5930 FILE *p;
5931 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
5932
5933 if (!str1 || !str2) {
5934 ast_free(str1);
5935 ast_free(str2);
5936 return -1;
5937 }
5938
5939 if (cidnum) {
5940 strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
5941 }
5942 if (cidname) {
5943 strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
5944 }
5945
5947 ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
5948 ast_free(str1);
5949 ast_free(str2);
5950 return -1;
5951 }
5952 gethostname(host, sizeof(host)-1);
5953 if (strchr(srcemail, '@')) {
5954 ast_copy_string(who, srcemail, sizeof(who));
5955 } else {
5956 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
5957 }
5958 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
5959 ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
5960 fprintf(p, "Date: %s\n", date);
5961
5962 /* Reformat for custom pager format */
5963 ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
5964
5966 struct ast_channel *ast;
5967 if ((ast = ast_dummy_channel_alloc())) {
5968 char *ptr;
5969 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5971
5972 if (check_mime(ast_str_buffer(str1))) {
5973 int first_line = 1;
5974 ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
5975 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5976 *ptr = '\0';
5977 fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
5978 first_line = 0;
5979 /* Substring is smaller, so this will never grow */
5980 ast_str_set(&str2, 0, "%s", ptr + 1);
5981 }
5982 fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
5983 } else {
5984 fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
5985 }
5986 ast = ast_channel_unref(ast);
5987 } else {
5988 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
5989 }
5990 } else {
5991 fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
5992 }
5993
5994 if (check_mime(vmu->fullname)) {
5995 int first_line = 1;
5996 char *ptr;
5997 ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
5998 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
5999 *ptr = '\0';
6000 fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
6001 first_line = 0;
6002 /* Substring is smaller, so this will never grow */
6003 ast_str_set(&str2, 0, "%s", ptr + 1);
6004 }
6005 fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
6006 } else {
6007 fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
6008 }
6009
6011 struct ast_channel *ast;
6012 if ((ast = ast_dummy_channel_alloc())) {
6013 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
6015 if (check_mime(ast_str_buffer(str1))) {
6016 int first_line = 1;
6017 char *ptr;
6018 ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
6019 while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
6020 *ptr = '\0';
6021 fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
6022 first_line = 0;
6023 /* Substring is smaller, so this will never grow */
6024 ast_str_set(&str2, 0, "%s", ptr + 1);
6025 }
6026 fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
6027 } else {
6028 fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
6029 }
6030 ast = ast_channel_unref(ast);
6031 } else {
6032 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
6033 }
6034 } else {
6035 if (ast_strlen_zero(flag)) {
6036 fprintf(p, "Subject: New VM" ENDL);
6037 } else {
6038 fprintf(p, "Subject: New %s VM" ENDL, flag);
6039 }
6040 }
6041
6042 /* End of headers */
6043 fputs(ENDL, p);
6044
6045 if (pagerbody) {
6046 struct ast_channel *ast;
6047 if ((ast = ast_dummy_channel_alloc())) {
6048 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
6050 fprintf(p, "%s" ENDL, ast_str_buffer(str1));
6051 ast = ast_channel_unref(ast);
6052 } else {
6053 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
6054 }
6055 } else {
6056 fprintf(p, "New %s long %s msg in box %s\n"
6057 "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
6058 }
6059
6060 fclose(p);
6061 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
6062 ast_safe_system(tmp2);
6063 ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
6064 ast_free(str1);
6065 ast_free(str2);
6066 return 0;
6067}

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 1237 of file app_voicemail_odbc.c.

1238{
1239 if (ast_strlen_zero(mailbox_id) || !mailbox || !context) {
1240 return -1;
1241 }
1242 *context = mailbox_id;
1243 *mailbox = strsep(context, "@");
1244 if (ast_strlen_zero(*mailbox)) {
1245 return -1;
1246 }
1247 if (ast_strlen_zero(*context)) {
1248 *context = "default";
1249 }
1250 return 0;
1251}

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 11982 of file app_voicemail_odbc.c.

11983{
11984#define VMBOX_STRING_HEADER_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11985#define VMBOX_STRING_DATA_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11986
11987 const char *mailbox = a->argv[3];
11988 const char *context = a->argv[4];
11989 struct vm_state vms;
11990 struct ast_vm_user *vmu = NULL, vmus;
11991 memset(&vmus, 0, sizeof(vmus));
11992 memset(&vms, 0, sizeof(vms));
11993
11994 if (!(vmu = find_user(&vmus, context, mailbox))) {
11995 ast_cli(a->fd, "Can't find voicemail user %s@%s\n", mailbox, context);
11996 return -1;
11997 }
11998
11999 ast_cli(a->fd, VMBOX_STRING_HEADER_FORMAT, "Full Name", "Email", "Pager", "Language", "Locale", "Time Zone");
12000 ast_cli(a->fd, VMBOX_STRING_DATA_FORMAT, vmu->fullname, vmu->email, vmu->pager, vmu->language, vmu->locale, vmu->zonetag);
12001
12002 return 0;
12003}
#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 12005 of file app_voicemail_odbc.c.

12006{
12007#define VM_STRING_HEADER_FORMAT "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"
12008 const char *mailbox = a->argv[3];
12009 const char *context = a->argv[4];
12010 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
12011 struct ast_vm_msg_snapshot *msg;
12012 int i;
12013
12014 /* Take a snapshot of the mailbox and walk through each folder's contents */
12016 if (!mailbox_snapshot) {
12017 ast_cli(a->fd, "Can't create snapshot for voicemail user %s@%s\n", mailbox, context);
12018 return -1;
12019 }
12020
12021 ast_cli(a->fd, VM_STRING_HEADER_FORMAT, "Folder", "Caller ID", "Date", "Duration", "Flag", "ID");
12022
12023 for (i = 0; i < mailbox_snapshot->folders; i++) {
12024 AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) {
12025 ast_cli(a->fd, VM_STRING_HEADER_FORMAT, msg->folder_name, msg->callerid, msg->origdate, msg->duration,
12026 msg->flag, msg->msg_id);
12027 }
12028 }
12029
12030 ast_cli(a->fd, "%d Message%s Total\n", mailbox_snapshot->total_msg_num, ESS(mailbox_snapshot->total_msg_num));
12031 /* done, destroy. */
12032 mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
12033
12034 return 0;
12035}
#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 12037 of file app_voicemail_odbc.c.

12038{
12039 if (show_mailbox_details(a)){
12040 return -1;
12041 }
12042 ast_cli(a->fd, "\n");
12043 return show_mailbox_snapshot(a);
12044}
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 13728 of file app_voicemail_odbc.c.

13729{
13730 struct ast_config *cfg;
13731 const char *cat = NULL;
13732
13733 if (!(cfg = ast_load_realtime_multientry("voicemail",
13734 "context", context, SENTINEL))) {
13735 return CLI_FAILURE;
13736 }
13737
13738 ast_cli(fd,
13739 "\n"
13740 "=============================================================\n"
13741 "=== Configured Voicemail Users ==============================\n"
13742 "=============================================================\n"
13743 "===\n");
13744
13745 while ((cat = ast_category_browse(cfg, cat))) {
13746 struct ast_variable *var = NULL;
13747 ast_cli(fd,
13748 "=== Mailbox ...\n"
13749 "===\n");
13750 for (var = ast_variable_browse(cfg, cat); var; var = var->next)
13751 ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
13752 ast_cli(fd,
13753 "===\n"
13754 "=== ---------------------------------------------------------\n"
13755 "===\n");
13756 }
13757
13758 ast_cli(fd,
13759 "=============================================================\n"
13760 "\n");
13761
13762 ast_config_destroy(cfg);
13763
13764 return CLI_SUCCESS;
13765}
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3637

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 14129 of file app_voicemail_odbc.c.

14130{
14131 int errcode;
14133
14134 poll_thread_run = 1;
14135
14136 if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
14137 ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
14138 }
14139}
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 14141 of file app_voicemail_odbc.c.

14142{
14143 poll_thread_run = 0;
14144
14148
14149 pthread_join(poll_thread, NULL);
14151
14153}
#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 1318 of file app_voicemail_odbc.c.

1319{
1320 char *bufptr = buf;
1321 for (; *input; input++) {
1322 if (*input < 32) {
1323 continue;
1324 }
1325 *bufptr++ = *input;
1326 if (bufptr == buf + buflen - 1) {
1327 break;
1328 }
1329 }
1330 *bufptr = '\0';
1331 return buf;
1332}
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 14642 of file app_voicemail_odbc.c.

14643{
14644 char *current;
14645
14646 /* Add 16 for fudge factor */
14647 struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
14648
14650
14651 /* Substitute strings \r, \n, and \t into the appropriate characters */
14652 for (current = (char *) value; *current; current++) {
14653 if (*current == '\\') {
14654 current++;
14655 if (!*current) {
14656 ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
14657 break;
14658 }
14659 switch (*current) {
14660 case '\\':
14661 ast_str_append(&str, 0, "\\");
14662 break;
14663 case 'r':
14664 ast_str_append(&str, 0, "\r");
14665 break;
14666 case 'n':
14667#ifdef IMAP_STORAGE
14668 if (!str->used || str->str[str->used - 1] != '\r') {
14669 ast_str_append(&str, 0, "\r");
14670 }
14671#endif
14672 ast_str_append(&str, 0, "\n");
14673 break;
14674 case 't':
14675 ast_str_append(&str, 0, "\t");
14676 break;
14677 default:
14678 ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
14679 break;
14680 }
14681 } else {
14682 ast_str_append(&str, 0, "%c", *current);
14683 }
14684 }
14685
14686 return ast_str_buffer(str);
14687}
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 16227 of file app_voicemail_odbc.c.

16228{
16229 int res;
16230
16237 res |= ast_manager_unregister("VoicemailUsersList");
16238 res |= ast_manager_unregister("VoicemailUserStatus");
16239 res |= ast_manager_unregister("VoicemailRefresh");
16240 res |= ast_manager_unregister("VoicemailBoxSummary");
16241 res |= ast_manager_unregister("VoicemailMove");
16242 res |= ast_manager_unregister("VoicemailRemove");
16243 res |= ast_manager_unregister("VoicemailForward");
16244#ifdef TEST_FRAMEWORK
16245 res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
16246 res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
16247 res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
16248 res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
16249 res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
16250 res |= AST_TEST_UNREGISTER(test_voicemail_vm_info);
16251#endif
16255#ifdef TEST_FRAMEWORK
16256 ast_uninstall_vm_test_functions();
16257#endif
16259
16260 ao2_container_unregister("voicemail_alias_mailbox_mappings");
16262 ao2_container_unregister("voicemail_mailbox_alias_mappings");
16264
16267
16269 ast_unload_realtime("voicemail");
16270 ast_unload_realtime("voicemail_data");
16271
16272#ifdef IMAP_STORAGE
16273 ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
16274#endif
16275 free_vm_users();
16276 free_vm_zones();
16277 return res;
16278}
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:7608
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 2038 of file app_voicemail_odbc.c.

2039{
2040 return cfg && cfg != CONFIG_STATUS_FILEINVALID;
2041}

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 2292 of file app_voicemail_odbc.c.

2292 {
2293
2294 int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
2295
2296 /* remove old allocation */
2297 if (vms->deleted) {
2298 ast_free(vms->deleted);
2299 vms->deleted = NULL;
2300 }
2301 if (vms->heard) {
2302 ast_free(vms->heard);
2303 vms->heard = NULL;
2304 }
2305 vms->dh_arraysize = 0;
2306
2307 if (arraysize > 0) {
2308 if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
2309 return -1;
2310 }
2311 if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
2312 ast_free(vms->deleted);
2313 vms->deleted = NULL;
2314 return -1;
2315 }
2316 vms->dh_arraysize = arraysize;
2317 }
2318
2319 return 0;
2320}

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 11703 of file app_voicemail_odbc.c.

11706{
11707 int useadsi = 0, valid = 0, logretries = 0;
11708 char password[AST_MAX_EXTENSION], *passptr = NULL;
11709 struct ast_vm_user vmus, *vmu = NULL;
11710
11711 /* If ADSI is supported, setup login screen */
11712 adsi_begin(chan, &useadsi);
11713 if (!skipuser && useadsi)
11714 adsi_login(chan);
11715 if (!silent && !skipuser && ast_streamfile(chan, vm_login, ast_channel_language(chan))) {
11716 ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
11717 return -1;
11718 }
11719
11720 /* Authenticate them and get their mailbox/password */
11721
11722 while (!valid && (logretries < max_logins)) {
11723 /* Prompt for, and read in the username */
11724 if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
11725 ast_log(AST_LOG_WARNING, "Couldn't read username\n");
11726 return -1;
11727 }
11728 if (ast_strlen_zero(mailbox)) {
11729 if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
11730 ast_copy_string(mailbox, ast_channel_caller(chan)->id.number.str, mailbox_size);
11731 } else {
11732 ast_verb(3, "Username not entered\n");
11733 return -1;
11734 }
11735 } else if (mailbox[0] == '*') {
11736 /* user entered '*' */
11737 ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
11738 if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
11739 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11740 return -1;
11741 }
11742 ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
11743 mailbox[0] = '\0';
11744 }
11745
11746 if (useadsi)
11747 adsi_password(chan);
11748
11749 if (!ast_strlen_zero(prefix)) {
11750 char fullusername[80];
11751
11752 ast_copy_string(fullusername, prefix, sizeof(fullusername));
11753 strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
11754 ast_copy_string(mailbox, fullusername, mailbox_size);
11755 }
11756
11757 ast_debug(1, "Before find user for mailbox %s\n", mailbox);
11758 memset(&vmus, 0, sizeof(vmus));
11759 vmu = find_user(&vmus, context, mailbox);
11760 if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
11761 /* saved password is blank, so don't bother asking */
11762 password[0] = '\0';
11763 } else {
11765 if (!ast_check_hangup(chan)) {
11766 ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
11767 }
11768 free_user(vmu);
11769 return -1;
11770 }
11771 if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
11772 ast_log(AST_LOG_NOTICE, "Unable to read password\n");
11773 free_user(vmu);
11774 return -1;
11775 } else if (password[0] == '*') {
11776 /* user entered '*' */
11777 ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
11778 if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1,
11779 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11780 mailbox[0] = '*';
11781 free_user(vmu);
11782 return -1;
11783 }
11784 ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11785 mailbox[0] = '\0';
11786 /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
11787 free_user(vmu);
11788 vmu = NULL;
11789 }
11790 }
11791
11792 if (vmu) {
11793 passptr = vmu->password;
11794 if (passptr[0] == '-') passptr++;
11795 }
11796 if (vmu && !strcmp(passptr, password))
11797 valid++;
11798 else {
11799 ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
11800 if (!ast_strlen_zero(prefix))
11801 mailbox[0] = '\0';
11802 }
11803 logretries++;
11804 if (!valid) {
11805 if (skipuser || logretries >= max_logins) {
11806 if (ast_streamfile(chan, "vm-incorrect", ast_channel_language(chan))) {
11807 ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
11808 free_user(vmu);
11809 return -1;
11810 }
11811 if (ast_waitstream(chan, "")) { /* Channel is hung up */
11812 free_user(vmu);
11813 return -1;
11814 }
11815 } else {
11816 if (useadsi)
11817 adsi_login(chan);
11818 if (ast_streamfile(chan, "vm-incorrect-mailbox", ast_channel_language(chan))) {
11819 ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
11820 free_user(vmu);
11821 return -1;
11822 }
11823 }
11824 }
11825 }
11826 if (!valid && (logretries >= max_logins)) {
11827 ast_stopstream(chan);
11828 ast_play_and_wait(chan, "vm-goodbye");
11829 free_user(vmu);
11830 return -1;
11831 }
11832 if (vmu && !skipuser) {
11833 *res_vmu = *vmu;
11834 }
11835 return 0;
11836}
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 11680 of file app_voicemail_odbc.c.

11681{
11682 if (!strncasecmp(ast_channel_language(chan), "es", 2)) { /* SPANISH */
11683 return vm_browse_messages_es(chan, vms, vmu);
11684 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK */
11685 return vm_browse_messages_gr(chan, vms, vmu);
11686 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW */
11687 return vm_browse_messages_he(chan, vms, vmu);
11688 } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN */
11689 return vm_browse_messages_it(chan, vms, vmu);
11690 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE */
11691 return vm_browse_messages_ja(chan, vms, vmu);
11692 } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE */
11693 return vm_browse_messages_pt(chan, vms, vmu);
11694 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE */
11695 return vm_browse_messages_vi(chan, vms, vmu);
11696 } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) */
11697 return vm_browse_messages_zh(chan, vms, vmu);
11698 } else { /* Default to English syntax */
11699 return vm_browse_messages_en(chan, vms, vmu);
11700 }
11701}
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 11492 of file app_voicemail_odbc.c.

11493{
11494 int cmd = 0;
11495
11496 if (vms->lastmsg > -1) {
11497 cmd = play_message(chan, vmu, vms);
11498 } else {
11499 cmd = ast_play_and_wait(chan, "vm-youhave");
11500 if (!cmd)
11501 cmd = ast_play_and_wait(chan, "vm-no");
11502 if (!cmd) {
11503 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11504 cmd = ast_play_and_wait(chan, vms->fn);
11505 }
11506 if (!cmd)
11507 cmd = ast_play_and_wait(chan, "vm-messages");
11508 }
11509 return cmd;
11510}
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 11573 of file app_voicemail_odbc.c.

11574{
11575 int cmd;
11576
11577 if (vms->lastmsg > -1) {
11578 cmd = play_message(chan, vmu, vms);
11579 } else {
11580 cmd = ast_play_and_wait(chan, "vm-youhaveno");
11581 if (!cmd)
11582 cmd = ast_play_and_wait(chan, "vm-messages");
11583 if (!cmd) {
11584 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11585 cmd = ast_play_and_wait(chan, vms->fn);
11586 }
11587 }
11588 return cmd;
11589}

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 11440 of file app_voicemail_odbc.c.

11441{
11442 int cmd = 0;
11443
11444 if (vms->lastmsg > -1) {
11445 cmd = play_message(chan, vmu, vms);
11446 } else {
11447 cmd = ast_play_and_wait(chan, "vm-youhaveno");
11448 if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
11449 if (!cmd) {
11450 snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
11451 cmd = ast_play_and_wait(chan, vms->fn);
11452 }
11453 if (!cmd)
11454 cmd = ast_play_and_wait(chan, "vm-messages");
11455 } else {
11456 if (!cmd)
11457 cmd = ast_play_and_wait(chan, "vm-messages");
11458 if (!cmd) {
11459 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11460 cmd = ast_play_and_wait(chan, vms->fn);
11461 }
11462 }
11463 }
11464 return cmd;
11465}

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 11468 of file app_voicemail_odbc.c.

11469{
11470 int cmd = 0;
11471
11472 if (vms->lastmsg > -1) {
11473 cmd = play_message(chan, vmu, vms);
11474 } else {
11475 if (!strcasecmp(vms->fn, "INBOX")) {
11476 cmd = ast_play_and_wait(chan, "vm-nonewmessages");
11477 } else {
11478 cmd = ast_play_and_wait(chan, "vm-nomessages");
11479 }
11480 }
11481 return cmd;
11482}

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 11520 of file app_voicemail_odbc.c.

11521{
11522 int cmd;
11523
11524 if (vms->lastmsg > -1) {
11525 cmd = play_message(chan, vmu, vms);
11526 } else {
11527 cmd = ast_play_and_wait(chan, "vm-no");
11528 if (!cmd)
11529 cmd = ast_play_and_wait(chan, "vm-message");
11530 if (!cmd) {
11531 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11532 cmd = ast_play_and_wait(chan, vms->fn);
11533 }
11534 }
11535 return cmd;
11536}

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 11546 of file app_voicemail_odbc.c.

11547{
11548 int cmd = 0;
11549
11550 if (vms->lastmsg > -1) {
11551 cmd = play_message(chan, vmu, vms);
11552 } else {
11553 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11554 cmd = ast_play_and_wait(chan, vms->fn);
11555 if (!cmd)
11556 cmd = ast_play_and_wait(chan, "vm-messages");
11557 if (!cmd)
11558 cmd = ast_play_and_wait(chan, "jp-wa");
11559 if (!cmd)
11560 cmd = ast_play_and_wait(chan, "jp-arimasen");
11561 }
11562 return cmd;
11563}

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 11599 of file app_voicemail_odbc.c.

11600{
11601 int cmd;
11602
11603 if (vms->lastmsg > -1) {
11604 cmd = play_message(chan, vmu, vms);
11605 } else {
11606 cmd = ast_play_and_wait(chan, "vm-no");
11607 if (!cmd) {
11608 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11609 cmd = ast_play_and_wait(chan, vms->fn);
11610 }
11611 if (!cmd)
11612 cmd = ast_play_and_wait(chan, "vm-messages");
11613 }
11614 return cmd;
11615}

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 11653 of file app_voicemail_odbc.c.

11654{
11655 int cmd = 0;
11656
11657 if (vms->lastmsg > -1) {
11658 cmd = play_message(chan, vmu, vms);
11659 } else {
11660 cmd = ast_play_and_wait(chan, "vm-no");
11661 if (!cmd) {
11662 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11663 cmd = ast_play_and_wait(chan, vms->fn);
11664 }
11665 }
11666 return cmd;
11667}

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 11625 of file app_voicemail_odbc.c.

11626{
11627 int cmd;
11628
11629 if (vms->lastmsg > -1) {
11630 cmd = play_message(chan, vmu, vms);
11631 } else {
11632 cmd = ast_play_and_wait(chan, "vm-you");
11633 if (!cmd)
11634 cmd = ast_play_and_wait(chan, "vm-haveno");
11635 if (!cmd)
11636 cmd = ast_play_and_wait(chan, "vm-messages");
11637 if (!cmd) {
11638 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11639 cmd = ast_play_and_wait(chan, vms->fn);
11640 }
11641 }
11642 return cmd;
11643}

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 2050 of file app_voicemail_odbc.c.

2051{
2052 struct ast_config *cfg = NULL;
2053 struct ast_variable *var = NULL;
2054 struct ast_category *cat = NULL;
2055 char *category = NULL;
2056 const char *tmp = NULL;
2057 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
2058 char secretfn[PATH_MAX] = "";
2059 int found = 0;
2060
2061 if (!change_password_realtime(vmu, newpassword))
2062 return;
2063
2064 /* check if we should store the secret in the spool directory next to the messages */
2065 switch (vmu->passwordlocation) {
2066 case OPT_PWLOC_SPOOLDIR:
2067 snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
2068 if (write_password_to_file(secretfn, newpassword) == 0) {
2069 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
2070 ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
2071 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
2072 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
2073 break;
2074 } else {
2075 ast_log(LOG_WARNING, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
2076 }
2077 /* Fall-through */
2079 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
2080 while ((category = ast_category_browse(cfg, category))) {
2081 if (!strcasecmp(category, vmu->context)) {
2082 char *value = NULL;
2083 char *new = NULL;
2084 if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
2085 ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
2086 break;
2087 }
2088 value = strstr(tmp, ",");
2089 if (!value) {
2090 new = ast_malloc(strlen(newpassword) + 1);
2091 sprintf(new, "%s", newpassword);
2092 } else {
2093 new = ast_malloc((strlen(value) + strlen(newpassword) + 1));
2094 sprintf(new, "%s%s", newpassword, value);
2095 }
2096 if (!(cat = ast_category_get(cfg, category, NULL))) {
2097 ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
2098 ast_free(new);
2099 break;
2100 }
2101 ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
2102 found = 1;
2103 ast_free(new);
2104 }
2105 }
2106 /* save the results */
2107 if (found) {
2108 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
2109 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
2110 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
2111 ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "app_voicemail");
2112 ast_config_destroy(cfg);
2113 break;
2114 }
2115
2116 ast_config_destroy(cfg);
2117 }
2118 /* Fall-through */
2120 /* check users.conf and update the password stored for the mailbox */
2121 /* if no vmsecret entry exists create one. */
2122 if ((cfg = ast_config_load("users.conf", config_flags)) && valid_config(cfg)) {
2123 ast_debug(4, "we are looking for %s\n", vmu->mailbox);
2124 for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
2125 ast_debug(4, "users.conf: %s\n", category);
2126 if (!strcasecmp(category, vmu->mailbox)) {
2127 char new[strlen(newpassword) + 1];
2128 if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
2129 ast_debug(3, "looks like we need to make vmsecret!\n");
2130 var = ast_variable_new("vmsecret", newpassword, "");
2131 } else {
2132 var = NULL;
2133 }
2134
2135 sprintf(new, "%s", newpassword);
2136 if (!(cat = ast_category_get(cfg, category, NULL))) {
2137 ast_debug(4, "failed to get category!\n");
2138 ast_free(var);
2139 break;
2140 }
2141 if (!var) {
2142 ast_variable_update(cat, "vmsecret", new, NULL, 0);
2143 } else {
2145 }
2146 found = 1;
2147 break;
2148 }
2149 }
2150 /* save the results and clean things up */
2151 if (found) {
2152 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
2153 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
2154 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
2155 ast_config_text_file_save("users.conf", cfg, "app_voicemail");
2156 }
2157
2158 ast_config_destroy(cfg);
2159 }
2160 }
2161}
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:1542
@ 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 2163 of file app_voicemail_odbc.c.

2164{
2165 char buf[255];
2166 snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
2167 ast_debug(1, "External password: %s\n",buf);
2168 if (!ast_safe_system(buf)) {
2169 ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
2170 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
2171 /* Reset the password in memory, too */
2172 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
2173 }
2174}

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 1668 of file app_voicemail_odbc.c.

1669{
1670 int fds[2], pid = 0;
1671
1672 memset(buf, 0, len);
1673
1674 if (pipe(fds)) {
1675 snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
1676 } else {
1677 /* good to go*/
1678 pid = ast_safe_fork(0);
1679
1680 if (pid < 0) {
1681 /* ok maybe not */
1682 close(fds[0]);
1683 close(fds[1]);
1684 snprintf(buf, len, "FAILURE: Fork failed");
1685 } else if (pid) {
1686 /* parent */
1687 close(fds[1]);
1688 if (read(fds[0], buf, len) < 0) {
1689 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
1690 }
1691 close(fds[0]);
1692 } else {
1693 /* child */
1695 AST_APP_ARG(v)[20];
1696 );
1697 char *mycmd = ast_strdupa(command);
1698
1699 close(fds[0]);
1700 dup2(fds[1], STDOUT_FILENO);
1701 close(fds[1]);
1702 ast_close_fds_above_n(STDOUT_FILENO);
1703
1704 AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
1705
1706 execv(arg.v[0], arg.v);
1707 printf("FAILURE: %s", strerror(errno));
1708 _exit(0);
1709 }
1710 }
1711 return buf;
1712}
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:3207
#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:3202

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 5221 of file app_voicemail_odbc.c.

5222{
5223 char *txt;
5224 int txtsize = 0;
5225 int res = 0;
5226 SCOPE_ENTER(3, "file: %s\n", file);
5227
5228 txtsize = (strlen(file) + 5)*sizeof(char);
5229 txt = ast_alloca(txtsize);
5230 /* Sprintf here would safe because we alloca'd exactly the right length,
5231 * but trying to eliminate all sprintf's anyhow
5232 */
5233 if (ast_check_realtime("voicemail_data")) {
5234 ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
5235 }
5236 snprintf(txt, txtsize, "%s.txt", file);
5237 ast_trace(-1, "unlinking '%s'\n", txt);
5238 unlink(txt);
5239 ast_trace(-1, "deleting sound files '%s'\n", file);
5240 res = ast_filedelete(file, NULL);
5241 SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res);
5242}

References ast_alloca, ast_check_realtime(), ast_destroy_realtime(), ast_filedelete(), ast_trace, make_ari_stubs::file, NULL, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, 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 13192 of file app_voicemail_odbc.c.

13193{
13194 int res = 0;
13195 char *tmp;
13196 struct leave_vm_options leave_options;
13197 struct ast_flags flags = { 0 };
13198 char *opts[OPT_ARG_ARRAY_SIZE];
13200 AST_APP_ARG(argv0);
13201 AST_APP_ARG(argv1);
13202 );
13203 SCOPE_ENTER(3, "%s\n", ast_channel_name(chan));
13204
13205 memset(&leave_options, 0, sizeof(leave_options));
13206
13207 if (!ast_strlen_zero(data)) {
13208 tmp = ast_strdupa(data);
13210 if (args.argc == 2) {
13211 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
13212 SCOPE_EXIT_RTN_VALUE(-1, "parse options failed for '%s'\n", args.argv1);
13213 }
13216 int gain;
13217
13218 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
13219 SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
13220 } else {
13221 leave_options.record_gain = (signed char) gain;
13222 }
13223 }
13226 leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
13227 }
13228 }
13229 if (ast_test_flag(&flags, OPT_BEEP)) { /* Use custom beep (or none at all) */
13230 leave_options.beeptone = opts[OPT_ARG_BEEP_TONE];
13231 } else { /* Use default beep */
13232 leave_options.beeptone = "beep";
13233 }
13234 } else {
13235 char temp[256];
13236 res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
13237 if (res < 0) {
13238 SCOPE_EXIT_RTN_VALUE(res, "getdata failed. RC: %d", res);
13239 }
13240 if (ast_strlen_zero(temp)) {
13242 }
13243 args.argv0 = ast_strdupa(temp);
13244 }
13245
13246 if (ast_channel_state(chan) != AST_STATE_UP) {
13249 } else {
13250 ast_answer(chan);
13251 }
13252 }
13253
13254 res = SCOPE_CALL_WITH_INT_RESULT(-1, leave_voicemail, chan, args.argv0, &leave_options);
13255 if (res == 't') {
13256 ast_play_and_wait(chan, "vm-goodbye");
13257 res = 0;
13258 }
13259
13260 if (res == OPERATOR_EXIT) {
13261 res = 0;
13262 }
13263
13264 if (res == ERROR_LOCK_PATH) {
13265 ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
13266 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
13267 res = 0;
13268 }
13269
13270 SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d", res);
13271}
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:4296
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:3066
@ 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_channel_name(), 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, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, 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 12361 of file app_voicemail_odbc.c.

12362{
12363 /* XXX This is, admittedly, some pretty horrendous code. For some
12364 reason it just seemed a lot easier to do with GOTO's. I feel
12365 like I'm back in my GWBASIC days. XXX */
12366 int res = -1;
12367 int cmd = 0;
12368 int valid = 0;
12369 char prefixstr[80] ="";
12370 char ext_context[256]="";
12371 int box;
12372 int useadsi = 0;
12373 int skipuser = 0;
12374 struct vm_state vms = {{0}};
12375 struct ast_vm_user *vmu = NULL, vmus = {{0}};
12376 char *context = NULL;
12377 int silentexit = 0;
12378 struct ast_flags flags = { 0 };
12379 signed char record_gain = 0;
12380 int play_auto = 0;
12381 int play_folder = 0;
12382 int in_urgent = 0;
12383 int nodelete = 0;
12384#ifdef IMAP_STORAGE
12385 int deleted = 0;
12386#endif
12387 SCOPE_ENTER(3, "%s:\n", ast_channel_name(chan));
12388
12389 /* Add the vm_state to the active list and keep it active */
12390 vms.lastmsg = -1;
12391
12392 ast_test_suite_event_notify("START", "Message: vm_execmain started");
12393 if (ast_channel_state(chan) != AST_STATE_UP) {
12394 ast_debug(1, "Before ast_answer\n");
12395 ast_answer(chan);
12396 }
12397
12398 if (!ast_strlen_zero(data)) {
12399 char *opts[OPT_ARG_ARRAY_SIZE];
12400 char *parse;
12402 AST_APP_ARG(argv0);
12403 AST_APP_ARG(argv1);
12404 );
12405
12406 parse = ast_strdupa(data);
12407
12409
12410 if (args.argc == 2) {
12411 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
12412 SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid option string '%s'\n", args.argv1);
12413 }
12415 int gain;
12416 if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
12417 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
12418 SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
12419 } else {
12420 record_gain = (signed char) gain;
12421 }
12422 } else {
12423 ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
12424 }
12425 }
12427 play_auto = 1;
12428 if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
12429 /* See if it is a folder name first */
12430 if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
12431 if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
12432 play_folder = -1;
12433 }
12434 } else {
12435 play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
12436 }
12437 } else {
12438 ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
12439 }
12440 if (play_folder > 9 || play_folder < 0) {
12442 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
12443 opts[OPT_ARG_PLAYFOLDER]);
12444 play_folder = 0;
12445 }
12446 }
12448 nodelete = 1;
12449 }
12450 } else {
12451 /* old style options parsing */
12452 while (*(args.argv0)) {
12453 if (*(args.argv0) == 's')
12455 else if (*(args.argv0) == 'p')
12457 else
12458 break;
12459 (args.argv0)++;
12460 }
12461
12462 }
12463
12464 valid = ast_test_flag(&flags, OPT_SILENT);
12465
12466 if ((context = strchr(args.argv0, '@')))
12467 *context++ = '\0';
12468
12470 ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
12471 else
12472 ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
12473
12474 if (!ast_strlen_zero(vms.username)) {
12475 if ((vmu = find_user(&vmus, context ,vms.username))) {
12476 skipuser++;
12477 } else {
12478 ast_log(LOG_WARNING, "Mailbox '%s%s%s' doesn't exist\n", vms.username, context ? "@": "", context ? context : "");
12479 valid = 0;
12480 }
12481 } else {
12482 valid = 0;
12483 }
12484 }
12485
12486 if (!valid)
12487 res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
12488
12489 ast_trace(-1, "vm_authenticate user: %s\n", vms.username);
12490
12491 if (vms.username[0] == '*') {
12492 ast_trace(-1, "user pressed * in context '%s'\n", ast_channel_context(chan));
12493
12494 /* user entered '*' */
12495 if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) {
12496 ast_test_suite_event_notify("REDIRECT", "Message: redirecting user to 'a' extension");
12497 res = 0; /* prevent hangup */
12498 goto out;
12499 }
12500 }
12501
12502 if (!res) {
12503 valid = 1;
12504 if (!skipuser)
12505 vmu = &vmus;
12506 } else {
12507 res = 0;
12508 }
12509
12510 /* If ADSI is supported, setup login screen */
12511 adsi_begin(chan, &useadsi);
12512
12513 if (!valid) {
12514 ast_trace(-1, "Invalid user\n");
12515 goto out;
12516 }
12517 ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated");
12518
12519#ifdef IMAP_STORAGE
12520 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
12521 pthread_setspecific(ts_vmstate.key, &vms);
12522
12523 vms.interactive = 1;
12524 vms.updated = 1;
12525 if (vmu)
12526 ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
12527 vmstate_insert(&vms);
12528 init_vm_state(&vms);
12529#endif
12530
12531 /* Set language from config to override channel language */
12532 if (!ast_strlen_zero(vmu->language)) {
12533 ast_channel_lock(chan);
12534 ast_channel_language_set(chan, vmu->language);
12535 ast_channel_unlock(chan);
12536 }
12537
12538 /* Retrieve urgent, old and new message counts */
12539 ast_trace(-1, "Before open_mailbox\n");
12540 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
12541 if (res < 0) {
12542 ast_trace(-1, "open mailbox: %d\n", res);
12543 goto out;
12544 }
12545 vms.oldmessages = vms.lastmsg + 1;
12546 ast_trace(-1, "Number of old messages: %d\n", vms.oldmessages);
12547 /* check INBOX */
12548 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER);
12549 if (res < 0) {
12550 ast_trace(-1, "open mailbox: %d\n", res);
12551 goto out;
12552 }
12553 vms.newmessages = vms.lastmsg + 1;
12554 ast_trace(-1, "Number of new messages: %d\n", vms.newmessages);
12555 /* Start in Urgent */
12556 in_urgent = 1;
12557 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, 11); /*11 is the Urgent folder */
12558 if (res < 0) {
12559 ast_trace(-1, "open mailbox: %d\n", res);
12560 goto out;
12561 }
12562 vms.urgentmessages = vms.lastmsg + 1;
12563 ast_trace(-1, "Number of urgent messages: %d\n", vms.urgentmessages);
12564
12565 /* Select proper mailbox FIRST!! */
12566 if (play_auto) {
12567 ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages");
12568 if (vms.urgentmessages) {
12569 in_urgent = 1;
12570 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, 11);
12571 } else {
12572 in_urgent = 0;
12573 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, play_folder);
12574 }
12575 if (res < 0) {
12576 ast_trace(-1, "open mailbox: %d\n", res);
12577 goto out;
12578 }
12579
12580 /* If there are no new messages, inform the user and hangup */
12581 if (vms.lastmsg == -1) {
12582 in_urgent = 0;
12583 cmd = vm_browse_messages(chan, &vms, vmu);
12584 res = 0;
12585 goto out;
12586 }
12587 } else {
12588 if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
12589 /* If we only have old messages start here */
12590 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
12591 in_urgent = 0;
12592 play_folder = 1;
12593 if (res < 0)
12594 goto out;
12595 } else if (!vms.urgentmessages && vms.newmessages) {
12596 /* If we have new messages but none are urgent */
12597 in_urgent = 0;
12598 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER);
12599 if (res < 0)
12600 goto out;
12601 }
12602 }
12603
12604 if (useadsi)
12605 adsi_status(chan, &vms);
12606 res = 0;
12607
12608 /* Check to see if this is a new user */
12609 if (!strcasecmp(vmu->mailbox, vmu->password) &&
12611 if (ast_play_and_wait(chan, vm_newuser) == -1)
12612 ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
12613 cmd = vm_newuser_setup(chan, vmu, &vms, vmfmts, record_gain);
12614 if ((cmd == 't') || (cmd == '#')) {
12615 /* Timeout */
12616 ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out");
12617 res = 0;
12618 ast_trace(-1, "Timeout\n");
12619 goto out;
12620 } else if (cmd < 0) {
12621 /* Hangup */
12622 ast_test_suite_event_notify("HANGUP", "Message: hangup detected");
12623 res = -1;
12624 ast_trace(-1, "Hangup\n");
12625 goto out;
12626 }
12627 }
12628#ifdef IMAP_STORAGE
12629 ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
12630 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
12631 ast_debug(1, "*** QUOTA EXCEEDED!!\n");
12632 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
12633 }
12634 ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
12635 if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
12636 ast_log(AST_LOG_WARNING, "No more messages possible. User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
12637 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
12638 }
12639#endif
12640
12641 ast_test_suite_event_notify("INTRO", "Message: playing intro menu");
12642 if (play_auto) {
12643 cmd = '1';
12644 } else {
12645 cmd = vm_intro(chan, vmu, &vms);
12646 }
12647 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12648 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12649
12650 vms.repeats = 0;
12651 vms.starting = 1;
12652 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
12653 /* Run main menu */
12654 ast_trace(-1, "Main menu: %d %c\n", cmd, (cmd >= 32 && cmd <= 126 ? cmd : ' '));
12655 switch (cmd) {
12656 case '1': /* First message */
12657 vms.curmsg = 0;
12658 /* Fall through */
12659 case '5': /* Play current message */
12660 ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
12661 cmd = vm_browse_messages(chan, &vms, vmu);
12662 break;
12663 case '2': /* Change folders */
12664 ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder");
12665 if (useadsi)
12666 adsi_folders(chan, 0, "Change to folder...");
12667
12668 cmd = get_folder2(chan, "vm-changeto", 0);
12669 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12670 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12671 if (cmd == '#') {
12672 cmd = 0;
12673 } else if (cmd > 0) {
12674 cmd = cmd - '0';
12675 res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu);
12676 if (res == ERROR_LOCK_PATH) {
12677 ast_trace(-1, "close mailbox: %d\n", res);
12678 goto out;
12679 }
12680 /* If folder is not urgent, set in_urgent to zero! */
12681 if (cmd != 11) in_urgent = 0;
12682 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, cmd);
12683 if (res < 0) {
12684 ast_trace(-1, "open mailbox: %d\n", res);
12685 goto out;
12686 }
12687 play_folder = cmd;
12688 cmd = 0;
12689 }
12690 if (useadsi)
12691 adsi_status2(chan, &vms);
12692
12693 if (!cmd) {
12694 cmd = vm_play_folder_name(chan, vms.vmbox);
12695 }
12696
12697 vms.starting = 1;
12698 vms.curmsg = 0;
12699 break;
12700 case '3': /* Advanced options */
12701 ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");
12702 cmd = 0;
12703 vms.repeats = 0;
12704 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
12705 switch (cmd) {
12706 case '1': /* Reply */
12707 if (vms.lastmsg > -1 && !vms.starting) {
12708 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
12709 if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
12710 res = cmd;
12711 ast_trace(-1, "advanced options: %d\n", cmd);
12712 goto out;
12713 }
12714 } else {
12715 cmd = ast_play_and_wait(chan, "vm-sorry");
12716 }
12717 cmd = 't';
12718 break;
12719 case '2': /* Callback */
12720 if (!vms.starting)
12721 ast_verb(3, "Callback Requested\n");
12722 if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
12723 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
12724 ast_trace(-1, "advanced options: %d\n", cmd);
12725 if (cmd == 9) {
12726 silentexit = 1;
12727 goto out;
12728 } else if (cmd == ERROR_LOCK_PATH) {
12729 res = cmd;
12730 goto out;
12731 }
12732 } else {
12733 cmd = ast_play_and_wait(chan, "vm-sorry");
12734 }
12735 cmd = 't';
12736 break;
12737 case '3': /* Envelope */
12738 if (vms.lastmsg > -1 && !vms.starting) {
12739 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
12740 if (cmd == ERROR_LOCK_PATH) {
12741 res = cmd;
12742 ast_trace(-1, "advanced options: %d\n", cmd);
12743 goto out;
12744 }
12745 } else {
12746 cmd = ast_play_and_wait(chan, "vm-sorry");
12747 }
12748 cmd = 't';
12749 break;
12750 case '4': /* Dialout */
12751 if (!ast_strlen_zero(vmu->dialout)) {
12752 cmd = dialout(chan, vmu, NULL, vmu->dialout);
12753 if (cmd == 9) {
12754 silentexit = 1;
12755 ast_trace(-1, "dialout: %d\n", cmd);
12756 goto out;
12757 }
12758 } else {
12759 cmd = ast_play_and_wait(chan, "vm-sorry");
12760 }
12761 cmd = 't';
12762 break;
12763
12764 case '5': /* Leave VoiceMail */
12765 if (ast_test_flag(vmu, VM_SVMAIL)) {
12766 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, forward_message, chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
12767 if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
12768 res = cmd;
12769 ast_trace(-1, "forward message: %d\n", cmd);
12770 goto out;
12771 }
12772 } else {
12773 cmd = ast_play_and_wait(chan, "vm-sorry");
12774 }
12775 cmd = 't';
12776 break;
12777
12778 case '*': /* Return to main menu */
12779 cmd = 't';
12780 break;
12781
12782 default:
12783 cmd = 0;
12784 if (!vms.starting) {
12785 cmd = ast_play_and_wait(chan, "vm-toreply");
12786 }
12787 if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
12788 cmd = ast_play_and_wait(chan, "vm-tocallback");
12789 }
12790 if (!cmd && !vms.starting) {
12791 cmd = ast_play_and_wait(chan, "vm-tohearenv");
12792 }
12793 if (!ast_strlen_zero(vmu->dialout) && !cmd) {
12794 cmd = ast_play_and_wait(chan, "vm-tomakecall");
12795 }
12796 if (ast_test_flag(vmu, VM_SVMAIL) && !cmd) {
12797 cmd = ast_play_and_wait(chan, "vm-leavemsg");
12798 }
12799 if (!cmd) {
12800 cmd = ast_play_and_wait(chan, "vm-starmain");
12801 }
12802 if (!cmd) {
12803 cmd = ast_waitfordigit(chan, 6000);
12804 }
12805 if (!cmd) {
12806 vms.repeats++;
12807 }
12808 if (vms.repeats > 3) {
12809 cmd = 't';
12810 }
12811 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
12812 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
12813 }
12814 }
12815 if (cmd == 't') {
12816 cmd = 0;
12817 vms.repeats = 0;
12818 }
12819 break;
12820 case '4': /* Go to the previous message */
12821 ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1);
12822 if (vms.curmsg > 0) {
12823 vms.curmsg--;
12824 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
12825 } else {
12826 /* Check if we were listening to new
12827 messages. If so, go to Urgent messages
12828 instead of saying "no more messages"
12829 */
12830 if (in_urgent == 0 && vms.urgentmessages > 0) {
12831 /* Check for Urgent messages */
12832 in_urgent = 1;
12833 res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu);
12834 if (res == ERROR_LOCK_PATH) {
12835 ast_trace(-1, "close mailbox: %d\n", res);
12836 goto out;
12837 }
12838 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, 11); /* Open Urgent folder */
12839 if (res < 0) {
12840 ast_trace(-1, "open mailbox: %d\n", res);
12841 goto out;
12842 }
12843 ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
12844 vms.curmsg = vms.lastmsg;
12845 if (vms.lastmsg < 0) {
12846 cmd = ast_play_and_wait(chan, "vm-nomore");
12847 }
12848 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12849 vms.curmsg = vms.lastmsg;
12850 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
12851 } else {
12852 cmd = ast_play_and_wait(chan, "vm-nomore");
12853 }
12854 }
12855 break;
12856 case '6': /* Go to the next message */
12857 ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1);
12858 if (vms.curmsg < vms.lastmsg) {
12859 vms.curmsg++;
12860 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
12861 } else {
12862 if (in_urgent && vms.newmessages > 0) {
12863 /* Check if we were listening to urgent
12864 * messages. If so, go to regular new messages
12865 * instead of saying "no more messages"
12866 */
12867 in_urgent = 0;
12868 res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu);
12869 if (res == ERROR_LOCK_PATH) {
12870 ast_trace(-1, "close mailbox: %d\n", res);
12871 goto out;
12872 }
12873 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER);
12874 if (res < 0) {
12875 ast_trace(-1, "open mailbox: %d\n", res);
12876 goto out;
12877 }
12878 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12879 vms.curmsg = -1;
12880 if (vms.lastmsg < 0) {
12881 cmd = ast_play_and_wait(chan, "vm-nomore");
12882 }
12883 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12884 vms.curmsg = 0;
12885 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
12886 } else {
12887 cmd = ast_play_and_wait(chan, "vm-nomore");
12888 }
12889 }
12890 break;
12891 case '7': /* Delete the current message */
12892 if (!nodelete && vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
12893 vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
12894 if (useadsi)
12895 adsi_delete(chan, &vms);
12896 if (vms.deleted[vms.curmsg]) {
12897 if (play_folder == 0) {
12898 if (in_urgent) {
12899 vms.urgentmessages--;
12900 } else {
12901 vms.newmessages--;
12902 }
12903 }
12904 else if (play_folder == 1)
12905 vms.oldmessages--;
12906 cmd = ast_play_and_wait(chan, "vm-deleted");
12907 } else {
12908 if (play_folder == 0) {
12909 if (in_urgent) {
12910 vms.urgentmessages++;
12911 } else {
12912 vms.newmessages++;
12913 }
12914 }
12915 else if (play_folder == 1)
12916 vms.oldmessages++;
12917 cmd = ast_play_and_wait(chan, "vm-undeleted");
12918 }
12919 if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
12920 if (vms.curmsg < vms.lastmsg) {
12921 vms.curmsg++;
12922 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
12923 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
12924 vms.curmsg = 0;
12925 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
12926 } else {
12927 /* Check if we were listening to urgent
12928 messages. If so, go to regular new messages
12929 instead of saying "no more messages"
12930 */
12931 if (in_urgent == 1) {
12932 /* Check for new messages */
12933 in_urgent = 0;
12934 res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu);
12935 if (res == ERROR_LOCK_PATH) {
12936 ast_trace(-1, "close mailbox: %d\n", res);
12937 goto out;
12938 }
12939 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER);
12940 if (res < 0) {
12941 ast_trace(-1, "open mailbox: %d\n", res);
12942 goto out;
12943 }
12944 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12945 vms.curmsg = -1;
12946 if (vms.lastmsg < 0) {
12947 cmd = ast_play_and_wait(chan, "vm-nomore");
12948 }
12949 } else {
12950 cmd = ast_play_and_wait(chan, "vm-nomore");
12951 }
12952 }
12953 }
12954 } else /* Delete not valid if we haven't selected a message */
12955 cmd = 0;
12956#ifdef IMAP_STORAGE
12957 deleted = 1;
12958#endif
12959 break;
12960
12961 case '8': /* Forward the current message */
12962 if (vms.lastmsg > -1) {
12963 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, forward_message, chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
12964 if (cmd == ERROR_LOCK_PATH) {
12965 res = cmd;
12966 ast_trace(-1, "forward message: %d\n", res);
12967 goto out;
12968 }
12969 } else {
12970 /* Check if we were listening to urgent
12971 messages. If so, go to regular new messages
12972 instead of saying "no more messages"
12973 */
12974 if (in_urgent == 1 && vms.newmessages > 0) {
12975 /* Check for new messages */
12976 in_urgent = 0;
12977 res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu);
12978 if (res == ERROR_LOCK_PATH) {
12979 ast_trace(-1, "close mailbox: %d\n", res);
12980 goto out;
12981 }
12982 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER);
12983 if (res < 0) {
12984 ast_trace(-1, "open mailbox: %d\n", res);
12985 goto out;
12986 }
12987 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
12988 vms.curmsg = -1;
12989 if (vms.lastmsg < 0) {
12990 cmd = ast_play_and_wait(chan, "vm-nomore");
12991 }
12992 } else {
12993 cmd = ast_play_and_wait(chan, "vm-nomore");
12994 }
12995 }
12996 break;
12997 case '9': /* Save message to folder */
12998 ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
12999 if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
13000 /* No message selected */
13001 cmd = 0;
13002 break;
13003 }
13004 if (useadsi)
13005 adsi_folders(chan, 1, "Save to folder...");
13006 cmd = get_folder2(chan, "vm-savefolder", 1);
13007 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
13008 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
13009 box = 0; /* Shut up compiler */
13010 if (cmd == '#') {
13011 cmd = 0;
13012 break;
13013 } else if (cmd > 0) {
13014 box = cmd = cmd - '0';
13015 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, &vms, vms.curmsg, cmd, NULL, 0);
13016 if (cmd == ERROR_LOCK_PATH) {
13017 res = cmd;
13018 ast_trace(-1, "save to folder: %d\n", res);
13019 goto out;
13020#ifndef IMAP_STORAGE
13021 } else if (!cmd) {
13022 vms.deleted[vms.curmsg] = 1;
13023#endif
13024 } else {
13025 vms.deleted[vms.curmsg] = 0;
13026 vms.heard[vms.curmsg] = 0;
13027 }
13028 }
13029 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
13030 if (useadsi)
13031 adsi_message(chan, &vms);
13032 snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
13033 if (!cmd) {
13034 cmd = ast_play_and_wait(chan, "vm-message");
13035 if (!cmd)
13036 cmd = say_and_wait(chan, vms.curmsg + 1, ast_channel_language(chan));
13037 if (!cmd)
13038 cmd = ast_play_and_wait(chan, "vm-savedto");
13039 if (!cmd)
13040 cmd = vm_play_folder_name(chan, vms.fn);
13041 } else {
13042 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
13043 }
13045 if (vms.curmsg < vms.lastmsg) {
13046 vms.curmsg++;
13047 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
13048 } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
13049 vms.curmsg = 0;
13050 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms);
13051 } else {
13052 /* Check if we were listening to urgent
13053 messages. If so, go to regular new messages
13054 instead of saying "no more messages"
13055 */
13056 if (in_urgent == 1 && vms.newmessages > 0) {
13057 /* Check for new messages */
13058 in_urgent = 0;
13059 res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu);
13060 if (res == ERROR_LOCK_PATH) {
13061 ast_trace(-1, "close mailbox: %d\n", res);
13062 goto out;
13063 }
13064 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER);
13065 if (res < 0) {
13066 ast_trace(-1, "open mailbox: %d\n", res);
13067 goto out;
13068 }
13069 ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
13070 vms.curmsg = -1;
13071 if (vms.lastmsg < 0) {
13072 cmd = ast_play_and_wait(chan, "vm-nomore");
13073 }
13074 } else {
13075 cmd = ast_play_and_wait(chan, "vm-nomore");
13076 }
13077 }
13078 }
13079 break;
13080 case '*': /* Help */
13081 if (!vms.starting) {
13082 if (!strncasecmp(ast_channel_language(chan), "ja", 2)) {
13083 cmd = vm_play_folder_name(chan, vms.vmbox);
13084 if (!cmd)
13085 cmd = ast_play_and_wait(chan, "jp-wa");
13086 if (!cmd)
13087 cmd = ast_play_and_wait(chan, "digits/1");
13088 if (!cmd)
13089 cmd = ast_play_and_wait(chan, "jp-wo");
13090 if (!cmd)
13091 cmd = ast_play_and_wait(chan, "silence/1");
13092 if (!cmd)
13093 cmd = ast_play_and_wait(chan, "vm-opts");
13094 if (!cmd)
13095 cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete);
13096 break;
13097 }
13098 cmd = ast_play_and_wait(chan, "vm-onefor");
13099 if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
13100 cmd = ast_play_and_wait(chan, "vm-for");
13101 }
13102 if (!cmd)
13103 cmd = vm_play_folder_name(chan, vms.vmbox);
13104 if (!cmd)
13105 cmd = ast_play_and_wait(chan, "vm-opts");
13106 if (!cmd)
13107 cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete);
13108 } else
13109 cmd = 0;
13110 break;
13111 case '0': /* Mailbox options */
13112 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, vm_options,chan, vmu, &vms, vmfmts, record_gain);
13113 if (useadsi)
13114 adsi_status(chan, &vms);
13115 /* Reopen play_folder */
13116 res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, play_folder);
13117 if (res < 0) {
13118 ast_trace(-1, "open mailbox: %d\n", res);
13119 goto out;
13120 }
13121 vms.starting = 1;
13122 break;
13123 default: /* Nothing */
13124 ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
13125 cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent, nodelete);
13126 break;
13127 }
13128 }
13129 if ((cmd == 't') || (cmd == '#')) {
13130 /* Timeout */
13131 res = 0;
13132 } else {
13133 /* Hangup */
13134 res = -1;
13135 }
13136
13137out:
13138 if (res > -1) {
13139 ast_stopstream(chan);
13140 adsi_goodbye(chan);
13141 if (valid && res != OPERATOR_EXIT) {
13142 if (silentexit)
13143 res = ast_play_and_wait(chan, "vm-dialout");
13144 else
13145 res = ast_play_and_wait(chan, "vm-goodbye");
13146 }
13147 if ((valid && res > 0) || res == OPERATOR_EXIT) {
13148 res = 0;
13149 }
13150 if (useadsi)
13152 }
13153 if (vmu) {
13154 SCOPE_CALL(-1, close_mailbox, &vms, vmu);
13155 }
13156 if (valid) {
13157 int new = 0, old = 0, urgent = 0;
13158 snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
13159 /* Urgent flag not passwd to externnotify here */
13160 run_externnotify(vmu->context, vmu->mailbox, NULL);
13161 ast_app_inboxcount2(ext_context, &urgent, &new, &old);
13162 queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgent, new, old);
13163 }
13164#ifdef IMAP_STORAGE
13165 /* expunge message - use UID Expunge if supported on IMAP server*/
13166 ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
13167 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
13168 ast_mutex_lock(&vms.lock);
13169#ifdef HAVE_IMAP_TK2006
13170 if (LEVELUIDPLUS (vms.mailstream)) {
13171 mail_expunge_full(vms.mailstream, NIL, EX_UID);
13172 } else
13173#endif
13174 mail_expunge(vms.mailstream);
13175 ast_mutex_unlock(&vms.lock);
13176 }
13177 /* before we delete the state, we should copy pertinent info
13178 * back to the persistent model */
13179 if (vmu) {
13180 vmstate_delete(&vms);
13181 }
13182#endif
13183 if (vmu)
13184 free_user(vmu);
13185
13186#ifdef IMAP_STORAGE
13187 pthread_setspecific(ts_vmstate.key, NULL);
13188#endif
13189 SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res);
13190}
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_name(), 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_trace, 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(), SCOPE_CALL, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, 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 8354 of file app_voicemail_odbc.c.

8357{
8358 int cmd = 0;
8359 int retries = 0, prepend_duration = 0, already_recorded = 0;
8360 char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
8361 char textfile[PATH_MAX];
8362 struct ast_config *msg_cfg;
8363 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
8364#ifndef IMAP_STORAGE
8365 signed char zero_gain = 0;
8366#else
8367 const char *msg_id = NULL;
8368#endif
8369 const char *duration_str;
8370 SCOPE_ENTER(3, "mbox: %s msgnum: %d curdir: %s", vmu->mailbox, curmsg, curdir);
8371
8372 /* Must always populate duration correctly */
8373 make_file(msgfile, sizeof(msgfile), curdir, curmsg);
8374 ast_trace(-1, "msgfile: %s\n", msgfile);
8375 strcpy(textfile, msgfile);
8376 strcpy(backup, msgfile);
8377 strcpy(backup_textfile, msgfile);
8378 strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
8379 strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
8380 strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8381
8382 if ((msg_cfg = ast_config_load(textfile, config_flags)) && valid_config(msg_cfg) && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
8383 *duration = atoi(duration_str);
8384 } else {
8385 *duration = 0;
8386 }
8387
8388 while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
8389 if (cmd)
8390 retries = 0;
8391 switch (cmd) {
8392 case '1':
8393
8394#ifdef IMAP_STORAGE
8395 /* Record new intro file */
8396 if (msg_cfg && msg_cfg != CONFIG_STATUS_FILEINVALID) {
8397 msg_id = ast_variable_retrieve(msg_cfg, "message", "msg_id");
8398 }
8399 make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
8400 strncat(vms->introfn, "intro", sizeof(vms->introfn));
8401 ast_play_and_wait(chan, "vm-record-prepend");
8402 ast_play_and_wait(chan, "beep");
8403 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);
8404 if (cmd == -1) {
8405 break;
8406 }
8407 cmd = 't';
8408#else
8409
8410 /* prepend a message to the current message, update the metadata and return */
8411 ast_trace(-1, "Prepending to message %d\n", curmsg);
8412
8413 make_file(msgfile, sizeof(msgfile), curdir, curmsg);
8414 ast_trace(-1, "msgfile: %s\n", msgfile);
8415
8416 strcpy(textfile, msgfile);
8417 strncat(textfile, ".txt", sizeof(textfile) - 1);
8418 *duration = 0;
8419
8420 /* if we can't read the message metadata, stop now */
8421 if (!valid_config(msg_cfg)) {
8422 cmd = 0;
8423 break;
8424 }
8425
8426 /* Back up the original file, so we can retry the prepend and restore it after forward. */
8427#ifndef IMAP_STORAGE
8428 if (already_recorded) {
8429 ast_trace(-1, "Restoring '%s' to '%s'\n", backup, msgfile);
8430 ast_filecopy(backup, msgfile, NULL);
8431 copy(backup_textfile, textfile);
8432 }
8433 else {
8434 ast_trace(-1, "Backing up '%s' to '%s'\n", backup, msgfile);
8435 ast_filecopy(msgfile, backup, NULL);
8436 copy(textfile, backup_textfile);
8437 }
8438#endif
8439 already_recorded = 1;
8440
8441 if (record_gain)
8442 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
8443
8444 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, ast_play_and_prepend, chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
8445
8446 if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
8447 ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
8449 ast_filerename(backup, msgfile, NULL);
8450 }
8451
8452 if (record_gain)
8453 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
8454
8455
8456 if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
8457 *duration = atoi(duration_str);
8458
8459 if (prepend_duration) {
8460 struct ast_category *msg_cat;
8461 /* need enough space for a maximum-length message duration */
8462 char duration_buf[12];
8463
8464 *duration += prepend_duration;
8465 ast_trace(-1, "Prepending duration: %d total duration: %ld\n", prepend_duration, *duration);
8466 msg_cat = ast_category_get(msg_cfg, "message", NULL);
8467 snprintf(duration_buf, sizeof(duration_buf), "%ld", *duration);
8468 if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
8469 ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
8470 }
8471 }
8472
8473#endif
8474 break;
8475 case '2':
8476 /* NULL out introfile so we know there is no intro! */
8477#ifdef IMAP_STORAGE
8478 *vms->introfn = '\0';
8479#endif
8480 cmd = 't';
8481 break;
8482 case '*':
8483 cmd = '*';
8484 break;
8485 default:
8486 /* If time_out and return to menu, reset already_recorded */
8487 already_recorded = 0;
8488
8489 cmd = ast_play_and_wait(chan, "vm-forwardoptions");
8490 /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
8491 if (!cmd) {
8492 cmd = ast_play_and_wait(chan, "vm-starmain");
8493 /* "press star to return to the main menu" */
8494 }
8495 if (!cmd) {
8496 cmd = ast_waitfordigit(chan, 6000);
8497 }
8498 if (!cmd) {
8499 retries++;
8500 }
8501 if (retries > 3) {
8502 cmd = '*'; /* Let's cancel this beast */
8503 }
8504 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
8505 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
8506 }
8507 }
8508
8509 if (valid_config(msg_cfg))
8510 ast_config_destroy(msg_cfg);
8511 if (prepend_duration)
8512 *duration = prepend_duration;
8513
8514 if (already_recorded && cmd == -1) {
8515 /* restore original message if prepention cancelled */
8516 ast_trace(-1, "Restoring '%s' to '%s'\n", backup, msgfile);
8517 ast_filerename(backup, msgfile, NULL);
8518 rename(backup_textfile, textfile);
8519 }
8520
8521 if (cmd == 't' || cmd == 'S') { /* XXX entering this block with a value of 'S' is probably no longer possible. */
8522 cmd = 0;
8523 }
8524 SCOPE_EXIT_RTN_VALUE(cmd, "Done. CMD: %d %c\n", cmd, cmd >= 32 && cmd < 127 ? cmd : '?');
8525}
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:2159

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_trace, ast_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), CONFIG_FLAG_NOCACHE, CONFIG_STATUS_FILEINVALID, copy(), ast_vm_user::mailbox, make_file(), ast_vm_user::maxsecs, maxsilence, NULL, PATH_MAX, play_record_review(), SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, 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 2242 of file app_voicemail_odbc.c.

2243{
2244 return mbox(NULL, id);
2245}

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 11111 of file app_voicemail_odbc.c.

11112{
11113 if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
11114 return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11115 } else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
11116 return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11117 } else { /* Default to ENGLISH */
11118 return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11119 }
11120}
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 10901 of file app_voicemail_odbc.c.

10902{
10903 int res = 0;
10904 /* Play instructions and wait for new command */
10905 while (!res) {
10906 if (vms->starting) {
10907 if (vms->lastmsg > -1) {
10908 if (skipadvanced)
10909 res = ast_play_and_wait(chan, "vm-onefor-full");
10910 else
10911 res = ast_play_and_wait(chan, "vm-onefor");
10912 if (!res)
10913 res = vm_play_folder_name(chan, vms->vmbox);
10914 }
10915 if (!res) {
10916 if (skipadvanced)
10917 res = ast_play_and_wait(chan, "vm-opts-full");
10918 else
10919 res = ast_play_and_wait(chan, "vm-opts");
10920 }
10921 } else {
10922 /* Added for additional help */
10923 if (skipadvanced) {
10924 res = ast_play_and_wait(chan, "vm-onefor-full");
10925 if (!res)
10926 res = vm_play_folder_name(chan, vms->vmbox);
10927 res = ast_play_and_wait(chan, "vm-opts-full");
10928 }
10929 /* Logic:
10930 * If the current message is not the first OR
10931 * if we're listening to the first new message and there are
10932 * also urgent messages, then prompt for navigation to the
10933 * previous message
10934 */
10935 if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
10936 res = ast_play_and_wait(chan, "vm-prev");
10937 }
10938 if (!res && !skipadvanced)
10939 res = ast_play_and_wait(chan, "vm-advopts");
10940 if (!res)
10941 res = ast_play_and_wait(chan, "vm-repeat");
10942 /* Logic:
10943 * If we're not listening to the last message OR
10944 * we're listening to the last urgent message and there are
10945 * also new non-urgent messages, then prompt for navigation
10946 * to the next message
10947 */
10948 if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
10949 (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
10950 res = ast_play_and_wait(chan, "vm-next");
10951 }
10952 if (!res) {
10953 int curmsg_deleted;
10954#ifdef IMAP_STORAGE
10955 ast_mutex_lock(&vms->lock);
10956#endif
10957 curmsg_deleted = vms->deleted[vms->curmsg];
10958#ifdef IMAP_STORAGE
10959 ast_mutex_unlock(&vms->lock);
10960#endif
10961 if (!nodelete) {
10962 if (!curmsg_deleted) {
10963 res = ast_play_and_wait(chan, "vm-delete");
10964 } else {
10965 res = ast_play_and_wait(chan, "vm-undelete");
10966 }
10967 }
10968 if (!res) {
10969 res = ast_play_and_wait(chan, "vm-toforward");
10970 }
10971 if (!res) {
10972 res = ast_play_and_wait(chan, "vm-savemessage");
10973 }
10974 }
10975 }
10976 if (!res) {
10977 res = ast_play_and_wait(chan, "vm-helpexit");
10978 }
10979 if (!res)
10980 res = ast_waitfordigit(chan, 6000);
10981 if (!res) {
10982 vms->repeats++;
10983 if (vms->repeats > 2) {
10984 res = 't';
10985 }
10986 }
10987 }
10988 return res;
10989}

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 10991 of file app_voicemail_odbc.c.

10992{
10993 int res = 0;
10994 /* Play instructions and wait for new command */
10995 while (!res) {
10996 if (vms->starting) {
10997 if (vms->lastmsg > -1) {
10998 res = vm_play_folder_name(chan, vms->vmbox);
10999 if (!res)
11000 res = ast_play_and_wait(chan, "jp-wa");
11001 if (!res)
11002 res = ast_play_and_wait(chan, "digits/1");
11003 if (!res)
11004 res = ast_play_and_wait(chan, "jp-wo");
11005 if (!res)
11006 res = ast_play_and_wait(chan, "silence/1");
11007 }
11008 if (!res)
11009 res = ast_play_and_wait(chan, "vm-opts");
11010 } else {
11011 /* Added for additional help */
11012 if (skipadvanced) {
11013 res = vm_play_folder_name(chan, vms->vmbox);
11014 if (!res)
11015 res = ast_play_and_wait(chan, "jp-wa");
11016 if (!res)
11017 res = ast_play_and_wait(chan, "digits/1");
11018 if (!res)
11019 res = ast_play_and_wait(chan, "jp-wo");
11020 if (!res)
11021 res = ast_play_and_wait(chan, "silence/1");
11022 res = ast_play_and_wait(chan, "vm-opts-full");
11023 }
11024 /* Logic:
11025 * If the current message is not the first OR
11026 * if we're listening to the first new message and there are
11027 * also urgent messages, then prompt for navigation to the
11028 * previous message
11029 */
11030 if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
11031 res = ast_play_and_wait(chan, "vm-prev");
11032 }
11033 if (!res && !skipadvanced)
11034 res = ast_play_and_wait(chan, "vm-advopts");
11035 if (!res)
11036 res = ast_play_and_wait(chan, "vm-repeat");
11037 /* Logic:
11038 * If we're not listening to the last message OR
11039 * we're listening to the last urgent message and there are
11040 * also new non-urgent messages, then prompt for navigation
11041 * to the next message
11042 */
11043 if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
11044 (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
11045 res = ast_play_and_wait(chan, "vm-next");
11046 }
11047 if (!res) {
11048 int curmsg_deleted;
11049#ifdef IMAP_STORAGE
11050 ast_mutex_lock(&vms->lock);
11051#endif
11052 curmsg_deleted = vms->deleted[vms->curmsg];
11053#ifdef IMAP_STORAGE
11054 ast_mutex_unlock(&vms->lock);
11055#endif
11056 if (!curmsg_deleted) {
11057 res = ast_play_and_wait(chan, "vm-delete");
11058 } else {
11059 res = ast_play_and_wait(chan, "vm-undelete");
11060 }
11061 if (!res) {
11062 res = ast_play_and_wait(chan, "vm-toforward");
11063 }
11064 if (!res) {
11065 res = ast_play_and_wait(chan, "vm-savemessage");
11066 }
11067 }
11068 }
11069
11070 if (!res) {
11071 res = ast_play_and_wait(chan, "vm-helpexit");
11072 }
11073 if (!res)
11074 res = ast_waitfordigit(chan, 6000);
11075 if (!res) {
11076 vms->repeats++;
11077 if (vms->repeats > 2) {
11078 res = 't';
11079 }
11080 }
11081
11082 }
11083
11084 return res;
11085}

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 11087 of file app_voicemail_odbc.c.

11088{
11089 int res = 0;
11090 /* Play instructions and wait for new command */
11091 while (!res) {
11092 if (vms->lastmsg > -1) {
11093 res = ast_play_and_wait(chan, "vm-listen");
11094 if (!res)
11095 res = vm_play_folder_name(chan, vms->vmbox);
11096 if (!res)
11097 res = ast_play_and_wait(chan, "press");
11098 if (!res)
11099 res = ast_play_and_wait(chan, "digits/1");
11100 }
11101 if (!res)
11102 res = ast_play_and_wait(chan, "vm-opts");
11103 if (!res) {
11104 vms->starting = 0;
11105 return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11106 }
11107 }
11108 return res;
11109}

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 10833 of file app_voicemail_odbc.c.

10834{
10835 char prefile[256];
10836
10837 /* Notify the user that the temp greeting is set and give them the option to remove it */
10838 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
10839 if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10840 RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
10841 if (ast_fileexists(prefile, NULL, NULL) > 0) {
10842 ast_play_and_wait(chan, "vm-tempgreetactive");
10843 }
10844 DISPOSE(prefile, -1);
10845 }
10846
10847 /* Play voicemail intro - syntax is different for different languages */
10848 if (0) {
10849 return 0;
10850 } else if (!strncasecmp(ast_channel_language(chan), "cs", 2)) { /* CZECH syntax */
10851 return vm_intro_cs(chan, vms);
10852 } else if (!strncasecmp(ast_channel_language(chan), "cz", 2)) { /* deprecated CZECH syntax */
10853 static int deprecation_warning = 0;
10854 if (deprecation_warning++ % 10 == 0) {
10855 ast_log(LOG_WARNING, "cz is not a standard language code. Please switch to using cs instead.\n");
10856 }
10857 return vm_intro_cs(chan, vms);
10858 } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */
10859 return vm_intro_de(chan, vms);
10860 } else if (!strncasecmp(ast_channel_language(chan), "es", 2)) { /* SPANISH syntax */
10861 return vm_intro_es(chan, vms);
10862 } else if (!strncasecmp(ast_channel_language(chan), "fr", 2)) { /* FRENCH syntax */
10863 return vm_intro_fr(chan, vms);
10864 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */
10865 return vm_intro_gr(chan, vms);
10866 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW syntax */
10867 return vm_intro_he(chan, vms);
10868 } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC syntax */
10869 return vm_intro_is(chan, vms);
10870 } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */
10871 return vm_intro_it(chan, vms);
10872 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE syntax */
10873 return vm_intro_ja(chan, vms);
10874 } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */
10875 return vm_intro_nl(chan, vms);
10876 } else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
10877 return vm_intro_no(chan, vms);
10878 } else if (!strncasecmp(ast_channel_language(chan), "da", 2)) { /* DANISH syntax */
10879 return vm_intro_da(chan, vms);
10880 } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
10881 return vm_intro_pl(chan, vms);
10882 } else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* BRAZILIAN PORTUGUESE syntax */
10883 return vm_intro_pt_BR(chan, vms);
10884 } else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE syntax */
10885 return vm_intro_pt(chan, vms);
10886 } else if (!strncasecmp(ast_channel_language(chan), "ru", 2)) { /* RUSSIAN syntax */
10887 return vm_intro_multilang(chan, vms, "n");
10888 } else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
10889 return vm_intro_se(chan, vms);
10890 } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* UKRAINIAN syntax */
10891 return vm_intro_multilang(chan, vms, "n");
10892 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE syntax */
10893 return vm_intro_vi(chan, vms);
10894 } else if (!strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
10895 return vm_intro_zh(chan, vms);
10896 } else { /* Default to ENGLISH */
10897 return vm_intro_en(chan, vms);
10898 }
10899}
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 10703 of file app_voicemail_odbc.c.

10704{
10705 int res;
10706 res = ast_play_and_wait(chan, "vm-youhave");
10707 if (!res) {
10708 if (vms->newmessages) {
10709 if (vms->newmessages == 1) {
10710 res = ast_play_and_wait(chan, "digits/jednu");
10711 } else {
10712 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10713 }
10714 if (!res) {
10715 if (vms->newmessages == 1)
10716 res = ast_play_and_wait(chan, "vm-novou");
10717 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
10718 res = ast_play_and_wait(chan, "vm-nove");
10719 if (vms->newmessages > 4)
10720 res = ast_play_and_wait(chan, "vm-novych");
10721 }
10722 if (vms->oldmessages && !res)
10723 res = ast_play_and_wait(chan, "vm-and");
10724 else if (!res) {
10725 if (vms->newmessages == 1)
10726 res = ast_play_and_wait(chan, "vm-zpravu");
10727 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
10728 res = ast_play_and_wait(chan, "vm-zpravy");
10729 if (vms->newmessages > 4)
10730 res = ast_play_and_wait(chan, "vm-zprav");
10731 }
10732 }
10733 if (!res && vms->oldmessages) {
10734 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10735 if (!res) {
10736 if (vms->oldmessages == 1)
10737 res = ast_play_and_wait(chan, "vm-starou");
10738 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
10739 res = ast_play_and_wait(chan, "vm-stare");
10740 if (vms->oldmessages > 4)
10741 res = ast_play_and_wait(chan, "vm-starych");
10742 }
10743 if (!res) {
10744 if (vms->oldmessages == 1)
10745 res = ast_play_and_wait(chan, "vm-zpravu");
10746 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
10747 res = ast_play_and_wait(chan, "vm-zpravy");
10748 if (vms->oldmessages > 4)
10749 res = ast_play_and_wait(chan, "vm-zprav");
10750 }
10751 }
10752 if (!res) {
10753 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10754 res = ast_play_and_wait(chan, "vm-no");
10755 if (!res)
10756 res = ast_play_and_wait(chan, "vm-zpravy");
10757 }
10758 }
10759 }
10760 return res;
10761}

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 10354 of file app_voicemail_odbc.c.

10355{
10356 /* Introduce messages they have */
10357 int res;
10358
10359 res = ast_play_and_wait(chan, "vm-youhave");
10360 if (res)
10361 return res;
10362
10363 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10364 res = ast_play_and_wait(chan, "vm-no");
10365 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10366 return res;
10367 }
10368
10369 if (vms->newmessages) {
10370 if ((vms->newmessages == 1)) {
10371 res = ast_play_and_wait(chan, "digits/1");
10372 res = res ? res : ast_play_and_wait(chan, "vm-INBOX");
10373 res = res ? res : ast_play_and_wait(chan, "vm-message");
10374 } else {
10375 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10376 res = res ? res : ast_play_and_wait(chan, "vm-INBOXs");
10377 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10378 }
10379 if (!res && vms->oldmessages)
10380 res = ast_play_and_wait(chan, "vm-and");
10381 }
10382 if (!res && vms->oldmessages) {
10383 if (vms->oldmessages == 1) {
10384 res = ast_play_and_wait(chan, "digits/1");
10385 res = res ? res : ast_play_and_wait(chan, "vm-Old");
10386 res = res ? res : ast_play_and_wait(chan, "vm-message");
10387 } else {
10388 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10389 res = res ? res : ast_play_and_wait(chan, "vm-Olds");
10390 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10391 }
10392 }
10393
10394 return res;
10395}

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 10399 of file app_voicemail_odbc.c.

10400{
10401 /* Introduce messages they have */
10402 int res;
10403 res = ast_play_and_wait(chan, "vm-youhave");
10404 if (!res) {
10405 if (vms->newmessages) {
10406 if (vms->newmessages == 1)
10407 res = ast_play_and_wait(chan, "digits/1F");
10408 else
10409 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10410 if (!res)
10411 res = ast_play_and_wait(chan, "vm-INBOX");
10412 if (vms->oldmessages && !res)
10413 res = ast_play_and_wait(chan, "vm-and");
10414 else if (!res) {
10415 if (vms->newmessages == 1)
10416 res = ast_play_and_wait(chan, "vm-message");
10417 else
10418 res = ast_play_and_wait(chan, "vm-messages");
10419 }
10420
10421 }
10422 if (!res && vms->oldmessages) {
10423 if (vms->oldmessages == 1)
10424 res = ast_play_and_wait(chan, "digits/1F");
10425 else
10426 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10427 if (!res)
10428 res = ast_play_and_wait(chan, "vm-Old");
10429 if (!res) {
10430 if (vms->oldmessages == 1)
10431 res = ast_play_and_wait(chan, "vm-message");
10432 else
10433 res = ast_play_and_wait(chan, "vm-messages");
10434 }
10435 }
10436 if (!res) {
10437 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10438 res = ast_play_and_wait(chan, "vm-no");
10439 if (!res)
10440 res = ast_play_and_wait(chan, "vm-messages");
10441 }
10442 }
10443 }
10444 return res;
10445}

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 10034 of file app_voicemail_odbc.c.

10035{
10036 int res;
10037
10038 /* Introduce messages they have */
10039 res = ast_play_and_wait(chan, "vm-youhave");
10040 if (!res) {
10041 if (vms->urgentmessages) {
10042 res = say_and_wait(chan, vms->urgentmessages, ast_channel_language(chan));
10043 if (!res)
10044 res = ast_play_and_wait(chan, "vm-Urgent");
10045 if ((vms->oldmessages || vms->newmessages) && !res) {
10046 res = ast_play_and_wait(chan, "vm-and");
10047 } else if (!res) {
10048 if (vms->urgentmessages == 1)
10049 res = ast_play_and_wait(chan, "vm-message");
10050 else
10051 res = ast_play_and_wait(chan, "vm-messages");
10052 }
10053 }
10054 if (vms->newmessages) {
10055 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10056 if (!res)
10057 res = ast_play_and_wait(chan, "vm-INBOX");
10058 if (vms->oldmessages && !res)
10059 res = ast_play_and_wait(chan, "vm-and");
10060 else if (!res) {
10061 if (vms->newmessages == 1)
10062 res = ast_play_and_wait(chan, "vm-message");
10063 else
10064 res = ast_play_and_wait(chan, "vm-messages");
10065 }
10066
10067 }
10068 if (!res && vms->oldmessages) {
10069 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10070 if (!res)
10071 res = ast_play_and_wait(chan, "vm-Old");
10072 if (!res) {
10073 if (vms->oldmessages == 1)
10074 res = ast_play_and_wait(chan, "vm-message");
10075 else
10076 res = ast_play_and_wait(chan, "vm-messages");
10077 }
10078 }
10079 if (!res) {
10080 if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
10081 res = ast_play_and_wait(chan, "vm-no");
10082 if (!res)
10083 res = ast_play_and_wait(chan, "vm-messages");
10084 }
10085 }
10086 }
10087 return res;
10088}

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 10448 of file app_voicemail_odbc.c.

10449{
10450 /* Introduce messages they have */
10451 int res;
10452 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10453 res = ast_play_and_wait(chan, "vm-youhaveno");
10454 if (!res)
10455 res = ast_play_and_wait(chan, "vm-messages");
10456 } else {
10457 res = ast_play_and_wait(chan, "vm-youhave");
10458 }
10459 if (!res) {
10460 if (vms->newmessages) {
10461 if (!res) {
10462 if (vms->newmessages == 1) {
10463 res = ast_play_and_wait(chan, "digits/1M");
10464 if (!res)
10465 res = ast_play_and_wait(chan, "vm-message");
10466 if (!res)
10467 res = ast_play_and_wait(chan, "vm-INBOXs");
10468 } else {
10469 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10470 if (!res)
10471 res = ast_play_and_wait(chan, "vm-messages");
10472 if (!res)
10473 res = ast_play_and_wait(chan, "vm-INBOX");
10474 }
10475 }
10476 if (vms->oldmessages && !res)
10477 res = ast_play_and_wait(chan, "vm-and");
10478 }
10479 if (vms->oldmessages) {
10480 if (!res) {
10481 if (vms->oldmessages == 1) {
10482 res = ast_play_and_wait(chan, "digits/1M");
10483 if (!res)
10484 res = ast_play_and_wait(chan, "vm-message");
10485 if (!res)
10486 res = ast_play_and_wait(chan, "vm-Olds");
10487 } else {
10488 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10489 if (!res)
10490 res = ast_play_and_wait(chan, "vm-messages");
10491 if (!res)
10492 res = ast_play_and_wait(chan, "vm-Old");
10493 }
10494 }
10495 }
10496 }
10497return res;
10498}

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 10546 of file app_voicemail_odbc.c.

10547{
10548 /* Introduce messages they have */
10549 int res;
10550 res = ast_play_and_wait(chan, "vm-youhave");
10551 if (!res) {
10552 if (vms->newmessages) {
10553 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10554 if (!res)
10555 res = ast_play_and_wait(chan, "vm-INBOX");
10556 if (vms->oldmessages && !res)
10557 res = ast_play_and_wait(chan, "vm-and");
10558 else if (!res) {
10559 if (vms->newmessages == 1)
10560 res = ast_play_and_wait(chan, "vm-message");
10561 else
10562 res = ast_play_and_wait(chan, "vm-messages");
10563 }
10564
10565 }
10566 if (!res && vms->oldmessages) {
10567 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10568 if (!res)
10569 res = ast_play_and_wait(chan, "vm-Old");
10570 if (!res) {
10571 if (vms->oldmessages == 1)
10572 res = ast_play_and_wait(chan, "vm-message");
10573 else
10574 res = ast_play_and_wait(chan, "vm-messages");
10575 }
10576 }
10577 if (!res) {
10578 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10579 res = ast_play_and_wait(chan, "vm-no");
10580 if (!res)
10581 res = ast_play_and_wait(chan, "vm-messages");
10582 }
10583 }
10584 }
10585 return res;
10586}

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 9794 of file app_voicemail_odbc.c.

9795{
9796 int res = 0;
9797
9798 if (vms->newmessages) {
9799 res = ast_play_and_wait(chan, "vm-youhave");
9800 if (!res)
9802 if (!res) {
9803 if (vms->newmessages == 1) {
9804 res = ast_play_and_wait(chan, "vm-INBOX");
9805 if (!res)
9806 res = ast_play_and_wait(chan, "vm-message");
9807 } else {
9808 res = ast_play_and_wait(chan, "vm-INBOXs");
9809 if (!res)
9810 res = ast_play_and_wait(chan, "vm-messages");
9811 }
9812 }
9813 } else if (vms->oldmessages){
9814 res = ast_play_and_wait(chan, "vm-youhave");
9815 if (!res)
9817 if (vms->oldmessages == 1){
9818 res = ast_play_and_wait(chan, "vm-Old");
9819 if (!res)
9820 res = ast_play_and_wait(chan, "vm-message");
9821 } else {
9822 res = ast_play_and_wait(chan, "vm-Olds");
9823 if (!res)
9824 res = ast_play_and_wait(chan, "vm-messages");
9825 }
9826 } else if (!vms->oldmessages && !vms->newmessages)
9827 res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
9828 return res;
9829}

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 9928 of file app_voicemail_odbc.c.

9929{
9930 int res = 0;
9931
9932 /* Introduce messages they have */
9933 if (!res) {
9934 if ((vms->newmessages) || (vms->oldmessages)) {
9935 res = ast_play_and_wait(chan, "vm-youhave");
9936 }
9937 /*
9938 * The word "shtei" refers to the number 2 in hebrew when performing a count
9939 * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
9940 * an element, this is one of them.
9941 */
9942 if (vms->newmessages) {
9943 if (!res) {
9944 if (vms->newmessages == 1) {
9945 res = ast_play_and_wait(chan, "vm-INBOX1");
9946 } else {
9947 if (vms->newmessages == 2) {
9948 res = ast_play_and_wait(chan, "vm-shtei");
9949 } else {
9950 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9951 }
9952 res = ast_play_and_wait(chan, "vm-INBOX");
9953 }
9954 }
9955 if (vms->oldmessages && !res) {
9956 res = ast_play_and_wait(chan, "vm-and");
9957 if (vms->oldmessages == 1) {
9958 res = ast_play_and_wait(chan, "vm-Old1");
9959 } else {
9960 if (vms->oldmessages == 2) {
9961 res = ast_play_and_wait(chan, "vm-shtei");
9962 } else {
9963 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9964 }
9965 res = ast_play_and_wait(chan, "vm-Old");
9966 }
9967 }
9968 }
9969 if (!res && vms->oldmessages && !vms->newmessages) {
9970 if (!res) {
9971 if (vms->oldmessages == 1) {
9972 res = ast_play_and_wait(chan, "vm-Old1");
9973 } else {
9974 if (vms->oldmessages == 2) {
9975 res = ast_play_and_wait(chan, "vm-shtei");
9976 } else {
9977 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
9978 }
9979 res = ast_play_and_wait(chan, "vm-Old");
9980 }
9981 }
9982 }
9983 if (!res) {
9984 if (!vms->oldmessages && !vms->newmessages) {
9985 if (!res) {
9986 res = ast_play_and_wait(chan, "vm-nomessages");
9987 }
9988 }
9989 }
9990 }
9991 return res;
9992}

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 10091 of file app_voicemail_odbc.c.

10092{
10093 int res;
10094
10095 /* Introduce messages they have */
10096 res = ast_play_and_wait(chan, "vm-youhave");
10097 if (!res) {
10098 if (vms->urgentmessages) {
10099 /* Digits 1-4 are spoken in neutral and plural when talking about messages,
10100 however, feminine is used for 1 as it is the same as the neutral for plural,
10101 and singular neutral is the same after 1. */
10102 if (vms->urgentmessages < 5) {
10103 char recname[16];
10104 if (vms->urgentmessages == 1)
10105 snprintf(recname, sizeof(recname), "digits/1kvk");
10106 else
10107 snprintf(recname, sizeof(recname), "digits/%dhk", vms->urgentmessages);
10108 res = ast_play_and_wait(chan, recname);
10109 } else if (!res)
10110 res = ast_play_and_wait(chan, "vm-Urgent");
10111 if ((vms->oldmessages || vms->newmessages) && !res) {
10112 res = ast_play_and_wait(chan, "vm-and");
10113 } else if (!res)
10114 res = ast_play_and_wait(chan, "vm-messages");
10115 }
10116 if (vms->newmessages) {
10117 if (vms->newmessages < 5) {
10118 char recname[16];
10119 if (vms->newmessages == 1)
10120 snprintf(recname, sizeof(recname), "digits/1kvk");
10121 else
10122 snprintf(recname, sizeof(recname), "digits/%dhk", vms->newmessages);
10123 res = ast_play_and_wait(chan, recname);
10124 } else
10125 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10126 if (!res)
10127 res = ast_play_and_wait(chan, "vm-INBOX");
10128 if (vms->oldmessages && !res)
10129 res = ast_play_and_wait(chan, "vm-and");
10130 else if (!res)
10131 res = ast_play_and_wait(chan, "vm-messages");
10132 }
10133 if (!res && vms->oldmessages) {
10134 if (vms->oldmessages < 5) {
10135 char recname[16];
10136 if (vms->oldmessages == 1)
10137 snprintf(recname, sizeof(recname), "digits/1kvk");
10138 else
10139 snprintf(recname, sizeof(recname), "digits/%dhk", vms->oldmessages);
10140 res = ast_play_and_wait(chan, recname);
10141 } else
10142 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10143 if (!res)
10144 res = ast_play_and_wait(chan, "vm-Old");
10145 if (!res)
10146 res = ast_play_and_wait(chan, "vm-messages");
10147 }
10148 if (!res) {
10149 if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
10150 res = ast_play_and_wait(chan, "vm-no");
10151 if (!res)
10152 res = ast_play_and_wait(chan, "vm-messages");
10153 }
10154 }
10155 }
10156 return res;
10157}

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 10160 of file app_voicemail_odbc.c.

10161{
10162 /* Introduce messages they have */
10163 int res;
10164 if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
10165 res = ast_play_and_wait(chan, "vm-no") ||
10166 ast_play_and_wait(chan, "vm-message");
10167 else
10168 res = ast_play_and_wait(chan, "vm-youhave");
10169 if (!res && vms->newmessages) {
10170 res = (vms->newmessages == 1) ?
10171 ast_play_and_wait(chan, "digits/un") ||
10172 ast_play_and_wait(chan, "vm-nuovo") ||
10173 ast_play_and_wait(chan, "vm-message") :
10174 /* 2 or more new messages */
10175 say_and_wait(chan, vms->newmessages, ast_channel_language(chan)) ||
10176 ast_play_and_wait(chan, "vm-nuovi") ||
10177 ast_play_and_wait(chan, "vm-messages");
10178 if (!res && vms->oldmessages)
10179 res = ast_play_and_wait(chan, "vm-and");
10180 }
10181 if (!res && vms->oldmessages) {
10182 res = (vms->oldmessages == 1) ?
10183 ast_play_and_wait(chan, "digits/un") ||
10184 ast_play_and_wait(chan, "vm-vecchio") ||
10185 ast_play_and_wait(chan, "vm-message") :
10186 /* 2 or more old messages */
10187 say_and_wait(chan, vms->oldmessages, ast_channel_language(chan)) ||
10188 ast_play_and_wait(chan, "vm-vecchi") ||
10189 ast_play_and_wait(chan, "vm-messages");
10190 }
10191 return res;
10192}

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 9995 of file app_voicemail_odbc.c.

9996{
9997 /* Introduce messages they have */
9998 int res;
9999 if (vms->newmessages) {
10000 res = ast_play_and_wait(chan, "vm-INBOX");
10001 if (!res)
10002 res = ast_play_and_wait(chan, "vm-message");
10003 if (!res)
10004 res = ast_play_and_wait(chan, "jp-ga");
10005 if (!res)
10006 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10007 if (vms->oldmessages && !res)
10008 res = ast_play_and_wait(chan, "silence/1");
10009
10010 }
10011 if (vms->oldmessages) {
10012 res = ast_play_and_wait(chan, "vm-Old");
10013 if (!res)
10014 res = ast_play_and_wait(chan, "vm-message");
10015 if (!res)
10016 res = ast_play_and_wait(chan, "jp-ga");
10017 if (!res)
10018 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10019 }
10020 if (!vms->oldmessages && !vms->newmessages) {
10021 res = ast_play_and_wait(chan, "vm-messages");
10022 if (!res)
10023 res = ast_play_and_wait(chan, "jp-wa");
10024 if (!res)
10025 res = ast_play_and_wait(chan, "jp-arimasen");
10026 }
10027 else {
10028 res = ast_play_and_wait(chan, "jp-arimasu");
10029 }
10030 return res;
10031} /* 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 9888 of file app_voicemail_odbc.c.

9889{
9890 int res;
9891 int lastnum = 0;
9892
9893 res = ast_play_and_wait(chan, "vm-youhave");
9894
9895 if (!res && vms->newmessages) {
9896 lastnum = vms->newmessages;
9897
9898 if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
9899 res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
9900 }
9901
9902 if (!res && vms->oldmessages) {
9903 res = ast_play_and_wait(chan, "vm-and");
9904 }
9905 }
9906
9907 if (!res && vms->oldmessages) {
9908 lastnum = vms->oldmessages;
9909
9910 if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, ast_channel_language(chan), message_gender))) {
9911 res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
9912 }
9913 }
9914
9915 if (!res) {
9916 if (lastnum == 0) {
9917 res = ast_play_and_wait(chan, "vm-no");
9918 }
9919 if (!res) {
9920 res = ast_say_counted_noun(chan, lastnum, "vm-message");
9921 }
9922 }
9923
9924 return res;
9925}
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 10589 of file app_voicemail_odbc.c.

10590{
10591 /* Introduce messages they have */
10592 int res;
10593 res = ast_play_and_wait(chan, "vm-youhave");
10594 if (!res) {
10595 if (vms->newmessages) {
10596 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10597 if (!res) {
10598 if (vms->newmessages == 1)
10599 res = ast_play_and_wait(chan, "vm-INBOXs");
10600 else
10601 res = ast_play_and_wait(chan, "vm-INBOX");
10602 }
10603 if (vms->oldmessages && !res)
10604 res = ast_play_and_wait(chan, "vm-and");
10605 else if (!res) {
10606 if (vms->newmessages == 1)
10607 res = ast_play_and_wait(chan, "vm-message");
10608 else
10609 res = ast_play_and_wait(chan, "vm-messages");
10610 }
10611
10612 }
10613 if (!res && vms->oldmessages) {
10614 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10615 if (!res) {
10616 if (vms->oldmessages == 1)
10617 res = ast_play_and_wait(chan, "vm-Olds");
10618 else
10619 res = ast_play_and_wait(chan, "vm-Old");
10620 }
10621 if (!res) {
10622 if (vms->oldmessages == 1)
10623 res = ast_play_and_wait(chan, "vm-message");
10624 else
10625 res = ast_play_and_wait(chan, "vm-messages");
10626 }
10627 }
10628 if (!res) {
10629 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10630 res = ast_play_and_wait(chan, "vm-no");
10631 if (!res)
10632 res = ast_play_and_wait(chan, "vm-messages");
10633 }
10634 }
10635 }
10636 return res;
10637}

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 10310 of file app_voicemail_odbc.c.

10311{
10312 /* Introduce messages they have */
10313 int res;
10314
10315 res = ast_play_and_wait(chan, "vm-youhave");
10316 if (res)
10317 return res;
10318
10319 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10320 res = ast_play_and_wait(chan, "vm-no");
10321 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10322 return res;
10323 }
10324
10325 if (vms->newmessages) {
10326 if (vms->newmessages == 1) {
10327 res = ast_play_and_wait(chan, "digits/1");
10328 res = res ? res : ast_play_and_wait(chan, "vm-ny");
10329 res = res ? res : ast_play_and_wait(chan, "vm-message");
10330 } else {
10331 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10332 res = res ? res : ast_play_and_wait(chan, "vm-nye");
10333 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10334 }
10335 if (!res && vms->oldmessages)
10336 res = ast_play_and_wait(chan, "vm-and");
10337 }
10338 if (!res && vms->oldmessages) {
10339 if (vms->oldmessages == 1) {
10340 res = ast_play_and_wait(chan, "digits/1");
10341 res = res ? res : ast_play_and_wait(chan, "vm-gamel");
10342 res = res ? res : ast_play_and_wait(chan, "vm-message");
10343 } else {
10344 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10345 res = res ? res : ast_play_and_wait(chan, "vm-gamle");
10346 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10347 }
10348 }
10349
10350 return res;
10351}

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 10195 of file app_voicemail_odbc.c.

10196{
10197 /* Introduce messages they have */
10198 int res;
10199 div_t num;
10200
10201 if (!vms->oldmessages && !vms->newmessages) {
10202 res = ast_play_and_wait(chan, "vm-no");
10203 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10204 return res;
10205 } else {
10206 res = ast_play_and_wait(chan, "vm-youhave");
10207 }
10208
10209 if (vms->newmessages) {
10210 num = div(vms->newmessages, 10);
10211 if (vms->newmessages == 1) {
10212 res = ast_play_and_wait(chan, "digits/1-a");
10213 res = res ? res : ast_play_and_wait(chan, "vm-new-a");
10214 res = res ? res : ast_play_and_wait(chan, "vm-message");
10215 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10216 if (num.rem == 2) {
10217 if (!num.quot) {
10218 res = ast_play_and_wait(chan, "digits/2-ie");
10219 } else {
10220 res = say_and_wait(chan, vms->newmessages - 2 , ast_channel_language(chan));
10221 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
10222 }
10223 } else {
10224 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10225 }
10226 res = res ? res : ast_play_and_wait(chan, "vm-new-e");
10227 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10228 } else {
10229 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10230 res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
10231 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10232 }
10233 if (!res && vms->oldmessages)
10234 res = ast_play_and_wait(chan, "vm-and");
10235 }
10236 if (!res && vms->oldmessages) {
10237 num = div(vms->oldmessages, 10);
10238 if (vms->oldmessages == 1) {
10239 res = ast_play_and_wait(chan, "digits/1-a");
10240 res = res ? res : ast_play_and_wait(chan, "vm-old-a");
10241 res = res ? res : ast_play_and_wait(chan, "vm-message");
10242 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10243 if (num.rem == 2) {
10244 if (!num.quot) {
10245 res = ast_play_and_wait(chan, "digits/2-ie");
10246 } else {
10247 res = say_and_wait(chan, vms->oldmessages - 2 , ast_channel_language(chan));
10248 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
10249 }
10250 } else {
10251 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10252 }
10253 res = res ? res : ast_play_and_wait(chan, "vm-old-e");
10254 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10255 } else {
10256 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10257 res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
10258 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10259 }
10260 }
10261
10262 return res;
10263}

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 10640 of file app_voicemail_odbc.c.

10641{
10642 /* Introduce messages they have */
10643 int res;
10644 res = ast_play_and_wait(chan, "vm-youhave");
10645 if (!res) {
10646 if (vms->newmessages) {
10647 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10648 if (!res) {
10649 if (vms->newmessages == 1) {
10650 res = ast_play_and_wait(chan, "vm-message");
10651 if (!res)
10652 res = ast_play_and_wait(chan, "vm-INBOXs");
10653 } else {
10654 res = ast_play_and_wait(chan, "vm-messages");
10655 if (!res)
10656 res = ast_play_and_wait(chan, "vm-INBOX");
10657 }
10658 }
10659 if (vms->oldmessages && !res)
10660 res = ast_play_and_wait(chan, "vm-and");
10661 }
10662 if (!res && vms->oldmessages) {
10663 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10664 if (!res) {
10665 if (vms->oldmessages == 1) {
10666 res = ast_play_and_wait(chan, "vm-message");
10667 if (!res)
10668 res = ast_play_and_wait(chan, "vm-Olds");
10669 } else {
10670 res = ast_play_and_wait(chan, "vm-messages");
10671 if (!res)
10672 res = ast_play_and_wait(chan, "vm-Old");
10673 }
10674 }
10675 }
10676 if (!res) {
10677 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10678 res = ast_play_and_wait(chan, "vm-no");
10679 if (!res)
10680 res = ast_play_and_wait(chan, "vm-messages");
10681 }
10682 }
10683 }
10684 return res;
10685}

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 10501 of file app_voicemail_odbc.c.

10501 {
10502 /* Introduce messages they have */
10503 int res;
10504 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10505 res = ast_play_and_wait(chan, "vm-nomessages");
10506 return res;
10507 } else {
10508 res = ast_play_and_wait(chan, "vm-youhave");
10509 }
10510 if (vms->newmessages) {
10511 if (!res)
10512 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10513 if (vms->newmessages == 1) {
10514 if (!res)
10515 res = ast_play_and_wait(chan, "vm-message");
10516 if (!res)
10517 res = ast_play_and_wait(chan, "vm-INBOXs");
10518 } else {
10519 if (!res)
10520 res = ast_play_and_wait(chan, "vm-messages");
10521 if (!res)
10522 res = ast_play_and_wait(chan, "vm-INBOX");
10523 }
10524 if (vms->oldmessages && !res)
10525 res = ast_play_and_wait(chan, "vm-and");
10526 }
10527 if (vms->oldmessages) {
10528 if (!res)
10529 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, ast_channel_language(chan), "f");
10530 if (vms->oldmessages == 1) {
10531 if (!res)
10532 res = ast_play_and_wait(chan, "vm-message");
10533 if (!res)
10534 res = ast_play_and_wait(chan, "vm-Olds");
10535 } else {
10536 if (!res)
10537 res = ast_play_and_wait(chan, "vm-messages");
10538 if (!res)
10539 res = ast_play_and_wait(chan, "vm-Old");
10540 }
10541 }
10542 return res;
10543}

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 10266 of file app_voicemail_odbc.c.

10267{
10268 /* Introduce messages they have */
10269 int res;
10270
10271 res = ast_play_and_wait(chan, "vm-youhave");
10272 if (res)
10273 return res;
10274
10275 if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
10276 res = ast_play_and_wait(chan, "vm-no");
10277 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10278 return res;
10279 }
10280
10281 if (vms->newmessages) {
10282 if (vms->newmessages == 1) {
10283 res = ast_play_and_wait(chan, "digits/ett");
10284 res = res ? res : ast_play_and_wait(chan, "vm-nytt");
10285 res = res ? res : ast_play_and_wait(chan, "vm-message");
10286 } else {
10287 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10288 res = res ? res : ast_play_and_wait(chan, "vm-nya");
10289 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10290 }
10291 if (!res && vms->oldmessages)
10292 res = ast_play_and_wait(chan, "vm-and");
10293 }
10294 if (!res && vms->oldmessages) {
10295 if (vms->oldmessages == 1) {
10296 res = ast_play_and_wait(chan, "digits/ett");
10297 res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
10298 res = res ? res : ast_play_and_wait(chan, "vm-message");
10299 } else {
10300 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10301 res = res ? res : ast_play_and_wait(chan, "vm-gamla");
10302 res = res ? res : ast_play_and_wait(chan, "vm-messages");
10303 }
10304 }
10305
10306 return res;
10307}

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 10803 of file app_voicemail_odbc.c.

10804{
10805 int res;
10806
10807 /* Introduce messages they have */
10808 res = ast_play_and_wait(chan, "vm-youhave");
10809 if (!res) {
10810 if (vms->newmessages) {
10811 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10812 if (!res)
10813 res = ast_play_and_wait(chan, "vm-INBOX");
10814 if (vms->oldmessages && !res)
10815 res = ast_play_and_wait(chan, "vm-and");
10816 }
10817 if (!res && vms->oldmessages) {
10818 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10819 if (!res)
10820 res = ast_play_and_wait(chan, "vm-Old");
10821 }
10822 if (!res) {
10823 if (!vms->oldmessages && !vms->newmessages) {
10824 res = ast_play_and_wait(chan, "vm-no");
10825 if (!res)
10826 res = ast_play_and_wait(chan, "vm-message");
10827 }
10828 }
10829 }
10830 return res;
10831}

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 10764 of file app_voicemail_odbc.c.

10765{
10766 int res;
10767 /* Introduce messages they have */
10768 res = ast_play_and_wait(chan, "vm-you");
10769
10770 if (!res && vms->newmessages) {
10771 res = ast_play_and_wait(chan, "vm-have");
10772 if (!res)
10773 res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
10774 if (!res)
10775 res = ast_play_and_wait(chan, "vm-tong");
10776 if (!res)
10777 res = ast_play_and_wait(chan, "vm-INBOX");
10778 if (vms->oldmessages && !res)
10779 res = ast_play_and_wait(chan, "vm-and");
10780 else if (!res)
10781 res = ast_play_and_wait(chan, "vm-messages");
10782 }
10783 if (!res && vms->oldmessages) {
10784 res = ast_play_and_wait(chan, "vm-have");
10785 if (!res)
10786 res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
10787 if (!res)
10788 res = ast_play_and_wait(chan, "vm-tong");
10789 if (!res)
10790 res = ast_play_and_wait(chan, "vm-Old");
10791 if (!res)
10792 res = ast_play_and_wait(chan, "vm-messages");
10793 }
10794 if (!res && !vms->oldmessages && !vms->newmessages) {
10795 res = ast_play_and_wait(chan, "vm-haveno");
10796 if (!res)
10797 res = ast_play_and_wait(chan, "vm-messages");
10798 }
10799 return res;
10800}

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 4007 of file app_voicemail_odbc.c.

4008{
4009 switch (ast_lock_path(path)) {
4010 case AST_LOCK_TIMEOUT:
4011 return -1;
4012 default:
4013 return 0;
4014 }
4015}
@ AST_LOCK_TIMEOUT
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2614

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 17131 of file app_voicemail_odbc.c.

17137{
17138 struct ast_vm_mailbox_snapshot *mailbox_snapshot;
17139 struct vm_state vms;
17140 struct ast_vm_user *vmu = NULL, vmus;
17141 int res;
17142 int i;
17143 int this_index_only = -1;
17144 int open = 0;
17145 int inbox_index = get_folder_by_name("INBOX");
17146 int old_index = get_folder_by_name("Old");
17147 int urgent_index = get_folder_by_name("Urgent");
17148
17149 if (ast_strlen_zero(mailbox)) {
17150 ast_log(LOG_WARNING, "Cannot create a mailbox snapshot since no mailbox was specified\n");
17151 return NULL;
17152 }
17153
17154 memset(&vmus, 0, sizeof(vmus));
17155
17156 if (!(ast_strlen_zero(folder))) {
17157 /* find the folder index */
17158 for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
17159 if (!strcasecmp(mailbox_folders[i], folder)) {
17160 this_index_only = i;
17161 break;
17162 }
17163 }
17164 if (this_index_only == -1) {
17165 /* Folder was specified and it did not match any folder in our list */
17166 return NULL;
17167 }
17168 }
17169
17170 if (!(vmu = find_user(&vmus, context, mailbox))) {
17171 ast_log(AST_LOG_WARNING, "Failed to create mailbox snapshot for unknown voicemail user %s@%s\n", mailbox, context);
17172 return NULL;
17173 }
17174
17175 if (!(mailbox_snapshot = ast_calloc(1, sizeof(*mailbox_snapshot)))) {
17176 ast_log(AST_LOG_ERROR, "Failed to allocate memory for mailbox snapshot\n");
17177 free_user(vmu);
17178 return NULL;
17179 }
17180
17181 if (!(mailbox_snapshot->snapshots = ast_calloc(ARRAY_LEN(mailbox_folders), sizeof(*mailbox_snapshot->snapshots)))) {
17182 ast_free(mailbox_snapshot);
17183 free_user(vmu);
17184 return NULL;
17185 }
17186
17187 mailbox_snapshot->folders = ARRAY_LEN(mailbox_folders);
17188
17189 for (i = 0; i < mailbox_snapshot->folders; i++) {
17190 int msg_folder_index = i;
17191
17192 /* We want this message in the snapshot if any of the following:
17193 * No folder was specified.
17194 * The specified folder matches the current folder.
17195 * The specified folder is INBOX AND we were asked to combine messages AND the current folder is either Old or Urgent.
17196 */
17197 if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
17198 continue;
17199 }
17200
17201 /* Make sure that Old or Urgent messages are marked as being in INBOX. */
17202 if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
17203 msg_folder_index = inbox_index;
17204 }
17205
17206 memset(&vms, 0, sizeof(vms));
17207 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17208 vms.lastmsg = -1;
17209 open = 0;
17210
17211 /* open the mailbox state */
17212 if ((res = open_mailbox(&vms, vmu, i)) < 0) {
17213 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17214 goto snapshot_cleanup;
17215 }
17216 open = 1;
17217
17218 /* Iterate through each msg, storing off info */
17219 if (vms.lastmsg != -1) {
17220 if ((vm_msg_snapshot_create(vmu, &vms, mailbox_snapshot, msg_folder_index, i, descending, sort_val))) {
17221 ast_log(LOG_WARNING, "Failed to create msg snapshots for %s@%s\n", mailbox, context);
17222 goto snapshot_cleanup;
17223 }
17224 }
17225
17226 /* close mailbox */
17227 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
17228 goto snapshot_cleanup;
17229 }
17230 open = 0;
17231 }
17232
17233snapshot_cleanup:
17234 if (vmu && open) {
17235 close_mailbox(&vms, vmu);
17236 }
17237
17238#ifdef IMAP_STORAGE
17239 if (vmu) {
17240 vmstate_delete(&vms);
17241 }
17242#endif
17243
17244 free_user(vmu);
17245 return mailbox_snapshot;
17246}
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 17248 of file app_voicemail_odbc.c.

17249{
17250 int i;
17251 struct ast_vm_msg_snapshot *msg_snapshot;
17252
17253 for (i = 0; i < mailbox_snapshot->folders; i++) {
17254 while ((msg_snapshot = AST_LIST_REMOVE_HEAD(&mailbox_snapshot->snapshots[i], msg))) {
17255 msg_snapshot = vm_msg_snapshot_destroy(msg_snapshot);
17256 }
17257 }
17258 ast_free(mailbox_snapshot->snapshots);
17259 ast_free(mailbox_snapshot);
17260 return NULL;
17261}
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 17342 of file app_voicemail_odbc.c.

17351{
17352 struct vm_state from_vms;
17353 struct ast_vm_user *vmu = NULL, vmus;
17354 struct ast_vm_user *to_vmu = NULL, to_vmus;
17355 struct ast_config *msg_cfg;
17356 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
17357 char filename[PATH_MAX];
17358 int from_folder_index;
17359 int open = 0;
17360 int res = 0;
17361 int i;
17362 int *msg_nums;
17363
17364 if (ast_strlen_zero(from_mailbox) || ast_strlen_zero(to_mailbox)) {
17365 ast_log(LOG_WARNING, "Cannot forward message because either the from or to mailbox was not specified\n");
17366 return -1;
17367 }
17368
17369 if (!num_msgs) {
17370 ast_log(LOG_WARNING, "Invalid number of messages specified to forward: %zu\n", num_msgs);
17371 return -1;
17372 }
17373
17374 if (ast_strlen_zero(from_folder) || ast_strlen_zero(to_folder)) {
17375 ast_log(LOG_WARNING, "Cannot forward message because the from_folder or to_folder was not specified\n");
17376 return -1;
17377 }
17378
17379 memset(&vmus, 0, sizeof(vmus));
17380 memset(&to_vmus, 0, sizeof(to_vmus));
17381 memset(&from_vms, 0, sizeof(from_vms));
17382
17383 from_folder_index = get_folder_by_name(from_folder);
17384 if (from_folder_index == -1) {
17385 return -1;
17386 }
17387
17388 if (get_folder_by_name(to_folder) == -1) {
17389 return -1;
17390 }
17391
17392 if (!(vmu = find_user(&vmus, from_context, from_mailbox))) {
17393 ast_log(LOG_WARNING, "Can't find voicemail user to forward from (%s@%s)\n", from_mailbox, from_context);
17394 return -1;
17395 }
17396
17397 if (!(to_vmu = find_user(&to_vmus, to_context, to_mailbox))) {
17398 ast_log(LOG_WARNING, "Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
17399 free_user(vmu);
17400 return -1;
17401 }
17402
17403 ast_copy_string(from_vms.username, from_mailbox, sizeof(from_vms.username));
17404 from_vms.lastmsg = -1;
17405 open = 0;
17406
17407 /* open the mailbox state */
17408 if ((res = open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
17409 ast_log(LOG_WARNING, "Could not open mailbox %s\n", from_mailbox);
17410 res = -1;
17411 goto vm_forward_cleanup;
17412 }
17413
17414 open = 1;
17415
17416 if ((from_vms.lastmsg + 1) < num_msgs) {
17417 ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", from_folder, num_msgs);
17418 res = -1;
17419 goto vm_forward_cleanup;
17420 }
17421
17422 msg_nums = ast_alloca(sizeof(int) * num_msgs);
17423
17424 if ((res = message_range_and_existence_check(&from_vms, msg_ids, num_msgs, msg_nums, vmu) < 0)) {
17425 goto vm_forward_cleanup;
17426 }
17427
17428 /* Now we actually forward the messages */
17429 for (i = 0; i < num_msgs; i++) {
17430 int cur_msg = msg_nums[i];
17431 int duration = 0;
17432 const char *value;
17433
17434 make_file(from_vms.fn, sizeof(from_vms.fn), from_vms.curdir, cur_msg);
17435 snprintf(filename, sizeof(filename), "%s.txt", from_vms.fn);
17436 RETRIEVE(from_vms.curdir, cur_msg, vmu->mailbox, vmu->context);
17437 msg_cfg = ast_config_load(filename, config_flags);
17438 /* XXX This likely will not fail since we previously ensured that the
17439 * message we are looking for exists. However, there still could be some
17440 * circumstance where this fails, so atomicity is not guaranteed.
17441 */
17442 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
17443 DISPOSE(from_vms.curdir, cur_msg);
17444 continue;
17445 }
17446 if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
17447 duration = atoi(value);
17448 }
17449
17450 copy_message(NULL, vmu, from_folder_index, cur_msg, duration, to_vmu, vmfmts, from_vms.curdir, "", to_folder);
17451
17452 if (delete_old) {
17453 from_vms.deleted[cur_msg] = 1;
17454 }
17455 ast_config_destroy(msg_cfg);
17456 DISPOSE(from_vms.curdir, cur_msg);
17457 }
17458
17459 /* close mailbox */
17460 if ((res = close_mailbox(&from_vms, vmu) == ERROR_LOCK_PATH)) {
17461 res = -1;
17462 goto vm_forward_cleanup;
17463 }
17464 open = 0;
17465
17466vm_forward_cleanup:
17467 if (vmu && open) {
17468 close_mailbox(&from_vms, vmu);
17469 }
17470#ifdef IMAP_STORAGE
17471 if (vmu) {
17472 vmstate_delete(&from_vms);
17473 }
17474#endif
17475
17476 if (!res) {
17477 notify_new_state(to_vmu);
17478 }
17479
17480 free_user(vmu);
17481 free_user(to_vmu);
17482 return res;
17483}

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 17485 of file app_voicemail_odbc.c.

17491{
17492 struct vm_state vms;
17493 struct ast_vm_user *vmu = NULL, vmus;
17494 int old_folder_index;
17495 int new_folder_index;
17496 int open = 0;
17497 int res = 0;
17498 int i;
17499 int *old_msg_nums;
17500
17501 if (ast_strlen_zero(mailbox)) {
17502 ast_log(LOG_WARNING, "Cannot move message because no mailbox was specified\n");
17503 return -1;
17504 }
17505
17506 if (!num_msgs) {
17507 ast_log(LOG_WARNING, "Invalid number of messages specified to move: %zu\n", num_msgs);
17508 return -1;
17509 }
17510
17511 if (ast_strlen_zero(oldfolder) || ast_strlen_zero(newfolder)) {
17512 ast_log(LOG_WARNING, "Cannot move message because either oldfolder or newfolder was not specified\n");
17513 return -1;
17514 }
17515
17516 old_folder_index = get_folder_by_name(oldfolder);
17517 new_folder_index = get_folder_by_name(newfolder);
17518
17519 memset(&vmus, 0, sizeof(vmus));
17520 memset(&vms, 0, sizeof(vms));
17521
17522 if (old_folder_index == -1 || new_folder_index == -1) {
17523 return -1;
17524 }
17525
17526 if (!(vmu = find_user(&vmus, context, mailbox))) {
17527 return -1;
17528 }
17529
17530 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17531 vms.lastmsg = -1;
17532 open = 0;
17533
17534 /* open the mailbox state */
17535 if ((res = open_mailbox(&vms, vmu, old_folder_index)) < 0) {
17536 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17537 res = -1;
17538 goto vm_move_cleanup;
17539 }
17540
17541 open = 1;
17542
17543 if ((vms.lastmsg + 1) < num_msgs) {
17544 ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", oldfolder, num_msgs);
17545 res = -1;
17546 goto vm_move_cleanup;
17547 }
17548
17549 old_msg_nums = ast_alloca(sizeof(int) * num_msgs);
17550
17551 if ((res = message_range_and_existence_check(&vms, old_msg_ids, num_msgs, old_msg_nums, vmu)) < 0) {
17552 goto vm_move_cleanup;
17553 }
17554
17555 /* Now actually move the message */
17556 for (i = 0; i < num_msgs; ++i) {
17557 if (save_to_folder(vmu, &vms, old_msg_nums[i], new_folder_index, NULL, 0)) {
17558 res = -1;
17559 goto vm_move_cleanup;
17560 }
17561 vms.deleted[old_msg_nums[i]] = 1;
17562 }
17563
17564 /* close mailbox */
17565 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
17566 res = -1;
17567 goto vm_move_cleanup;
17568 }
17569 open = 0;
17570
17571vm_move_cleanup:
17572 if (vmu && open) {
17573 close_mailbox(&vms, vmu);
17574 }
17575#ifdef IMAP_STORAGE
17576 if (vmu) {
17577 vmstate_delete(&vms);
17578 }
17579#endif
17580
17581 if (!res) {
17582 notify_new_state(vmu);
17583 }
17584
17585 free_user(vmu);
17586 return res;
17587}

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 17687 of file app_voicemail_odbc.c.

17693{
17694 struct vm_state vms;
17695 struct ast_vm_user *vmu = NULL, vmus;
17696 int res = 0;
17697 int open = 0;
17698 int i;
17699 char filename[PATH_MAX];
17700 struct ast_config *msg_cfg;
17701 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
17702 int duration = 0;
17703 const char *value;
17704
17705 if (ast_strlen_zero(mailbox)) {
17706 ast_log(LOG_WARNING, "Cannot play message because no mailbox was specified\n");
17707 return -1;
17708 }
17709
17710 if (ast_strlen_zero(folder)) {
17711 ast_log(LOG_WARNING, "Cannot play message because no folder was specified\n");
17712 return -1;
17713 }
17714
17715 if (ast_strlen_zero(msg_id)) {
17716 ast_log(LOG_WARNING, "Cannot play message because no message number was specified\n");
17717 return -1;
17718 }
17719
17720 memset(&vmus, 0, sizeof(vmus));
17721 memset(&vms, 0, sizeof(vms));
17722
17723 if (ast_strlen_zero(context)) {
17724 context = "default";
17725 }
17726
17727 if (!(vmu = find_user(&vmus, context, mailbox))) {
17728 return -1;
17729 }
17730
17731 i = get_folder_by_name(folder);
17732 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17733 vms.lastmsg = -1;
17734 if ((res = open_mailbox(&vms, vmu, i)) < 0) {
17735 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17736 goto play2_msg_cleanup;
17737 }
17738 open = 1;
17739
17740 if (message_range_and_existence_check(&vms, &msg_id, 1, &vms.curmsg, vmu)) {
17741 res = -1;
17742 goto play2_msg_cleanup;
17743 }
17744
17745 /* Find the msg */
17746 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
17747 snprintf(filename, sizeof(filename), "%s.txt", vms.fn);
17748 RETRIEVE(vms.curdir, vms.curmsg, vmu->mailbox, vmu->context);
17749
17750 msg_cfg = ast_config_load(filename, config_flags);
17751 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
17752 DISPOSE(vms.curdir, vms.curmsg);
17753 res = -1;
17754 goto play2_msg_cleanup;
17755 }
17756 if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
17757 duration = atoi(value);
17758 }
17759 ast_config_destroy(msg_cfg);
17760
17761#ifdef IMAP_STORAGE
17762 /*IMAP storage stores any prepended message from a forward
17763 * as a separate file from the rest of the message
17764 */
17765 if (!ast_strlen_zero(vms.introfn) && ast_fileexists(vms.introfn, NULL, NULL) > 0) {
17766 wait_file(chan, &vms, vms.introfn);
17767 }
17768#endif
17769 if (cb) {
17770 cb(chan, vms.fn, duration);
17771 } else if ((wait_file(chan, &vms, vms.fn)) < 0) {
17772 ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms.fn);
17773 } else {
17774 res = 0;
17775 }
17776
17777 vms.heard[vms.curmsg] = 1;
17778
17779 /* cleanup configs and msg */
17780 DISPOSE(vms.curdir, vms.curmsg);
17781
17782play2_msg_cleanup:
17783 if (vmu && open) {
17784 close_mailbox(&vms, vmu);
17785 }
17786
17787#ifdef IMAP_STORAGE
17788 if (vmu) {
17789 vmstate_delete(&vms);
17790 }
17791#endif
17792
17793 if (!res) {
17794 notify_new_state(vmu);
17795 }
17796
17797 free_user(vmu);
17798 return res;
17799}

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 17589 of file app_voicemail_odbc.c.

17594{
17595 struct vm_state vms;
17596 struct ast_vm_user *vmu = NULL, vmus;
17597 int folder_index;
17598 int open = 0;
17599 int res = 0;
17600 int i;
17601 int *msg_nums;
17602
17603 if (ast_strlen_zero(mailbox)) {
17604 ast_log(LOG_WARNING, "Cannot remove message because no mailbox was specified\n");
17605 return -1;
17606 }
17607
17608 if (!num_msgs) {
17609 ast_log(LOG_WARNING, "Invalid number of messages specified to remove: %zu\n", num_msgs);
17610 return -1;
17611 }
17612
17613 if (ast_strlen_zero(folder)) {
17614 ast_log(LOG_WARNING, "Cannot remove message because no folder was specified\n");
17615 return -1;
17616 }
17617
17618 memset(&vmus, 0, sizeof(vmus));
17619 memset(&vms, 0, sizeof(vms));
17620
17621 folder_index = get_folder_by_name(folder);
17622 if (folder_index == -1) {
17623 ast_log(LOG_WARNING, "Could not remove msgs from unknown folder %s\n", folder);
17624 return -1;
17625 }
17626
17627 if (!(vmu = find_user(&vmus, context, mailbox))) {
17628 ast_log(LOG_WARNING, "Can't find voicemail user to remove msg from (%s@%s)\n", mailbox, context);
17629 return -1;
17630 }
17631
17632 ast_copy_string(vms.username, mailbox, sizeof(vms.username));
17633 vms.lastmsg = -1;
17634 open = 0;
17635
17636 /* open the mailbox state */
17637 if ((res = open_mailbox(&vms, vmu, folder_index)) < 0) {
17638 ast_log(LOG_WARNING, "Could not open mailbox %s\n", mailbox);
17639 res = -1;
17640 goto vm_remove_cleanup;
17641 }
17642
17643 open = 1;
17644
17645 if ((vms.lastmsg + 1) < num_msgs) {
17646 ast_log(LOG_WARNING, "Folder %s has less than %zu messages\n", folder, num_msgs);
17647 res = -1;
17648 goto vm_remove_cleanup;
17649 }
17650
17651 msg_nums = ast_alloca(sizeof(int) * num_msgs);
17652
17653 if ((res = message_range_and_existence_check(&vms, msgs, num_msgs, msg_nums, vmu)) < 0) {
17654 goto vm_remove_cleanup;
17655 }
17656
17657 for (i = 0; i < num_msgs; i++) {
17658 vms.deleted[msg_nums[i]] = 1;
17659 }
17660
17661 /* close mailbox */
17662 if ((res = close_mailbox(&vms, vmu) == ERROR_LOCK_PATH)) {
17663 res = -1;
17664 ast_log(AST_LOG_ERROR, "Failed to close mailbox folder %s while removing msgs\n", folder);
17665 goto vm_remove_cleanup;
17666 }
17667 open = 0;
17668
17669vm_remove_cleanup:
17670 if (vmu && open) {
17671 close_mailbox(&vms, vmu);
17672 }
17673#ifdef IMAP_STORAGE
17674 if (vmu) {
17675 vmstate_delete(&vms);
17676 }
17677#endif
17678
17679 if (!res) {
17680 notify_new_state(vmu);
17681 }
17682
17683 free_user(vmu);
17684 return res;
17685}

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 16948 of file app_voicemail_odbc.c.

16949{
16950 struct ast_vm_msg_snapshot *msg_snapshot;
16951
16952 if (!(msg_snapshot = ast_calloc(1, sizeof(*msg_snapshot)))) {
16953 return NULL;
16954 }
16955
16956 if (ast_string_field_init(msg_snapshot, 512)) {
16957 ast_free(msg_snapshot);
16958 return NULL;
16959 }
16960
16961 return msg_snapshot;
16962}
#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 17016 of file app_voicemail_odbc.c.

17023{
17024 struct ast_vm_msg_snapshot *msg_snapshot;
17025 struct ast_vm_msg_snapshot *msg_snapshot_tmp;
17026 struct ast_config *msg_cfg;
17027 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
17028 char filename[PATH_MAX];
17029 const char *value;
17030
17031 for (vms->curmsg = 0; vms->curmsg <= vms->lastmsg; vms->curmsg++) {
17032 int inserted = 0;
17033 /* Find the msg */
17034 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
17035 snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
17036 RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
17037 msg_cfg = ast_config_load(filename, config_flags);
17038 if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
17039 DISPOSE(vms->curdir, vms->curmsg);
17040 continue;
17041 }
17042
17043 /* Create the snapshot object */
17044 if (!(msg_snapshot = vm_msg_snapshot_alloc())) {
17045 ast_config_destroy(msg_cfg);
17046 return -1;
17047 }
17048
17049 /* Fill in the snapshot object */
17050 if ((value = ast_variable_retrieve(msg_cfg, "message", "msg_id"))) {
17051 ast_string_field_set(msg_snapshot, msg_id, value);
17052 } else {
17053 /* Message snapshots *really* should have a
17054 * message ID. Add one to the message config
17055 * if it does not already exist
17056 */
17057 char id[MSG_ID_LEN];
17058 if (!(add_message_id(msg_cfg, vms->curdir, vms->curmsg,
17059 filename, id, sizeof(id), vmu, mailbox_index))) {
17060 ast_string_field_set(msg_snapshot, msg_id, id);
17061 } else {
17062 ast_log(LOG_WARNING, "Unable to create a message ID for message %s/%d\n", vms->curdir, vms->curmsg);
17063 }
17064 }
17065 if ((value = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
17066 ast_string_field_set(msg_snapshot, callerid, value);
17067 }
17068 if ((value = ast_variable_retrieve(msg_cfg, "message", "callerchan"))) {
17069 ast_string_field_set(msg_snapshot, callerchan, value);
17070 }
17071 if ((value = ast_variable_retrieve(msg_cfg, "message", "exten"))) {
17072 ast_string_field_set(msg_snapshot, exten, value);
17073 }
17074 if ((value = ast_variable_retrieve(msg_cfg, "message", "origdate"))) {
17075 ast_string_field_set(msg_snapshot, origdate, value);
17076 }
17077 if ((value = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
17078 ast_string_field_set(msg_snapshot, origtime, value);
17079 }
17080 if ((value = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
17081 ast_string_field_set(msg_snapshot, duration, value);
17082 }
17083 if ((value = ast_variable_retrieve(msg_cfg, "message", "flag"))) {
17084 ast_string_field_set(msg_snapshot, flag, value);
17085 }
17086 msg_snapshot->msg_number = vms->curmsg;
17087 ast_string_field_set(msg_snapshot, folder_name, mailbox_folders[mailbox_index]);
17088
17089 /* store msg snapshot in mailbox snapshot */
17090 switch (sort_val) {
17091 default:
17093 if (descending) {
17094 AST_LIST_INSERT_HEAD(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
17095 } else {
17096 AST_LIST_INSERT_TAIL(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
17097 }
17098 inserted = 1;
17099 break;
17101 AST_LIST_TRAVERSE_SAFE_BEGIN(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot_tmp, msg) {
17102 int val = strcmp(msg_snapshot->origtime, msg_snapshot_tmp->origtime);
17103 if (descending && val >= 0) {
17104 AST_LIST_INSERT_BEFORE_CURRENT(msg_snapshot, msg);
17105 inserted = 1;
17106 break;
17107 } else if (!descending && val <= 0) {
17108 AST_LIST_INSERT_BEFORE_CURRENT(msg_snapshot, msg);
17109 inserted = 1;
17110 break;
17111 }
17112 }
17114 break;
17115 }
17116
17117 if (!inserted) {
17118 AST_LIST_INSERT_TAIL(&mailbox_snapshot->snapshots[snapshot_index], msg_snapshot, msg);
17119 }
17120
17121 mailbox_snapshot->total_msg_num++;
17122
17123 /* cleanup configs and msg */
17124 ast_config_destroy(msg_cfg);
17125 DISPOSE(vms->curdir, vms->curmsg);
17126 }
17127
17128 return 0;
17129}
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 16964 of file app_voicemail_odbc.c.

16965{
16966 ast_string_field_free_memory(msg_snapshot);
16967 ast_free(msg_snapshot);
16968
16969 return NULL;
16970}
#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 11122 of file app_voicemail_odbc.c.

11123{
11124 int cmd = 0;
11125 int duration = 0;
11126 int tries = 0;
11127 char newpassword[80] = "";
11128 char newpassword2[80] = "";
11129 char prefile[PATH_MAX] = "";
11130 unsigned char buf[256];
11131 int bytes = 0;
11132
11133 ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
11134 if (ast_adsi_available(chan)) {
11135 bytes += adsi_logo(buf + bytes);
11136 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
11137 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
11138 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
11139 bytes += ast_adsi_voice_mode(buf + bytes, 0);
11141 }
11142
11143 /* If forcename is set, have the user record their name */
11144 if (ast_test_flag(vmu, VM_FORCENAME)) {
11145 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
11146 if (ast_fileexists(prefile, NULL, NULL) < 1) {
11147 cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11148 if (cmd < 0 || cmd == 't' || cmd == '#')
11149 return cmd;
11150 }
11151 }
11152
11153 /* If forcegreetings is set, have the user record their greetings */
11154 if (ast_test_flag(vmu, VM_FORCEGREET)) {
11155 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
11156 if (ast_fileexists(prefile, NULL, NULL) < 1) {
11157 cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11158 if (cmd < 0 || cmd == 't' || cmd == '#')
11159 return cmd;
11160 }
11161
11162 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
11163 if (ast_fileexists(prefile, NULL, NULL) < 1) {
11164 cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11165 if (cmd < 0 || cmd == 't' || cmd == '#')
11166 return cmd;
11167 }
11168 }
11169
11170 /*
11171 * Change the password last since new users will be able to skip over any steps this one comes before
11172 * by hanging up and calling back to voicemail main since the password is used to verify new user status.
11173 */
11174 for (;;) {
11175 newpassword[1] = '\0';
11176 newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
11177 if (cmd == '#')
11178 newpassword[0] = '\0';
11179 if (cmd < 0 || cmd == 't' || cmd == '#')
11180 return cmd;
11181 cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
11182 if (cmd < 0 || cmd == 't' || cmd == '#')
11183 return cmd;
11184 cmd = check_password(vmu, newpassword); /* perform password validation */
11185 if (cmd != 0) {
11186 ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
11188 } else {
11189 newpassword2[1] = '\0';
11190 newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
11191 if (cmd == '#')
11192 newpassword2[0] = '\0';
11193 if (cmd < 0 || cmd == 't' || cmd == '#')
11194 return cmd;
11195 cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
11196 if (cmd < 0 || cmd == 't' || cmd == '#')
11197 return cmd;
11198 if (!strcmp(newpassword, newpassword2))
11199 break;
11200 ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
11201 cmd = ast_play_and_wait(chan, vm_mismatch);
11202 }
11203 if (++tries == 3)
11204 return -1;
11205 if (cmd != 0) {
11207 }
11208 }
11210 vm_change_password(vmu, newpassword);
11212 vm_change_password_shell(vmu, newpassword);
11213
11214 ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
11215 cmd = ast_play_and_wait(chan, vm_passchanged);
11216
11217 return cmd;
11218}
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 11220 of file app_voicemail_odbc.c.

11221{
11222 int cmd = 0;
11223 int retries = 0;
11224 int duration = 0;
11225 char newpassword[80] = "";
11226 char newpassword2[80] = "";
11227 char prefile[PATH_MAX] = "";
11228 unsigned char buf[256];
11229 int bytes = 0;
11230 SCOPE_ENTER(3, "%s: %s entering mailbox options", ast_channel_name(chan), vms->username);
11231
11232 ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
11233 if (ast_adsi_available(chan)) {
11234 bytes += adsi_logo(buf + bytes);
11235 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
11236 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
11237 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
11238 bytes += ast_adsi_voice_mode(buf + bytes, 0);
11240 }
11241 while ((cmd >= 0) && (cmd != 't')) {
11242 if (cmd)
11243 retries = 0;
11244 switch (cmd) {
11245 case '1': /* Record your unavailable message */
11246 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
11247 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11248 break;
11249 case '2': /* Record your busy message */
11250 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
11251 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11252 break;
11253 case '3': /* Record greeting */
11254 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
11255 cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11256 break;
11257 case '4': /* manage the temporary greeting */
11258 cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
11259 break;
11260 case '5': /* change password */
11261 if (vmu->password[0] == '-') {
11262 cmd = ast_play_and_wait(chan, "vm-no");
11263 break;
11264 }
11265 newpassword[1] = '\0';
11266 newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
11267 if (cmd == '#')
11268 newpassword[0] = '\0';
11269 else {
11270 if (cmd < 0)
11271 break;
11272 if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
11273 break;
11274 }
11275 }
11276 cmd = check_password(vmu, newpassword); /* perform password validation */
11277 if (cmd != 0) {
11278 ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
11280 if (!cmd) {
11282 }
11283 break;
11284 }
11285 newpassword2[1] = '\0';
11286 newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
11287 if (cmd == '#')
11288 newpassword2[0] = '\0';
11289 else {
11290 if (cmd < 0)
11291 break;
11292
11293 if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
11294 break;
11295 }
11296 }
11297 if (strcmp(newpassword, newpassword2)) {
11298 ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
11299 cmd = ast_play_and_wait(chan, vm_mismatch);
11300 if (!cmd) {
11302 }
11303 break;
11304 }
11305
11307 vm_change_password(vmu, newpassword);
11308 }
11310 vm_change_password_shell(vmu, newpassword);
11311 }
11312
11313 ast_debug(1, "User %s set password to %s of length %d\n",
11314 vms->username, newpassword, (int) strlen(newpassword));
11315 cmd = ast_play_and_wait(chan, vm_passchanged);
11316 break;
11317 case '*':
11318 cmd = 't';
11319 break;
11320 default:
11321 cmd = 0;
11322 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
11323 SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, vmu->context);
11324 if (ast_fileexists(prefile, NULL, NULL)) {
11325 cmd = ast_play_and_wait(chan, "vm-tmpexists");
11326 }
11327 SCOPE_CALL(-1, DISPOSE, prefile, -1);
11328 if (!cmd) {
11329 cmd = ast_play_and_wait(chan, "vm-options");
11330 }
11331 if (!cmd) {
11332 cmd = ast_waitfordigit(chan, 6000);
11333 }
11334 if (!cmd) {
11335 retries++;
11336 }
11337 if (retries > 3) {
11338 cmd = 't';
11339 }
11340 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
11341 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
11342 }
11343 }
11344 if (cmd == 't')
11345 cmd = 0;
11346 SCOPE_EXIT_RTN_VALUE(cmd, "Done\n");
11347}
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_channel_name(), 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, SCOPE_CALL, SCOPE_CALL_WITH_INT_RESULT, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, 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 9755 of file app_voicemail_odbc.c.

9756{
9757 int cmd;
9758
9759 if ( !strncasecmp(ast_channel_language(chan), "it", 2) ||
9760 !strncasecmp(ast_channel_language(chan), "es", 2) ||
9761 !strncasecmp(ast_channel_language(chan), "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
9762 cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
9763 return cmd ? cmd : ast_play_and_wait(chan, box);
9764 } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) {
9765 return vm_play_folder_name_gr(chan, box);
9766 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* Hebrew syntax */
9767 return ast_play_and_wait(chan, box);
9768 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
9769 return vm_play_folder_name_ja(chan, box);
9770 } else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
9771 return vm_play_folder_name_pl(chan, box);
9772 } else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* Ukrainian syntax */
9773 return vm_play_folder_name_ua(chan, box);
9774 } else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) {
9775 return ast_play_and_wait(chan, box);
9776 } else { /* Default English */
9777 cmd = ast_play_and_wait(chan, box);
9778 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
9779 }
9780}
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 9695 of file app_voicemail_odbc.c.

9696{
9697 int cmd;
9698 char *buf;
9699
9700 buf = ast_alloca(strlen(box) + 2);
9701 strcpy(buf, box);
9702 strcat(buf, "s");
9703
9704 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
9705 cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
9706 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
9707 } else {
9708 cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
9709 return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
9710 }
9711}

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 9713 of file app_voicemail_odbc.c.

9714{
9715 int cmd;
9716
9717 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9718 cmd = ast_play_and_wait(chan, box);
9719 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9720 } else {
9721 cmd = ast_play_and_wait(chan, box);
9722 return cmd;
9723 }
9724}

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 9726 of file app_voicemail_odbc.c.

9727{
9728 int cmd;
9729
9730 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9731 if (!strcasecmp(box, "vm-INBOX"))
9732 cmd = ast_play_and_wait(chan, "vm-new-e");
9733 else
9734 cmd = ast_play_and_wait(chan, "vm-old-e");
9735 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9736 } else {
9737 cmd = ast_play_and_wait(chan, "vm-messages");
9738 return cmd ? cmd : ast_play_and_wait(chan, box);
9739 }
9740}

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 9742 of file app_voicemail_odbc.c.

9743{
9744 int cmd;
9745
9746 if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
9747 cmd = ast_play_and_wait(chan, "vm-messages");
9748 return cmd ? cmd : ast_play_and_wait(chan, box);
9749 } else {
9750 cmd = ast_play_and_wait(chan, box);
9751 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9752 }
9753}

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 11943 of file app_voicemail_odbc.c.

11944{
11945 char *parse;
11946 char *mailbox = NULL;
11947 char *context = NULL;
11948 int res;
11949
11952 AST_APP_ARG(msg_id);
11953 );
11954
11955 if (ast_channel_state(chan) != AST_STATE_UP) {
11956 ast_debug(1, "Before ast_answer\n");
11957 ast_answer(chan);
11958 }
11959
11960 if (ast_strlen_zero(data)) {
11961 return -1;
11962 }
11963
11964 parse = ast_strdupa(data);
11966
11967 if (ast_strlen_zero(args.mailbox) || ast_strlen_zero(args.msg_id)) {
11968 return -1;
11969 }
11970
11971 if ((context = strchr(args.mailbox, '@'))) {
11972 *context++ = '\0';
11973 }
11974 mailbox = args.mailbox;
11975
11976 res = play_message_by_id(chan, mailbox, context, args.msg_id);
11977 pbx_builtin_setvar_helper(chan, "VOICEMAIL_PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS");
11978
11979 return 0;
11980}
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 15556 of file app_voicemail_odbc.c.

15557{
15558 char *context;
15559 char *mailbox;
15560
15561 if (ast_strlen_zero(mailbox_id)
15562 || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
15563 return -1;
15564 }
15565 return sayname(chan, mailbox, context);
15566}
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 11365 of file app_voicemail_odbc.c.

11366{
11367 int cmd = 0;
11368 int retries = 0;
11369 int duration = 0;
11370 char prefile[PATH_MAX] = "";
11371 unsigned char buf[256];
11372 int bytes = 0;
11373
11374 if (ast_adsi_available(chan)) {
11375 bytes += adsi_logo(buf + bytes);
11376 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
11377 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
11378 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
11379 bytes += ast_adsi_voice_mode(buf + bytes, 0);
11381 }
11382
11383 ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
11384 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
11385 while ((cmd >= 0) && (cmd != 't')) {
11386 if (cmd)
11387 retries = 0;
11388 RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
11389 if (ast_fileexists(prefile, NULL, NULL) <= 0) {
11390 cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11391 if (cmd == -1) {
11392 break;
11393 }
11394 cmd = 't';
11395 } else {
11396 switch (cmd) {
11397 case '1':
11398 cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0);
11399 break;
11400 case '2':
11401 DELETE(prefile, -1, prefile, vmu);
11402 ast_play_and_wait(chan, "vm-tempremoved");
11403 cmd = 't';
11404 break;
11405 case '*':
11406 cmd = 't';
11407 break;
11408 default:
11409 cmd = ast_play_and_wait(chan,
11410 ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
11411 "vm-tempgreeting2" : "vm-tempgreeting");
11412 if (!cmd) {
11413 cmd = ast_waitfordigit(chan, 6000);
11414 }
11415 if (!cmd) {
11416 retries++;
11417 }
11418 if (retries > 3) {
11419 cmd = 't';
11420 }
11421 ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c",
11422 isprint(cmd) ? cmd : '?', isprint(cmd) ? cmd : '?');
11423 }
11424 }
11425 DISPOSE(prefile, -1);
11426 }
11427 if (cmd == 't')
11428 cmd = 0;
11429 return cmd;
11430}

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 13687 of file app_voicemail_odbc.c.

13688{
13689 char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
13690 struct ast_vm_user vmus = {{0}};
13691 char *options = NULL;
13692 int silent = 0, skipuser = 0;
13693 int res = -1;
13694
13695 if (data) {
13696 s = ast_strdupa(data);
13697 user = strsep(&s, ",");
13698 options = strsep(&s, ",");
13699 if (user) {
13700 s = user;
13701 user = strsep(&s, "@");
13702 context = strsep(&s, "");
13703 if (!ast_strlen_zero(user))
13704 skipuser++;
13706 }
13707 }
13708
13709 if (options) {
13710 silent = (strchr(options, 's')) != NULL;
13711 }
13712
13713 if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
13714 pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
13715 pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
13716 ast_play_and_wait(chan, "auth-thankyou");
13717 res = 0;
13718 } else if (mailbox[0] == '*') {
13719 /* user entered '*' */
13720 if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) {
13721 res = 0; /* prevent hangup */
13722 }
13723 }
13724
13725 return res;
13726}
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 15618 of file app_voicemail_odbc.c.

15619{
15620 char *context;
15621 char *mailbox;
15622 int res;
15623
15624 if (ast_strlen_zero(data)
15626 ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
15627 return -1;
15628 }
15629
15630 if ((res = sayname(chan, mailbox, context)) < 0) {
15631 ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", mailbox, context);
15632 res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
15633 if (!res) {
15635 }
15636 }
15637
15638 return res;
15639}
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:8293
@ 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 5328 of file app_voicemail_odbc.c.

5329{
5330 const struct vm_zone *z = NULL;
5331 struct timeval t = ast_tvnow();
5332
5333 /* Does this user have a timezone specified? */
5334 if (!ast_strlen_zero(vmu->zonetag)) {
5335 /* Find the zone in the list */
5337 AST_LIST_TRAVERSE(&zones, z, list) {
5338 if (!strcmp(z->name, vmu->zonetag))
5339 break;
5340 }
5342 }
5343 ast_localtime(&t, tm, z ? z->timezone : NULL);
5344 return tm;
5345}

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 9039 of file app_voicemail_odbc.c.

9040{
9041 ast_test_suite_event_notify("PLAYVOICE", "Message: Playing %s", file);
9043}
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 9031 of file app_voicemail_odbc.c.

9032{
9033 int res;
9034 if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
9035 ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file);
9036 return res;
9037}

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 15585 of file app_voicemail_odbc.c.

15585 {
15586 struct ast_config *conf;
15587 struct ast_category *cat;
15588 struct ast_variable *var;
15589 int res = -1;
15590
15591 if (!(conf = ast_config_new())) {
15592 ast_log(LOG_ERROR, "Error creating new config structure\n");
15593 return res;
15594 }
15595 if (!(cat = ast_category_new("general", "", 1))) {
15596 ast_log(LOG_ERROR, "Error creating new category structure\n");
15598 return res;
15599 }
15600 if (!(var = ast_variable_new("password", password, ""))) {
15601 ast_log(LOG_ERROR, "Error creating new variable structure\n");
15604 return res;
15605 }
15608 if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
15609 res = 0;
15610 } else {
15611 ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
15612 }
15613
15615 return res;
15616}
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 17811 of file app_voicemail_odbc.c.

◆ addesc

char* addesc = "Comedian Mail"
static

Definition at line 1043 of file app_voicemail_odbc.c.

Referenced by adsi_load_vmail().

◆ adsifdn

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

Definition at line 1166 of file app_voicemail_odbc.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 1167 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and adsi_load_vmail().

◆ adsiver

int adsiver = 1
static

Definition at line 1168 of file app_voicemail_odbc.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 17811 of file app_voicemail_odbc.c.

◆ callcontext

char callcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1152 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ charset

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

Definition at line 1164 of file app_voicemail_odbc.c.

◆ cidinternalcontexts

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static

Definition at line 1155 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and play_message_callerid().

◆ cli_voicemail

struct ast_cli_entry cli_voicemail[]
static

Definition at line 13970 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ dialcontext

char dialcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1151 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ emailbody

char* emailbody
static

Definition at line 1158 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and make_email_file().

◆ emaildateformat

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

Definition at line 1169 of file app_voicemail_odbc.c.

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

◆ emailsubject

char* emailsubject
static

Definition at line 1159 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and make_email_file().

◆ exitcontext

char exitcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1153 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ ext_pass_check_cmd

char ext_pass_check_cmd[128]
static

Definition at line 1023 of file app_voicemail_odbc.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 1067 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and run_externnotify().

◆ fromstring

char fromstring[100]
static

◆ globalflags

struct ast_flags globalflags = {0}
static

◆ inprocess_container

struct ao2_container* inprocess_container

Definition at line 1253 of file app_voicemail_odbc.c.

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

◆ listen_control_forward_key

char listen_control_forward_key[12]
static

Definition at line 1118 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_pause_key

char listen_control_pause_key[12]
static

Definition at line 1120 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_restart_key

char listen_control_restart_key[12]
static

Definition at line 1121 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_reverse_key

char listen_control_reverse_key[12]
static

Definition at line 1119 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and wait_file().

◆ listen_control_stop_key

char listen_control_stop_key[12]
static

Definition at line 1122 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and wait_file().

◆ locale

char locale[20]
static

Definition at line 1060 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ mailbox_alias_mappings

struct ao2_container* mailbox_alias_mappings
static

◆ mailbox_folders

const char* const mailbox_folders[]
static

◆ mailcmd

char mailcmd[160] = SENDMAIL
static

◆ maxdeletedmsg

int maxdeletedmsg
static

Definition at line 1063 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ maxgreet

int maxgreet
static

◆ maxlogins

int maxlogins = 3
static

Definition at line 1075 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and vm_execmain().

◆ maxmsg

int maxmsg = MAXMSG
static

Definition at line 1062 of file app_voicemail_odbc.c.

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

◆ maxsilence

int maxsilence
static

◆ minpassword

int minpassword = MINPASSWORD
static

Definition at line 1076 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and check_password().

◆ msg_id_incrementor

int msg_id_incrementor
static

Definition at line 4020 of file app_voicemail_odbc.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 14124 of file app_voicemail_odbc.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 1160 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and sendpage().

◆ pagerdateformat

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

Definition at line 1170 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and sendpage().

◆ pagerfromstring

char pagerfromstring[100]
static

Definition at line 1163 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and sendpage().

◆ pagersubject

char* pagersubject
static

Definition at line 1161 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and sendpage().

◆ passwordlocation

int passwordlocation
static

Definition at line 1077 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ playmsg_app

char* playmsg_app = "VoiceMailPlayMsg"
static

Definition at line 1053 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ poll_cond

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static

Definition at line 1090 of file app_voicemail_odbc.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 1087 of file app_voicemail_odbc.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 1089 of file app_voicemail_odbc.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 1082 of file app_voicemail_odbc.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 1092 of file app_voicemail_odbc.c.

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

◆ pwdchange

int pwdchange = PWDCHANGE_INTERNAL
static

Definition at line 1029 of file app_voicemail_odbc.c.

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

◆ saydurationminfo

int saydurationminfo = 2
static

Definition at line 1149 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().

◆ sayname_app

char* sayname_app = "VMSayName"
static

Definition at line 1055 of file app_voicemail_odbc.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

Definition at line 1074 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and wait_file().

◆ smdi_iface

struct ast_smdi_interface* smdi_iface = NULL
static

Definition at line 1068 of file app_voicemail_odbc.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 1041 of file app_voicemail_odbc.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 754 of file app_voicemail_odbc.c.

Referenced by vm_exec(), and vm_execmain().

◆ vm_greeter_table

const struct ast_vm_greeter_functions vm_greeter_table
static

Definition at line 16215 of file app_voicemail_odbc.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 13682 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ vm_invalid_password

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

Definition at line 1132 of file app_voicemail_odbc.c.

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

◆ vm_login

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

Definition at line 1125 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and vm_authenticate().

◆ vm_mismatch

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

Definition at line 1131 of file app_voicemail_odbc.c.

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

◆ vm_newpassword

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

Definition at line 1128 of file app_voicemail_odbc.c.

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

◆ vm_newuser

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

Definition at line 1126 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and vm_execmain().

◆ vm_passchanged

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

Definition at line 1129 of file app_voicemail_odbc.c.

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

◆ vm_password

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

Definition at line 1127 of file app_voicemail_odbc.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 1145 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and vm_forwardoptions().

◆ vm_reenterpassword

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

Definition at line 1130 of file app_voicemail_odbc.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

Definition at line 16197 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ vmauthenticate_app

char* vmauthenticate_app = "VMAuthenticate"
static

Definition at line 1051 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ vmfmts

char vmfmts[80] = "wav"
static

◆ vmmaxsecs

int vmmaxsecs
static

Definition at line 1072 of file app_voicemail_odbc.c.

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

◆ vmminsecs

int vmminsecs
static

Definition at line 1071 of file app_voicemail_odbc.c.

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

◆ voicemail_app

char* voicemail_app = "VoiceMail"
static

Definition at line 1046 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ voicemailmain_app

char* voicemailmain_app = "VoiceMailMain"
static

Definition at line 1049 of file app_voicemail_odbc.c.

Referenced by load_module(), and unload_module().

◆ volgain

double volgain
static

Definition at line 1070 of file app_voicemail_odbc.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 1059 of file app_voicemail_odbc.c.

Referenced by actual_load_config(), and populate_defaults().