Asterisk - The Open Source Telephony Project GIT-master-f45f878
Data Structures | Macros | Enumerations | Functions | Variables
app_voicemail_imap.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_imap.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_imap.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_imap.c.

◆ CHUNKSIZE

#define CHUNKSIZE   65536

Definition at line 635 of file app_voicemail_imap.c.

◆ COMMAND_TIMEOUT

#define COMMAND_TIMEOUT   5000

Definition at line 631 of file app_voicemail_imap.c.

◆ COPY

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

Definition at line 1014 of file app_voicemail_imap.c.

◆ COUNT

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

Definition at line 1007 of file app_voicemail_imap.c.

◆ DEFAULT_LISTEN_CONTROL_FORWARD_KEY

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 643 of file app_voicemail_imap.c.

◆ DEFAULT_LISTEN_CONTROL_PAUSE_KEY

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 645 of file app_voicemail_imap.c.

◆ DEFAULT_LISTEN_CONTROL_RESTART_KEY

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 646 of file app_voicemail_imap.c.

◆ DEFAULT_LISTEN_CONTROL_REVERSE_KEY

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 644 of file app_voicemail_imap.c.

◆ DEFAULT_LISTEN_CONTROL_STOP_KEY

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 647 of file app_voicemail_imap.c.

◆ DEFAULT_POLL_FREQ

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 1085 of file app_voicemail_imap.c.

◆ DELETE

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

Definition at line 1015 of file app_voicemail_imap.c.

◆ DISPOSE

#define DISPOSE (   a,
  b 
)

Definition at line 1010 of file app_voicemail_imap.c.

◆ ENDL

#define ENDL   "\n"

Definition at line 665 of file app_voicemail_imap.c.

◆ ERROR_LOCK_PATH

#define ERROR_LOCK_PATH   -100

Definition at line 694 of file app_voicemail_imap.c.

◆ ERROR_MAX_MSGS

#define ERROR_MAX_MSGS   -101

Definition at line 695 of file app_voicemail_imap.c.

◆ EXISTS

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

Definition at line 1012 of file app_voicemail_imap.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_imap.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_imap.c.

◆ LAST_MSG_INDEX

#define LAST_MSG_INDEX (   a)    last_message_index(a)

Definition at line 1008 of file app_voicemail_imap.c.

◆ MAPPING_BUCKETS

#define MAPPING_BUCKETS   511

Definition at line 1108 of file app_voicemail_imap.c.

◆ MAX_DATETIME_FORMAT

#define MAX_DATETIME_FORMAT   512

Definition at line 668 of file app_voicemail_imap.c.

◆ MAX_MAIL_BODY_CONTENT_SIZE

#define MAX_MAIL_BODY_CONTENT_SIZE   134217728L

Definition at line 655 of file app_voicemail_imap.c.

◆ MAX_NUM_CID_CONTEXTS

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 669 of file app_voicemail_imap.c.

◆ MAX_VM_CONTEXT_LEN

#define MAX_VM_CONTEXT_LEN   (AST_MAX_CONTEXT)

Definition at line 886 of file app_voicemail_imap.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_imap.c.

◆ MAX_VM_MBOX_ID_LEN

#define MAX_VM_MBOX_ID_LEN   (AST_MAX_EXTENSION)

Definition at line 885 of file app_voicemail_imap.c.

◆ MAXMSG

#define MAXMSG   100

Definition at line 657 of file app_voicemail_imap.c.

◆ MAXMSGLIMIT

#define MAXMSGLIMIT   9999

Definition at line 658 of file app_voicemail_imap.c.

◆ MINPASSWORD

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 660 of file app_voicemail_imap.c.

◆ MSG_ID_LEN

#define MSG_ID_LEN   256

Definition at line 4017 of file app_voicemail_imap.c.

◆ MSGFILE_LEN

#define MSGFILE_LEN   (7)

Length of the message file name: msgXXXX

Definition at line 698 of file app_voicemail_imap.c.

◆ OPERATOR_EXIT

#define OPERATOR_EXIT   300

Definition at line 696 of file app_voicemail_imap.c.

◆ PWDCHANGE_EXTERNAL

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 1028 of file app_voicemail_imap.c.

◆ PWDCHANGE_INTERNAL

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 1027 of file app_voicemail_imap.c.

◆ RENAME

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

Definition at line 1013 of file app_voicemail_imap.c.

◆ RETRIEVE

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

Definition at line 1009 of file app_voicemail_imap.c.

◆ SENDMAIL

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

Definition at line 652 of file app_voicemail_imap.c.

◆ SMDI_MWI_WAIT_TIMEOUT

#define SMDI_MWI_WAIT_TIMEOUT   1000 /* 1 second */

Definition at line 629 of file app_voicemail_imap.c.

◆ STORE

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

Definition at line 1011 of file app_voicemail_imap.c.

◆ tdesc

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 1037 of file app_voicemail_imap.c.

◆ UPDATE_MSG_ID

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

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

◆ VM_ATTACH

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 682 of file app_voicemail_imap.c.

◆ VM_DELETE

#define VM_DELETE   (1 << 12)

Delete message after sending notification

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

◆ VM_FORCEGREET

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 679 of file app_voicemail_imap.c.

◆ VM_FORCENAME

#define VM_FORCENAME   (1 << 7)

Have new users record their name

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

◆ VM_SAYCID

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

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

◆ VM_SEARCH

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

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

◆ VM_TEMPGREETWARN

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

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

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 637 of file app_voicemail_imap.c.

◆ VOICEMAIL_DIR_MODE

#define VOICEMAIL_DIR_MODE   0777

Definition at line 633 of file app_voicemail_imap.c.

◆ VOICEMAIL_FILE_MODE

#define VOICEMAIL_FILE_MODE   0666

Definition at line 634 of file app_voicemail_imap.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_imap.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_imap.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_imap.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_imap.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 6428 of file app_voicemail_imap.c.

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

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 17807 of file app_voicemail_imap.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 13595 of file app_voicemail_imap.c.

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

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

References adsifdn, adsisec, adsiver, alias_mailbox_mappings, aliasescontext, ao2_callback, apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, AST_LOG_ERROR, AST_LOG_WARNING, ast_mwi_state_callback_all(), AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_taskprocessor_alert_set_levels(), AST_TASKPROCESSOR_HIGH_WATER_LEVEL, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, cidinternalcontexts, current, DEFAULT_LISTEN_CONTROL_FORWARD_KEY, DEFAULT_LISTEN_CONTROL_PAUSE_KEY, DEFAULT_LISTEN_CONTROL_RESTART_KEY, DEFAULT_LISTEN_CONTROL_REVERSE_KEY, DEFAULT_LISTEN_CONTROL_STOP_KEY, DEFAULT_POLL_FREQ, dialcontext, emailbody, emaildateformat, emailsubject, exitcontext, ext_pass_check_cmd, ext_pass_cmd, externnotify, find_or_create(), free_vm_users(), free_vm_zones(), fromstring, globalflags, is_valid_dtmf(), listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, load_aliases(), load_users(), load_zonemessages(), locale, LOG_ERROR, mailbox_alias_mappings, mailcmd, MAX_NUM_CID_CONTEXTS, maxdeletedmsg, maxgreet, maxlogins, MAXMSG, maxmsg, MAXMSGLIMIT, maxsilence, MINPASSWORD, minpassword, mwi_subscription_tps, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, passwordlocation, PATH_MAX, poll_freq, poll_mailboxes, poll_thread, populate_defaults(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), S_OR, saydurationminfo, SENDMAIL, serveremail, silencethreshold, skipms, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, tmp(), userscontext, VM_ATTACH, VM_DIRECTFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, vm_login, VM_MARK_URGENT, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, vm_newuser, VM_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_imap.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 13267 of file app_voicemail_imap.c.

13268{
13269 struct ast_variable *var;
13270 struct ast_category *cat;
13271 generate_msg_id(id);
13272
13273 var = ast_variable_new("msg_id", id, "");
13274 if (!var) {
13275 return -1;
13276 }
13277
13278 cat = ast_category_get(msg_cfg, "message", NULL);
13279 if (!cat) {
13280 ast_log(LOG_ERROR, "Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
13282 return -1;
13283 }
13284
13286
13287 if (ast_config_text_file_save(filename, msg_cfg, "app_voicemail")) {
13288 ast_log(LOG_WARNING, "Unable to update %s to have a message ID\n", filename);
13289 return -1;
13290 }
13291
13292 UPDATE_MSG_ID(dir, msg, id, vmu, msg_cfg, folder);
13293 return 0;
13294}
#define UPDATE_MSG_ID(a, b, c, d, e, f)
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
#define var
Definition: ast_expr2f.c:605
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
Definition: main/config.c:2701
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#define ast_variable_new(name, value, filename)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1111
Structure for variables, used for configurations and for channel variables.

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

Referenced by vm_msg_snapshot_create().

◆ adsi_begin()

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

Definition at line 7845 of file app_voicemail_imap.c.

7846{
7847 int x;
7848 if (!ast_adsi_available(chan))
7849 return;
7850 x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
7851 if (x < 0) {
7852 *useadsi = 0;
7854 return;
7855 }
7856 if (!x) {
7857 if (adsi_load_vmail(chan, useadsi)) {
7858 ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
7859 return;
7860 }
7861 } else
7862 *useadsi = 1;
7863}
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay,...
Definition: adsi.c:76
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:871
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)

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

Referenced by vm_authenticate(), and vm_execmain().

◆ adsi_delete()

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

Definition at line 8044 of file app_voicemail_imap.c.

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

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

8200{
8201 unsigned char buf[256];
8202 int bytes = 0;
8203
8204 if (!ast_adsi_available(chan))
8205 return;
8206 bytes += adsi_logo(buf + bytes);
8207 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
8208 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
8209 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
8210 bytes += ast_adsi_voice_mode(buf + bytes, 0);
8211
8213}
#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 7716 of file app_voicemail_imap.c.

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

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

7709{
7710 int bytes = 0;
7711 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
7712 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
7713 return bytes;
7714}

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 7942 of file app_voicemail_imap.c.

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

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

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 8096 of file app_voicemail_imap.c.

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

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

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 16486 of file app_voicemail_imap.c.

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

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log, AST_LOG_WARNING, AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_test_suite_event_notify, ast_variable_retrieve(), ast_verb, ast_waitfordigit(), leave_vm_options::beeptone, ast_vm_user::callback, CONFIG_FLAG_NOCACHE, ast_vm_user::context, voicemailpwcheck::context, vm_state::curdir, vm_state::curmsg, dialout(), ast_vm_user::dialout, DISPOSE, find_user(), vm_state::fn, free_user(), vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, voicemailpwcheck::mailbox, make_file(), name, NULL, PATH_MAX, play_message_callerid(), play_message_datetime(), leave_vm_options::record_gain, RETRIEVE, vm_state::starting, valid_config(), and wait_file().

Referenced by vm_execmain().

◆ alias_mailbox_mapping_create()

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

Definition at line 14738 of file app_voicemail_imap.c.

14739{
14740 struct alias_mailbox_mapping *mapping;
14741 size_t from_len = strlen(alias) + 1;
14742 size_t to_len = strlen(mailbox) + 1;
14743
14744 mapping = ao2_alloc(sizeof(*mapping) + from_len + to_len, NULL);
14745 if (!mapping) {
14746 return NULL;
14747 }
14748 mapping->alias = mapping->buf;
14749 mapping->mailbox = mapping->buf + from_len;
14750 ast_copy_string(mapping->alias, alias, from_len); /* Safe */
14751 ast_copy_string(mapping->mailbox, mailbox, to_len); /* Safe */
14752
14753 return mapping;
14754}
#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 13336 of file app_voicemail_imap.c.

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

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

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

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

Referenced by vm_change_password().

◆ check_mime()

static int check_mime ( const char *  str)
static

Check if the string would need encoding within the MIME standard, to avoid confusing certain mail software that expects messages to be 7-bit clean.

Definition at line 5351 of file app_voicemail_imap.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_imap.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 9567 of file app_voicemail_imap.c.

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

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

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

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 13761 of file app_voicemail_imap.c.

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

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_imap.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 6337 of file app_voicemail_imap.c.

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

References ast_channel_caller(), ast_channel_language(), ast_copy_string(), ast_log, AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_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_imap.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:3740
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3506

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

Referenced by copy_message().

◆ count_messages()

static int count_messages ( struct ast_vm_user vmu,
char *  dir 
)
static

Find all .txt files - even if they are not in sequence from 0000.

Parameters
vmu
dir

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

Returns
the count of messages, zero or more.

Definition at line 5003 of file app_voicemail_imap.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_imap.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 16414 of file app_voicemail_imap.c.

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

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

Referenced by advanced_options(), and vm_execmain().

◆ find_or_create()

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

Definition at line 13296 of file app_voicemail_imap.c.

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

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

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

14616{
14617 struct ast_vm_user *current;
14619 while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
14622 }
14624}
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 14627 of file app_voicemail_imap.c.

14628{
14629 struct vm_zone *zcur;
14631 while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
14632 free_zone(zcur);
14634}
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 6119 of file app_voicemail_imap.c.

6120{
6121 ast_free(z);
6122}

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 6658 of file app_voicemail_imap.c.

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

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

8220{
8221 int x;
8222 int d;
8223 char fn[PATH_MAX];
8224 d = ast_play_and_wait(chan, "vm-press"); /* "Press" */
8225 if (d)
8226 return d;
8227 for (x = start; x < 5; x++) { /* For all folders */
8228 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), NULL)))
8229 return d;
8230 d = ast_play_and_wait(chan, "vm-for"); /* "for" */
8231 if (d)
8232 return d;
8233 snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
8234
8235 /* The inbox folder can have its name changed under certain conditions
8236 * so this checks if the sound file exists for the inbox folder name and
8237 * if it doesn't, plays the default name instead. */
8238 if (x == 0) {
8239 if (ast_fileexists(fn, NULL, NULL)) {
8240 d = vm_play_folder_name(chan, fn);
8241 } else {
8242 ast_verb(4, "Failed to find file %s; falling back to INBOX\n", fn);
8243 d = vm_play_folder_name(chan, "vm-INBOX");
8244 }
8245 } else {
8246 ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
8247 d = vm_play_folder_name(chan, fn);
8248 }
8249
8250 if (d)
8251 return d;
8252 d = ast_waitfordigit(chan, 500);
8253 if (d)
8254 return d;
8255 }
8256
8257 d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
8258 if (d)
8259 return d;
8260 d = ast_waitfordigit(chan, 4000);
8261 return d;
8262}
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8235
static struct test_val d

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

Referenced by get_folder2().

◆ get_folder2()

static int get_folder2 ( struct ast_channel chan,
char *  fn,
int  start 
)
static

plays a prompt and waits for a keypress.

Parameters
chan
fnthe name of the voice prompt file to be played. For example, 'vm-changeto', 'vm-savefolder'
startDoes not appear to be used at this time.

This is used by the main menu option to move a message to a folder or to save a message into a folder. After playing the message identified by the fn parameter value, it calls get_folder(), which plays the prompting for the number inputs that correspond to the available folders.

Returns
zero on success, or -1 on error.

Definition at line 8304 of file app_voicemail_imap.c.

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

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

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 12276 of file app_voicemail_imap.c.

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

12304{
12305 switch (cmd) {
12306 case CLI_INIT:
12307 e->command = "voicemail move";
12308 e->usage =
12309 "Usage: voicemail move <mailbox> <context> <from_folder> <messageid> <to_folder>\n"
12310 " Move message <messageid> in mailbox <mailbox>&<context> from <from_folder> to <to_folder>\n";
12311 return NULL;
12312 case CLI_GENERATE:
12314 case CLI_HANDLER:
12315 break;
12316 }
12317
12318 if (a->argc != 7) {
12319 return CLI_SHOWUSAGE;
12320 }
12321
12323 return CLI_FAILURE;
12324 }
12325
12326 return CLI_SUCCESS;
12327}
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 13942 of file app_voicemail_imap.c.

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

12330{
12331 switch (cmd) {
12332 case CLI_INIT:
12333 e->command = "voicemail remove";
12334 e->usage =
12335 "Usage: voicemail remove <mailbox> <context> <from_folder> <messageid>\n"
12336 " Remove message <messageid> from <from_folder> in mailbox <mailbox>@<context>\n";
12337 return NULL;
12338 case CLI_GENERATE:
12340 case CLI_HANDLER:
12341 break;
12342 }
12343
12344 if (a->argc != 6) {
12345 return CLI_SHOWUSAGE;
12346 }
12347
12349 return CLI_FAILURE;
12350 }
12351
12352 return CLI_SUCCESS;
12353}
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 13902 of file app_voicemail_imap.c.

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

12143{
12144 switch (cmd) {
12145 case CLI_INIT:
12146 e->command = "voicemail show mailbox";
12147 e->usage =
12148 "Usage: voicemail show mailbox <mailbox> <context>\n"
12149 " Show contents of mailbox <mailbox>@<context>\n";
12150 return NULL;
12151 case CLI_GENERATE:
12153 case CLI_HANDLER:
12154 break;
12155 }
12156
12157 if (a->argc != 5) {
12158 return CLI_SHOWUSAGE;
12159 }
12160
12162 return CLI_FAILURE;
12163 }
12164
12165 return CLI_SUCCESS;
12166}
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 13790 of file app_voicemail_imap.c.

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

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

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

6592{
6593 int urgentmsgs = 0;
6594 int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
6595 if (newmsgs) {
6596 *newmsgs += urgentmsgs;
6597 }
6598 return res;
6599}

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 6521 of file app_voicemail_imap.c.

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

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_imap.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_imap.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_imap.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 6085 of file app_voicemail_imap.c.

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

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_imap.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_imap.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 6990 of file app_voicemail_imap.c.

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

References ast_answer(), ast_callerid_merge(), ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_language(), ast_channel_lock, ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_redirecting(), ast_channel_unlock, ast_check_realtime(), ast_copy_string(), ast_debug, ast_destroy_realtime(), ast_exists_extension(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log, AST_LOG_ERROR, AST_LOG_NOTICE, AST_LOG_WARNING, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STATE_UP, ast_stopstream(), ast_store_realtime(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strdupa, ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_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 14756 of file app_voicemail_imap.c.

14757{
14758 struct ast_variable *var;
14759
14761 return;
14762 }
14764 while (var) {
14765 struct alias_mailbox_mapping *mapping = alias_mailbox_mapping_create(var->name, var->value);
14766 if (mapping) {
14769 ao2_ref(mapping, -1);
14770 }
14771 var = var->next;
14772 }
14773}
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 14724 of file app_voicemail_imap.c.

14725{
14726 return load_config_force(reload, 0);
14727}
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 14683 of file app_voicemail_imap.c.

14684{
14685 struct ast_config *cfg, *ucfg;
14686 struct ast_flags config_flags = { reload && !force ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14687 int res;
14688
14689 ast_unload_realtime("voicemail");
14690 ast_unload_realtime("voicemail_data");
14691
14692 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
14693 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
14694 return 0;
14695 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
14696 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
14697 ucfg = NULL;
14698 }
14700 if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
14701 ast_config_destroy(ucfg);
14702 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
14703 return 0;
14704 }
14705 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
14706 ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format. Aborting.\n");
14707 return 0;
14708 } else {
14710 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
14711 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Avoiding.\n");
14712 ucfg = NULL;
14713 }
14714 }
14715
14716 res = actual_load_config(reload, cfg, ucfg);
14717
14718 ast_config_destroy(cfg);
14719 ast_config_destroy(ucfg);
14720
14721 return res;
14722}
#define VOICEMAIL_CONFIG
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: main/config.c:3576
#define CONFIG_STATUS_FILEUNCHANGED
@ CONFIG_FLAG_FILEUNCHANGED

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

Referenced by load_config().

◆ load_module()

static int load_module ( void  )
static

Load the module.

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

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

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

On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 16300 of file app_voicemail_imap.c.

16301{
16302 int res;
16303 my_umask = umask(0);
16304 umask(my_umask);
16305
16308 if (!inprocess_container) {
16310 }
16311
16313 alias_mailbox_mapping_hash_fn, NULL, alias_mailbox_mapping_cmp_fn);
16315 ast_log(LOG_ERROR, "Unable to create alias_mailbox_mappings container\n");
16318 }
16319 res = ao2_container_register("voicemail_alias_mailbox_mappings", alias_mailbox_mappings, print_mappings);
16320 if (res) {
16321 ast_log(LOG_ERROR, "Unable to register alias_mailbox_mappings container\n");
16325 }
16326
16328 mailbox_alias_mapping_hash_fn, NULL, mailbox_alias_mapping_cmp_fn);
16330 ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");
16332 ao2_container_unregister("voicemail_alias_mailbox_mappings");
16335 }
16336 res = ao2_container_register("voicemail_mailbox_alias_mappings", mailbox_alias_mappings, print_mappings);
16337 if (res) {
16338 ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");
16340 ao2_container_unregister("voicemail_alias_mailbox_mappings");
16344 }
16345
16346 /* compute the location of the voicemail spool directory */
16347 snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
16348
16349 if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
16350 ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor. MWI will not work\n");
16351 }
16352
16353 if ((res = load_config(0))) {
16354 unload_module();
16356 }
16357
16371#ifdef TEST_FRAMEWORK
16372 res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
16373 res |= AST_TEST_REGISTER(test_voicemail_msgcount);
16374 res |= AST_TEST_REGISTER(test_voicemail_vmuser);
16375 res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
16376 res |= AST_TEST_REGISTER(test_voicemail_load_config);
16377 res |= AST_TEST_REGISTER(test_voicemail_vm_info);
16378#endif
16379
16380 if (res) {
16381 ast_log(LOG_ERROR, "Failure registering applications, functions or tests\n");
16382 unload_module();
16384 }
16385
16386 /* ast_vm_register may return DECLINE if another module registered for vm */
16387 res = ast_vm_register(&vm_table);
16388 if (res) {
16389 ast_log(LOG_ERROR, "Failure registering as a voicemail provider\n");
16390 unload_module();
16392 }
16393
16394 /* ast_vm_greeter_register may return DECLINE if another module registered as a greeter */
16396 if (res) {
16397 ast_log(LOG_ERROR, "Failure registering as a greeter provider\n");
16398 unload_module();
16400 }
16401
16403
16404#ifdef TEST_FRAMEWORK
16405 ast_install_vm_test_functions(vm_test_create_user, vm_test_destroy_user);
16406#endif
16407
16408 ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
16409 ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
16410
16412}
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 14810 of file app_voicemail_imap.c.

14811{
14812 struct ast_variable *var;
14813 char *cat = NULL;
14814
14815 while ((cat = ast_category_browse(cfg, cat))) {
14816 if (strcasecmp(cat, "general") == 0
14817 || strcasecmp(cat, aliasescontext) == 0
14818 || strcasecmp(cat, "zonemessages") == 0) {
14819 continue;
14820 }
14821
14822 var = ast_variable_browse(cfg, cat);
14823 while (var) {
14824 append_mailbox(cat, var->name, var->value);
14825 var = var->next;
14826 }
14827 }
14828}
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 14775 of file app_voicemail_imap.c.

14776{
14777 struct ast_variable *var;
14778
14779 var = ast_variable_browse(cfg, "zonemessages");
14780 while (var) {
14781 if (var->value) {
14782 struct vm_zone *z;
14783 char *msg_format, *tzone;
14784 char storage[strlen(var->value) + 1];
14785
14786 z = ast_malloc(sizeof(*z));
14787 if (!z) {
14788 return;
14789 }
14790
14791 strcpy(storage, var->value); /* safe */
14792 msg_format = storage;
14793 tzone = strsep(&msg_format, "|,");
14794 if (msg_format) {
14795 ast_copy_string(z->name, var->name, sizeof(z->name));
14796 ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
14801 } else {
14802 ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
14803 ast_free(z);
14804 }
14805 }
14806 var = var->next;
14807 }
14808}
#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_imap.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_imap.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:2958
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2452
#define MAXHOSTNAMELEN
Definition: network.h:69
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
static char email[80]
Definition: pbx_dundi.c:206
Main Channel structure associated with a channel.
long int ast_random(void)
Definition: utils.c:2312

References add_email_attachment(), ast_channel_priority(), ast_channel_unref, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_free, ast_localtime(), ast_log, AST_LOG_WARNING, ast_random(), ast_str_buffer(), ast_str_create, ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime(), ast_strftime_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), check_mime(), CONFIG_FLAG_NOCACHE, ast_vm_user::context, voicemailpwcheck::context, ast_vm_user::email, email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, ast_vm_user::fromstring, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, voicemailpwcheck::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, NULL, prep_email_sub_vars(), S_OR, strip_control_and_high(), strsep(), valid_config(), VM_PBXSKIP, and vmu_tm().

Referenced by sendmail().

◆ make_file()

static int make_file ( char *  dest,
const int  len,
const char *  dir,
const int  num 
)
static

Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.

Parameters
destThe variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
lenThe length of the path string that was written out.
dir
num

The path is constructed as VM_SPOOL_DIRcontext/ext/folder

Returns
zero on success, -1 on error.

Definition at line 2206 of file app_voicemail_imap.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 14457 of file app_voicemail_imap.c.

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

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 14416 of file app_voicemail_imap.c.

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

14333{
14334 const char *context = astman_get_header(data, "Context");
14335 const char *mailbox = astman_get_header(data, "Mailbox");
14336 const char *at;
14337
14338 if (!ast_strlen_zero(mwi_state->uniqueid)) {
14339 if (
14340 /* First case: everything matches */
14342 /* Second case: match the mailbox only */
14344 (at = strchr(mwi_state->uniqueid, '@')) &&
14345 strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0) ||
14346 /* Third case: match the context only */
14348 (at = strchr(mwi_state->uniqueid, '@')) &&
14349 strcmp(context, at + 1) == 0) ||
14350 /* Final case: match an exact specified mailbox */
14352 (at = strchr(mwi_state->uniqueid, '@')) &&
14353 strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0 &&
14354 strcmp(context, at + 1) == 0)
14355 ) {
14356 poll_subscribed_mailbox(mwi_state, NULL);
14357 }
14358 }
14359
14360 return 0;
14361}
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 14370 of file app_voicemail_imap.c.

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

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 14566 of file app_voicemail_imap.c.

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

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 14495 of file app_voicemail_imap.c.

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

14364{
14366 astman_send_ack(s, m, "Refresh sent");
14367 return RESULT_SUCCESS;
14368}
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 14533 of file app_voicemail_imap.c.

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

14001{
14002 while (poll_thread_run) {
14003 struct timespec ts = { 0, };
14004 struct timeval wait;
14005
14007
14008 if (!poll_thread_run) {
14009 break;
14010 }
14011
14013 ts.tv_sec = wait.tv_sec;
14014 ts.tv_nsec = wait.tv_usec * 1000;
14015
14019 }
14020
14021 return NULL;
14022}
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_imap.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:1638

References ARRAY_LEN, id, and mailbox_folders.

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

◆ message_range_and_existence_check()

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

common bounds checking and existence check for Voicemail API functions.

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

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

Definition at line 17278 of file app_voicemail_imap.c.

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

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 6415 of file app_voicemail_imap.c.

6416{
6417 char *context;
6418 char *mailbox;
6419
6420 if (ast_strlen_zero(mailbox_id)
6421 || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
6422 return 0;
6423 }
6424
6425 return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
6426}

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 12060 of file app_voicemail_imap.c.

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

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 6682 of file app_voicemail_imap.c.

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

14108{
14109 void *data = ast_mwi_subscriber_data(sub);
14110
14111 /* Don't bump data's reference. We'll just use the one returned above */
14113 /* A reference was returned for data when retrieving, so remove it on error */
14114 ao2_ref(data, -1);
14115 }
14116}
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 14100 of file app_voicemail_imap.c.

14101{
14103 ao2_ref(data, -1);
14104 return 0;
14105}

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 14089 of file app_voicemail_imap.c.

14090{
14091 void *data = ast_mwi_subscriber_data(sub);
14092
14093 /* Don't bump data's reference. We'll just use the one returned above */
14095 /* A reference was returned for data when retrieving, so remove it on error */
14096 ao2_ref(data, -1);
14097 }
14098}
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 14070 of file app_voicemail_imap.c.

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

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

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

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 9513 of file app_voicemail_imap.c.

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

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

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

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

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

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

9040{
9041 int res = 0;
9042
9043 if (!ast_strlen_zero(category))
9044 res = ast_play_and_wait(chan, category);
9045
9046 if (res) {
9047 ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
9048 res = 0;
9049 }
9050
9051 return res;
9052}

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 9054 of file app_voicemail_imap.c.

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

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

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

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

16277{
16278 struct alias_mailbox_mapping *mapping = v_obj;
16279
16280 if (!mapping) {
16281 return;
16282 }
16283 prnt(where, "Alias: %s Mailbox: %s", mapping->alias, mapping->mailbox);
16284}

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 8521 of file app_voicemail_imap.c.

8522{
8523 char *mailbox;
8524 char *context;
8525
8527 return;
8528 }
8529
8530 ast_debug(3, "Queueing event for mailbox %s New: %d Old: %d\n", box, new + urgent, old);
8531 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8532
8534 struct ao2_iterator *aliases;
8535 struct mailbox_alias_mapping *mapping;
8536
8538 while ((mapping = ao2_iterator_next(aliases))) {
8539 char alias[strlen(mapping->alias) + 1];
8540 strcpy(alias, mapping->alias); /* safe */
8541 mailbox = NULL;
8542 context = NULL;
8543 ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);
8545 ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
8546 ao2_ref(mapping, -1);
8547 }
8549 }
8550}
#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 15562 of file app_voicemail_imap.c.

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

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 16218 of file app_voicemail_imap.c.

16219{
16220 return load_config(1);
16221}

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 12078 of file app_voicemail_imap.c.

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

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_imap.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 7568 of file app_voicemail_imap.c.

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

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_imap.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:2063
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 6601 of file app_voicemail_imap.c.

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

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

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

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_imap.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_imap.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\n\n");
6037 } else {
6038 fprintf(p, "Subject: New %s VM\n\n", flag);
6039 }
6040 }
6041
6042 if (pagerbody) {
6043 struct ast_channel *ast;
6044 if ((ast = ast_dummy_channel_alloc())) {
6045 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
6047 fprintf(p, "%s" ENDL, ast_str_buffer(str1));
6048 ast = ast_channel_unref(ast);
6049 } else {
6050 ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
6051 }
6052 } else {
6053 fprintf(p, "New %s long %s msg in box %s\n"
6054 "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
6055 }
6056
6057 fclose(p);
6058 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
6059 ast_safe_system(tmp2);
6060 ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
6061 ast_free(str1);
6062 ast_free(str2);
6063 return 0;
6064}

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_imap.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 11976 of file app_voicemail_imap.c.

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

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

12032{
12033 if (show_mailbox_details(a)){
12034 return -1;
12035 }
12036 ast_cli(a->fd, "\n");
12037 return show_mailbox_snapshot(a);
12038}
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 13722 of file app_voicemail_imap.c.

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

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

Referenced by handle_voicemail_show_users().

◆ start_poll_thread()

static void start_poll_thread ( void  )
static

Definition at line 14123 of file app_voicemail_imap.c.

14124{
14125 int errcode;
14127
14128 poll_thread_run = 1;
14129
14130 if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
14131 ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
14132 }
14133}
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 14135 of file app_voicemail_imap.c.

14136{
14137 poll_thread_run = 0;
14138
14142
14143 pthread_join(poll_thread, NULL);
14145
14147}
#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_imap.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 14636 of file app_voicemail_imap.c.

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

16224{
16225 int res;
16226
16233 res |= ast_manager_unregister("VoicemailUsersList");
16234 res |= ast_manager_unregister("VoicemailUserStatus");
16235 res |= ast_manager_unregister("VoicemailRefresh");
16236 res |= ast_manager_unregister("VoicemailBoxSummary");
16237 res |= ast_manager_unregister("VoicemailMove");
16238 res |= ast_manager_unregister("VoicemailRemove");
16239 res |= ast_manager_unregister("VoicemailForward");
16240#ifdef TEST_FRAMEWORK
16241 res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
16242 res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
16243 res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
16244 res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
16245 res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
16246 res |= AST_TEST_UNREGISTER(test_voicemail_vm_info);
16247#endif
16251#ifdef TEST_FRAMEWORK
16252 ast_uninstall_vm_test_functions();
16253#endif
16255
16256 ao2_container_unregister("voicemail_alias_mailbox_mappings");
16258 ao2_container_unregister("voicemail_mailbox_alias_mappings");
16260
16263
16265 ast_unload_realtime("voicemail");
16266 ast_unload_realtime("voicemail_data");
16267
16268#ifdef IMAP_STORAGE
16269 ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);
16270#endif
16271 free_vm_users();
16272 free_vm_zones();
16273 return res;
16274}
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:8057
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_imap.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_imap.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 11697 of file app_voicemail_imap.c.

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

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

11487{
11488 int cmd = 0;
11489
11490 if (vms->lastmsg > -1) {
11491 cmd = play_message(chan, vmu, vms);
11492 } else {
11493 cmd = ast_play_and_wait(chan, "vm-youhave");
11494 if (!cmd)
11495 cmd = ast_play_and_wait(chan, "vm-no");
11496 if (!cmd) {
11497 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11498 cmd = ast_play_and_wait(chan, vms->fn);
11499 }
11500 if (!cmd)
11501 cmd = ast_play_and_wait(chan, "vm-messages");
11502 }
11503 return cmd;
11504}
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 11567 of file app_voicemail_imap.c.

11568{
11569 int cmd;
11570
11571 if (vms->lastmsg > -1) {
11572 cmd = play_message(chan, vmu, vms);
11573 } else {
11574 cmd = ast_play_and_wait(chan, "vm-youhaveno");
11575 if (!cmd)
11576 cmd = ast_play_and_wait(chan, "vm-messages");
11577 if (!cmd) {
11578 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11579 cmd = ast_play_and_wait(chan, vms->fn);
11580 }
11581 }
11582 return cmd;
11583}

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 11434 of file app_voicemail_imap.c.

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

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 11462 of file app_voicemail_imap.c.

11463{
11464 int cmd = 0;
11465
11466 if (vms->lastmsg > -1) {
11467 cmd = play_message(chan, vmu, vms);
11468 } else {
11469 if (!strcasecmp(vms->fn, "INBOX")) {
11470 cmd = ast_play_and_wait(chan, "vm-nonewmessages");
11471 } else {
11472 cmd = ast_play_and_wait(chan, "vm-nomessages");
11473 }
11474 }
11475 return cmd;
11476}

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 11514 of file app_voicemail_imap.c.

11515{
11516 int cmd;
11517
11518 if (vms->lastmsg > -1) {
11519 cmd = play_message(chan, vmu, vms);
11520 } else {
11521 cmd = ast_play_and_wait(chan, "vm-no");
11522 if (!cmd)
11523 cmd = ast_play_and_wait(chan, "vm-message");
11524 if (!cmd) {
11525 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11526 cmd = ast_play_and_wait(chan, vms->fn);
11527 }
11528 }
11529 return cmd;
11530}

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 11540 of file app_voicemail_imap.c.

11541{
11542 int cmd = 0;
11543
11544 if (vms->lastmsg > -1) {
11545 cmd = play_message(chan, vmu, vms);
11546 } else {
11547 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11548 cmd = ast_play_and_wait(chan, vms->fn);
11549 if (!cmd)
11550 cmd = ast_play_and_wait(chan, "vm-messages");
11551 if (!cmd)
11552 cmd = ast_play_and_wait(chan, "jp-wa");
11553 if (!cmd)
11554 cmd = ast_play_and_wait(chan, "jp-arimasen");
11555 }
11556 return cmd;
11557}

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 11593 of file app_voicemail_imap.c.

11594{
11595 int cmd;
11596
11597 if (vms->lastmsg > -1) {
11598 cmd = play_message(chan, vmu, vms);
11599 } else {
11600 cmd = ast_play_and_wait(chan, "vm-no");
11601 if (!cmd) {
11602 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11603 cmd = ast_play_and_wait(chan, vms->fn);
11604 }
11605 if (!cmd)
11606 cmd = ast_play_and_wait(chan, "vm-messages");
11607 }
11608 return cmd;
11609}

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 11647 of file app_voicemail_imap.c.

11648{
11649 int cmd = 0;
11650
11651 if (vms->lastmsg > -1) {
11652 cmd = play_message(chan, vmu, vms);
11653 } else {
11654 cmd = ast_play_and_wait(chan, "vm-no");
11655 if (!cmd) {
11656 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11657 cmd = ast_play_and_wait(chan, vms->fn);
11658 }
11659 }
11660 return cmd;
11661}

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 11619 of file app_voicemail_imap.c.

11620{
11621 int cmd;
11622
11623 if (vms->lastmsg > -1) {
11624 cmd = play_message(chan, vmu, vms);
11625 } else {
11626 cmd = ast_play_and_wait(chan, "vm-you");
11627 if (!cmd)
11628 cmd = ast_play_and_wait(chan, "vm-haveno");
11629 if (!cmd)
11630 cmd = ast_play_and_wait(chan, "vm-messages");
11631 if (!cmd) {
11632 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
11633 cmd = ast_play_and_wait(chan, vms->fn);
11634 }
11635 }
11636 return cmd;
11637}

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_imap.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:1533
@ CONFIG_FLAG_WITHCOMMENTS

References ast_category_browse(), ast_category_get(), ast_config_destroy(), ast_config_load, ast_config_text_file_save(), ast_copy_string(), ast_debug, ast_free, ast_log, AST_LOG_WARNING, ast_malloc, ast_test_suite_event_notify, ast_variable_append(), ast_variable_new, ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, ast_vm_user::context, LOG_WARNING, ast_vm_user::mailbox, NULL, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, PATH_MAX, reset_user_pw(), tmp(), valid_config(), value, var, VM_SPOOL_DIR, VOICEMAIL_CONFIG, and write_password_to_file().

Referenced by vm_newuser_setup(), and vm_options().

◆ vm_change_password_shell()

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

Definition at line 2163 of file app_voicemail_imap.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_imap.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_imap.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 13186 of file app_voicemail_imap.c.

13187{
13188 int res = 0;
13189 char *tmp;
13190 struct leave_vm_options leave_options;
13191 struct ast_flags flags = { 0 };
13192 char *opts[OPT_ARG_ARRAY_SIZE];
13194 AST_APP_ARG(argv0);
13195 AST_APP_ARG(argv1);
13196 );
13197 SCOPE_ENTER(3, "%s\n", ast_channel_name(chan));
13198
13199 memset(&leave_options, 0, sizeof(leave_options));
13200
13201 if (!ast_strlen_zero(data)) {
13202 tmp = ast_strdupa(data);
13204 if (args.argc == 2) {
13205 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
13206 SCOPE_EXIT_RTN_VALUE(-1, "parse options failed for '%s'\n", args.argv1);
13207 }
13210 int gain;
13211
13212 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
13213 SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
13214 } else {
13215 leave_options.record_gain = (signed char) gain;
13216 }
13217 }
13220 leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
13221 }
13222 }
13223 if (ast_test_flag(&flags, OPT_BEEP)) { /* Use custom beep (or none at all) */
13224 leave_options.beeptone = opts[OPT_ARG_BEEP_TONE];
13225 } else { /* Use default beep */
13226 leave_options.beeptone = "beep";
13227 }
13228 } else {
13229 char temp[256];
13230 res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
13231 if (res < 0) {
13232 SCOPE_EXIT_RTN_VALUE(res, "getdata failed. RC: %d", res);
13233 }
13234 if (ast_strlen_zero(temp)) {
13236 }
13237 args.argv0 = ast_strdupa(temp);
13238 }
13239
13240 if (ast_channel_state(chan) != AST_STATE_UP) {
13243 } else {
13244 ast_answer(chan);
13245 }
13246 }
13247
13248 res = SCOPE_CALL_WITH_INT_RESULT(-1, leave_voicemail, chan, args.argv0, &leave_options);
13249 if (res == 't') {
13250 ast_play_and_wait(chan, "vm-goodbye");
13251 res = 0;
13252 }
13253
13254 if (res == OPERATOR_EXIT) {
13255 res = 0;
13256 }
13257
13258 if (res == ERROR_LOCK_PATH) {
13259 ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
13260 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
13261 res = 0;
13262 }
13263
13264 SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d", res);
13265}
static const struct ast_app_option vm_app_options[128]
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
Definition: main/app.c:188
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c: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 12355 of file app_voicemail_imap.c.

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

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

11106{
11107 if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
11108 return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11109 } else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
11110 return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11111 } else { /* Default to ENGLISH */
11112 return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
11113 }
11114}
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 10895 of file app_voicemail_imap.c.

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

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 10985 of file app_voicemail_imap.c.

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

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 11081 of file app_voicemail_imap.c.

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

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 10827 of file app_voicemail_imap.c.

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

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

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 10348 of file app_voicemail_imap.c.

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

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 10393 of file app_voicemail_imap.c.

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

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 10028 of file app_voicemail_imap.c.

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

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 10442 of file app_voicemail_imap.c.

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

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 10540 of file app_voicemail_imap.c.

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

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 9788 of file app_voicemail_imap.c.

9789{
9790 int res = 0;
9791
9792 if (vms->newmessages) {
9793 res = ast_play_and_wait(chan, "vm-youhave");
9794 if (!res)
9796 if (!res) {
9797 if (vms->newmessages == 1) {
9798 res = ast_play_and_wait(chan, "vm-INBOX");
9799 if (!res)
9800 res = ast_play_and_wait(chan, "vm-message");
9801 } else {
9802 res = ast_play_and_wait(chan, "vm-INBOXs");
9803 if (!res)
9804 res = ast_play_and_wait(chan, "vm-messages");
9805 }
9806 }
9807 } else if (vms->oldmessages){
9808 res = ast_play_and_wait(chan, "vm-youhave");
9809 if (!res)
9811 if (vms->oldmessages == 1){
9812 res = ast_play_and_wait(chan, "vm-Old");
9813 if (!res)
9814 res = ast_play_and_wait(chan, "vm-message");
9815 } else {
9816 res = ast_play_and_wait(chan, "vm-Olds");
9817 if (!res)
9818 res = ast_play_and_wait(chan, "vm-messages");
9819 }
9820 } else if (!vms->oldmessages && !vms->newmessages)
9821 res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
9822 return res;
9823}

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 9922 of file app_voicemail_imap.c.

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

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 10085 of file app_voicemail_imap.c.

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

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 10154 of file app_voicemail_imap.c.

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

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 9989 of file app_voicemail_imap.c.

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

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

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

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 10304 of file app_voicemail_imap.c.

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

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 10189 of file app_voicemail_imap.c.

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

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 10634 of file app_voicemail_imap.c.

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

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 10495 of file app_voicemail_imap.c.

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

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 10260 of file app_voicemail_imap.c.

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

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 10797 of file app_voicemail_imap.c.

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

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 10758 of file app_voicemail_imap.c.

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

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_imap.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 17127 of file app_voicemail_imap.c.

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

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

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

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 17481 of file app_voicemail_imap.c.

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

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 17683 of file app_voicemail_imap.c.

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

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 17585 of file app_voicemail_imap.c.

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

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 16944 of file app_voicemail_imap.c.

16945{
16946 struct ast_vm_msg_snapshot *msg_snapshot;
16947
16948 if (!(msg_snapshot = ast_calloc(1, sizeof(*msg_snapshot)))) {
16949 return NULL;
16950 }
16951
16952 if (ast_string_field_init(msg_snapshot, 512)) {
16953 ast_free(msg_snapshot);
16954 return NULL;
16955 }
16956
16957 return msg_snapshot;
16958}
#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 17012 of file app_voicemail_imap.c.

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

16961{
16962 ast_string_field_free_memory(msg_snapshot);
16963 ast_free(msg_snapshot);
16964
16965 return NULL;
16966}
#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 11116 of file app_voicemail_imap.c.

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

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

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

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

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 9707 of file app_voicemail_imap.c.

9708{
9709 int cmd;
9710
9711 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9712 cmd = ast_play_and_wait(chan, box);
9713 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9714 } else {
9715 cmd = ast_play_and_wait(chan, box);
9716 return cmd;
9717 }
9718}

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 9720 of file app_voicemail_imap.c.

9721{
9722 int cmd;
9723
9724 if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
9725 if (!strcasecmp(box, "vm-INBOX"))
9726 cmd = ast_play_and_wait(chan, "vm-new-e");
9727 else
9728 cmd = ast_play_and_wait(chan, "vm-old-e");
9729 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9730 } else {
9731 cmd = ast_play_and_wait(chan, "vm-messages");
9732 return cmd ? cmd : ast_play_and_wait(chan, box);
9733 }
9734}

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 9736 of file app_voicemail_imap.c.

9737{
9738 int cmd;
9739
9740 if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
9741 cmd = ast_play_and_wait(chan, "vm-messages");
9742 return cmd ? cmd : ast_play_and_wait(chan, box);
9743 } else {
9744 cmd = ast_play_and_wait(chan, box);
9745 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
9746 }
9747}

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 11937 of file app_voicemail_imap.c.

11938{
11939 char *parse;
11940 char *mailbox = NULL;
11941 char *context = NULL;
11942 int res;
11943
11946 AST_APP_ARG(msg_id);
11947 );
11948
11949 if (ast_channel_state(chan) != AST_STATE_UP) {
11950 ast_debug(1, "Before ast_answer\n");
11951 ast_answer(chan);
11952 }
11953
11954 if (ast_strlen_zero(data)) {
11955 return -1;
11956 }
11957
11958 parse = ast_strdupa(data);
11960
11961 if (ast_strlen_zero(args.mailbox) || ast_strlen_zero(args.msg_id)) {
11962 return -1;
11963 }
11964
11965 if ((context = strchr(args.mailbox, '@'))) {
11966 *context++ = '\0';
11967 }
11968 mailbox = args.mailbox;
11969
11970 res = play_message_by_id(chan, mailbox, context, args.msg_id);
11971 pbx_builtin_setvar_helper(chan, "VOICEMAIL_PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS");
11972
11973 return 0;
11974}
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 15550 of file app_voicemail_imap.c.

15551{
15552 char *context;
15553 char *mailbox;
15554
15555 if (ast_strlen_zero(mailbox_id)
15556 || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
15557 return -1;
15558 }
15559 return sayname(chan, mailbox, context);
15560}
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 11359 of file app_voicemail_imap.c.

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

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 13681 of file app_voicemail_imap.c.

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

15613{
15614 char *context;
15615 char *mailbox;
15616 int res;
15617
15618 if (ast_strlen_zero(data)
15620 ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
15621 return -1;
15622 }
15623
15624 if ((res = sayname(chan, mailbox, context)) < 0) {
15625 ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", mailbox, context);
15626 res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
15627 if (!res) {
15629 }
15630 }
15631
15632 return res;
15633}
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
Definition: channel.c:8271
@ AST_SAY_CASE_NONE
Definition: say.h:182

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

Referenced by load_module().

◆ vmu_tm()

static const struct ast_tm * vmu_tm ( const struct ast_vm_user vmu,
struct ast_tm tm 
)
static

fill in *tm for current time according to the proper timezone, if any.

Returns
tm so it can be used as a function argument.

Definition at line 5328 of file app_voicemail_imap.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 9033 of file app_voicemail_imap.c.

9034{
9035 ast_test_suite_event_notify("PLAYVOICE", "Message: Playing %s", file);
9037}
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 9025 of file app_voicemail_imap.c.

9026{
9027 int res;
9028 if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
9029 ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file);
9030 return res;
9031}

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 15579 of file app_voicemail_imap.c.

15579 {
15580 struct ast_config *conf;
15581 struct ast_category *cat;
15582 struct ast_variable *var;
15583 int res = -1;
15584
15585 if (!(conf = ast_config_new())) {
15586 ast_log(LOG_ERROR, "Error creating new config structure\n");
15587 return res;
15588 }
15589 if (!(cat = ast_category_new("general", "", 1))) {
15590 ast_log(LOG_ERROR, "Error creating new category structure\n");
15592 return res;
15593 }
15594 if (!(var = ast_variable_new("password", password, ""))) {
15595 ast_log(LOG_ERROR, "Error creating new variable structure\n");
15598 return res;
15599 }
15602 if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
15603 res = 0;
15604 } else {
15605 ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
15606 }
15607
15609 return res;
15610}
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 17807 of file app_voicemail_imap.c.

◆ addesc

char* addesc = "Comedian Mail"
static

Definition at line 1043 of file app_voicemail_imap.c.

Referenced by adsi_load_vmail().

◆ adsifdn

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

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

Referenced by actual_load_config(), and adsi_load_vmail().

◆ adsiver

int adsiver = 1
static

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

◆ callcontext

char callcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1152 of file app_voicemail_imap.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_imap.c.

◆ cidinternalcontexts

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static

Definition at line 1155 of file app_voicemail_imap.c.

Referenced by actual_load_config(), and play_message_callerid().

◆ cli_voicemail

struct ast_cli_entry cli_voicemail[]
static

Definition at line 13964 of file app_voicemail_imap.c.

Referenced by load_module(), and unload_module().

◆ dialcontext

char dialcontext[AST_MAX_CONTEXT] = ""
static

Definition at line 1151 of file app_voicemail_imap.c.

Referenced by actual_load_config(), and populate_defaults().

◆ emailbody

char* emailbody
static

Definition at line 1158 of file app_voicemail_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.c.

Referenced by actual_load_config(), and wait_file().

◆ locale

char locale[20]
static

Definition at line 1060 of file app_voicemail_imap.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_imap.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_imap.c.

Referenced by actual_load_config(), and vm_execmain().

◆ maxmsg

int maxmsg = MAXMSG
static

Definition at line 1062 of file app_voicemail_imap.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_imap.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_imap.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 14118 of file app_voicemail_imap.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_imap.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_imap.c.

Referenced by actual_load_config(), and sendpage().

◆ pagerfromstring

char pagerfromstring[100]
static

Definition at line 1163 of file app_voicemail_imap.c.

Referenced by actual_load_config(), and sendpage().

◆ pagersubject

char* pagersubject
static

Definition at line 1161 of file app_voicemail_imap.c.

Referenced by actual_load_config(), and sendpage().

◆ passwordlocation

int passwordlocation
static

Definition at line 1077 of file app_voicemail_imap.c.

Referenced by actual_load_config(), and populate_defaults().

◆ playmsg_app

char* playmsg_app = "VoiceMailPlayMsg"
static

Definition at line 1053 of file app_voicemail_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.c.

Referenced by actual_load_config(), and populate_defaults().

◆ sayname_app

char* sayname_app = "VMSayName"
static

Definition at line 1055 of file app_voicemail_imap.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_imap.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_imap.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_imap.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_imap.c.

Referenced by vm_exec(), and vm_execmain().

◆ vm_greeter_table

const struct ast_vm_greeter_functions vm_greeter_table
static

Definition at line 16211 of file app_voicemail_imap.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 13676 of file app_voicemail_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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_imap.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 16193 of file app_voicemail_imap.c.

Referenced by load_module(), and unload_module().

◆ vmauthenticate_app

char* vmauthenticate_app = "VMAuthenticate"
static

Definition at line 1051 of file app_voicemail_imap.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_imap.c.

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

◆ vmminsecs

int vmminsecs
static

Definition at line 1071 of file app_voicemail_imap.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_imap.c.

Referenced by load_module(), and unload_module().

◆ voicemailmain_app

char* voicemailmain_app = "VoiceMailMain"
static

Definition at line 1049 of file app_voicemail_imap.c.

Referenced by load_module(), and unload_module().

◆ volgain

double volgain
static

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

Referenced by actual_load_config(), and populate_defaults().